Exemplo n.º 1
0
        //log in registered player
        //player sends updatedetails message to register
        public void LoginRequest(MClient c, MNetMessage m)
        {
            if (MassiveConnections.Count >= MAXCONNECTIONS)
            {
                DisconnectClient(c.connection, "Maximum Connections exceded");
                return;
            }

            MLoginMessageRequest mlir = MLoginMessageRequest.Deserialize <MLoginMessageRequest>(m.Payload);
            //check database
            //if password matches, continue
            //if not, send failed message
            IPEndPoint ipe = (IPEndPoint)c.connection.ConnectionInfo.RemoteEndPoint;
            string     s   = ipe.Address + ":" + ipe.Port;

            c.Account.ClientIP = s;
            if (c.Account.UserID == null)
            {
                c.Account.UserID = m.UserID;
            }
            _DataBase.UpdatePlayerIP(c.Account);
            _DataBase.UpdatePlayerUsage(c.Account);

            MUserAccount mu = _DataBase.GetPlayerByEmail(mlir.Email, mlir.Password);

            if (mu == null)
            {
                MNetMessage mli = new MNetMessage();
                mli.Command = MNetMessage.ERROR;
                mli.Payload = "User not found. Building Disabled. Register User and Login again.";
                Send(c, "Message", mli.Serialize());
            }
            else
            {
                MNetMessage mli = new MNetMessage();
                mli.Command = MNetMessage.LOGIN;
                mli.UserID  = mu.UserID;
                mli.Payload = mu.Serialize();
                Send(c, "Message", mli.Serialize());
                c.Account = mu;
            }

            ClientLoggedIn?.Invoke(this, new ServerEvent("Logged In:" + c.ToString()));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Creates a new <see cref="Account"/> and binds it to the given <see cref="Client"/> with a <see cref="Session"/>.
        /// <remarks>Removes any session that is already active on the given client(if the creation was successful).</remarks>
        /// </summary>
        /// <param name="client">The <see cref="Client"/> to which the new <see cref="Account"/> should be bound with a <see cref="Session"/>.</param>
        /// <param name="userName">The username of the new <see cref="Account"/>.</param>
        /// <param name="password">The password of the new <see cref="Account"/>.</param>
        /// <returns>A <see cref="LoginResult"/> indicating the success of the operation and the newly created <see cref="Session"/>.</returns>
        public Task <LoginResult> CreateAndLoginAccountAsync(Client.Client client, string userName, string password)
        {
            if (client == null)
            {
                throw new ArgumentNullException(nameof(client));
            }

            if (string.IsNullOrWhiteSpace(userName))
            {
                throw new ArgumentException(@"Value cannot be null or whitespace.", nameof(userName));
            }

            if (string.IsNullOrWhiteSpace(password))
            {
                throw new ArgumentException(@"Value cannot be null or whitespace.", nameof(password));
            }

            //Chain the tasks for checking the usernames existence and the creation of the new account. All of this is done in another thread.
            return(CheckAccountExistsAsync(userName).ContinueWith(nameCheckTask =>
            {
                try
                {
                    if (nameCheckTask.Result)
                    {
                        // The given username is already in use. Return unsuccessful.
                        return (LoginResult) new LoginFailedResult(LoginFailedReason.UserNameAlreadyInUse, "Username already in use.");
                    }

                    using (var context = _ContextFactory.CreateContext())
                    {
                        //Create the account in the database.
                        AccountEntity accountEntity = new AccountEntity
                        {
                            UserName = userName,
                            PasswordHash = _PasswordService.CreatePasswordHash(password),
                            CreationTime = DateTime.Now,
                            LastLogin = DateTime.Now,
                            LastIpAddress = client.SystemAddress
                        };

                        context.Accounts.Add(accountEntity);
                        context.SaveChanges();


                        //Login the new account
                        lock (_Lock)
                        {
                            //Logout the client just in case it is already logged in(this is a case that should not be allowed by the Frontend => Gothic client).
                            LogoutClient(client);

                            Account account = new Account(accountEntity.UserName, accountEntity.AccountId, accountEntity.PasswordHash, _ComponentSelector);
                            Session session = new Session(client, account);
                            _SessionByClient.Add(client, session);
                            _ClientIdLoggedIn[client.Id] = true;

                            //Invoke account creation event. Enqueue it on the dispatcher, so it will be executed after we leave the current lock.
                            _Dispatcher.EnqueueAction(() => AccountCreated?.Invoke(this, new AccountCreatedEventArgs(account)));

                            //Invoke the login event. Enqueue it on the dispatcher, so it will be executed after we leave the current lock.
                            _Dispatcher.EnqueueAction(() => ClientLoggedIn?.Invoke(this, new LoginEventArgs(session)));

                            return (LoginResult) new LoginSuccessfulResult(session);
                        }
                    }
                }
                catch (Exception e)
                {
                    _Log.Error($"Something went wrong while creating a new account and login in. Exception: {e}");
                    return new LoginFailedResult(LoginFailedReason.None, "Internal server error.");
                }
            }));
        }
Exemplo n.º 3
0
        /// <summary>
        /// Logs in the given <see cref="Client"/> and binds its <see cref="Account"/> to the <see cref="Client"/> with a <see cref="Session"/>.
        /// <remarks>Fails if the <see cref="Client"/> is already logged in.</remarks>
        /// </summary>
        /// <param name="client">The <see cref="Client"/> that should be logged in.</param>
        /// <param name="userName">The username of the <see cref="Account"/> that should be used in the login.</param>
        /// <param name="password">The password of the <see cref="Account"/> that should be used in the login.</param>
        /// <returns>A <see cref="LoginResult"/> indicating the success of the operation and the newly created <see cref="Session"/>.</returns>
        public Task <LoginResult> LoginClientAsync(Client.Client client, string userName, string password)
        {
            if (client == null)
            {
                throw new ArgumentNullException(nameof(client));
            }

            if (string.IsNullOrWhiteSpace(userName))
            {
                throw new ArgumentException(@"Value cannot be null or whitespace.", nameof(userName));
            }

            if (string.IsNullOrWhiteSpace(password))
            {
                throw new ArgumentException(@"Value cannot be null or whitespace.", nameof(password));
            }

            //Run the database access in another thread.
            var task = new Task <LoginResult>(() =>
            {
                //Check that neither the client is already logged in nor the account with the given username is already in use by another client.
                lock (_Lock)
                {
                    if (_SessionByClient.ContainsKey(client))
                    {
                        throw new InvalidOperationException(@"The given client is already logged in.");
                    }

                    if (_SessionByClient.Values.Any(session =>
                                                    session.Account.UserName.Equals(userName, StringComparison.OrdinalIgnoreCase)))
                    {
                        return(new LoginFailedResult(LoginFailedReason.AccountAlreadyLoggedIn, string.Empty));
                    }


                    using (var context = _ContextFactory.CreateContext())
                    {
                        //Try to get an Account with the given username
                        AccountEntity accountEntity = context.Accounts.FirstOrDefault(ac =>
                                                                                      ac.UserName.Equals(userName, StringComparison.OrdinalIgnoreCase));

                        //An account with the given name does not exist or the password is wrong or is banned.
                        if (accountEntity == null || !_PasswordService.VerifyPassword(password, accountEntity.PasswordHash))
                        {
                            return(new LoginFailedResult(LoginFailedReason.InvalidLoginData, string.Empty));
                        }

                        if (accountEntity.IsBanned)
                        {
                            return(new LoginFailedResult(LoginFailedReason.Banned, accountEntity.BannedReasonText));
                        }

                        //Save last login info to the database.
                        accountEntity.LastLogin     = DateTime.Now;
                        accountEntity.LastIpAddress = client.SystemAddress;
                        context.SaveChanges();

                        // Login successful, create an Account object and bind it to the client with a session.
                        Account account = new Account(accountEntity.UserName, accountEntity.AccountId, accountEntity.PasswordHash, _ComponentSelector);
                        Session session = new Session(client, account);
                        _SessionByClient.Add(client, session);
                        _ClientIdLoggedIn[client.Id] = true;

                        //Invoke the login event. Enqueue it on the dispatcher, so it will be executed after we leave the current lock.
                        _Dispatcher.EnqueueAction(() => ClientLoggedIn?.Invoke(this, new LoginEventArgs(session)));

                        return(new LoginSuccessfulResult(session));
                    }
                }
            });

            //Run the task.
            task.Start();
            return(task);
        }
Exemplo n.º 4
0
 public static void LogClientIn(ClientAccount clientAccount)
 {
     LoggedClients.Add(clientAccount);
     CalculateMaxTasksPerClient();
     ClientLoggedIn?.Invoke(LoggedClients);
 }