Esempio n. 1
0
        /// <summary> Attempts to read data from a client once </summary>
        /// <param name="client"> Client information to read data for </param>
        public void RecieveData(Client client)
        {
            // Helper method to handle reading
            Client.ReadState read(Client.ReadState state, int kind)
            {
                if (state.bytesRead > 0)
                {
                    state.message = state.buffer.Chop(state.bytesRead);
                    state.message = client.dec(state.message);
                    string str = state.message.GetStringUTF8();

                    state.held += str;
                    int index = state.held.IndexOf(RPCMessage.EOT);
                    while (index >= 0)
                    {
                        string pulled = state.held.Substring(0, index);
                        state.held = state.held.Remove(0, index + 1);
                        index      = state.held.IndexOf(RPCMessage.EOT);

                        if (pulled.Length > 0)
                        {
                            RPCMessage msg = kind == UDP?RPCMessage.UDP(client, pulled) : RPCMessage.TCP(client, pulled);

                            incoming.Enqueue(msg);
                        }
                    }
                }
                return(state);
            }

            if (client.udp != null)
            {
                try {
                    bool     canReadUDP = !client.closed && client.udp.Available > 0;
                    EndPoint ep         = client.remoteUdpHost;
                    client.udpReadState.bytesRead = canReadUDP
                                                ? client.udp.ReceiveFrom(client.udpReadState.buffer, ref ep)
                                                : -1;
                    client.udpReadState = read(client.udpReadState, UDP);
                    if (canReadUDP && client.udpReadState.bytesRead > 0 && ep is IPEndPoint)
                    {
                        client.remoteUdpHost = (IPEndPoint)ep;
                        Log.Info($"{client.identity} recieved from {client.remoteUdpHost}");
                    }
                } catch (Exception e) {
                    Log.Warning($"Server.RecieveData(Client): {client.identity} Error during UDP read. {e.GetType()}. Will defer to TCP closure to disconnect.", e);
                }
            }


            try {
                client.tcpReadState.bytesRead = !client.closed && client.tcpStream.CanRead && client.tcpStream.DataAvailable
                                        ? client.tcpStream.Read(client.tcpReadState.buffer, 0, client.tcpReadState.buffer.Length)
                                        : -1;
                client.tcpReadState = read(client.tcpReadState, TCP);
            } catch (ObjectDisposedException e) {
                Log.Verbose($"Server.RecieveData(Client): {client.identity} Probably Disconnected. {e.GetType()}", e);
                Close(client);
            } catch (SocketException e) {
                Log.Verbose($"Server.RecieveData(Client): {client.identity} Probably Disconnected. {e.GetType()}", e);
                Close(client);
            } catch (IOException e) {
                Log.Verbose($"Server.RecieveData(Client): {client.identity} Probably timed out. {e.GetType()}", e);
                Close(client);
            } catch (InvalidOperationException e) {
                Log.Verbose($"Server.RecieveData(Client): {client.identity} Probably timed out. {e.GetType()}", e);
                Close(client);
            } catch (Exception e) {
                Log.Warning($"Server.RecieveData(Client): ", e);
            }
        }
Esempio n. 2
0
 /// <summary> Testing Method at the end of a small response chain </summary>
 /// <param name="msg"> RPCMessage info </param>
 public void Ack(RPCMessage msg)
 {
     Log.Verbose($"Ack from {msg.sender.identity}: {msg[0]}");
 }
Esempio n. 3
0
 public void Pong(RPCMessage msg)
 {
     Log.Info($"Pong'd by {msg.sender.identity}");
 }
Esempio n. 4
0
 /// <summary> Testing Method in the middle of a small response chain </summary>
 /// <param name="msg"> RPCMessage info </param>
 public void SynAck(RPCMessage msg)
 {
     Log.Verbose($"SynAck from {msg.sender.identity}: {msg[0]}");
     msg.sender.Call(Ack, msg[0]);
 }
Esempio n. 5
0
        /// <summary> Connected database service </summary>

        /// <summary> Client -> Server RPC. Checks user and credentials to validate login, responds with <see cref="LoginResponse(RPCMessage)"/></summary>
        /// <param name="msg"> RPC Info. </param>
        public void Login(RPCMessage msg)
        {
#if !UNITY
            string user    = msg[0];
            string hash    = msg[1];
            string version = msg.numArgs >= 3 ? msg[2] : "[[Version Not Set]]";
            // Login flow.
            Credentials   creds    = null;
            LoginResult   result   = LoginResult.Failed_Unspecified;
            string        reason   = "none";
            UserLoginInfo userInfo = null;

            #region Submethod CheckLogin()
            {             // SubMethod: CheckLogin()
                if (version != versionCode)
                {
                    Log.Debug($"{nameof(LoginService)}: Version mismatch {version}, expected {versionCode}");
                    reason = VERSION_MISMATCH;
                    result = LoginResult.Failed_VersionMismatch;
                }
                else if (!usernameValidator(user))
                {
                    Log.Debug($"{nameof(LoginService)}: Bad username {user}");
                    reason = "Invalid Username";
                    result = LoginResult.Failed_BadUsername;
                }
                else if (GetLogin(msg.sender) != null)
                {
                    Log.Debug($"{nameof(LoginService)}: Client {msg.sender.identity} already logged in");
                    reason = "Already Logged In";
                    result = LoginResult.Failed_ClientAlreadyLoggedIn;
                }
                else
                {
                    userInfo = dbService.Get <UserLoginInfo>(nameof(userInfo.userName), user);

                    if (userInfo == null)
                    {
                        Log.Debug($"{nameof(LoginService)}: User {user} not found, creating them now. ");

                        Guid userId = Guid.NewGuid();
                        userInfo = CreateNewUser(msg);

                        if (userInfo != null)
                        {
                            result = LoginResult.Success_Created;
                            creds  = new Credentials(user, hash, userInfo.guid);
                        }
                        else
                        {
                            result = LoginResult.Failed_CreationCooldown;
                            reason = "Too many account creations";
                        }
                    }
                    else
                    {
                        // Check credentials against existing credentials.
                        if (loginsByUserId.ContainsKey(userInfo.guid))
                        {
                            reason = "Already logged in";
                            result = LoginResult.Failed_UserAlreadyLoggedIn;
                        }
                        else if (hash != userInfo.hash)
                        {
                            reason = "Bad credentials";
                            result = LoginResult.Failed_BadCredentials;
                        }
                        else
                        {
                            creds  = new Credentials(user, hash, userInfo.guid);
                            result = LoginResult.Success;
                        }
                    }
                }
            }             // Submethod: CheckLogin()
            #endregion

            #region Submethod RecordLoginAttempt
            {             // SubMethod: RecordLoginAttempt()
                LoginAttempt attempt = new LoginAttempt();
                attempt.result      = result;
                attempt.result_desc = result.ToString();
                attempt.timestamp   = DateTime.UtcNow;
                attempt.hash        = hash;
                attempt.userName    = user;
                attempt.ip          = msg.sender.remoteIP;
                if (userInfo != null)
                {
                    attempt.success  = true;
                    attempt.creation = result == LoginResult.Success_Created;
                    attempt.guid     = userInfo.guid;
                }
                else
                {
                    attempt.success = attempt.creation = false;
                    attempt.guid    = Guid.Empty;
                }

                dbService.Save(attempt);
            }             // Submethod: RecordLoginAttempt()
            #endregion

            #region Submethod Respond
            {            // Submethod: Respond()
                if (creds == null)
                {
                    msg.sender.Call(LoginResponse, "fail", reason);

                    Log.Info($"Client {msg.sender.identity} Failed to login.");

                    server.On(new LoginFailure_Server()
                    {
                        ip = msg.sender.remoteIP
                    });
                }
                else
                {
                    var session = new Session(msg.sender, creds);
                    loginsByClient[msg.sender]   = session;
                    loginsByUserId[creds.userId] = session;

                    userInfo.lastLogin = DateTime.UtcNow;
                    dbService.Save(userInfo);

                    msg.sender.Call(LoginResponse, "succ", creds.userId);

                    Log.Info($"Client {msg.sender.identity} logged in as user {creds.username} / {creds.userId}. ");

                    server.On(new LoginSuccess_Server(msg.sender));
                }
            }             // Submethod: Respond()
            #endregion
#endif
        }