public static void SendPacket(UdpClient client, IPEndPoint endPoint, ChunkConstruct packet) { if (packet.DataSize == 0) { return; } Debug.Assert((packet.Token & ~TokenHelper.TokenMask) == 0, "token out of range"); var buffer = new byte[MaxPacketSize]; var compressedSize = -1; if (!packet.Flags.HasFlag(PacketFlags.Control)) { compressedSize = Huffman.Compress(packet.Data, 0, packet.DataSize, buffer, PacketHeaderSize, MaxPayload); } int finalSize; if (compressedSize > 0 && compressedSize < packet.DataSize) { finalSize = compressedSize; packet.Flags |= PacketFlags.Compression; } else { finalSize = packet.DataSize; Buffer.BlockCopy(packet.Data, 0, buffer, PacketHeaderSize, packet.DataSize); packet.Flags &= ~PacketFlags.Compression; } finalSize += PacketHeaderSize; buffer[0] = (byte)((((int)packet.Flags << 2) & 0xfc) | ((packet.Ack >> 8) & 0x03)); // flags and ack buffer[1] = (byte)((packet.Ack) & 0xff); buffer[2] = (byte)((packet.NumChunks) & 0xff); buffer[3] = (byte)((packet.Token >> 24) & 0xff); buffer[4] = (byte)((packet.Token >> 16) & 0xff); buffer[5] = (byte)((packet.Token >> 8) & 0xff); buffer[6] = (byte)((packet.Token) & 0xff); client.Send(buffer, finalSize, endPoint); }
public static void SendConnectionMsg(UdpClient client, IPEndPoint endPoint, uint token, int ack, ConnectionMessages msg, byte[] extraData, int extraSize) { var packet = new ChunkConstruct(1 + extraSize) { Token = token, Flags = PacketFlags.Control, Ack = ack, NumChunks = 0, DataSize = 1 + extraSize }; packet.Data[0] = (byte)msg; if (extraSize > 0) { Buffer.BlockCopy(extraData, 0, packet.Data, 1, extraSize); } SendPacket(client, endPoint, packet); }
/* * [5c22fc7f][unpack]: 1 * [5c22fc7f][test]: token=4294967295 res=3569422453 * [5c22fc7f][test]: bytes=520 accept 0 1 * [5c22fc7f][unpack]: 8 * [5c22fc7f][test]: token=157418043 res=4168385603 * [5c22fc7f][check]: cur=157418043 seed=1257701721 * [5c22fc7f][test]: bytes=22 accept 1 8 * */ public override int ProcessMessage(IPEndPoint endPoint, ChunkConstruct packet) { var broadcastResponse = false; // TODO ODODODO if (packet.Token != TokenHelper.TokenNone && !CheckToken(endPoint, packet.Token, packet.ResponseToken, ref broadcastResponse)) { return(0); } var verified = packet.Token != TokenHelper.TokenNone; var tokenMessage = packet.Flags.HasFlag(PacketFlags.Control) && packet.Data[0] == (int)ConnectionMessages.Token; if (packet.Flags.HasFlag(PacketFlags.Connless)) { return((verified && !broadcastResponse) ? 1 : 0); } if (!tokenMessage) { return((verified && !broadcastResponse) ? 1 : 0); } if (verified) { return(broadcastResponse ? -1 : 1); } if (packet.DataSize >= TokenHelper.TokenRequestDataSize) { NetworkHelper.SendConnectionMsgWithToken(Client, endPoint, packet.ResponseToken, 0, ConnectionMessages.Token, GenerateToken(endPoint), false); } return(0); }
public abstract int ProcessMessage(IPEndPoint endPoint, ChunkConstruct chunkConstruct);
public ChunkReceiver() { ChunkConstruct = new ChunkConstruct(NetworkHelper.MaxPayload); }
public abstract bool Feed(ChunkConstruct packet, IPEndPoint endPoint);
public override bool Feed(ChunkConstruct packet, IPEndPoint endPoint) { if (Sequence >= PeerAck) { if (packet.Ack < PeerAck || packet.Ack > Sequence) { return(false); } } else { if (packet.Ack < PeerAck && packet.Ack > Sequence) { return(false); } } PeerAck = packet.Ack; if (packet.Token == TokenHelper.TokenNone || packet.Token != Token) { return(false); } if (packet.Flags.HasFlag(PacketFlags.Resend)) { Resend(); } if (packet.Flags.HasFlag(PacketFlags.Connless)) { return(true); } var now = Time.Get(); if (packet.Flags.HasFlag(PacketFlags.Control)) { var msg = (ConnectionMessages)packet.Data[0]; if (msg == ConnectionMessages.Close) { State = ConnectionState.Error; RemoteClosed = true; string reason = null; if (packet.DataSize > 1) { reason = Encoding.UTF8.GetString(packet.Data, 1, Math.Clamp(packet.DataSize - 1, 1, 128)); reason = reason.SanitizeStrong(); } Error = reason; Debug.Log("connection", $"closed reason='{reason}'"); } else if (msg == ConnectionMessages.Token) { PeerToken = packet.ResponseToken; if (State == ConnectionState.Token) { LastReceiveTime = now; State = ConnectionState.Connect; SendConnectionMsgWithToken(ConnectionMessages.Connect); Debug.Log("connection", $"got token, replying, token={PeerToken:X} mytoken={Token:X}"); } else { Debug.Log("connection", $"got token, token={PeerToken:X}"); } } else { if (State == ConnectionState.Offline) { if (msg == ConnectionMessages.Connect) { var token = Token; Reset(); State = ConnectionState.Pending; EndPoint = endPoint; Token = token; PeerToken = packet.ResponseToken; LastSendTime = now; LastReceiveTime = now; ConnectedAt = now; SendConnectionMsg(ConnectionMessages.ConnectAccept, null); Debug.Log("connection", "got connection, sending connect+accept"); } } else if (State == ConnectionState.Connect) { if (msg == ConnectionMessages.ConnectAccept) { LastReceiveTime = now; SendConnectionMsg(ConnectionMessages.Accept, null); State = ConnectionState.Online; Debug.Log("connection", "got connect+accept, sending accept. connection online"); } } } } else if (State == ConnectionState.Pending) { LastReceiveTime = now; State = ConnectionState.Online; Debug.Log("connection", "connecting online"); } if (State == ConnectionState.Online) { LastReceiveTime = now; AckChunks(packet.Ack); } return(true); }
public NetworkConnection() { ChunksForResends = new List <ChunkResend>(); ResendChunkConstruct = new ChunkConstruct(NetworkHelper.MaxPayload); }
public static bool UnpackPacket(byte[] data, int dataSize, ChunkConstruct chunkConstruct) { if (dataSize < PacketHeaderSize || dataSize > MaxPacketSize) { Debug.Log("network", $"packet size wrong, size={dataSize}"); return(false); } chunkConstruct.Flags = (PacketFlags)((data[0] & 0xfc) >> 2); if (chunkConstruct.Flags.HasFlag(PacketFlags.Connless)) { if (dataSize < PacketHeaderSizeConnless) { Debug.Log("network", $"connless packet too small, size={dataSize}"); return(false); } chunkConstruct.Flags = PacketFlags.Connless; chunkConstruct.Ack = 0; chunkConstruct.NumChunks = 0; var version = data[0] & 0x3; if (version != PacketVersion) { return(false); } chunkConstruct.DataSize = dataSize - PacketHeaderSizeConnless; chunkConstruct.Token = (uint)((data[1] << 24) | (data[2] << 16) | (data[3] << 8) | (data[4])); chunkConstruct.ResponseToken = (uint)((data[5] << 24) | (data[6] << 16) | (data[7] << 8) | (data[8])); Buffer.BlockCopy(data, PacketHeaderSizeConnless, chunkConstruct.Data, 0, chunkConstruct.DataSize); } else { if (dataSize - PacketHeaderSize > MaxPayload) { Debug.Log("network", $"packet payload too big, size={dataSize}"); return(false); } chunkConstruct.Ack = ((data[0] & 0x3) << 8) | data[1]; chunkConstruct.NumChunks = data[2]; chunkConstruct.DataSize = dataSize - PacketHeaderSize; chunkConstruct.ResponseToken = TokenHelper.TokenNone; chunkConstruct.Token = (uint)((data[3] << 24) | (data[4] << 16) | (data[5] << 8) | (data[6])); if (chunkConstruct.Flags.HasFlag(PacketFlags.Compression)) { chunkConstruct.DataSize = Huffman.Decompress(data, PacketHeaderSize, chunkConstruct.DataSize, chunkConstruct.Data, 0, chunkConstruct.Data.Length); } else { Buffer.BlockCopy(data, PacketHeaderSize, chunkConstruct.Data, 0, chunkConstruct.DataSize); } } if (chunkConstruct.DataSize < 0) { Debug.Log("network", "error during packet decoding"); return(false); } if (chunkConstruct.Flags.HasFlag(PacketFlags.Control)) { if (chunkConstruct.DataSize >= 5) { if (chunkConstruct.Data[0] == (int)ConnectionMessages.Connect || chunkConstruct.Data[0] == (int)ConnectionMessages.Token) { chunkConstruct.ResponseToken = (uint)((chunkConstruct.Data[1] << 24) | (chunkConstruct.Data[2] << 16) | (chunkConstruct.Data[3] << 8) | (chunkConstruct.Data[4])); } } } return(true); }