コード例 #1
0
    private void SendChallengeResponse(long cSalt, long sSalt)
    {
        ChallengeResponsePacket responsePacket = new ChallengeResponsePacket();

        responsePacket.payload.result = cSalt ^ sSalt;
        SendToServer(responsePacket);
    }
コード例 #2
0
    public void OnReceivePacket(IPEndPoint ipEndpoint, PacketType packetType, Stream stream)
    {
        switch (packetType)
        {
        case PacketType.ConnectionRequest:
            ConnectionRequestPacket connectionRequestPacket = new ConnectionRequestPacket();
            connectionRequestPacket.Deserialize(stream);
            CheckAndSendChallengeRequest(ipEndpoint, connectionRequestPacket.payload);
            break;

        case PacketType.ChallengeRequest:
            ChallengeRequestPacket challengeRequestPacket = new ChallengeRequestPacket();
            challengeRequestPacket.Deserialize(stream);
            CheckAndSendChallengeResponse(ipEndpoint, challengeRequestPacket.payload);
            break;

        case PacketType.ChallengeResponse:
            ChallengeResponsePacket challengeResponsePacket = new ChallengeResponsePacket();
            challengeResponsePacket.Deserialize(stream);
            CheckResult(ipEndpoint, challengeResponsePacket.payload);
            break;

        case PacketType.Connected:
            if (!isServer && currentState == State.RespondingChallenge)
            {
                currentState = State.Connected;
            }
            break;
        }
    }
コード例 #3
0
    void SendChallengeResponse(long clientSalt, long serverSalt)
    {
        ChallengeResponsePacket packet = new ChallengeResponsePacket();

        packet.payload.result = clientSalt ^ serverSalt; // Example: 110011 ^ 000011 = 110000
        PacketManager.Instance.SendPacketToServer(packet);
    }
コード例 #4
0
ファイル: ConnectionManager.cs プロジェクト: Luciano94/IA
    private void SendChallengeResponse(ulong clientSalt, ulong serverSalt)
    {
        ChallengeResponsePacket request = new ChallengeResponsePacket();

        request.payload.result = clientSalt ^ serverSalt;
        SendToServer(request);
    }
コード例 #5
0
        public static async Task HandleProofAsync(LogonRemoteClient client, LogonPacket logonPacket)
        {
            var proofPacket = new ProofPacket(logonPacket);

            var proofValid = client.AuthData.Srp6.IsClientProofValid(proofPacket.A, proofPacket.M1);

            Console.WriteLine($"Authentication {(proofValid ? "successful" : "failed")}");

            if (!proofValid)
            {
                var response = new ChallengeResponsePacket
                {
                    Error = ChallengeResponsePacket.ChallengeResponseError.NoSuchAccount
                };
                await client.SendDataAsync(new LogonMetaPacket(response.FinalizePacket()));

                return;
            }

            var successPacket = new Packet();

            successPacket.WriteByte(0x1);
            successPacket.WriteByte(0x0);
            successPacket.WriteBytes(client.AuthData.Srp6.ServerSessionKeyProof.GetBytes(20));
            successPacket.WriteInt32(0);
            successPacket.WriteInt32(0);
            successPacket.WriteInt16(0);

            await client.SendDataAsync(new LogonMetaPacket(successPacket.FinalizePacket()));
        }
コード例 #6
0
ファイル: ConnectionManager.cs プロジェクト: Luciano94/IA
    public void OnReceivePacket(IPEndPoint ipEndpoint, PacketType packetType, Stream stream)
    {
        switch (packetType)
        {
        case PacketType.ConnectionRequest: {
            ConnectionRequestPacket connectionRequestPacket = new ConnectionRequestPacket();
            connectionRequestPacket.Deserialize(stream);
            CheckAndSendChallengeRequest(ipEndpoint, connectionRequestPacket.payload);
        } break;

        case PacketType.ChallengeRequest: {
            ChallengeRequestPacket challengeRequestPacket = new ChallengeRequestPacket();
            challengeRequestPacket.Deserialize(stream);
            CheckAndSendChallengeResponse(ipEndpoint, challengeRequestPacket.payload);
        } break;

        case PacketType.ChallengeResponse: {
            ChallengeResponsePacket challengeResponsePacket = new ChallengeResponsePacket();
            challengeResponsePacket.Deserialize(stream);
            CheckResult(ipEndpoint, challengeResponsePacket.payload);
        } break;

        case PacketType.Connected: {
            FinishHandShake();
        } break;
        }
    }
コード例 #7
0
    private void OnChallengeResponse(IPEndPoint iPEndPoint, Stream stream)
    {
        Debug.Log("OnChallengeResponse");
        ChallengeResponsePacket challengeResponsePacket = new ChallengeResponsePacket();

        challengeResponsePacket.Deserialize(stream);
        CheckResultForConnection(iPEndPoint, challengeResponsePacket.payload);
    }
コード例 #8
0
    void SendChallengeResponse()
    {
        Debug.Log("Enviando Challenge Response");
        ChallengeResponsePacket packet = new ChallengeResponsePacket();

        packet.payload = challengeResolved;
        PacketsManager.Instance.SendPacket(packet, objectId);
    }
コード例 #9
0
    private void SendChallengeResponse(ulong clientSalt, ulong serverSalt)
    {
        Debug.Log("Sending challenge response");

        ChallengeResponsePacket challengeResponsePacket = new ChallengeResponsePacket();

        challengeResponsePacket.payload.result = clientSalt ^ serverSalt;

        SendToServer(challengeResponsePacket);
    }
コード例 #10
0
    void SendChallengeResponse()
    {
        ChallengeResponsePacket challengeResponsePacket = new ChallengeResponsePacket();
        ChallengeResponseData   challengeResponseData;

        challengeResponseData.result    = challengeResultGeneratedByClient;
        challengeResponsePacket.Payload = challengeResponseData;

        PacketsManager.Instance.SendPacket(challengeResponsePacket);
    }
コード例 #11
0
 public void ReceivingChallengeResponse(Stream stream, IPEndPoint iPEnd)
 {
     if (NetworkManager.Instance.isServer)
     {
         ChallengeResponsePacket responsePacket = new ChallengeResponsePacket();
         responsePacket.Deserialize(stream);
         if (NetworkManager.Instance.ipToId.ContainsKey(iPEnd))
         {
             Client client = NetworkManager.Instance.clients[NetworkManager.Instance.ipToId[iPEnd]];
             challengeResult = client._clientSalt ^ client._serverSalt;
             if (responsePacket.payload.result == challengeResult)
             {
                 client.state = Client.ClientConnection.Connected;
                 SendConnected(client._id, iPEnd);
             }
         }
     }
 }
コード例 #12
0
        public void TestChallengeResponsePacket()
        {
            Random rnd                      = new Random(0);
            ulong  clientRandom             = (ulong)rnd.Next(int.MaxValue);
            ulong  serverRandom             = (ulong)rnd.Next(int.MaxValue);
            ulong  challengeResponse        = (ulong)rnd.Next(int.MaxValue);
            ChallengeResponsePacket packet1 = new ChallengeResponsePacket(clientRandom, serverRandom, challengeResponse);

            byte[] output  = new byte[1024];
            int    written = packet1.Write(output, null);

            ChallengeResponsePacket packet2 = new ChallengeResponsePacket();

            packet2.Read(output, written);

            Assert.AreEqual(packet1.ClientRandom, packet2.ClientRandom);
            Assert.AreEqual(packet1.ServerRandom, packet2.ServerRandom);
            Assert.AreEqual(packet1.ChallengeResponse, packet2.ChallengeResponse);
        }
コード例 #13
0
    void OnChallengeResponse(Stream stream, IPEndPoint iPEndPoint)
    {
        if (NetworkManager.Instance.isServer)
        {
            ChallengeResponsePacket packet = new ChallengeResponsePacket();
            packet.Deserialize(stream);

            if (ipToId.ContainsKey(iPEndPoint))
            {
                Client client = clients[ipToId[iPEndPoint]];

                long result = client.clientSalt ^ client.serverSalt;

                if (result == packet.payload.result)
                {
                    client.state = Client.ClientState.Connected;
                    SendConnected(client.id, iPEndPoint);
                }
            }
        }
    }
コード例 #14
0
    void OnRecieve(ushort type, Stream stream, IPEndPoint ip)
    {
        switch (type)
        {
        case (ushort)PacketType.ConnectionRequest:
        {
            ConnectionRequestPacket packet = new ConnectionRequestPacket();
            packet.Deserialize(stream);
            AddNewClient(ip, packet.payload);
            break;
        }

        case (ushort)PacketType.ChallengeRequest:
        {
            onConectionRequest = false;
            ChallengeRequestPacket packet = new ChallengeRequestPacket();
            packet.Deserialize(stream);
            serverDirt = packet.payload;

            DoChallenge();
            break;
        }

        case (ushort)PacketType.ChallengeResponse:
        {
            ChallengeResponsePacket packet = new ChallengeResponsePacket();
            packet.Deserialize(stream);
            CheckChallengeRecieved(ip, packet.payload);
            break;
        }


        case (ushort)PacketType.Conected:
            OnConected();
            break;
        }
    }
コード例 #15
0
        public static async Task HandleChallengeAsync(LogonRemoteClient client, LogonPacket logonPacket)
        {
            var packet = new ChallengePacket(logonPacket);

            Console.WriteLine("Received logon packet:");
            Console.WriteLine($"\tError:\t\t\t{packet.Error}");
            Console.WriteLine($"\tSize:\t\t\t{packet.Size}");
            Console.WriteLine($"\tGame:\t\t\t{packet.Game}");
            Console.WriteLine($"\tBuild:\t\t\t{packet.Build}");
            Console.WriteLine($"\tPlatform:\t\t{packet.Platform}");
            Console.WriteLine($"\tOS:\t\t\t{packet.OS}");
            Console.WriteLine($"\tCountry:\t\t{packet.Country}");
            Console.WriteLine($"\tTimezone Bias:\t\t{packet.TimezoneBias}");
            Console.WriteLine($"\tIP:\t\t\t{packet.IP}");
            Console.WriteLine($"\tAccount Name:\t\t{packet.AccountName}");

            Console.Write($"Validating username... ");
            var account = LogonServices.Accounts.GetAccount(packet.AccountName);

            if (account == null)
            {
                Console.WriteLine($"failed. Account {packet.AccountName} does not exist.");

                var response = new ChallengeResponsePacket
                {
                    Error = ChallengeResponsePacket.ChallengeResponseError.NoSuchAccount
                };
                await client.SendDataAsync(new LogonMetaPacket(response.FinalizePacket()));
            }
            else
            {
                Console.WriteLine("success!");

                if (account.Banned)
                {
                    Console.WriteLine($"Account {account.Username} is currently banned.");
                    var response = new ChallengeResponsePacket
                    {
                        Error = ChallengeResponsePacket.ChallengeResponseError.AccountClosed
                    };
                    await client.SendDataAsync(new LogonMetaPacket(response.FinalizePacket()));

                    client.Disconnect();
                    return;
                }

                client.AuthData.DbAccount = account;

                Console.WriteLine($"Validating username and password for account {account.Username}");

                client.AuthData.InitSRP6(account.Username,
                                         account.PasswordHash.ByteRepresentationToByteArray());

                var pack = new Packet();
                pack.WriteByte(0);
                pack.WriteByte(0);
                pack.WriteByte(0);
                var b = client.AuthData.Srp6.PublicEphemeralValueB;
                pack.WriteBytes(b.GetBytes(32));

                pack.WriteByte(1);
                pack.WriteBytes(client.AuthData.Srp6.Generator.GetBytes(1));

                pack.WriteByte(32);
                pack.WriteBytes(client.AuthData.Srp6.Modulus.GetBytes(32));

                pack.WriteBytes(client.AuthData.Srp6.Salt.GetBytes(32));

                var rand      = new Random(Environment.TickCount);
                var randBytes = new byte[16];
                rand.NextBytes(randBytes);
                pack.WriteBytes(randBytes);

                pack.WriteByte(0);

                await client.SendDataAsync(new LogonMetaPacket(pack.FinalizePacket()));
            }
        }
コード例 #16
0
        /// <summary>
        /// Initializes serverobject with IP
        /// </summary>
        /// <param name="useLocalhost">Whether the server should use 127.0.0.1 ip or use its actual outgoing one</param>
        public Server(bool useLocalhost = false)
        {
            WorldManager.OnServer = true;

            isDisposed     = false;
            isDoingCleanup = false;

            IPAddress ip;

            if (useLocalhost)
            {
                ip = IPAddress.Parse("127.0.0.1");
            }
            else
            {
                ip = GetIP();
            }
            IPEndPoint iep = new IPEndPoint(ip, PORT);

            listener = new CustomUdpClient(PORT);
            listener.PacketRecieved += PacketReceived;

            pending   = new Connection[PENDING_SLOTS];
            connected = new Connection[CONNECTED_SLOTS];
            games     = new Game[GAME_SLOTS];

            packetCallbacks = new Dictionary <Type, Action <Packet> >()
            {
                {
                    typeof(StringPacket), (Packet p) =>
                    {
                        StringPacket sp = (StringPacket)p;
                        Console.WriteLine(sp.Content);
                    }
                },
                { typeof(ConnectPacket), (Packet p) =>
                  {
                      int             connectionIndex = GetConnectionIndexFromIEP(pending, p.Sender);
                      ChallengePacket challenge;
                      ConnectPacket   cp = (ConnectPacket)p;
                      if (connectionIndex == -1)
                      {
                          int i = GetFirstFreeIndex(pending);
                          if (i == -1)
                          {
                              listener.Send(new DeclineConnectPacket(), p.Sender);
                              return;
                          }

                          challenge  = new ChallengePacket(cp.ClientSalt);
                          pending[i] = new Connection(cp.Sender, cp.ClientSalt, challenge.ServerSalt);
                          pending[i].RefreshRecievedPacketTimestamp();
                      }
                      else
                      {
                          Connection c = pending[connectionIndex];
                          c.ClientSalt = cp.ClientSalt;
                          challenge    = new ChallengePacket(c.ClientSalt, c.ServerSalt);
                          c.RefreshRecievedPacketTimestamp();
                      }
                      listener.Send(challenge, p.Sender);
                  } },
                {
                    typeof(ChallengeResponsePacket), (Packet p) =>
                    {
                        int connectionIndex = GetConnectionIndexFromIEP(pending, p.Sender);
                        if (connectionIndex == -1)
                        {
                            return;
                        }
                        Connection c = pending[connectionIndex];
                        ChallengeResponsePacket crp = (ChallengeResponsePacket)p;
                        if (crp.Xored == c.Xored) // response packet was correct
                        {
                            pending[connectionIndex] = null;
                            connectionIndex          = GetFirstFreeIndex(connected);
                            if (connectionIndex == -1)
                            {
                                listener.Send(new DeclineConnectPacket(), p.Sender);
                                return;
                            }
                            connected[connectionIndex] = c;
                            c.RefreshRecievedPacketTimestamp();
                            KeepClientAlivePacket kcap = new KeepClientAlivePacket();
                            listener.Send(kcap, p.Sender);
                            return;
                        }
                        listener.Send(new DeclineConnectPacket(), p.Sender);
                    }
                }
            };

            connectedPacketCallbacks = new Dictionary <Type, Action <SaltedPacket, Connection> >()
            {
                {
                    typeof(KeepAlivePacket), (SaltedPacket p, Connection c) =>
                    {
                        c.RefreshRecievedPacketTimestamp();
                    }
                },
                {
                    typeof(QueuePacket), (SaltedPacket p, Connection c) =>
                    {
                        int gameIndex = GetGameIndexFromIep(p.Sender);
                        int gameId    = -1;
                        if (gameIndex != -1)
                        {
                            gameId = games[gameIndex].Id;
                        }
                        else
                        {
                            lock (games)
                            {
                                foreach (Game g in games)
                                {
                                    if (g != null && g.AddConnection(c))
                                    {
                                        gameId = g.Id;
                                        break;
                                    }
                                }


                                if (gameId == -1)
                                {
                                    int newGameIndex = GetFirstFreeIndex(games);
                                    if (newGameIndex != -1)
                                    {
                                        Game g = new Game();
                                        games[newGameIndex] = g;
                                        g.AddConnection(c);
                                        gameId = g.Id;
                                        g.StartHandle(SendPacket);
                                        g.GameEnded += (object sender, EventArgs e) =>
                                        {
                                            lock (games)
                                                games[newGameIndex] = null;
                                        };
                                    }
                                }
                            }
                        }

                        QueueResponsePacket qrp = new QueueResponsePacket(gameId);
                        listener.Send(qrp, p.Sender);
                        c.RefreshSentPacketTimestamp();
                    }
                },
                {
                    typeof(GetGameInfoPacket), (SaltedPacket p, Connection c) =>
                    {
                        int gameIndex = GetGameIndexFromIep(c.Client);
                        if (gameIndex == -1)
                        {
                            return;
                        }

                        Game           g    = games[gameIndex];
                        GameInfoPacket ggip = new GameInfoPacket(g);
                        listener.Send(ggip, p.Sender);
                        c.RefreshSentPacketTimestamp();
                    }
                },
                {
                    typeof(InputPacket), (SaltedPacket p, Connection c) =>
                    {
                        int gameIndex = GetGameIndexFromIep(c.Client);
                        if (gameIndex == -1)
                        {
                            SendPacket(new QueueResponsePacket(-1), c.Client);
                            return;
                        }

                        Game        g    = games[gameIndex];
                        InputPacket inpt = (InputPacket)p;
                        g.HandleInputPacket(inpt, c);
                    }
                }
            };
        }
コード例 #17
0
    void ReceiveConnectionData(ushort packetTypeIndex, IPEndPoint ipEndPoint, Stream stream)
    {
        switch ((PacketType)packetTypeIndex)
        {
        case PacketType.ChallengeRequest:
            if (!UdpNetworkManager.Instance.IsServer && clientConnectionState == ClientConnectionState.RequestingConnection)
            {
                ChallengeRequestPacket challengeRequestPacket = new ChallengeRequestPacket();

                challengeRequestPacket.Deserialize(stream);

                challengeResultGeneratedByClient = saltGeneratedByClient ^ challengeRequestPacket.Payload.serverSalt;
                clientConnectionState            = ClientConnectionState.SendingChallengeResponse;
            }
            break;

        case PacketType.ConnectionAccepted:
            if (!UdpNetworkManager.Instance.IsServer && clientConnectionState == ClientConnectionState.SendingChallengeResponse)
            {
                ConnectionAcceptedPacket connectionAcceptedPacket = new ConnectionAcceptedPacket();

                connectionAcceptedPacket.Deserialize(stream);
                UdpNetworkManager.Instance.SetClientID(connectionAcceptedPacket.Payload.clientID);
                onClientConnectedCallback?.Invoke(connectionAcceptedPacket.Payload.clientsInSession);
                onClientConnectedCallback = null;
                clientConnectionState     = ClientConnectionState.Connected;
            }
            break;

        case PacketType.ClientJoined:
            if (!UdpNetworkManager.Instance.IsServer && clientConnectionState == ClientConnectionState.Connected)
            {
                ClientJoinedPacket clientJoinedPacket = new ClientJoinedPacket();

                clientJoinedPacket.Deserialize(stream);
                OnOtherClientJoined.Invoke(clientJoinedPacket.Payload.clientID);
            }
            break;

        case PacketType.ConnectionRequest:
            if (UdpNetworkManager.Instance.IsServer && !udpClientsIDs.ContainsKey(ipEndPoint))
            {
                if (!udpPendingClientsData.ContainsKey(ipEndPoint))
                {
                    ConnectionRequestPacket connectionRequestPacket = new ConnectionRequestPacket();

                    connectionRequestPacket.Deserialize(stream);
                    AddPendingClient(ipEndPoint, connectionRequestPacket.Payload.clientSalt);
                }

                UdpPendingClientData udpPendingClientData = udpPendingClientsData[ipEndPoint];

                SendChallengeRequest(udpPendingClientData);
            }
            break;

        case PacketType.ChallengeResponse:
            if (UdpNetworkManager.Instance.IsServer)
            {
                if (udpPendingClientsData.ContainsKey(ipEndPoint))
                {
                    ChallengeResponsePacket challengeResponsePacket = new ChallengeResponsePacket();
                    UdpPendingClientData    udpPendingClientData    = udpPendingClientsData[ipEndPoint];

                    challengeResponsePacket.Deserialize(stream);

                    long serverResult = udpPendingClientData.clientSalt ^ udpPendingClientData.serverSalt;

                    if (challengeResponsePacket.Payload.result == serverResult)
                    {
                        ClientJoinedPacket clientJoinedPacket = new ClientJoinedPacket();
                        ClientJoinedData   clientJoinedData;

                        clientJoinedData.clientID  = ClientID;
                        clientJoinedPacket.Payload = clientJoinedData;

                        PacketsManager.Instance.SendPacket(clientJoinedPacket, null, 0, 0, reliable: true);
                        AddClient(ipEndPoint);
                        RemovePendingClient(ipEndPoint);
                        OnClientAddedByServer?.Invoke(udpClientsIDs[ipEndPoint]);
                    }
                }
                if (udpClientsIDs.ContainsKey(ipEndPoint))
                {
                    SendConnectionAccepted(udpClientsData[udpClientsIDs[ipEndPoint]]);
                }
            }
            break;
        }
    }
コード例 #18
0
ファイル: LocalPeer.cs プロジェクト: Vyxlose/Rudel
        private void HandlePacket(byte[] data, int length, EndPoint fromEndpoint)
        {
            if (length < 1)
            {
                // TODO: Shit hit the fan
            }

            PacketType type = (PacketType)data[0];

            switch (type)
            {
            case PacketType.ConnectionRequest:
            {
                ConnectionRequestPacket connectionRequest = new ConnectionRequestPacket();
                if (connectionRequest.Read(data, length) && !PendingPeers.ContainsKey(new ConnectKey(fromEndpoint, connectionRequest.ClientRandom)))
                {
                    ulong localSessionPart = RandomUtils.GetULong(Constants.USE_CRYPTO_RANDOM);

                    RemotePeer peer = new RemotePeer()
                    {
                        ChallengeData           = connectionRequest.ClientRandom,
                        RemoteEndpoint          = fromEndpoint,
                        ConnectionState         = ConnectState.WaitingForChallengeResponse,
                        ChallengeSeed           = localSessionPart,
                        ChallengeResult         = localSessionPart ^ connectionRequest.ClientRandom,
                        LastIncomingMessageDate = DateTime.Now
                    };

                    PendingPeers.Add(new ConnectKey(fromEndpoint, connectionRequest.ClientRandom), peer);

                    ChallengePacket packet = new ChallengePacket(peer.ChallengeData, peer.ChallengeSeed);

                    SendPacket(packet, peer);

                    for (int i = 0; i < Constants.CONNECTION_SEGMENT_RETRIES - 1; i++)
                    {
                        _network.PacketScheduler.Add(DateTime.Now.Add(new TimeSpan(0, 0, 0, 0, Constants.CONNECTION_SEGMENT_RETRY_TIMEOUT * i)), new ScheduledPacket()
                            {
                                Packet     = packet,
                                LocalPeer  = this,
                                RemotePeer = peer
                            });
                    }
                }
            }
            break;

            case PacketType.Challenge:
            {
                ChallengePacket challenge = new ChallengePacket();
                if (challenge.Read(data, length) && PendingPeers.ContainsKey(new ConnectKey(fromEndpoint, challenge.ClientRandom)))
                {
                    RemotePeer peer = PendingPeers[new ConnectKey(fromEndpoint, challenge.ClientRandom)];
                    if (peer.ConnectionState == ConnectState.WaitingForChallenge)
                    {
                        peer.CreateChannels(_network.ChannelTypes);
                        peer.LastIncomingMessageDate = DateTime.Now;
                        peer.ChallengeData           = challenge.ServerRandom;
                        peer.ChallengeResult         = peer.ChallengeData ^ peer.ChallengeSeed;
                        peer.ConnectionState         = ConnectState.Connected;

                        PendingPeers.Remove(new ConnectKey(fromEndpoint, challenge.ClientRandom));
                        Connected.Add(fromEndpoint, peer);

                        incomingEvents.Enqueue(new NetworkEvent()
                            {
                                EventType  = EventType.Connect,
                                Packet     = null,
                                RemotePeer = peer,
                                LocalPeer  = this
                            });

                        ChallengeResponsePacket packet = new ChallengeResponsePacket(peer.ChallengeSeed, peer.ChallengeData, peer.ChallengeResult);

                        SendPacket(packet, peer);

                        for (int i = 0; i < Constants.CONNECTION_SEGMENT_RETRIES - 1; i++)
                        {
                            _network.PacketScheduler.Add(DateTime.Now.Add(new TimeSpan(0, 0, 0, 0, Constants.CONNECTION_SEGMENT_RETRY_TIMEOUT * i)), new ScheduledPacket()
                                {
                                    Packet     = packet,
                                    LocalPeer  = this,
                                    RemotePeer = peer
                                });
                        }
                    }
                }
            }
            break;

            case PacketType.ChallengeResponse:
            {
                ChallengeResponsePacket challengeResponse = new ChallengeResponsePacket();
                if (challengeResponse.Read(data, length) && PendingPeers.ContainsKey(new ConnectKey(fromEndpoint, challengeResponse.ClientRandom)))
                {
                    RemotePeer peer = PendingPeers[new ConnectKey(fromEndpoint, challengeResponse.ClientRandom)];
                    if (peer.ConnectionState == ConnectState.WaitingForChallengeResponse && peer.ChallengeResult == challengeResponse.ChallengeResponse)
                    {
                        peer.CreateChannels(_network.ChannelTypes);
                        peer.LastIncomingMessageDate = DateTime.Now;
                        peer.ConnectionState         = ConnectState.Connected;
                        PendingPeers.Remove(new ConnectKey(fromEndpoint, challengeResponse.ClientRandom));
                        Connected.Add(fromEndpoint, peer);
                        incomingEvents.Enqueue(new NetworkEvent()
                            {
                                EventType  = EventType.Connect,
                                Packet     = null,
                                RemotePeer = peer,
                                LocalPeer  = this
                            });
                    }
                }
            }
            break;

            case PacketType.Data:
            {
                ChanneledPacket channeledPacket = new ChanneledPacket();
                if (channeledPacket.Read(data, length) && Connected.ContainsKey(fromEndpoint))
                {
                    RemotePeer peer = Connected[fromEndpoint];
                    if (peer.ConnectionState == ConnectState.Connected)
                    {
                        ChanneledPacket incomingPacket = peer.Channels[channeledPacket.Channel].HandleIncomingMessagePoll(data, length, out bool hasMore);
                        while (incomingPacket != null)
                        {
                            peer.LastIncomingMessageDate = DateTime.Now;
                            incomingEvents.Enqueue(new NetworkEvent()
                                {
                                    EventType  = EventType.Data,
                                    Packet     = incomingPacket,
                                    RemotePeer = peer,
                                    LocalPeer  = this
                                });
                            if (!hasMore)
                            {
                                break;
                            }
                            incomingPacket = peer.Channels[channeledPacket.Channel].HandlePoll();
                        }
                    }
                }
            }
            break;

            case PacketType.Disconnect:
            {
                DisconnectPacket disconnectPacket = new DisconnectPacket();
                if (disconnectPacket.Read(data, length) && Connected.ContainsKey(fromEndpoint))
                {
                    RemotePeer peer = Connected[fromEndpoint];
                    peer.ConnectionState = ConnectState.Disconnected;
                    Connected.Remove(fromEndpoint);
                    incomingEvents.Enqueue(new NetworkEvent()
                        {
                            EventType  = EventType.Disconnect,
                            Packet     = null,
                            RemotePeer = peer,
                            LocalPeer  = this
                        });
                }
            }
            break;

            case PacketType.Ack:
            {
                AckPacket ackPacket = new AckPacket();
                if (ackPacket.Read(data, length) && Connected.ContainsKey(fromEndpoint))
                {
                    RemotePeer peer = Connected[fromEndpoint];
                    if (peer.Channels[ackPacket.Channel].SupportsAck)
                    {
                        peer.Channels[ackPacket.Channel].HandleAck(ackPacket);
                    }
                }
            }
            break;
            }
        }