protected void processPacket(ushort seq, byte[] packetData, int packetLen) { using (ByteArrayReaderWriter byteArrayReaderWriter = ByteArrayReaderWriter.Get(packetData)) { while (byteArrayReaderWriter.ReadPosition < packetLen) { ushort num = byteArrayReaderWriter.ReadUInt16(); ushort num2 = readVariableLengthUShort(byteArrayReaderWriter); if (num2 != 0) { if (!receiveBuffer.Exists(num)) { BufferedPacket bufferedPacket = receiveBuffer.Insert(num); bufferedPacket.buffer.SetSize(num2); byteArrayReaderWriter.ReadBytesIntoBuffer(bufferedPacket.buffer.InternalBuffer, num2); } else { byteArrayReaderWriter.SeekRead(byteArrayReaderWriter.ReadPosition + (int)num2); } while (receiveBuffer.Exists(nextReceive)) { BufferedPacket bufferedPacket2 = receiveBuffer.Find(nextReceive); ReceiveCallback(ChannelID, bufferedPacket2.buffer.InternalBuffer, bufferedPacket2.buffer.Length); receiveBuffer.Remove(nextReceive); nextReceive++; } } } } }
protected void ackPacket(ushort seq) { OutgoingPacketSet outgoingPacketSet = ackBuffer.Find(seq); if (outgoingPacketSet == null) { return; } for (int i = 0; i < outgoingPacketSet.MessageIds.Count; i++) { ushort num = outgoingPacketSet.MessageIds[i]; if (sendBuffer.Exists(num)) { sendBuffer.Find(num).writeLock = true; sendBuffer.Remove(num); } } bool flag = true; ushort num2 = oldestUnacked; while (num2 == sequence || PacketIO.SequenceLessThan(num2, sequence)) { if (sendBuffer.Exists(num2)) { oldestUnacked = num2; flag = false; break; } num2 = (ushort)(num2 + 1); } if (flag) { oldestUnacked = sequence; } }
protected void processSendBuffer() { for (ushort seq = oldestUnacked; PacketIO.SequenceLessThan(seq, this.sequence); seq++) { // never send message ID >= ( oldestUnacked + bufferSize ) if (seq >= (oldestUnacked + 256)) { break; } // for any message that hasn't been sent in the last 0.1 seconds and fits in the available space of our message packer, add it var packet = sendBuffer.Find(seq); if (packet != null) { if (time - packet.time < 0.1) { continue; } bool packetFits = false; if (packet.buffer.Length < config.FragmentThreshold) { packetFits = (messagePacker.Length + packet.buffer.Length) <= (config.FragmentThreshold - Defines.MAX_PACKET_HEADER_BYTES); } else { packetFits = (messagePacker.Length + packet.buffer.Length) <= (config.MaxPacketSize - Defines.FRAGMENT_HEADER_BYTES - Defines.MAX_PACKET_HEADER_BYTES); } // if the packet won't fit, flush the message packer if (!packetFits) { flushMessagePacker(); } packet.time = time; int ptr = messagePacker.Length; messagePacker.SetSize(messagePacker.Length + packet.buffer.Length); messagePacker.BufferCopy(packet.buffer, 0, ptr, packet.buffer.Length); tempList.Add(seq); lastMessageSend = time; } } // if it has been 0.1 seconds since the last time we sent a message, send an empty message if (time - lastMessageSend >= 0.1) { sendAckPacket(); lastMessageSend = time; } // flush any remaining messages in message packer flushMessagePacker(); }
protected void processSendBuffer() { int num = 0; ushort num2 = oldestUnacked; while (PacketIO.SequenceLessThan(num2, sequence)) { num++; num2 = (ushort)(num2 + 1); } ushort num3 = oldestUnacked; while (PacketIO.SequenceLessThan(num3, sequence) && num3 < oldestUnacked + 256) { BufferedPacket bufferedPacket = sendBuffer.Find(num3); if (bufferedPacket != null && !bufferedPacket.writeLock && !(time - bufferedPacket.time < 0.1)) { bool flag = false; if (!((bufferedPacket.buffer.Length >= config.FragmentThreshold) ? (messagePacker.Length + bufferedPacket.buffer.Length <= config.MaxPacketSize - 6 - 10) : (messagePacker.Length + bufferedPacket.buffer.Length <= config.FragmentThreshold - 10))) { flushMessagePacker(); } bufferedPacket.time = time; int length = messagePacker.Length; messagePacker.SetSize(messagePacker.Length + bufferedPacket.buffer.Length); messagePacker.BufferCopy(bufferedPacket.buffer, 0, length, bufferedPacket.buffer.Length); tempList.Add(num3); lastMessageSend = time; } num3 = (ushort)(num3 + 1); } if (time - lastMessageSend >= 0.1) { sendAckPacket(); lastMessageSend = time; } flushMessagePacker(); }
protected void ackPacket(ushort seq) { // first, map seq to message IDs and ack them var outgoingPacket = ackBuffer.Find(seq); if (outgoingPacket == null) { return; } // process messages for (int i = 0; i < outgoingPacket.MessageIds.Count; i++) { // remove acked message from send buffer ushort messageID = outgoingPacket.MessageIds[i]; if (sendBuffer.Exists(messageID)) { sendBuffer.Find(messageID).writeLock = true; sendBuffer.Remove(messageID); } } // update oldest unacked message bool allAcked = true; for (ushort sequence = oldestUnacked; sequence == this.sequence || PacketIO.SequenceLessThan(sequence, this.sequence); sequence++) { // if it's still in the send buffer, it hasn't been acked if (sendBuffer.Exists(sequence)) { oldestUnacked = sequence; allAcked = false; break; } } if (allAcked) { oldestUnacked = this.sequence; } }
// process incoming packets and turn them into messages protected void processPacket(ushort seq, byte[] packetData, int packetLen) { using (var reader = ByteArrayReaderWriter.Get(packetData)) { while (reader.ReadPosition < packetLen) { // get message bytes and send to receive callback ushort messageID = reader.ReadUInt16(); ushort messageLength = readVariableLengthUShort(reader); if (messageLength == 0) { continue; } if (!receiveBuffer.Exists(messageID)) { var receivedMessage = receiveBuffer.Insert(messageID); receivedMessage.buffer.SetSize(messageLength); reader.ReadBytesIntoBuffer(receivedMessage.buffer.InternalBuffer, messageLength); } else { reader.SeekRead(reader.ReadPosition + messageLength); } // keep returning the next message we're expecting as long as it's available while (receiveBuffer.Exists(nextReceive)) { var msg = receiveBuffer.Find(nextReceive); ReceiveCallback(msg.buffer.InternalBuffer, msg.buffer.Length); receiveBuffer.Remove(nextReceive); nextReceive++; } } } }
public void ReceivePacket(byte[] packetData, int bufferLength) { if (bufferLength > config.MaxPacketSize) { throw new ArgumentOutOfRangeException("Packet is larger than max packet size"); } if (packetData == null) { throw new InvalidOperationException("Tried to receive null packet!"); } if (bufferLength > packetData.Length) { throw new InvalidOperationException("Buffer length exceeds actual packet length!"); } byte prefixByte = packetData[0]; if ((prefixByte & 1) == 0) { // regular packet ushort sequence; ushort ack; uint ackBits; byte channelID; bool compressed; int packetHeaderBytes = PacketIO.ReadPacketHeader(packetData, 0, bufferLength, out channelID, out sequence, out ack, out ackBits, out compressed); bool isStale; lock (receivedPackets) isStale = !receivedPackets.TestInsert(sequence); if (!isStale && (prefixByte & 0x80) == 0) { if (packetHeaderBytes >= bufferLength) { throw new FormatException($"Buffer too small for packet data! {packetHeaderBytes} packetHeaderBytes > {bufferLength} bufferLength"); } ByteBuffer tempBuffer = ObjPool <ByteBuffer> .Get(); if (compressed) { var decompressedBytes = LZ4Codec.Unwrap(packetData, packetHeaderBytes); tempBuffer.SetSize(decompressedBytes.Length); tempBuffer.BufferCopy(decompressedBytes, 0, 0, decompressedBytes.Length); bufferLength = decompressedBytes.Length + packetHeaderBytes; } else { tempBuffer.SetSize(bufferLength - packetHeaderBytes); tempBuffer.BufferCopy(packetData, packetHeaderBytes, 0, tempBuffer.Length); } // process packet config.ProcessPacketCallback(sequence, tempBuffer.InternalBuffer, tempBuffer.Length); // add to received buffer lock (receivedPackets) { ReceivedPacketData receivedPacketData = receivedPackets.Insert(sequence); if (receivedPacketData == null) { throw new InvalidOperationException("Failed to insert received packet!"); } receivedPacketData.time = this.time; receivedPacketData.packetBytes = (uint)(bufferLength); } ObjPool <ByteBuffer> .Return(tempBuffer); } if (!isStale || (prefixByte & 0x80) != 0) { for (int i = 0; i < 32; i++) { if ((ackBits & 1) != 0) { ushort ack_sequence = (ushort)(ack - i); SentPacketData sentPacketData = sentPackets.Find(ack_sequence); if (sentPacketData != null && !sentPacketData.acked) { sentPacketData.acked = true; if (config.AckPacketCallback != null) { config.AckPacketCallback(ack_sequence); } float rtt = (float)(this.time - sentPacketData.time) * 1000.0f; if ((this.rtt == 0f && rtt > 0f) || Math.Abs(this.rtt - rtt) < 0.00001f) { this.rtt = rtt; } else { this.rtt += (rtt - this.rtt) * config.RTTSmoothFactor; } } } ackBits >>= 1; } } } else { // fragment packet int fragmentID; int numFragments; int fragmentBytes; ushort sequence; ushort ack; uint ackBits; byte fragmentChannelID; bool compressed; int fragmentHeaderBytes = PacketIO.ReadFragmentHeader(packetData, 0, bufferLength, config.MaxFragments, config.FragmentSize, out fragmentID, out numFragments, out fragmentBytes, out sequence, out ack, out ackBits, out fragmentChannelID, out compressed); FragmentReassemblyData reassemblyData = fragmentReassembly.Find(sequence); if (reassemblyData == null) { reassemblyData = fragmentReassembly.Insert(sequence); // failed to insert into buffer (stale) if (reassemblyData == null) { return; } reassemblyData.Sequence = sequence; reassemblyData.Ack = 0; reassemblyData.AckBits = 0; reassemblyData.NumFragmentsReceived = 0; reassemblyData.NumFragmentsTotal = numFragments; reassemblyData.PacketBytes = 0; reassemblyData.PacketDataBuffer.SetSize(0); Array.Clear(reassemblyData.FragmentReceived, 0, reassemblyData.FragmentReceived.Length); } if (numFragments != reassemblyData.NumFragmentsTotal) { return; } if (reassemblyData.FragmentReceived[fragmentID]) { return; } reassemblyData.NumFragmentsReceived++; reassemblyData.FragmentReceived[fragmentID] = true; byte[] tempFragmentData = BufferPool.GetBuffer(2048); Buffer.BlockCopy(packetData, fragmentHeaderBytes, tempFragmentData, 0, bufferLength - fragmentHeaderBytes); reassemblyData.StoreFragmentData(fragmentChannelID, sequence, ack, ackBits, fragmentID, config.FragmentSize, tempFragmentData, bufferLength - fragmentHeaderBytes, compressed); BufferPool.ReturnBuffer(tempFragmentData); if (reassemblyData.NumFragmentsReceived == reassemblyData.NumFragmentsTotal) { // grab internal buffer and pass it to ReceivePacket. Internal buffer will be packet marked as normal packet, so it will go through normal packet path // copy into new buffer to remove preceding offset (used to simplify variable length header handling) ByteBuffer temp = ObjPool <ByteBuffer> .Get(); temp.SetSize(reassemblyData.PacketDataBuffer.Length - reassemblyData.HeaderOffset); Buffer.BlockCopy(reassemblyData.PacketDataBuffer.InternalBuffer, reassemblyData.HeaderOffset, temp.InternalBuffer, 0, temp.Length); // receive packet this.ReceivePacket(temp.InternalBuffer, temp.Length); // return temp buffer ObjPool <ByteBuffer> .Return(temp); // clear reassembly reassemblyData.PacketDataBuffer.SetSize(0); fragmentReassembly.Remove(sequence); } } }
public void Update(double newTime) { this.time = newTime; // calculate packet loss { uint baseSequence = (uint)((sentPackets.sequence - config.SentPacketBufferSize + 1) + 0xFFFF); int numDropped = 0; int numSamples = config.SentPacketBufferSize / 2; for (int i = 0; i < numSamples; i++) { ushort sequence = (ushort)(baseSequence + i); var sentPacketData = sentPackets.Find(sequence); if (sentPacketData != null && !sentPacketData.acked) { numDropped++; } } float packetLoss = (float)numDropped / (float)numSamples; if (Math.Abs(this.packetLoss - packetLoss) > 0.00001f) { this.packetLoss += (packetLoss - this.packetLoss) * config.PacketLossSmoothingFactor; } else { this.packetLoss = packetLoss; } } // calculate sent bandwidth { uint baseSequence = (uint)((sentPackets.sequence - config.SentPacketBufferSize + 1) + 0xFFFF); int bytesSent = 0; double startTime = double.MaxValue; double finishTime = 0.0; int numSamples = config.SentPacketBufferSize / 2; for (int i = 0; i < numSamples; i++) { ushort sequence = (ushort)(baseSequence + i); var sentPacketData = sentPackets.Find(sequence); if (sentPacketData == null) { continue; } bytesSent += (int)sentPacketData.packetBytes; startTime = Math.Min(startTime, sentPacketData.time); finishTime = Math.Max(finishTime, sentPacketData.time); } if (startTime != double.MaxValue && finishTime != 0.0) { float sentBandwidth = (float)bytesSent / (float)(finishTime - startTime) * 8f / 1000f; if (Math.Abs(this.sentBandwidthKBPS - sentBandwidth) > 0.00001f) { this.sentBandwidthKBPS += (sentBandwidth - this.sentBandwidthKBPS) * config.BandwidthSmoothingFactor; } else { this.sentBandwidthKBPS = sentBandwidth; } } } // calculate received bandwidth lock (receivedPackets) { uint baseSequence = (uint)((receivedPackets.sequence - config.ReceivedPacketBufferSize + 1) + 0xFFFF); int bytesReceived = 0; double startTime = double.MaxValue; double finishTime = 0.0; int numSamples = config.ReceivedPacketBufferSize / 2; for (int i = 0; i < numSamples; i++) { ushort sequence = (ushort)(baseSequence + i); var receivedPacketData = receivedPackets.Find(sequence); if (receivedPacketData == null) { continue; } bytesReceived += (int)receivedPacketData.packetBytes; startTime = Math.Min(startTime, receivedPacketData.time); finishTime = Math.Max(finishTime, receivedPacketData.time); } if (startTime != double.MaxValue && finishTime != 0.0) { float receivedBandwidth = (float)bytesReceived / (float)(finishTime - startTime) * 8f / 1000f; if (Math.Abs(this.receivedBandwidthKBPS - receivedBandwidth) > 0.00001f) { this.receivedBandwidthKBPS += (receivedBandwidth - this.receivedBandwidthKBPS) * config.BandwidthSmoothingFactor; } else { this.receivedBandwidthKBPS = receivedBandwidth; } } } // calculate acked bandwidth { uint baseSequence = (uint)((sentPackets.sequence - config.SentPacketBufferSize + 1) + 0xFFFF); int bytesSent = 0; double startTime = double.MaxValue; double finishTime = 0.0; int numSamples = config.SentPacketBufferSize / 2; for (int i = 0; i < numSamples; i++) { ushort sequence = (ushort)(baseSequence + i); var sentPacketData = sentPackets.Find(sequence); if (sentPacketData == null || sentPacketData.acked == false) { continue; } bytesSent += (int)sentPacketData.packetBytes; startTime = Math.Min(startTime, sentPacketData.time); finishTime = Math.Max(finishTime, sentPacketData.time); } if (startTime != double.MaxValue && finishTime != 0.0) { float ackedBandwidth = (float)bytesSent / (float)(finishTime - startTime) * 8f / 1000f; if (Math.Abs(this.ackedBandwidthKBPS - ackedBandwidth) > 0.00001f) { this.ackedBandwidthKBPS += (ackedBandwidth - this.ackedBandwidthKBPS) * config.BandwidthSmoothingFactor; } else { this.ackedBandwidthKBPS = ackedBandwidth; } } } }
public void Update(double newTime) { time = newTime; uint num = (uint)(sentPackets.sequence - config.SentPacketBufferSize + 1 + 65535); int num2 = 0; int num3 = config.SentPacketBufferSize / 2; for (int i = 0; i < num3; i++) { ushort num4 = (ushort)(num + i); SentPacketData sentPacketData = sentPackets.Find(num4); if (sentPacketData != null && !sentPacketData.acked) { num2++; } } float num5 = (float)num2 / (float)num3; if (Math.Abs(packetLoss - num5) > 1E-05f) { packetLoss += (num5 - packetLoss) * config.PacketLossSmoothingFactor; } else { packetLoss = num5; } uint num6 = (uint)(sentPackets.sequence - config.SentPacketBufferSize + 1 + 65535); int num7 = 0; double num8 = double.MaxValue; double num9 = 0.0; int num10 = config.SentPacketBufferSize / 2; for (int j = 0; j < num10; j++) { ushort num11 = (ushort)(num6 + j); SentPacketData sentPacketData2 = sentPackets.Find(num11); if (sentPacketData2 != null) { num7 += (int)sentPacketData2.packetBytes; num8 = Math.Min(num8, sentPacketData2.time); num9 = Math.Max(num9, sentPacketData2.time); } } if (num8 != double.MaxValue && num9 != 0.0) { float num12 = (float)num7 / (float)(num9 - num8) * 8f / 1000f; if (Math.Abs(sentBandwidthKBPS - num12) > 1E-05f) { sentBandwidthKBPS += (num12 - sentBandwidthKBPS) * config.BandwidthSmoothingFactor; } else { sentBandwidthKBPS = num12; } } lock (receivedPackets) { uint num13 = (uint)(receivedPackets.sequence - config.ReceivedPacketBufferSize + 1 + 65535); int num14 = 0; double num15 = double.MaxValue; double num16 = 0.0; int num17 = config.ReceivedPacketBufferSize / 2; for (int k = 0; k < num17; k++) { ushort num18 = (ushort)(num13 + k); ReceivedPacketData receivedPacketData = receivedPackets.Find(num18); if (receivedPacketData != null) { num14 += (int)receivedPacketData.packetBytes; num15 = Math.Min(num15, receivedPacketData.time); num16 = Math.Max(num16, receivedPacketData.time); } } if (num15 != double.MaxValue && num16 != 0.0) { float num19 = (float)num14 / (float)(num16 - num15) * 8f / 1000f; if (Math.Abs(receivedBandwidthKBPS - num19) > 1E-05f) { receivedBandwidthKBPS += (num19 - receivedBandwidthKBPS) * config.BandwidthSmoothingFactor; } else { receivedBandwidthKBPS = num19; } } } uint num20 = (uint)(sentPackets.sequence - config.SentPacketBufferSize + 1 + 65535); int num21 = 0; double num22 = double.MaxValue; double num23 = 0.0; int num24 = config.SentPacketBufferSize / 2; for (int l = 0; l < num24; l++) { ushort num25 = (ushort)(num20 + l); SentPacketData sentPacketData3 = sentPackets.Find(num25); if (sentPacketData3 != null && sentPacketData3.acked) { num21 += (int)sentPacketData3.packetBytes; num22 = Math.Min(num22, sentPacketData3.time); num23 = Math.Max(num23, sentPacketData3.time); } } if (num22 != double.MaxValue && num23 != 0.0) { float num26 = (float)num21 / (float)(num23 - num22) * 8f / 1000f; if (Math.Abs(ackedBandwidthKBPS - num26) > 1E-05f) { ackedBandwidthKBPS += (num26 - ackedBandwidthKBPS) * config.BandwidthSmoothingFactor; } else { ackedBandwidthKBPS = num26; } } }
public void ReceivePacket(byte[] packetData, int bufferLength) { if (bufferLength > config.MaxPacketSize) { throw new ArgumentOutOfRangeException("Packet is larger than max packet size"); } if (packetData == null) { throw new InvalidOperationException("Tried to receive null packet!"); } if (bufferLength > packetData.Length) { throw new InvalidOperationException("Buffer length exceeds actual packet length!"); } byte b = packetData[0]; if ((b & 1) == 0) { byte channelID; ushort arg; ushort ack; uint ackBits; int num = PacketIO.ReadPacketHeader(packetData, 0, bufferLength, out channelID, out arg, out ack, out ackBits); bool flag; lock (receivedPackets) { flag = !receivedPackets.TestInsert(arg); } if (!flag && (b & 0x80) == 0) { if (num >= bufferLength) { throw new FormatException("Buffer too small for packet data!"); } ByteBuffer byteBuffer = ObjPool <ByteBuffer> .Get(); byteBuffer.SetSize(bufferLength - num); byteBuffer.BufferCopy(packetData, num, 0, byteBuffer.Length); config.ProcessPacketCallback(arg, byteBuffer.InternalBuffer, byteBuffer.Length); lock (receivedPackets) { ReceivedPacketData receivedPacketData = receivedPackets.Insert(arg); if (receivedPacketData == null) { throw new InvalidOperationException("Failed to insert received packet!"); } receivedPacketData.time = time; receivedPacketData.packetBytes = (uint)(config.PacketHeaderSize + bufferLength); } ObjPool <ByteBuffer> .Return(byteBuffer); } if (flag && (b & 0x80) == 0) { return; } for (int i = 0; i < 32; i++) { if ((ackBits & 1) != 0) { ushort obj = (ushort)(ack - i); SentPacketData sentPacketData = sentPackets.Find(obj); if (sentPacketData != null && !sentPacketData.acked) { sentPacketData.acked = true; if (config.AckPacketCallback != null) { config.AckPacketCallback(obj); } float num2 = (float)(time - sentPacketData.time) * 1000f; if ((rtt == 0f && num2 > 0f) || Math.Abs(rtt - num2) < 1E-05f) { rtt = num2; } else { rtt += (num2 - rtt) * config.RTTSmoothFactor; } } } ackBits >>= 1; } return; } int fragmentID; int numFragments; int fragmentBytes; ushort num3; ushort ack2; uint ackBits2; byte channelID2; int num4 = PacketIO.ReadFragmentHeader(packetData, 0, bufferLength, config.MaxFragments, config.FragmentSize, out fragmentID, out numFragments, out fragmentBytes, out num3, out ack2, out ackBits2, out channelID2); FragmentReassemblyData fragmentReassemblyData = fragmentReassembly.Find(num3); if (fragmentReassemblyData == null) { fragmentReassemblyData = fragmentReassembly.Insert(num3); if (fragmentReassemblyData == null) { return; } fragmentReassemblyData.Sequence = num3; fragmentReassemblyData.Ack = 0; fragmentReassemblyData.AckBits = 0u; fragmentReassemblyData.NumFragmentsReceived = 0; fragmentReassemblyData.NumFragmentsTotal = numFragments; fragmentReassemblyData.PacketBytes = 0; Array.Clear(fragmentReassemblyData.FragmentReceived, 0, fragmentReassemblyData.FragmentReceived.Length); } if (numFragments == fragmentReassemblyData.NumFragmentsTotal && !fragmentReassemblyData.FragmentReceived[fragmentID]) { fragmentReassemblyData.NumFragmentsReceived++; fragmentReassemblyData.FragmentReceived[fragmentID] = true; byte[] buffer = BufferPool.GetBuffer(2048); Buffer.BlockCopy(packetData, num4, buffer, 0, bufferLength - num4); fragmentReassemblyData.StoreFragmentData(channelID2, num3, ack2, ackBits2, fragmentID, config.FragmentSize, buffer, bufferLength - num4); BufferPool.ReturnBuffer(buffer); if (fragmentReassemblyData.NumFragmentsReceived == fragmentReassemblyData.NumFragmentsTotal) { ByteBuffer byteBuffer2 = ObjPool <ByteBuffer> .Get(); byteBuffer2.SetSize(fragmentReassemblyData.PacketDataBuffer.Length - fragmentReassemblyData.HeaderOffset); Buffer.BlockCopy(fragmentReassemblyData.PacketDataBuffer.InternalBuffer, fragmentReassemblyData.HeaderOffset, byteBuffer2.InternalBuffer, 0, byteBuffer2.Length); ReceivePacket(byteBuffer2.InternalBuffer, byteBuffer2.Length); ObjPool <ByteBuffer> .Return(byteBuffer2); fragmentReassemblyData.PacketDataBuffer.SetSize(0); fragmentReassembly.Remove(num3); } } }
public void ReceivePacket(byte[] packetData, int bufferLength) { if (bufferLength > config.MaxPacketSize) { throw new ArgumentOutOfRangeException("Packet is larger than max packet size"); } byte prefixByte = packetData[0]; if ((prefixByte & 1) == 0) { // regular packet ushort sequence; ushort ack; uint ackBits; byte channelID; int packetHeaderBytes = PacketIO.ReadPacketHeader(packetData, 0, bufferLength, out channelID, out sequence, out ack, out ackBits); bool isStale = !receivedPackets.TestInsert(sequence); if (!isStale && (prefixByte & 0x80) == 0) { ByteBuffer tempBuffer = ObjPool <ByteBuffer> .Get(); tempBuffer.SetSize(bufferLength - packetHeaderBytes); tempBuffer.BufferCopy(packetData, packetHeaderBytes, 0, tempBuffer.Length); // process packet config.ProcessPacketCallback(sequence, tempBuffer.InternalBuffer, tempBuffer.Length); // add to received buffer ReceivedPacketData receivedPacketData = receivedPackets.Insert(sequence); receivedPacketData.time = this.time; receivedPacketData.packetBytes = (uint)(config.PacketHeaderSize + bufferLength); ObjPool <ByteBuffer> .Return(tempBuffer); } if (!isStale || (prefixByte & 0x80) != 0) { for (int i = 0; i < 32; i++) { if ((ackBits & 1) != 0) { ushort ack_sequence = (ushort)(ack - i); SentPacketData sentPacketData = sentPackets.Find(ack_sequence); if (sentPacketData != null && !sentPacketData.acked) { sentPacketData.acked = true; if (config.AckPacketCallback != null) { config.AckPacketCallback(ack_sequence); } float rtt = (float)(this.time - sentPacketData.time) * 1000.0f; if ((this.rtt == 0f && rtt > 0f) || Math.Abs(this.rtt - rtt) < 0.00001f) { this.rtt = rtt; } else { this.rtt += (rtt - this.rtt) * config.RTTSmoothFactor; } } } ackBits >>= 1; } } } else { // fragment packet int fragmentID; int numFragments; int fragmentBytes; ushort sequence; ushort ack; uint ackBits; byte fragmentChannelID; int fragmentHeaderBytes = PacketIO.ReadFragmentHeader(packetData, 0, bufferLength, config.MaxFragments, config.FragmentSize, out fragmentID, out numFragments, out fragmentBytes, out sequence, out ack, out ackBits, out fragmentChannelID); FragmentReassemblyData reassemblyData = fragmentReassembly.Find(sequence); if (reassemblyData == null) { reassemblyData = fragmentReassembly.Insert(sequence); // failed to insert into buffer (stale) if (reassemblyData == null) { return; } reassemblyData.Sequence = sequence; reassemblyData.Ack = 0; reassemblyData.AckBits = 0; reassemblyData.NumFragmentsReceived = 0; reassemblyData.NumFragmentsTotal = numFragments; reassemblyData.PacketBytes = 0; Array.Clear(reassemblyData.FragmentReceived, 0, reassemblyData.FragmentReceived.Length); } if (numFragments != reassemblyData.NumFragmentsTotal) { return; } if (reassemblyData.FragmentReceived[fragmentID]) { return; } reassemblyData.NumFragmentsReceived++; reassemblyData.FragmentReceived[fragmentID] = true; byte[] tempFragmentData = BufferPool.GetBuffer(2048); Buffer.BlockCopy(packetData, fragmentHeaderBytes, tempFragmentData, 0, bufferLength - fragmentHeaderBytes); reassemblyData.StoreFragmentData(fragmentChannelID, sequence, ack, ackBits, fragmentID, config.FragmentSize, tempFragmentData, bufferLength - fragmentHeaderBytes); BufferPool.ReturnBuffer(tempFragmentData); if (reassemblyData.NumFragmentsReceived == reassemblyData.NumFragmentsTotal) { // grab internal buffer and pass it to ReceivePacket. Internal buffer will be packet marked as normal packet, so it will go through normal packet path this.ReceivePacket(reassemblyData.PacketDataBuffer.InternalBuffer, reassemblyData.PacketDataBuffer.Length); reassemblyData.PacketDataBuffer.SetSize(0); fragmentReassembly.Remove(sequence); } } }