/// <summary> /// Decrypt a packet's data /// </summary> public static int DecryptPacketData(NetcodePacketHeader header, ulong protocolID, byte[] packetData, int packetDataLen, byte[] key, byte[] outBuffer) { byte[] additionalData = BufferPool.GetBuffer(Defines.NETCODE_VERSION_INFO_BYTES + 8 + 1); using (var writer = ByteArrayReaderWriter.Get(additionalData)) { writer.WriteASCII(Defines.NETCODE_VERSION_INFO_STR); writer.Write(protocolID); writer.Write(header.ReadSequenceByte); } byte[] nonce = BufferPool.GetBuffer(12); using (var writer = ByteArrayReaderWriter.Get(nonce)) { writer.Write((UInt32)0); writer.Write(header.SequenceNumber); } int ret; try { ret = CryptoUtils.Decrypt(packetData, 0, packetDataLen, additionalData, key, nonce, outBuffer); } catch (Exception e) { BufferPool.ReturnBuffer(additionalData); BufferPool.ReturnBuffer(nonce); throw e; } BufferPool.ReturnBuffer(additionalData); BufferPool.ReturnBuffer(nonce); return(ret); }
// process a received datagram private void processDatagram(byte[] payload, int size, EndPoint sender) { using (var reader = ByteArrayReaderWriter.Get(payload)) { NetcodePacketHeader packetHeader = new NetcodePacketHeader(); packetHeader.Read(reader); if (packetHeader.PacketType == NetcodePacketType.ConnectionRequest) { processConnectionRequest(reader, size, sender); } else { switch (packetHeader.PacketType) { case NetcodePacketType.ChallengeResponse: processConnectionResponse(reader, packetHeader, size, sender); break; case NetcodePacketType.ConnectionKeepAlive: processConnectionKeepAlive(reader, packetHeader, size, sender); break; case NetcodePacketType.ConnectionPayload: processConnectionPayload(reader, packetHeader, size, sender); break; case NetcodePacketType.ConnectionDisconnect: processConnectionDisconnect(reader, packetHeader, size, sender); break; } } } }
internal sealed override void Deserialize(byte[] buffer) { using (var packetWriter = ByteArrayReaderWriter.Get(buffer)) { Action = packetWriter.ReadByte(); var haveSendTime = packetWriter.ReadByte(); var havePayload = packetWriter.ReadByte(); if (havePayload == 0x1) { _payloadLen = packetWriter.ReadUInt16(); } SendType = (GProtocolSendType)packetWriter.ReadByte(); Hash = (long)packetWriter.ReadUInt64(); if (havePayload == 0x1) { Payload = packetWriter.ReadBytes(_payloadLen); } if (haveSendTime == 0x1) { ClientSendTime = packetWriter.ReadInt64(); } } }
// Decrypt a private connect token public static int DecryptPrivateConnectToken(byte[] encryptedConnectToken, ulong protocolID, ulong expireTimestamp, ulong sequence, byte[] key, byte[] outBuffer) { int len = encryptedConnectToken.Length; byte[] additionalData = BufferPool.GetBuffer(Defines.NETCODE_VERSION_INFO_BYTES + 8 + 8); using (var writer = ByteArrayReaderWriter.Get(additionalData)) { writer.WriteASCII(Defines.NETCODE_VERSION_INFO_STR); writer.Write(protocolID); writer.Write(expireTimestamp); } byte[] nonce = BufferPool.GetBuffer(12); using (var writer = ByteArrayReaderWriter.Get(nonce)) { writer.Write((UInt32)0); writer.Write(sequence); } var ret = CryptoUtils.Decrypt(encryptedConnectToken, 0, len, additionalData, key, nonce, outBuffer); BufferPool.ReturnBuffer(additionalData); BufferPool.ReturnBuffer(nonce); return(ret); }
/// <summary> /// Encrypt a challenge token /// </summary> public static int EncryptChallengeToken(ulong sequenceNum, byte[] packetData, byte[] key, byte[] outBuffer) { byte[] additionalData = BufferPool.GetBuffer(0); byte[] nonce = BufferPool.GetBuffer(12); using (var writer = ByteArrayReaderWriter.Get(nonce)) { writer.Write((UInt32)0); writer.Write(sequenceNum); } int ret; try { ret = AEAD_Chacha20_Poly1305.Encrypt(packetData, 0, 300 - Defines.MAC_SIZE, additionalData, nonce, key, outBuffer); } catch (Exception e) { BufferPool.ReturnBuffer(additionalData); BufferPool.ReturnBuffer(nonce); throw e; } BufferPool.ReturnBuffer(additionalData); BufferPool.ReturnBuffer(nonce); return(ret); }
// encrypts a packet and sends it to the endpoint private void sendPacketToClient(NetcodePacketHeader packetHeader, byte[] packetData, int packetDataLen, EndPoint endpoint, byte[] key) { // assign a sequence number to this packet packetHeader.SequenceNumber = this.nextSequenceNumber++; // encrypt packet data byte[] encryptedPacketBuffer = BufferPool.GetBuffer(2048); int encryptedBytes = PacketIO.EncryptPacketData(packetHeader, protocolID, packetData, packetDataLen, key, encryptedPacketBuffer); int packetLen = 0; // write packet to byte array var packetBuffer = BufferPool.GetBuffer(2048); using (var packetWriter = ByteArrayReaderWriter.Get(packetBuffer)) { packetHeader.Write(packetWriter); packetWriter.WriteBuffer(encryptedPacketBuffer, encryptedBytes); packetLen = (int)packetWriter.WritePosition; } // send packet listenSocket.SendTo(packetBuffer, packetLen, SocketFlags.None, endpoint); BufferPool.ReturnBuffer(packetBuffer); BufferPool.ReturnBuffer(encryptedPacketBuffer); }
public bool Read(ByteArrayReaderWriter stream, int length, byte[] key, ulong protocolID) { if (length != 8 + Defines.MAC_SIZE) { return(false); } byte[] tempBuffer = BufferPool.GetBuffer(length); try { PacketIO.ReadPacketData(Header, stream, length, protocolID, key, tempBuffer); } catch { BufferPool.ReturnBuffer(tempBuffer); return(false); } using (var dataReader = ByteArrayReaderWriter.Get(tempBuffer)) { ClientIndex = dataReader.ReadUInt32(); MaxSlots = dataReader.ReadUInt32(); } return(true); }
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++; } } } } }
private void sendPacket(NetcodePacketHeader packetHeader, byte[] packetData, int packetDataLen, byte[] key) { // assign a sequence number to this packet packetHeader.SequenceNumber = this.nextPacketSequence++; // encrypt packet data byte[] encryptedPacketBuffer = BufferPool.GetBuffer(2048); int encryptedBytes = PacketIO.EncryptPacketData(packetHeader, connectToken.ProtocolID, packetData, packetDataLen, key, encryptedPacketBuffer); int packetLen = 0; // write packet to byte array var packetBuffer = BufferPool.GetBuffer(2048); using (var packetWriter = ByteArrayReaderWriter.Get(packetBuffer)) { packetHeader.Write(packetWriter); packetWriter.WriteBuffer(encryptedPacketBuffer, encryptedBytes); packetLen = (int)packetWriter.WritePosition; } // send packet try { socket.SendTo(packetBuffer, packetLen, currentServerEndpoint); } catch { } BufferPool.ReturnBuffer(packetBuffer); BufferPool.ReturnBuffer(encryptedPacketBuffer); }
public bool Read(ByteArrayReaderWriter stream, int length, byte[] key, ulong protocolID) { byte[] packetBuffer = BufferPool.GetBuffer(8 + 300 + Defines.MAC_SIZE); int packetLen = 0; try { packetLen = PacketIO.ReadPacketData(Header, stream, length, protocolID, key, packetBuffer); } catch (System.Exception e) { BufferPool.ReturnBuffer(packetBuffer); return(false); } if (packetLen != 308) { BufferPool.ReturnBuffer(packetBuffer); return(false); } ChallengeTokenBytes = BufferPool.GetBuffer(300); using (var reader = ByteArrayReaderWriter.Get(packetBuffer)) { ChallengeTokenSequence = reader.ReadUInt64(); reader.ReadBytesIntoBuffer(ChallengeTokenBytes, 300); } BufferPool.ReturnBuffer(packetBuffer); return(true); }
/// <summary> /// Decrypt a challenge token /// </summary> public static int DecryptChallengeToken(ulong sequenceNum, byte[] packetData, byte[] key, byte[] outBuffer) { byte[] additionalData = BufferPool.GetBuffer(0); byte[] nonce = BufferPool.GetBuffer(12); using (var writer = ByteArrayReaderWriter.Get(nonce)) { writer.Write((UInt32)0); writer.Write(sequenceNum); } int ret; try { ret = CryptoUtils.Decrypt(packetData, 0, 300, additionalData, key, nonce, outBuffer); } catch (Exception e) { BufferPool.ReturnBuffer(additionalData); BufferPool.ReturnBuffer(nonce); throw e; } BufferPool.ReturnBuffer(additionalData); BufferPool.ReturnBuffer(nonce); return(ret); }
public void Connect(byte[] connectToken, bool autoTick) { if (state != ClientState.Disconnected) { throw new InvalidOperationException(); } keepAliveTimer = 0.0; connectServers.Clear(); replayProtection.Reset(); if (connectToken.Length != Defines.NETCODE_CONNECT_TOKEN_PUBLIC_BYTES) { changeState(ClientState.InvalidConnectToken); return; } NetcodePublicConnectToken tokenData = new NetcodePublicConnectToken(); using (var reader = ByteArrayReaderWriter.Get(connectToken)) { if (!tokenData.Read(reader)) { changeState(ClientState.InvalidConnectToken); return; } } if (tokenData.CreateTimestamp >= tokenData.ExpireTimestamp) { changeState(ClientState.InvalidConnectToken); return; } clientToServerKey = tokenData.ClientToServerKey; serverToClientKey = tokenData.ServerToClientKey; foreach (var server in tokenData.ConnectServers) { connectServers.Enqueue(server.Endpoint); } this.connectToken = tokenData; this.state = ClientState.SendingConnectionRequest; // bind socket, spin up threads, and start trying to connect isRunning = true; currentServerEndpoint = connectServers.Dequeue(); createSocket(currentServerEndpoint); if (autoTick) { this.time = DateTime.Now.GetTotalSeconds(); ThreadPool.QueueUserWorkItem(clientTick); } }
internal static Tuple <string, byte[]> GetObserver(byte[] buffer) { using (var packetReader = ByteArrayReaderWriter.Get(buffer)) { var len = packetReader.ReadByte(); var ownerId = GetStringFromBuffer(packetReader.ReadBytes(len), true); var payload = packetReader.ReadBytes(buffer.Length - len); return(Tuple.Create(ownerId, payload)); } }
// sends a connection challenge packet to the endpoint private void sendConnectionChallenge(NetcodePrivateConnectToken connectToken, EndPoint endpoint) { log("Sending connection challenge", NetcodeLogLevel.Debug); var challengeToken = new NetcodeChallengeToken(); challengeToken.ClientID = connectToken.ClientID; challengeToken.UserData = connectToken.UserData; ulong challengeSequence = nextChallengeSequenceNumber++; byte[] tokenBytes = BufferPool.GetBuffer(300); using (var tokenWriter = ByteArrayReaderWriter.Get(tokenBytes)) challengeToken.Write(tokenWriter); byte[] encryptedToken = BufferPool.GetBuffer(300); int encryptedTokenBytes; try { encryptedTokenBytes = PacketIO.EncryptChallengeToken(challengeSequence, tokenBytes, challengeKey, encryptedToken); } catch { BufferPool.ReturnBuffer(tokenBytes); BufferPool.ReturnBuffer(encryptedToken); return; } var challengePacket = new NetcodeConnectionChallengeResponsePacket(); challengePacket.ChallengeTokenSequence = challengeSequence; challengePacket.ChallengeTokenBytes = encryptedToken; var cryptIdx = encryptionManager.FindEncryptionMapping(endpoint, time); if (cryptIdx == -1) { return; } var cryptKey = encryptionManager.GetSendKey(cryptIdx); serializePacket(new NetcodePacketHeader() { PacketType = NetcodePacketType.ConnectionChallenge }, (writer) => { challengePacket.Write(writer); }, endpoint, cryptKey); BufferPool.ReturnBuffer(tokenBytes); BufferPool.ReturnBuffer(encryptedToken); }
private static void startClient() { // get token var webRequest = WebRequest.Create("http://127.0.0.1:8080/token"); webRequest.Credentials = CredentialCache.DefaultCredentials; HttpWebResponse response; try { response = (HttpWebResponse)webRequest.GetResponse(); } catch (Exception e) { Console.WriteLine("Failed to get token: " + e.Message); Console.ReadLine(); return; } if (response.StatusCode != HttpStatusCode.OK) { Console.WriteLine("Failed to get token: " + response.StatusDescription); Console.ReadLine(); return; } Stream dataStream = response.GetResponseStream(); StreamReader reader = new StreamReader(dataStream); string responseStr = reader.ReadToEnd(); reader.Close(); dataStream.Close(); response.Close(); byte[] connectToken = System.Convert.FromBase64String(responseStr); testPacket = new byte[256]; using (var testPacketWriter = ByteArrayReaderWriter.Get(testPacket)) { testPacketWriter.Write((uint)0xAABBCCDD); } client = new Client(); client.OnStateChanged += Client_OnStateChanged; client.OnMessageReceived += Client_OnMessageReceived; Console.WriteLine("Connecting..."); client.Connect(connectToken); Console.ReadLine(); client.Disconnect(); }
public bool Read(byte[] token, byte[] key, ulong protocolID, ulong expiration, ulong sequence) { byte[] tokenBuffer = BufferPool.GetBuffer(Defines.NETCODE_CONNECT_TOKEN_PRIVATE_BYTES); int tokenLen = 0; try { tokenLen = PacketIO.DecryptPrivateConnectToken(token, protocolID, expiration, sequence, key, tokenBuffer); } catch { BufferPool.ReturnBuffer(tokenBuffer); return(false); } try { using (var reader = ByteArrayReaderWriter.Get(tokenBuffer)) { this.ClientID = reader.ReadUInt64(); this.TimeoutSeconds = (int)reader.ReadUInt32(); uint numServerAddresses = reader.ReadUInt32(); if (numServerAddresses == 0 || numServerAddresses > Defines.MAX_SERVER_ADDRESSES) { BufferPool.ReturnBuffer(tokenBuffer); return(false); } this.ConnectServers = new ConnectTokenServerEntry[numServerAddresses]; for (int i = 0; i < numServerAddresses; i++) { this.ConnectServers[i] = new ConnectTokenServerEntry(); this.ConnectServers[i].ReadData(reader); } ClientToServerKey = new byte[32]; ServerToClientKey = new byte[32]; UserData = new byte[256]; reader.ReadBytesIntoBuffer(ClientToServerKey, 32); reader.ReadBytesIntoBuffer(ServerToClientKey, 32); reader.ReadBytesIntoBuffer(UserData, 256); } } catch { BufferPool.ReturnBuffer(tokenBuffer); return(false); } return(true); }
private void serializePacket(NetcodePacketHeader packetHeader, Action <ByteArrayReaderWriter> write, byte[] key) { byte[] tempPacket = BufferPool.GetBuffer(2048); int writeLen = 0; using (var writer = ByteArrayReaderWriter.Get(tempPacket)) { write(writer); writeLen = (int)writer.WritePosition; } sendPacket(packetHeader, tempPacket, writeLen, key); BufferPool.ReturnBuffer(tempPacket); }
internal override byte[] Serialize(string key, bool isCommand) { byte havePayload = 0x0, haveSendTime = 0x0; short prefixLen = 4 * sizeof(byte) + sizeof(ulong); if (Payload != null) { havePayload = 0x1; _payloadLen = Payload.Length; prefixLen += sizeof(ushort); } if (ClientSendTime != 0L) { haveSendTime = 0x1; prefixLen += sizeof(long); } var packetBuffer = BufferPool.GetBuffer(BufferSize(prefixLen)); using (var packetWriter = ByteArrayReaderWriter.Get(packetBuffer)) { // header Segment packetWriter.Write((byte)Action); packetWriter.Write(haveSendTime); packetWriter.Write(havePayload); if (havePayload == 0x1) { packetWriter.Write((ushort)_payloadLen); } // data Segment packetWriter.Write((byte)SendType); packetWriter.Write((ulong)Hash); if (havePayload == 0x1) { packetWriter.Write(Payload); } if (haveSendTime == 0x1) { packetWriter.Write(ClientSendTime); } } return(packetBuffer); }
internal static Queue <byte[]> GetQueueData(byte[] buffer) { var data = new Queue <byte[]>(); using (var packetReader = ByteArrayReaderWriter.Get(buffer)) { var count = packetReader.ReadByte(); for (var i = 0; i < count; i++) { data.Enqueue(packetReader.ReadBytes(packetReader.ReadUInt16())); } } return(data); }
private static string[] GetStringsFromBuffer(byte[] bytes) { var data = new List <string>(); using (var packetReader = ByteArrayReaderWriter.Get(bytes)) { var count = packetReader.ReadUInt16(); for (var i = 0; i < count; i++) { data.Add(GetStringFromBuffer(packetReader.ReadBytes(packetReader.ReadUInt16()), true)); } } return(data.ToArray()); }
private void sendConnectionRequest(EndPoint server) { byte[] packetBuffer = BufferPool.GetBuffer(1 + 13 + 8 + 8 + 8 + Defines.NETCODE_CONNECT_TOKEN_PRIVATE_BYTES); using (var stream = ByteArrayReaderWriter.Get(packetBuffer)) { stream.Write((byte)0); stream.WriteASCII(Defines.NETCODE_VERSION_INFO_STR); stream.Write(connectToken.ProtocolID); stream.Write(connectToken.ExpireTimestamp); stream.Write(connectToken.ConnectTokenSequence); stream.Write(connectToken.PrivateConnectTokenBytes); } socket.SendTo(packetBuffer, server); BufferPool.ReturnBuffer(packetBuffer); }
internal void Deserialize(byte[] buff) { using (var packetWriter = ByteArrayReaderWriter.Get(buff)) { var haveSender = packetWriter.ReadByte(); var haveReceiver = packetWriter.ReadByte(); var havePayload = packetWriter.ReadByte(); var haveExtra = packetWriter.ReadByte(); if (haveSender == 0x1) { _senderLen = packetWriter.ReadByte(); } if (haveReceiver == 0x1) { _receiverLen = packetWriter.ReadByte(); } if (havePayload == 0x1) { _payloadLen = packetWriter.ReadUInt16(); } if (haveExtra == 0x1) { _extraLen = packetWriter.ReadUInt16(); } if (haveSender == 0x1) { SenderId = ConvertToString(packetWriter.ReadBytes(_senderLen)); } if (haveReceiver == 0x1) { ReceiverId = ConvertToString(packetWriter.ReadBytes(_receiverLen)); } if (havePayload == 0x1) { Payload = packetWriter.ReadBytes(_payloadLen); } if (haveExtra == 0x1) { ExtraData = packetWriter.ReadBytes(_extraLen); } } }
internal static List <SnapShotData> GetSnapShotsFromBuffer(byte[] buffer) { var data = new List <SnapShotData>(); using (var packetReader = ByteArrayReaderWriter.Get(buffer)) { var count = packetReader.ReadUInt16(); for (var i = 0; i < count; i++) { var type = (SnapShotType)packetReader.ReadByte(); var ownerId = packetReader.ReadBytes(packetReader.ReadByte()); var payload = packetReader.ReadBytes(packetReader.ReadUInt16()); data.Add(new SnapShotData(type, GetStringFromBuffer(ownerId, true), payload)); } } return(data); }
internal static byte[] GetSendQueueBuffer(Queue <byte[]> queue) { var bufferSize = GetSendQueueBufferSize(queue); var packetBuffer = BufferPool.GetBuffer(bufferSize); using (var packetWriter = ByteArrayReaderWriter.Get(packetBuffer)) { packetWriter.Write((byte)queue.Count); while (queue.Count > 0) { var item = queue.Dequeue(); packetWriter.Write((ushort)item.Length); packetWriter.Write(item); } } return(packetBuffer); }
public override void SendMessage(byte[] buffer, int bufferPosition, int bufferLength) { int sendBufferSize = 0; for (ushort seq = oldestUnacked; PacketIO.SequenceLessThan(seq, this.sequence); seq++) { if (sendBuffer.Exists(seq)) { sendBufferSize++; } } if (sendBufferSize == sendBuffer.Size) { ByteBuffer tempBuff = ObjPool <ByteBuffer> .Get(); tempBuff.SetSize(bufferLength); tempBuff.BufferCopy(buffer, bufferPosition, 0, bufferLength); messageQueue.Enqueue(tempBuff); return; } ushort sequence = this.sequence++; var packet = sendBuffer.Insert(sequence); packet.time = -1.0; // ensure size for header int varLength = getVariableLengthBytes((ushort)bufferLength); packet.buffer.SetSize(2 + varLength + bufferLength); using (var writer = ByteArrayReaderWriter.Get(packet.buffer.InternalBuffer)) { writer.Write(sequence); writeVariableLengthUShort((ushort)bufferLength, writer); writer.WriteBuffer(buffer, bufferPosition, bufferLength); } // signal that packet is ready to be sent packet.writeLock = false; }
// 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++; } } } }
private void processDatagram(Datagram datagram) { if (!MiscUtils.AddressEqual(datagram.sender, currentServerEndpoint)) { return; } using (var reader = ByteArrayReaderWriter.Get(datagram.payload)) { NetcodePacketHeader packetHeader = new NetcodePacketHeader(); packetHeader.Read(reader); int length = datagram.payloadSize - (int)reader.ReadPosition; switch (packetHeader.PacketType) { case NetcodePacketType.ConnectionChallenge: processChallengePacket(packetHeader, length, reader); break; case NetcodePacketType.ConnectionDenied: processConnectionDenied(packetHeader, length, reader); break; case NetcodePacketType.ConnectionKeepAlive: processConnectionKeepAlive(packetHeader, length, reader); break; case NetcodePacketType.ConnectionPayload: processConnectionPayload(packetHeader, length, reader); break; case NetcodePacketType.ConnectionDisconnect: processConnectionDisconnect(packetHeader, length, reader); break; } } }
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); }
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 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); }