Skip to content

Commit 435ce17

Browse files
committed
fix: Made message merger thread safe
1 parent 49b0817 commit 435ce17

File tree

1 file changed

+92
-78
lines changed

1 file changed

+92
-78
lines changed

Ruffles/Messaging/MessageMerger.cs

Lines changed: 92 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ internal class MessageMerger
1212
private ushort _headerBytes;
1313
private ushort _packets;
1414

15+
private readonly object _lock = new object();
16+
1517
internal MessageMerger(int maxSize, ulong flushDelay)
1618
{
1719
_buffer = new byte[maxSize];
@@ -25,65 +27,74 @@ internal MessageMerger(int maxSize, ulong flushDelay)
2527

2628
internal void Clear()
2729
{
28-
_lastFlushTime = DateTime.Now;
29-
_position = 1;
30-
_headerBytes = 1;
31-
_packets = 0;
30+
lock (_lock)
31+
{
32+
_lastFlushTime = DateTime.Now;
33+
_position = 1;
34+
_headerBytes = 1;
35+
_packets = 0;
36+
}
3237
}
3338

3439
internal bool TryWrite(ArraySegment<byte> payload, ushort headerBytes)
3540
{
36-
if (payload.Count + _position + 2 > _buffer.Length)
37-
{
38-
// Wont fit
39-
return false;
40-
}
41-
else
41+
lock (_lock)
4242
{
43-
// TODO: VarInt
44-
// Write the segment size
45-
_buffer[_position] = (byte)(payload.Count);
46-
_buffer[_position + 1] = (byte)(payload.Count >> 8);
43+
if (payload.Count + _position + 2 > _buffer.Length)
44+
{
45+
// Wont fit
46+
return false;
47+
}
48+
else
49+
{
50+
// TODO: VarInt
51+
// Write the segment size
52+
_buffer[_position] = (byte)(payload.Count);
53+
_buffer[_position + 1] = (byte)(payload.Count >> 8);
4754

48-
// Copy the payload with the header
49-
Buffer.BlockCopy(payload.Array, payload.Offset, _buffer, _position + 2, payload.Count);
55+
// Copy the payload with the header
56+
Buffer.BlockCopy(payload.Array, payload.Offset, _buffer, _position + 2, payload.Count);
5057

51-
// Update the position
52-
_position += 2 + payload.Count;
58+
// Update the position
59+
_position += 2 + payload.Count;
5360

54-
// Update the amount of header bytes
55-
_headerBytes += headerBytes;
61+
// Update the amount of header bytes
62+
_headerBytes += headerBytes;
5663

57-
// Update the amount of packets
58-
_packets++;
64+
// Update the amount of packets
65+
_packets++;
5966

60-
return true;
67+
return true;
68+
}
6169
}
6270
}
6371

6472
internal ArraySegment<byte>? TryFlush(out ushort headerBytes)
6573
{
66-
if (_position > 1 && (DateTime.Now - _lastFlushTime).TotalMilliseconds > _flushDelay)
74+
lock (_lock)
6775
{
68-
// Its time to flush
76+
if (_position > 1 && (DateTime.Now - _lastFlushTime).TotalMilliseconds > _flushDelay)
77+
{
78+
// Its time to flush
6979

70-
// Save the size
71-
int flushSize = _position;
80+
// Save the size
81+
int flushSize = _position;
7282

73-
headerBytes = _headerBytes;
83+
headerBytes = _headerBytes;
7484

75-
// Reset values
76-
_position = 1;
77-
_lastFlushTime = DateTime.Now;
78-
_headerBytes = 1;
79-
_packets = 0;
85+
// Reset values
86+
_position = 1;
87+
_lastFlushTime = DateTime.Now;
88+
_headerBytes = 1;
89+
_packets = 0;
8090

81-
return new ArraySegment<byte>(_buffer, 0, flushSize);
82-
}
91+
return new ArraySegment<byte>(_buffer, 0, flushSize);
92+
}
8393

84-
headerBytes = 0;
94+
headerBytes = 0;
8595

86-
return null;
96+
return null;
97+
}
8798
}
8899

89100

@@ -93,56 +104,59 @@ internal bool TryWrite(ArraySegment<byte> payload, ushort headerBytes)
93104
// DONT MAKE STATIC FOR THREAD SAFETY.
94105
internal List<ArraySegment<byte>> Unpack(ArraySegment<byte> payload)
95106
{
96-
// TODO: VarInt
97-
if (payload.Count < 3)
98-
{
99-
// Payload is too small
100-
return null;
101-
}
102-
103-
// Clear the segments list
104-
_unpackSegments.Clear();
105-
106-
// The offset for walking the buffer
107-
int packetOffset = 0;
108-
109-
while (true)
107+
lock (_lock)
110108
{
111-
if (payload.Count < packetOffset + 2)
112-
{
113-
// No more data to be read
114-
return _unpackSegments;
115-
}
116-
117109
// TODO: VarInt
118-
// Read the size
119-
ushort size = (ushort)(payload.Array[payload.Offset + packetOffset] | (ushort)(payload.Array[payload.Offset + packetOffset + 1] << 8));
120-
121-
if (size < 1)
110+
if (payload.Count < 3)
122111
{
123-
// The size is too small. Doesnt fit the header
124-
return _unpackSegments;
112+
// Payload is too small
113+
return null;
125114
}
126115

127-
// Make sure the size can even fit
128-
if (payload.Count < (packetOffset + 2 + size))
129-
{
130-
// Payload is too small to fit the claimed size. Exit
131-
return _unpackSegments;
132-
}
116+
// Clear the segments list
117+
_unpackSegments.Clear();
133118

134-
// Read the header
135-
HeaderPacker.Unpack(payload.Array[payload.Offset + packetOffset + 2], out byte type, out bool fragment);
119+
// The offset for walking the buffer
120+
int packetOffset = 0;
136121

137-
// Prevent merging a merge
138-
if (type != (byte)MessageType.Merge)
122+
while (true)
139123
{
140-
// Add the new segment
141-
_unpackSegments.Add(new ArraySegment<byte>(payload.Array, payload.Offset + packetOffset + 2, size));
124+
if (payload.Count < packetOffset + 2)
125+
{
126+
// No more data to be read
127+
return _unpackSegments;
128+
}
129+
130+
// TODO: VarInt
131+
// Read the size
132+
ushort size = (ushort)(payload.Array[payload.Offset + packetOffset] | (ushort)(payload.Array[payload.Offset + packetOffset + 1] << 8));
133+
134+
if (size < 1)
135+
{
136+
// The size is too small. Doesnt fit the header
137+
return _unpackSegments;
138+
}
139+
140+
// Make sure the size can even fit
141+
if (payload.Count < (packetOffset + 2 + size))
142+
{
143+
// Payload is too small to fit the claimed size. Exit
144+
return _unpackSegments;
145+
}
146+
147+
// Read the header
148+
HeaderPacker.Unpack(payload.Array[payload.Offset + packetOffset + 2], out byte type, out bool fragment);
149+
150+
// Prevent merging a merge
151+
if (type != (byte)MessageType.Merge)
152+
{
153+
// Add the new segment
154+
_unpackSegments.Add(new ArraySegment<byte>(payload.Array, payload.Offset + packetOffset + 2, size));
155+
}
156+
157+
// Increment the packetOffset
158+
packetOffset += 2 + size;
142159
}
143-
144-
// Increment the packetOffset
145-
packetOffset += 2 + size;
146160
}
147161
}
148162
}

0 commit comments

Comments
 (0)