Pdelvo.Minecraft.Proxy.Library.Connection.ProxyConnection.HandleClient C# (CSharp) Method

HandleClient() private method

private HandleClient ( ) : void
return void
        internal virtual async void HandleClient()
        {
            string kickMessage = "Failed to login";
            bool success = true;
            try
            {
                ClientRemoteInterface clientRemoteInterface =
                    ClientRemoteInterface.Create(new NetworkStream(_networkSocket), 60);
                _clientEndPoint = new ProxyEndPoint(clientRemoteInterface, clientRemoteInterface.EndPoint.Version);
                _clientEndPoint.RemoteEndPoint = (IPEndPoint) _networkSocket.RemoteEndPoint;

                Packet packet = await clientRemoteInterface.ReadPacketAsync ();

                var listPing = packet as PlayerListPing;
                var handshakeRequest = packet as HandshakeRequest;


                if (listPing != null) // send motd
                {
                    _isMotDRequest = true;

                    if (listPing.MagicByte == 1)
                    {
                        //Plugin Message begins @ 1.6

                        AdditionalServerListInformation additionalInformation = null;

                        try
                        {
                            clientRemoteInterface.EndPoint.Stream.ReadTimeout = 1;
                        }
                        catch (InvalidOperationException)
                        {
                        }

                        try
                        {
                            additionalInformation =
                                await clientRemoteInterface.ReadAdditionalServerListInformationAsync();
                        }
                        catch (TimeoutException timeOut)
                        {
                        }

                        additionalInformation = additionalInformation ?? new AdditionalServerListInformation
                        {
                            Host = _server.LocalEndPoint.Address.ToString(),
                            Port = _server.LocalEndPoint.Port,
                            ProtocolVersion = (byte) _server.PublicMinecraftVersion
                        };
                        additionalInformation.ProtocolVersion = ProtocolInformation.MaxSupportedClientVersion <
                                                                additionalInformation.ProtocolVersion
                            ? (byte) ProtocolInformation.MaxSupportedClientVersion
                            : additionalInformation.ProtocolVersion;
                        additionalInformation.ProtocolVersion = ProtocolInformation.MinSupportedClientVersion >
                                                                additionalInformation.ProtocolVersion
                            ? (byte) ProtocolInformation.MinSupportedClientVersion
                            : additionalInformation.ProtocolVersion;

                        string response = ProtocolHelper.BuildMotDString(additionalInformation.ProtocolVersion,
                            _server.ServerVersionName, _server.MotD,
                            _server.ConnectedUsers, _server.MaxUsers);
                        await KickUserAsync(response);
                    }
                    else
                    {
                        string response = ProtocolHelper.BuildMotDString(_server.MotD, _server.ConnectedUsers,
                            _server.MaxUsers);
                        await KickUserAsync(response);
                    }
                    return;
                }

                if (handshakeRequest != null)
                {
                    Username = handshakeRequest.UserName;
                    Host = handshakeRequest.Host;
                    ClientEndPoint.ProtocolVersion = handshakeRequest.ProtocolVersion;

                    if (handshakeRequest.ProtocolVersion < ProtocolInformation.MinSupportedClientVersion)
                    {
                        await KickUserAsync("Outdated Client");
                        return;
                    }
                    else if (handshakeRequest.ProtocolVersion > ProtocolInformation.MaxSupportedClientVersion)
                    {
                        await KickUserAsync("Outdated Server");
                        return;
                    }

                    var args = new UserEventArgs(this);

                    _server.PluginManager.TriggerPlugin.OnPlayerConnected(args);

                    if (args.Canceled)
                    {
                        await ClientEndPoint.SendPacketAsync(new DisconnectPacket {Reason = args.CancelMessage});
                        _networkSocket.Close ();
                        _server.RemoveConnection(this);
                        return;
                    }

                    bool onlineMode = _server.OnlineModeEnabled(this);
                    string serverId = onlineMode ? Session.GetSessionHash () : "-";

                    var randomBuffer = new byte[4];
                    _random.NextBytes(randomBuffer);
                    await ClientEndPoint.SendPacketAsync(new EncryptionKeyRequest
                                                             {
                                                                 ServerId = serverId,
                                                                 PublicKey =
                                                                     AsnKeyBuilder.PublicKeyToX509(_server.RSAKeyPair).
                                                                     GetBytes (),
                                                                 VerifyToken = randomBuffer
                                                             });
                    do
                    {
                        packet = await ClientEndPoint.ReceivePacketAsync ();
                    } while (packet is KeepAlive);

                    var encryptionKeyResponse = (EncryptionKeyResponse) packet;
                    byte[] verification = ProtocolSecurity.RsaDecrypt(
                        encryptionKeyResponse.VerifyToken.ToArray (), _server.RSACryptoServiceProvider, true);
                    byte[] sharedKey = ProtocolSecurity.RsaDecrypt(
                        encryptionKeyResponse.SharedKey.ToArray (), _server.RSACryptoServiceProvider, true);
                    if (verification.Length != randomBuffer.Length
                        || !verification.Zip(randomBuffer, (a, b) => a == b).All(a => a))
                    {
                        await KickUserAsync("Verify token failure");
                        _logger.Error("Failed to login a Client, Verify token failure");
                        return;
                    }

                    await ClientEndPoint.SendPacketAsync(new EncryptionKeyResponse {SharedKey = new byte[0]});

                    ClientEndPoint.ConnectionKey = sharedKey;
                    ClientEndPoint.EnableAes (); //now everything is encrypted

                    Packet p = await ClientEndPoint.ReceivePacketAsync ();

                    if (!(p is RespawnRequestPacket))
                    {
                        await KickUserAsync("Protocol failure");
                        _logger.Error("Failed to login a Client, Protocol failure");
                        return;
                    }

                    string hash = ProtocolSecurity.ComputeHash(
                        Encoding.ASCII.GetBytes(serverId),
                        ClientEndPoint.ConnectionKey,
                        AsnKeyBuilder.PublicKeyToX509(_server.RSAKeyPair).GetBytes ());

                    if (onlineMode)
                    {
                        bool result;
                        try
                        {
                            result = await _server.CheckUserAccountAsync(this, hash);
                        }
                        catch (OperationCanceledException ex)
                        {
                            Task t = KickUserAsync(ex.Message);
                            return;
                        }

                        if (!result)
                        {
                            await KickUserAsync("User not premium");
                            return;
                        }
                    }

                    _logger.InfoFormat("{0}[{1}] is connected", Username, _networkSocket.RemoteEndPoint);

                    _server.PromoteConnection(this);

                    Packet response = await InitializeServerAsync ();

                    var logonResponse = response as LogOnResponse;
                    if (logonResponse != null)
                    {
                        EntityID = logonResponse.EntityId;
                    }

                    await ClientEndPoint.SendPacketAsync(response);

                    StartClientListening ();
                    StartServerListening ();

                    args = new UserEventArgs(this);

                    _server.PluginManager.TriggerPlugin.OnUserConnectedCompleted(args);

                    args.EnsureSuccess ();
                }
            }
            catch (TaskCanceledException)
            {
                return;
            }
            catch (OperationCanceledException ex)
            {
                kickMessage = ex.Message;
                success = false;
                _quitMessagePosted = true;
                _logger.Error(string.Format("Client login aborted ({0})", Username), ex);
            }
            catch (Exception ex)
            {
                success = false;
                _quitMessagePosted = true;
                if (!string.IsNullOrEmpty(Username))
                    _logger.Error(string.Format("Failed to login a client ({0})", Username), ex);
            }
            if (!success)
                await KickUserAsync(kickMessage);
        }

Usage Example

Ejemplo n.º 1
0
        private async void ReceiveClientsAsync()
        {
            _acceptingNewClients = true;
            while (true)
            {
                try
                {
                    Socket remote = await _listeningSocket.AcceptTaskAsync ();

                    IPAddress address = ((IPEndPoint) remote.RemoteEndPoint).Address;
                    var args = new CheckIPEventArgs(address, true);

                    PluginManager.TriggerPlugin.AllowJoining(args);

                    if (!args.AllowJoining)
                    {
                        remote.Close ();
                        _logger.Warn("Denied access from " + address);
                        continue;
                    }
                    //Connection accepted

                    var proxyConnection = new ProxyConnection(remote, this);

                    _openConnection.Add(proxyConnection);


                    proxyConnection.HandleClient ();
                }
                catch (TaskCanceledException)
                {
                    _acceptingNewClients = false;
                    return;
                }
                catch (Exception)
                {
                }
            }
        }