public bool Read(ByteArrayReaderWriter stream, int length, byte[] key, ulong protocolID) { Payload = BufferPool.GetBuffer(2048); Length = 0; try { Length = PacketIO.ReadPacketData(Header, stream, length, protocolID, key, Payload); } catch { BufferPool.ReturnBuffer(Payload); return(false); } if (Length < 1 || Length > Defines.MAX_PAYLOAD_SIZE) { BufferPool.ReturnBuffer(Payload); return(false); } return(true); }
public void StoreFragmentData(byte channelID, ushort sequence, ushort ack, uint ackBits, int fragmentID, int fragmentSize, byte[] fragmentData, int fragmentBytes, bool compressed) { int copyOffset = 0; if (fragmentID == 0) { byte[] packetHeader = BufferPool.GetBuffer(Defines.MAX_PACKET_HEADER_BYTES); int headerBytes = PacketIO.WritePacketHeader(packetHeader, channelID, sequence, ack, ackBits, compressed); this.HeaderOffset = Defines.MAX_PACKET_HEADER_BYTES - headerBytes; if (this.PacketDataBuffer.Length < (Defines.MAX_PACKET_HEADER_BYTES + fragmentSize)) { this.PacketDataBuffer.SetSize(Defines.MAX_PACKET_HEADER_BYTES + fragmentSize); } this.PacketDataBuffer.BufferCopy(packetHeader, 0, this.HeaderOffset, headerBytes); copyOffset = headerBytes; fragmentBytes -= headerBytes; BufferPool.ReturnBuffer(packetHeader); } int writePos = Defines.MAX_PACKET_HEADER_BYTES + fragmentID * fragmentSize; int end = writePos + fragmentBytes; if (this.PacketDataBuffer.Length < end) { this.PacketDataBuffer.SetSize(end); } if (fragmentID == NumFragmentsTotal - 1) { this.PacketBytes = (this.NumFragmentsTotal - 1) * fragmentSize + fragmentBytes; } this.PacketDataBuffer.BufferCopy(fragmentData, copyOffset, Defines.MAX_PACKET_HEADER_BYTES + fragmentID * fragmentSize, fragmentBytes); }
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(); }
public bool Read(byte[] token, ulong sequenceNum, byte[] key) { byte[] tokenBuffer = BufferPool.GetBuffer(300); int tokenLen = 0; try { tokenLen = PacketIO.DecryptChallengeToken(sequenceNum, token, key, tokenBuffer); } catch { BufferPool.ReturnBuffer(tokenBuffer); return(false); } using (var reader = ByteArrayReaderWriter.Get(tokenBuffer)) { ClientID = reader.ReadUInt64(); UserData = reader.ReadBytes(256); } return(true); }
static void StartServer(Config cfg) { TcpListener listener = new TcpListener(System.Net.IPAddress.Any, cfg.port); listener.Start(); int clients = 0; for (; ;) { Console.WriteLine("Waiting for new connection..."); TcpClient client = listener.AcceptTcpClient(); // wait until a client appears Client connection = new Client(); clientlist.Add(connection); connection.Start(client, clients++, BroadcastMsg); // Send MOTD foreach (string str in cfg.MOTD.Split('\n')) { PacketIO.Send(connection.socket, new Message(Commands.System, str, "MOTD", 0)); } } }
public override void SendMessage(byte[] buffer, int bufferLength) { int num = 0; ushort num2 = oldestUnacked; while (PacketIO.SequenceLessThan(num2, sequence)) { if (sendBuffer.Exists(num2)) { num++; } num2 = (ushort)(num2 + 1); } if (num == sendBuffer.Size) { ByteBuffer byteBuffer = ObjPool <ByteBuffer> .Get(); byteBuffer.SetSize(bufferLength); byteBuffer.BufferCopy(buffer, 0, 0, bufferLength); messageQueue.Enqueue(byteBuffer); } else { ushort val = sequence++; BufferedPacket bufferedPacket = sendBuffer.Insert(val); bufferedPacket.time = -1.0; int variableLengthBytes = getVariableLengthBytes((ushort)bufferLength); bufferedPacket.buffer.SetSize(bufferLength + 2 + variableLengthBytes); using (ByteArrayReaderWriter byteArrayReaderWriter = ByteArrayReaderWriter.Get(bufferedPacket.buffer.InternalBuffer)) { byteArrayReaderWriter.Write(val); writeVariableLengthUShort((ushort)bufferLength, byteArrayReaderWriter); byteArrayReaderWriter.WriteBuffer(buffer, bufferLength); } bufferedPacket.writeLock = false; } }
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 ushort SendPacket(byte[] packetData, int position, int length, byte channelID) { if (length > config.MaxPacketSize) { throw new ArgumentOutOfRangeException("Packet is too large to send, max packet size is " + config.MaxPacketSize + " bytes"); } if (length < 1) { throw new ArgumentOutOfRangeException("Packet is too small; minimum packet size is 1 byte."); } var compressedBuffer = LZ4Codec.Wrap(packetData, position, length); bool compressed = false; int bytesSaved = length - compressedBuffer.Length; if (bytesSaved > 0) { packetData = compressedBuffer; position = 0; length = compressedBuffer.Length; compressed = true; } ushort sequence = this.sequence++; ushort ack; uint ackBits; lock (receivedPackets) receivedPackets.GenerateAckBits(out ack, out ackBits); SentPacketData sentPacketData = sentPackets.Insert(sequence); sentPacketData.time = this.time; sentPacketData.packetBytes = (uint)(config.PacketHeaderSize + length); sentPacketData.acked = false; if (length <= config.FragmentThreshold) { // regular packet byte[] transmitData = BufferPool.GetBuffer(2048); int headerBytes = PacketIO.WritePacketHeader(transmitData, channelID, sequence, ack, ackBits, compressed); int transmitBufferLength = length + headerBytes; Buffer.BlockCopy(packetData, position, transmitData, headerBytes, length); config.TransmitPacketCallback(transmitData, transmitBufferLength); BufferPool.ReturnBuffer(transmitData); } else { // fragmented packet byte[] packetHeader = BufferPool.GetBuffer(Defines.MAX_PACKET_HEADER_BYTES); int packetHeaderBytes = 0; try { packetHeaderBytes = PacketIO.WritePacketHeader(packetHeader, channelID, sequence, ack, ackBits, compressed); } catch { throw; } int numFragments = (length / config.FragmentSize) + ((length % config.FragmentSize) != 0 ? 1 : 0); //int fragmentBufferSize = Defines.FRAGMENT_HEADER_BYTES + Defines.MAX_PACKET_HEADER_BYTES + config.FragmentSize; byte[] fragmentPacketData = BufferPool.GetBuffer(2048); int qpos = 0; byte prefixByte = 1; prefixByte |= (byte)((channelID & 0x03) << 6); for (int fragmentID = 0; fragmentID < numFragments; fragmentID++) { using (var writer = ByteArrayReaderWriter.Get(fragmentPacketData)) { writer.Write(prefixByte); writer.Write(channelID); writer.Write(sequence); writer.Write((byte)fragmentID); writer.Write((byte)(numFragments - 1)); writer.Write(compressed ? (byte)1 : (byte)0); if (fragmentID == 0) { writer.WriteBuffer(packetHeader, 0, packetHeaderBytes); } int bytesToCopy = config.FragmentSize; if (qpos + bytesToCopy > length) { bytesToCopy = length - qpos; } for (int i = 0; i < bytesToCopy; i++) { writer.Write(packetData[position + qpos++]); } int fragmentPacketBytes = (int)writer.WritePosition; config.TransmitPacketCallback(fragmentPacketData, fragmentPacketBytes); } } BufferPool.ReturnBuffer(packetHeader); BufferPool.ReturnBuffer(fragmentPacketData); } return(sequence); }
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 ushort SendPacket(byte[] packetData, int length, byte channelID) { if (length > config.MaxPacketSize) { throw new ArgumentOutOfRangeException("Packet is too large to send, max packet size is " + config.MaxPacketSize + " bytes"); } ushort num = sequence++; ushort ack; uint ackBits; lock (receivedPackets) { receivedPackets.GenerateAckBits(out ack, out ackBits); } SentPacketData sentPacketData = sentPackets.Insert(num); sentPacketData.time = time; sentPacketData.packetBytes = (uint)(config.PacketHeaderSize + length); sentPacketData.acked = false; if (length <= config.FragmentThreshold) { byte[] buffer = BufferPool.GetBuffer(2048); int num2 = PacketIO.WritePacketHeader(buffer, channelID, num, ack, ackBits); int arg = length + num2; Buffer.BlockCopy(packetData, 0, buffer, num2, length); config.TransmitPacketCallback(buffer, arg); BufferPool.ReturnBuffer(buffer); } else { byte[] buffer2 = BufferPool.GetBuffer(10); int num3 = 0; try { num3 = PacketIO.WritePacketHeader(buffer2, channelID, num, ack, ackBits); } catch { throw; } int num4 = length / config.FragmentSize + ((length % config.FragmentSize != 0) ? 1 : 0); byte[] buffer3 = BufferPool.GetBuffer(2048); int num5 = 0; byte b = 1; b = (byte)(b | (byte)((channelID & 3) << 6)); for (int i = 0; i < num4; i++) { using (ByteArrayReaderWriter byteArrayReaderWriter = ByteArrayReaderWriter.Get(buffer3)) { byteArrayReaderWriter.Write(b); byteArrayReaderWriter.Write(channelID); byteArrayReaderWriter.Write(num); byteArrayReaderWriter.Write((byte)i); byteArrayReaderWriter.Write((byte)(num4 - 1)); if (i == 0) { byteArrayReaderWriter.WriteBuffer(buffer2, num3); } int num6 = config.FragmentSize; if (num5 + num6 > length) { num6 = length - num5; } for (int j = 0; j < num6; j++) { byteArrayReaderWriter.Write(packetData[num5++]); } int arg2 = (int)byteArrayReaderWriter.WritePosition; config.TransmitPacketCallback(buffer3, arg2); } } BufferPool.ReturnBuffer(buffer2); BufferPool.ReturnBuffer(buffer3); } return(num); }
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); } } }
public bool TestInsert(ushort sequence) { return(!PacketIO.SequenceLessThan(sequence, (ushort)(this.sequence - numEntries))); }
//Queue<string> _sendQueue = new Queue<string>(); public Connection(TcpClient client) { _packetIO = new PacketIO(client.GetStream()); _client = client; }
/// <summary> /// Osc Constructor. Starts the Reader thread and initializes some internal state. /// </summary> /// <param name="oscPacketIO">The PacketIO instance used for packet IO.</param> public Osc(PacketIO oscPacketIO) { // Save the PacketExchage pointer OscPacketIO = oscPacketIO; // Create the hashtable for the address lookup mechanism AddressTable = new Hashtable(); ReadThread = new Thread(Read); ReaderRunning = true; ReadThread.IsBackground = true; ReadThread.Start(); }
protected void processSendBuffer() { int numUnacked = 0; for (ushort seq = oldestUnacked; PacketIO.SequenceLessThan(seq, this.sequence); seq++) { numUnacked++; } 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 && !packet.writeLock) { 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(); }
internal byte[] GenerateConnectToken(IPEndPoint[] addressList, double time, int expirySeconds, int serverTimeout, ulong sequence, ulong clientID, byte[] userData) { if (userData.Length > 256) { throw new ArgumentOutOfRangeException("User data cannot be larger than 256 bytes"); } if (addressList == null) { throw new NullReferenceException("Address list cannot be null"); } else if (addressList.Length == 0) { throw new ArgumentOutOfRangeException("Address list cannot be empty"); } else if (addressList.Length > Defines.MAX_SERVER_ADDRESSES) { throw new ArgumentOutOfRangeException("Address list cannot contain more than " + Defines.MAX_SERVER_ADDRESSES + " entries"); } NetcodePrivateConnectToken privateConnectToken = new NetcodePrivateConnectToken(); privateConnectToken.ClientID = clientID; privateConnectToken.TimeoutSeconds = serverTimeout; // generate random crypto keys byte[] clientToServerKey = new byte[32]; byte[] serverToClientKey = new byte[32]; KeyUtils.GenerateKey(clientToServerKey); KeyUtils.GenerateKey(serverToClientKey); privateConnectToken.ClientToServerKey = clientToServerKey; privateConnectToken.ServerToClientKey = serverToClientKey; privateConnectToken.UserData = new byte[256]; Buffer.BlockCopy(userData, 0, privateConnectToken.UserData, 0, userData.Length); privateConnectToken.ConnectServers = new ConnectTokenServerEntry[addressList.Length]; for (int i = 0; i < privateConnectToken.ConnectServers.Length; i++) { privateConnectToken.ConnectServers[i] = new ConnectTokenServerEntry() { AddressType = addressList[i].AddressFamily == AddressFamily.InterNetwork ? NetcodeAddressType.IPv4 : NetcodeAddressType.IPv6, Endpoint = addressList[i] }; } byte[] privateConnectTokenBytes = new byte[1024]; using (var writer = ByteArrayReaderWriter.Get(privateConnectTokenBytes)) { privateConnectToken.Write(writer); } ulong createTimestamp = (ulong)Math.Truncate(time); ulong expireTimestamp = expirySeconds >= 0 ? (createTimestamp + (ulong)expirySeconds) : 0xFFFFFFFFFFFFFFFFUL; byte[] encryptedPrivateToken = new byte[1024]; PacketIO.EncryptPrivateConnectToken(privateConnectTokenBytes, protocolID, expireTimestamp, sequence, privateKey, encryptedPrivateToken); NetcodePublicConnectToken publicToken = new NetcodePublicConnectToken(); publicToken.ProtocolID = protocolID; publicToken.CreateTimestamp = createTimestamp; publicToken.ExpireTimestamp = expireTimestamp; publicToken.ConnectTokenSequence = sequence; publicToken.PrivateConnectTokenBytes = encryptedPrivateToken; publicToken.ConnectServers = privateConnectToken.ConnectServers; publicToken.ClientToServerKey = clientToServerKey; publicToken.ServerToClientKey = serverToClientKey; publicToken.TimeoutSeconds = serverTimeout; byte[] publicTokenBytes = new byte[2048]; using (var writer = ByteArrayReaderWriter.Get(publicTokenBytes)) { publicToken.Write(writer); } return(publicTokenBytes); }
public override void Update(double newTime) { double dt = newTime - time; time = newTime; this.packetController.Update(time); // see if we can pop messages off of the message queue and put them on the send queue if (messageQueue.Count > 0) { int sendBufferSize = 0; for (ushort seq = oldestUnacked; PacketIO.SequenceLessThan(seq, this.sequence); seq++) { if (sendBuffer.Exists(seq)) { sendBufferSize++; } } if (sendBufferSize < sendBuffer.Size) { var message = messageQueue.Dequeue(); SendMessage(message.InternalBuffer, 0, message.Length); ObjPool <ByteBuffer> .Return(message); } } // update congestion mode { // conditions are bad if round-trip-time exceeds 250ms bool conditionsBad = (this.packetController.RTT >= 250f); // if conditions are bad, immediately enable congestion control and reset the congestion timer if (conditionsBad) { if (this.congestionControl == false) { // if we're within 10 seconds of the last time we switched, double the threshold interval if (time - lastCongestionSwitchTime < 10.0) { congestionDisableInterval = Math.Min(congestionDisableInterval * 2, 60.0); } lastCongestionSwitchTime = time; } this.congestionControl = true; this.congestionDisableTimer = 0.0; } // if we're in bad mode, and conditions are good, update the timer and see if we can disable congestion control if (this.congestionControl && !conditionsBad) { this.congestionDisableTimer += dt; if (this.congestionDisableTimer >= this.congestionDisableInterval) { this.congestionControl = false; lastCongestionSwitchTime = time; congestionDisableTimer = 0.0; } } // as long as conditions are good, halve the threshold interval every 10 seconds if (this.congestionControl == false) { congestionDisableTimer += dt; if (congestionDisableTimer >= 10.0) { congestionDisableInterval = Math.Max(congestionDisableInterval * 0.5, 5.0); } } } // if we're in congestion control mode, only send packets 10 times per second. // otherwise, send 30 times per second double flushInterval = congestionControl ? 0.1 : 0.033; if (time - lastBufferFlush >= flushInterval) { lastBufferFlush = time; processSendBuffer(); } }
public override void Update(double newTime) { double num = newTime - time; time = newTime; packetController.Update(time); if (messageQueue.Count > 0) { int num2 = 0; ushort num3 = oldestUnacked; while (PacketIO.SequenceLessThan(num3, sequence)) { if (sendBuffer.Exists(num3)) { num2++; } num3 = (ushort)(num3 + 1); } if (num2 < sendBuffer.Size) { ByteBuffer byteBuffer = messageQueue.Dequeue(); SendMessage(byteBuffer.InternalBuffer, byteBuffer.Length); ObjPool <ByteBuffer> .Return(byteBuffer); } } bool flag = packetController.RTT >= 250f; if (flag) { if (!congestionControl) { if (time - lastCongestionSwitchTime < 10.0) { congestionDisableInterval = Math.Min(congestionDisableInterval * 2.0, 60.0); } lastCongestionSwitchTime = time; } congestionControl = true; congestionDisableTimer = 0.0; } if (congestionControl && !flag) { congestionDisableTimer += num; if (congestionDisableTimer >= congestionDisableInterval) { congestionControl = false; lastCongestionSwitchTime = time; congestionDisableTimer = 0.0; } } if (!congestionControl) { congestionDisableTimer += num; if (congestionDisableTimer >= 10.0) { congestionDisableInterval = Math.Max(congestionDisableInterval * 0.5, 5.0); } } double num4 = (!congestionControl) ? 0.033 : 0.1; if (time - lastBufferFlush >= num4) { lastBufferFlush = time; processSendBuffer(); } }