Пример #1
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);
                }
            }
        }
Пример #2
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);
                    }
                }
            }
        }
Пример #3
0
 public override void AddToken(IPEndPoint endPoint, uint token)
 {
     TokenCache.AddToken(endPoint, token, TokenFlags.None);
 }