Exemple #1
0
        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);
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        /*
         * [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);
        }
Exemple #4
0
 public abstract int ProcessMessage(IPEndPoint endPoint,
                                    ChunkConstruct chunkConstruct);
Exemple #5
0
 public ChunkReceiver()
 {
     ChunkConstruct = new ChunkConstruct(NetworkHelper.MaxPayload);
 }
Exemple #6
0
 public abstract bool Feed(ChunkConstruct packet, IPEndPoint endPoint);
Exemple #7
0
        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);
        }
Exemple #8
0
 public NetworkConnection()
 {
     ChunksForResends     = new List <ChunkResend>();
     ResendChunkConstruct = new ChunkConstruct(NetworkHelper.MaxPayload);
 }
Exemple #9
0
        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);
        }