Example #1
0
        public override void SendPacketConnless(IPEndPoint endPoint, byte[] data,
                                                int dataSize, SendCallbackData callbackData = null)
        {
            var token = GetToken(endPoint);

            if (token != TokenHelper.TokenNone)
            {
                NetworkHelper.SendPacketConnless(Client, endPoint, token,
                                                 TokenManager.GenerateToken(endPoint), data, dataSize);
            }
            else
            {
                FetchToken(endPoint);

                var now  = Time.Get();
                var info = new ConnlessPacketInfo(dataSize)
                {
                    EndPoint         = endPoint,
                    Expiry           = now + Time.Freq() * TokenHelper.TokenCachePacketExpiry,
                    LastTokenRequest = now,
                };

                if (callbackData != null)
                {
                    info.SendCallback    = callbackData.Callback;
                    info.CallbackContext = callbackData.Context;

                    callbackData.TrackID = info.TrackID;
                }
                else
                {
                    info.SendCallback    = null;
                    info.CallbackContext = null;
                }

                Buffer.BlockCopy(data, 0, info.Data, 0, dataSize);
                ConnlessPacketList.Add(info);
            }
        }
Example #2
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);
        }
Example #3
0
        public override bool Open(NetworkServerConfig config)
        {
            if (!NetworkHelper.UdpClient(config.BindEndPoint, out var socket))
            {
                return(false);
            }

            UdpClient = socket;
            TokenManager.Init(UdpClient);
            TokenCache.Init(UdpClient, TokenManager);

            Config      = CheckConfig(config);
            Connections = new BaseNetworkConnection[Config.MaxClients];

            for (var i = 0; i < Connections.Count; i++)
            {
                Connections[i] = Kernel.Get <BaseNetworkConnection>();
                Connections[i].Init(UdpClient, Config.ConnectionConfig);
            }

            return(true);
        }
Example #4
0
        public override bool FetchChunk(ref Chunk packet)
        {
            var header = new ChunkHeader();
            var end    = ChunkConstruct.DataSize;

            while (true)
            {
                if (!Valid || CurrentChunk >= ChunkConstruct.NumChunks)
                {
                    Clear();
                    return(false);
                }

                var dataOffset = 0;
                for (var i = 0; i < CurrentChunk; i++)
                {
                    dataOffset  = header.Unpack(ChunkConstruct.Data, dataOffset);
                    dataOffset += header.Size;
                }

                dataOffset = header.Unpack(ChunkConstruct.Data, dataOffset);
                CurrentChunk++;

                if (dataOffset + header.Size > end)
                {
                    Clear();
                    return(false);
                }

                if (header.Flags.HasFlag(ChunkFlags.Vital))
                {
                    if (header.Sequence == (Connection.Ack + 1) % NetworkHelper.MaxSequence)
                    {
                        Connection.Ack = (Connection.Ack + 1) % NetworkHelper.MaxSequence;
                    }
                    else
                    {
                        if (NetworkHelper.IsSequenceInBackroom(header.Sequence, Connection.Ack))
                        {
                            continue;
                        }

                        Debug.Log("connection",
                                  $"asking for resend {header.Sequence} {(Connection.Ack + 1) % NetworkHelper.MaxSequence}");
                        Connection.SignalResend();
                        continue;
                    }
                }

                packet = new Chunk
                {
                    ClientId = ClientId,
                    EndPoint = EndPoint,
                    Flags    = header.Flags.HasFlag(ChunkFlags.Vital)
                        ? SendFlags.Vital
                        : SendFlags.None,
                    DataSize = header.Size,
                    Data     = new byte[header.Size]
                };

                Buffer.BlockCopy(ChunkConstruct.Data, dataOffset, packet.Data, 0, header.Size);
                return(true);
            }
        }
Example #5
0
 public override void FetchToken(IPEndPoint endPoint)
 {
     NetworkHelper.SendConnectionMsgWithToken(Client, endPoint,
                                              TokenHelper.TokenNone, 0, ConnectionMessages.Token,
                                              TokenManager.GenerateToken(endPoint), true);
 }
Example #6
0
        public override bool Receive(ref Chunk packet, ref uint responseToken)
        {
            while (true)
            {
                if (ChunkReceiver.FetchChunk(ref packet))
                {
                    return(true);
                }

                if (UdpClient.Available <= 0)
                {
                    return(false);
                }

                var    endPoint = default(IPEndPoint);
                byte[] data;

                try
                {
                    data = UdpClient.Receive(ref endPoint);
                }
                catch
                {
                    continue;
                }

                if (data.Length == 0)
                {
                    continue;
                }

                if (!NetworkHelper.UnpackPacket(data, data.Length, ChunkReceiver.ChunkConstruct))
                {
                    continue;
                }

                if (Connection.State != ConnectionState.Offline &&
                    Connection.State != ConnectionState.Error &&
                    Connection.EndPoint.Compare(endPoint, true))
                {
                    if (Connection.Feed(ChunkReceiver.ChunkConstruct, endPoint))
                    {
                        if (!ChunkReceiver.ChunkConstruct.Flags.HasFlag(PacketFlags.Connless))
                        {
                            ChunkReceiver.Start(endPoint, Connection, 0);
                        }
                    }
                }
                else
                {
                    var accept = TokenManager.ProcessMessage(endPoint, ChunkReceiver.ChunkConstruct);
                    if (accept == 0)
                    {
                        continue;
                    }

                    if (ChunkReceiver.ChunkConstruct.Flags.HasFlag(PacketFlags.Control))
                    {
                        if (ChunkReceiver.ChunkConstruct.Data[0] == (int)ConnectionMessages.Token)
                        {
                            TokenCache.AddToken(endPoint, ChunkReceiver.ChunkConstruct.ResponseToken,
                                                TokenFlags.AllowBroadcast | TokenFlags.ResponseOnly);
                        }
                    }
                    else if (ChunkReceiver.ChunkConstruct.Flags.HasFlag(PacketFlags.Connless) &&
                             accept != -1)
                    {
                        packet = new Chunk
                        {
                            ClientId = -1,
                            Flags    = SendFlags.Connless,
                            EndPoint = endPoint,
                            DataSize = ChunkReceiver.ChunkConstruct.DataSize,
                            Data     = ChunkReceiver.ChunkConstruct.Data,
                        };

                        responseToken = ChunkReceiver.ChunkConstruct.ResponseToken;
                        return(true);
                    }
                }
            }
        }
Example #7
0
        public override void Send(Chunk packet, uint token      = TokenHelper.TokenNone,
                                  SendCallbackData callbackData = null)
        {
            if (packet.Flags.HasFlag(SendFlags.Connless))
            {
                if (packet.DataSize > NetworkHelper.MaxPayload)
                {
                    Debug.Warning("network", $"packet payload too big, length={packet.DataSize}");
                    return;
                }

                if (packet.ClientId == -1 && Connection.EndPoint != null &&
                    packet.EndPoint.Compare(Connection.EndPoint, true))
                {
                    packet.ClientId = 0;
                }

                if (token != TokenHelper.TokenNone)
                {
                    NetworkHelper.SendPacketConnless(UdpClient, packet.EndPoint,
                                                     token, TokenManager.GenerateToken(packet.EndPoint),
                                                     packet.Data, packet.DataSize);
                }
                else
                {
                    if (packet.ClientId == -1)
                    {
                        TokenCache.SendPacketConnless(packet.EndPoint,
                                                      packet.Data, packet.DataSize, callbackData);
                    }
                    else
                    {
                        Debug.Assert(packet.ClientId == 0, "errornous client id");
                        Connection.SendPacketConnless(packet.Data, packet.DataSize);
                    }
                }
            }
            else
            {
                if (packet.DataSize + NetworkHelper.MaxChunkHeaderSize >= NetworkHelper.MaxPayload)
                {
                    Debug.Warning("network", $"chunk payload too big, length={packet.DataSize} dropping chunk");
                    return;
                }

                Debug.Assert(packet.ClientId == 0, "errornous client id");

                var flags = ChunkFlags.None;
                if (packet.Flags.HasFlag(SendFlags.Vital))
                {
                    flags = ChunkFlags.Vital;
                }

                Connection.QueueChunk(flags, packet.Data, packet.DataSize);

                if (packet.Flags.HasFlag(SendFlags.Flush))
                {
                    Connection.Flush();
                }
            }
        }
Example #8
0
 public override void SendPacketConnless(byte[] data, int dataSize)
 {
     NetworkHelper.SendPacketConnless(UdpClient, EndPoint, PeerToken, Token, data, dataSize);
 }
Example #9
0
 protected override void SendConnectionMsgWithToken(ConnectionMessages msg)
 {
     LastSendTime = Time.Get();
     NetworkHelper.SendConnectionMsgWithToken(UdpClient, EndPoint, PeerToken, 0,
                                              msg, Token, true);
 }
Example #10
0
 protected override void SendConnectionMsg(ConnectionMessages msg, string extra)
 {
     LastSendTime = Time.Get();
     NetworkHelper.SendConnectionMsg(UdpClient, EndPoint,
                                     PeerToken, Ack, msg, extra);
 }
Example #11
0
        public override bool Receive(ref Chunk packet, ref uint responseToken)
        {
            // TODO make multithreaded
            // https://docs.microsoft.com/ru-ru/dotnet/standard/io/how-to-use-named-pipes-for-network-interprocess-communication
            // https://blogs.msdn.microsoft.com/dotnet/2018/07/09/system-io-pipelines-high-performance-io-in-net/

            while (true)
            {
                if (ChunkReceiver.FetchChunk(ref packet))
                {
                    return(true);
                }

                if (UdpClient.Available <= 0)
                {
                    return(false);
                }

                var    endPoint = default(IPEndPoint);
                byte[] data;

                try
                {
                    data = UdpClient.Receive(ref endPoint);
                }
                catch
                {
                    continue;
                }

                if (data.Length == 0)
                {
                    continue;
                }

                if (!NetworkHelper.UnpackPacket(data, data.Length, ChunkReceiver.ChunkConstruct))
                {
                    continue;
                }

                if (NetworkBan.IsBanned(endPoint, out var banReason))
                {
                    NetworkHelper.SendConnectionMsg(UdpClient, endPoint,
                                                    ChunkReceiver.ChunkConstruct.ResponseToken, 0, ConnectionMessages.Close, banReason);
                    continue;
                }

                var freeSlot  = -1;
                var foundSlot = -1;
                var sameIps   = 0;

                for (var i = 0; i < Connections.Count; i++)
                {
                    if (Connections[i].State == ConnectionState.Offline && freeSlot < 0)
                    {
                        freeSlot = i;
                    }

                    if (Connections[i].State != ConnectionState.Offline &&
                        Connections[i].EndPoint.Compare(endPoint, comparePorts: false))
                    {
                        sameIps++;

                        if (Connections[i].EndPoint.Port != endPoint.Port)
                        {
                            continue;
                        }

                        if (Connections[i].Feed(ChunkReceiver.ChunkConstruct, endPoint))
                        {
                            if (ChunkReceiver.ChunkConstruct.DataSize > 0)
                            {
                                if (ChunkReceiver.ChunkConstruct.Flags.HasFlag(PacketFlags.Connless))
                                {
                                    packet = new Chunk()
                                    {
                                        Flags    = SendFlags.Connless,
                                        EndPoint = endPoint,
                                        ClientId = i,
                                        DataSize = ChunkReceiver.ChunkConstruct.DataSize,
                                        Data     = ChunkReceiver.ChunkConstruct.Data
                                    };

                                    responseToken = TokenHelper.TokenNone;
                                    return(true);
                                }

                                ChunkReceiver.Start(endPoint, Connections[i], i);
                            }
                        }

                        foundSlot = i;
                        break;
                    }
                }

                if (foundSlot >= 0)
                {
                    continue;
                }

                var accept = TokenManager.ProcessMessage(endPoint, ChunkReceiver.ChunkConstruct);
                if (accept <= 0)
                {
                    continue;
                }

                if (ChunkReceiver.ChunkConstruct.Flags.HasFlag(PacketFlags.Control))
                {
                    if (ChunkReceiver.ChunkConstruct.Data[0] == (int)ConnectionMessages.Connect)
                    {
                        if (sameIps >= Config.MaxClientsPerIp)
                        {
                            NetworkHelper.SendConnectionMsg(UdpClient, endPoint,
                                                            ChunkReceiver.ChunkConstruct.ResponseToken, 0,
                                                            ConnectionMessages.Close, $"Only {Config.MaxClientsPerIp} players with the same IP are allowed");
                            return(false);
                        }

                        if (freeSlot >= 0)
                        {
                            Connections[freeSlot].SetToken(ChunkReceiver.ChunkConstruct.Token);
                            Connections[freeSlot].Feed(ChunkReceiver.ChunkConstruct, endPoint);
                            OnClientConnected(freeSlot);
                            continue;
                        }

                        NetworkHelper.SendConnectionMsg(UdpClient, endPoint,
                                                        ChunkReceiver.ChunkConstruct.ResponseToken, 0,
                                                        ConnectionMessages.Close, "This server is full");
                        return(false);
                    }

                    if (ChunkReceiver.ChunkConstruct.Data[0] == (int)ConnectionMessages.Token)
                    {
                        TokenCache.AddToken(endPoint, ChunkReceiver.ChunkConstruct.ResponseToken,
                                            TokenFlags.ResponseOnly);
                    }
                }
                else if (ChunkReceiver.ChunkConstruct.Flags.HasFlag(PacketFlags.Connless))
                {
                    packet = new Chunk()
                    {
                        Flags    = SendFlags.Connless,
                        ClientId = -1,
                        EndPoint = endPoint,
                        DataSize = ChunkReceiver.ChunkConstruct.DataSize,
                        Data     = ChunkReceiver.ChunkConstruct.Data,
                    };

                    responseToken = ChunkReceiver.ChunkConstruct.ResponseToken;
                    return(true);
                }
            }
        }
Example #12
0
        public override bool Send(Chunk packet, uint token = TokenHelper.TokenNone)
        {
            if (packet.Flags.HasFlag(SendFlags.Connless))
            {
                if (packet.DataSize >= NetworkHelper.MaxPayload)
                {
                    Debug.Warning("netserver", $"packet payload too big ({packet.DataSize}). dropping packet");
                    return(false);
                }

                if (packet.ClientId == -1)
                {
                    for (var i = 0; i < Connections.Count; i++)
                    {
                        if (Connections[i].State != ConnectionState.Offline &&
                            Connections[i].EndPoint != null &&
                            Connections[i].EndPoint.Compare(packet.EndPoint, comparePorts: true))
                        {
                            packet.ClientId = i;
                            break;
                        }
                    }
                }

                if (token != TokenHelper.TokenNone)
                {
                    NetworkHelper.SendPacketConnless(UdpClient, packet.EndPoint, token,
                                                     TokenManager.GenerateToken(packet.EndPoint), packet.Data, packet.DataSize);
                }
                else
                {
                    if (packet.ClientId == -1)
                    {
                        TokenCache.SendPacketConnless(packet.EndPoint, packet.Data, packet.DataSize);
                    }
                    else
                    {
                        Debug.Assert(packet.ClientId >= 0 &&
                                     packet.ClientId < Connections.Count, "errornous client id");
                        Connections[packet.ClientId].SendPacketConnless(packet.Data, packet.DataSize);
                    }
                }
            }
            else
            {
                if (packet.DataSize + NetworkHelper.MaxChunkHeaderSize >= NetworkHelper.MaxPayload)
                {
                    Debug.Warning("netserver", $"packet payload too big ({packet.DataSize}). dropping packet");
                    return(false);
                }

                Debug.Assert(packet.ClientId >= 0 &&
                             packet.ClientId < Connections.Count, "errornous client id");

                var flags = packet.Flags.HasFlag(SendFlags.Vital)
                    ? ChunkFlags.Vital
                    : ChunkFlags.None;

                if (Connections[packet.ClientId].QueueChunk(flags, packet.Data, packet.DataSize))
                {
                    if (packet.Flags.HasFlag(SendFlags.Flush))
                    {
                        Connections[packet.ClientId].Flush();
                    }
                }
                else
                {
                    Drop(packet.ClientId, "Error sending data");
                }
            }

            return(true);
        }