private static string GenerateProofValue(LoginSocketState state)
        {
            string value = state.PasswordEncrypted;

            value += new String(' ', 48);
            value += state.Name;
            value += state.ServerChallenge;
            value += state.ClientChallenge;
            value += state.PasswordEncrypted;

            return(value.ToMD5());
        }
        public static byte[] NewUser(ref LoginSocketState state, Dictionary <string, string> keyValues)
        {
            string message = String.Empty;

            if (keyValues.ContainsKey("nick"))
            {
                state.Name = keyValues["nick"];
            }
            else
            {
                return(DataFunctions.StringToBytes(@"\error\\err\0\fatal\\errmsg\Invalid Query!\id\1\final\"));
            }

            if (keyValues.ContainsKey("email"))
            {
                state.Email = keyValues["email"];
            }
            else
            {
                return(DataFunctions.StringToBytes(@"\error\\err\0\fatal\\errmsg\Invalid Query!\id\1\final\"));
            }

            if (keyValues.ContainsKey("passwordenc"))
            {
                state.PasswordEncrypted = keyValues["passwordenc"];
            }
            else
            {
                return(DataFunctions.StringToBytes(@"\error\\err\0\fatal\\errmsg\Invalid Query!\id\1\final\"));
            }

            if (UsersDatabase.Instance.UserExists(state.Name))
            {
                return(DataFunctions.StringToBytes(@"\error\\err\516\fatal\\errmsg\This account name is already in use!\id\1\final\"));
            }
            else
            {
                string password = DecryptPassword(state.PasswordEncrypted);

                UsersDatabase.Instance.CreateUser(state.Name, password.ToMD5(), state.Email, "??", ((IPEndPoint)state.Socket.RemoteEndPoint).Address);

                var clientData = UsersDatabase.Instance.GetUserData(state.Name);

                if (clientData == null)
                {
                    return(DataFunctions.StringToBytes(@"\error\\err\0\fatal\\errmsg\Error creating account!\id\1\final\"));
                }

                message = String.Format(@"\nur\\userid\{0}\profileid\{1}\id\1\final\", clientData.UserId, clientData.ProfileId);
            }

            return(DataFunctions.StringToBytes(message));
        }
예제 #3
0
        private static string GenerateResponseValueWithEmail(ref LoginSocketState state, ref ProfileData clientData)
        {
            string value = state.PasswordEncrypted;

            value += new String(' ', 48);
            value += state.Name + "@" + (state.Email ?? clientData.Email);
            value += state.ClientChallenge;
            value += state.ServerChallenge;
            value += state.PasswordEncrypted;

            return(value.ToMD5());
        }
        private void OnToGameSent(IAsyncResult async)
        {
            LoginSocketState state = (LoginSocketState)async.AsyncState;

            if (state == null || state.GameSocket == null)
            {
                return;
            }

            try
            {
                int sent = state.GameSocket.EndSend(async);
                //Log(Category, String.Format("[{0}] Sent {1} byte response to: {2}:{3}", state.Type, sent, ((IPEndPoint)state.GameSocket.RemoteEndPoint).Address, ((IPEndPoint)state.GameSocket.RemoteEndPoint).Port));
            }
            catch (NullReferenceException)
            {
                if (state != null)
                {
                    state.Dispose();
                }
                state = null;
            }
            catch (SocketException e)
            {
                switch (e.SocketErrorCode)
                {
                case SocketError.ConnectionReset:
                case SocketError.Disconnecting:
                    if (state != null)
                    {
                        state.Dispose();
                    }
                    state = null;
                    return;

                default:
                    LogError(Category, "Error sending data");
                    LogError(Category, String.Format("{0} {1}", e.SocketErrorCode, e));
                    if (state != null)
                    {
                        state.Dispose();
                    }
                    state = null;
                    return;
                }
            }
            catch (Exception ex)
            {
                LogError(Category, "Error receiving data");
                LogError(Category, ex.ToString());
            }
        }
        private void WaitForData(ref LoginSocketState state)
        {
            Thread.Sleep(10);

            try
            {
                state.GameSocket.BeginReceive(state.Buffer, 0, state.Buffer.Length, SocketFlags.None, OnGameDataReceived, state);
            }
            catch (NullReferenceException)
            {
                if (state != null)
                {
                    state.Dispose();
                }
                state = null;
            }
            catch (ObjectDisposedException)
            {
                if (state != null)
                {
                    state.Dispose();
                }
                state = null;
            }
            catch (SocketException e)
            {
                if (e.SocketErrorCode == SocketError.NotConnected)
                {
                    if (state != null)
                    {
                        state.Dispose();
                    }
                    state = null;
                    return;
                }

                if (e.SocketErrorCode != SocketError.ConnectionAborted &&
                    e.SocketErrorCode != SocketError.ConnectionReset)
                {
                    LogError(Category, "Error receiving data");
                    LogError(Category, String.Format("{0} {1}", e.SocketErrorCode, e));
                }

                if (state != null)
                {
                    state.Dispose();
                }
                state = null;
                return;
            }
        }
        private void AcceptCallback(IAsyncResult ar)
        {
            LoginSocketState state = (LoginSocketState)ar.AsyncState;

            try
            {
                Socket client = state.GameSocket.EndAccept(ar);

                Thread.Sleep(1);

                state.GameSocket = client;

                if (state.Type == LoginSocketState.SocketType.Client)
                {
                    StartClientManagerServerSocket();

                    state.ServerSocket = _clientManagerServerSocket;

                    _clientManagerServerSocket.BeginConnect(new IPEndPoint(IPAddress.Parse(GameConstants.SERVER_ADDRESS), GameConstants.CLIENT_LOGIN_TCP_PORT), OnConnect, state);
                    RestartClientAcepting();
                }
                else if (state.Type == LoginSocketState.SocketType.Search)
                {
                    StartSearchManagerServerSocket();

                    state.ServerSocket = _searchManagerServerSocket;
                    _searchManagerServerSocket.BeginConnect(new IPEndPoint(IPAddress.Parse(GameConstants.SERVER_ADDRESS), GameConstants.SEARCH_LOGIN_TCP_PORT), OnConnect, state);
                    RestartSearchAcepting();
                }
            }
            catch (NullReferenceException)
            {
                if (state != null)
                {
                    state.Dispose();
                }
                state = null;
            }
            catch (SocketException e)
            {
                LogError(Category, "Error accepting client");
                LogError(Category, String.Format("{0} {1}", e.SocketErrorCode, e));
                if (state != null)
                {
                    state.Dispose();
                }
                state = null;
                return;
            }
        }
예제 #7
0
        private void WaitForData(ref LoginSocketState state)
        {
            Thread.Sleep(10);

            try
            {
                state.Socket.BeginReceive(state.Buffer, 0, state.Buffer.Length, SocketFlags.None, OnDataReceived, state);
            }
            catch (NullReferenceException)
            {
                if (state != null)
                {
                    state.Dispose();
                }
                state = null;
            }
            catch (ObjectDisposedException)
            {
                if (state != null)
                {
                    state.Dispose();
                }
                state = null;
            }
            catch (SocketException e)
            {
                if (e.SocketErrorCode == SocketError.NotConnected)
                {
                    if (state != null)
                    {
                        state.Dispose();
                    }
                    state = null;
                    return;
                }

                if (e.SocketErrorCode != SocketError.ConnectionAborted &&
                    e.SocketErrorCode != SocketError.ConnectionReset)
                {
                    Logger.Error(e, $"Error receiving data. SocketErrorCode: {e.SocketErrorCode}");
                }
                if (state != null)
                {
                    state.Dispose();
                }
                state = null;
                return;
            }
        }
예제 #8
0
        private void OnSent(IAsyncResult async)
        {
            LoginSocketState state = (LoginSocketState)async.AsyncState;

            if (state == null || state.Socket == null)
            {
                return;
            }

            try
            {
                int sent = state.Socket.EndSend(async);
                Logger.Info($"[{state.Type}] Sent {sent} byte response to: " +
                            $"{((IPEndPoint)state.Socket.RemoteEndPoint).Address}:{((IPEndPoint)state.Socket.RemoteEndPoint).Port}");
            }
            catch (NullReferenceException)
            {
                if (state != null)
                {
                    state.Dispose();
                }
                state = null;
            }
            catch (SocketException e)
            {
                switch (e.SocketErrorCode)
                {
                case SocketError.ConnectionReset:
                case SocketError.Disconnecting:
                    if (state != null)
                    {
                        state.Dispose();
                    }
                    state = null;
                    return;

                default:
                    Logger.Error(e, $"Error sending data. SocketErrorCode: {e.SocketErrorCode}");
                    if (state != null)
                    {
                        state.Dispose();
                    }
                    state = null;
                    return;
                }
            }
        }
        public static void UpdateProfile(ref LoginSocketState state, Dictionary <string, string> keyValues)
        {
            string country = "??";

            if (keyValues.ContainsKey("countrycode"))
            {
                country = keyValues["countrycode"].ToUpperInvariant();
            }

            Dictionary <string, object> clientData = new Dictionary <string, object>()
            {
                { "country", country }
            };

            UsersDatabase.Instance.SetUserData(state.Name, clientData);
            state.State++;
        }
        public bool SendToGame(ref LoginSocketState state, byte[] data, int count)
        {
            if (data == null || state == null || state.GameSocket == null)
            {
                return(false);
            }

            //Log("RESP", DataFunctions.BytesToString(data));

            try
            {
                state.GameSocket.BeginSend(data, 0, count, SocketFlags.None, OnToGameSent, state);
                return(true);
            }
            catch (NullReferenceException)
            {
                if (state != null)
                {
                    state.Dispose();
                }
                state = null;
                return(false);
            }
            catch (SocketException e)
            {
                if (e.SocketErrorCode != SocketError.ConnectionAborted &&
                    e.SocketErrorCode != SocketError.ConnectionReset)
                {
                    LogError(Category, "Error sending data");
                    LogError(Category, String.Format("{0} {1}", e.SocketErrorCode, e));
                }
                if (state != null)
                {
                    state.Dispose();
                }
                state = null;
                return(false);
            }
            catch (Exception ex)
            {
                LogError(Category, "Error receiving data");
                LogError(Category, ex.ToString());
            }

            return(false);
        }
예제 #11
0
        private void StartServerClientManager(object parameter)
        {
            AddressInfo info = (AddressInfo)parameter;

            Logger.Info("Starting Login Server ClientManager");

            try
            {
                _clientManagerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
                {
                    SendTimeout       = 30000,
                    ReceiveTimeout    = 30000,
                    SendBufferSize    = 8192,
                    ReceiveBufferSize = 8192,
                    Blocking          = false
                };

                _clientManagerSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse, true);
                _clientManagerSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, new LingerOption(false, 0));
                _clientManagerSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);

                _clientManagerSocket.Bind(new IPEndPoint(info.Address, info.Port));
                _clientManagerSocket.Listen(10);
            }
            catch (Exception e)
            {
                Logger.Error(e, $"Unable to bind Login Server ClientManager to {info.Address}:{info.Port}");
                return;
            }

            while (true)
            {
                _clientManagerReset.Reset();

                LoginSocketState state = new LoginSocketState()
                {
                    Type   = LoginSocketState.SocketType.Client,
                    Socket = _clientManagerSocket
                };

                _clientManagerSocket.BeginAccept(AcceptCallback, state);
                _clientManagerReset.WaitOne();
            }
        }
예제 #12
0
        private void ParseMessage(ref LoginSocketState state, string message)
        {
            string query;

            Logger.Info($"MESSAGE: {message}");

            var keyValues = GetKeyValue(message, out query);

            if (keyValues == null || String.IsNullOrWhiteSpace(query))
            {
                return;
            }

            if (keyValues.ContainsKey("name") && !keyValues.ContainsKey("email"))
            {
                var parts = keyValues["name"].Split('@');

                if (parts.Length > 2)
                {
                    keyValues["name"]  = parts[0];
                    keyValues["email"] = parts[1] + "@" + parts[2];
                }
            }

            Logger.Info($"[{state.Type}] Received {query} query from: " +
                        $"{((IPEndPoint)state.Socket.RemoteEndPoint).Address}:{((IPEndPoint)state.Socket.RemoteEndPoint).Port}");

            /*if (!keyValues.ContainsKey("ka"))
             * {
             *                  // say no to those not using bf2... Begone evil demon, bf2 for life!
             *                  return;
             *          }*/

            switch (state.Type)
            {
            case LoginSocketState.SocketType.Client:
                HandleClientManager(ref state, query, keyValues);
                break;

            case LoginSocketState.SocketType.Search:
                HandleSearchManager(ref state, query, keyValues);
                break;
            }
        }
        internal static byte[] SendNicks(ref LoginSocketState state, Dictionary <string, string> keyValues)
        {
            if (!keyValues.ContainsKey("email") || (!keyValues.ContainsKey("passenc") && !keyValues.ContainsKey("pass")))
            {
                return(DataFunctions.StringToBytes(@"\error\\err\0\fatal\\errmsg\Invalid Query!\id\1\final\"));
            }

            string password = String.Empty;

            if (keyValues.ContainsKey("passenc"))
            {
                password = DecryptPassword(keyValues["passenc"]);
            }
            else if (keyValues.ContainsKey("pass"))
            {
                password = keyValues["pass"];
            }

            password = password.ToMD5();

            var clientData = UsersDatabase.Instance.GetAllUserDatas(keyValues["email"], password);

            if (clientData == null)
            {
                return(DataFunctions.StringToBytes(@"\error\\err\551\fatal\\errmsg\Unable to get any associated profiles.\id\1\final\"));
            }

            List <string> nicks = new List <string>();

            foreach (var client in clientData)
            {
                nicks.Add(client.Name);
            }

            if (nicks.Count == 0)
            {
                return(DataFunctions.StringToBytes(@"\nr\0\ndone\\final\"));
            }

            state.State++;
            return(DataFunctions.StringToBytes(GenerateNicks(nicks.ToArray())));
        }
예제 #14
0
        private void KeepAliveCallback(object s)
        {
            LoginServer server = (LoginServer)s;

            try
            {
                if (_keepAliveTimer == null)
                {
                    Dispose();
                    return;
                }

                LoginSocketState state = this;
                HeartbeatState++;

                Console.WriteLine("sending keep alive");
                if (!server.SendToClient(ref state, LoginServerMessages.SendKeepAlive()))
                {
                    Dispose();
                    return;
                }

                // every 2nd keep alive request, we send an additional heartbeat
                if (HeartbeatState % 2 == 0)
                {
                    Console.WriteLine("sending heartbeat");
                    if (!server.SendToClient(ref state, LoginServerMessages.SendHeartbeat()))
                    {
                        Dispose();
                        return;
                    }
                }
            }
            catch (Exception e)
            {
                logger.Error(e, "Error running keep alive");
                Dispose();
            }
        }
예제 #15
0
 private void HandleSearchManager(ref LoginSocketState state, string query, Dictionary <string, string> keyValues)
 {
     if (state.State == 0)
     {
         if (query.Equals("nicks", StringComparison.InvariantCultureIgnoreCase))
         {
             SendToClient(ref state, LoginServerMessages.SendNicks(ref state, keyValues));
         }
         else if (query.Equals("check", StringComparison.InvariantCultureIgnoreCase))
         {
             SendToClient(ref state, LoginServerMessages.SendCheck(ref state, keyValues));
         }
     }
     else if (state.State == 1)
     {
         state.State++;
     }
     else if (state.State >= 2)
     {
         state.Dispose();
     }
 }
예제 #16
0
        public bool SendToClient(ref LoginSocketState state, byte[] data)
        {
            if (data == null || state == null || state.Socket == null)
            {
                return(false);
            }

            Logger.Info($"RESP: {DataFunctions.BytesToString(data)}");

            try
            {
                state.Socket.BeginSend(data, 0, data.Length, SocketFlags.None, OnSent, state);
                return(true);
            }
            catch (NullReferenceException)
            {
                if (state != null)
                {
                    state.Dispose();
                }
                state = null;
                return(false);
            }
            catch (SocketException e)
            {
                if (e.SocketErrorCode != SocketError.ConnectionAborted &&
                    e.SocketErrorCode != SocketError.ConnectionReset)
                {
                    Logger.Error(e, $"Error sending data. SocketErrorCode: {e.SocketErrorCode}");
                }
                if (state != null)
                {
                    state.Dispose();
                }
                state = null;
                return(false);
            }
        }
        private void StartServerSearchManager(AddressInfo info)
        {
            Log(Category, "Starting Login Server SearchManager");

            try
            {
                StartSearchManagerGameSocket(info);
            }
            catch (Exception e)
            {
                LogError(Category, String.Format("Unable to bind Login Server SearchManager to {0}:{1}", info.Address, info.Port));
                LogError(Category, e.ToString());
                return;
            }

            LoginSocketState state = new LoginSocketState()
            {
                Type       = LoginSocketState.SocketType.Search,
                GameSocket = _searchManagerGameSocket
            };

            RestartSearchAcepting();
        }
        private void OnGameDataReceived(IAsyncResult async)
        {
            LoginSocketState state = (LoginSocketState)async.AsyncState;

            if (state == null || state.GameSocket == null)
            {
                return;
            }

            try
            {
                // receive data from the socket
                int received = state.GameSocket.EndReceive(async);
                if (received == 0)
                {
                    goto CONTINUE;
                }

                //var str = Encoding.UTF8.GetString(state.Buffer, 0, received);

                // take what we received, and append it to the received data buffer
                //state.ReceivedData.Append(Encoding.UTF8.GetString(state.Buffer, 0, received));
                //string receivedData = state.ReceivedData.ToString();

                SendToServer(ref state, state.Buffer, received);


                // does what we received contain the \final\ delimiter?

                /*if (str.LastIndexOf(@"\final\") > -1)
                 * {
                 *  state.ReceivedData.Clear();
                 *
                 *
                 *  // lets split up the message based on the delimiter
                 *  string[] messages = receivedData.Split(new string[] { @"\final\" }, StringSplitOptions.RemoveEmptyEntries);
                 *
                 *  for (int i = 0; i < messages.Length; i++)
                 *  {
                 *      ParseMessage(ref state, messages[i]);
                 *  }
                 * }*/
            }
            catch (ObjectDisposedException)
            {
                if (state != null)
                {
                    state.Dispose();
                }
                state = null;
                return;
            }
            catch (SocketException e)
            {
                switch (e.SocketErrorCode)
                {
                case SocketError.ConnectionReset:
                case SocketError.Disconnecting:
                case SocketError.NotConnected:
                case SocketError.TimedOut:
                    if (state != null)
                    {
                        state.Dispose();
                    }
                    state = null;
                    return;

                default:
                    LogError(Category, "Error receiving data");
                    LogError(Category, String.Format("{0} {1}", e.SocketErrorCode, e));
                    if (state != null)
                    {
                        state.Dispose();
                    }
                    state = null;
                    return;
                }
            }
            catch (Exception e)
            {
                LogError(Category, "Error receiving data");
                LogError(Category, e.ToString());
            }

            // and we wait for more data...
            CONTINUE : WaitForData(ref state);
        }
        public static byte[] SendProof(ref LoginSocketState state, Dictionary <string, string> keyValues)
        {
            string response = String.Empty;

            int requiredValues = 0;

            if (keyValues.ContainsKey("uniquenick"))
            {
                state.Name = keyValues["uniquenick"];
            }
            else
            {
                var parts = keyValues["user"].Split('@');
                state.Name  = parts[0];
                state.Email = parts[1] + "@" + parts[2];
            }

            if (keyValues.ContainsKey("challenge"))
            {
                state.ClientChallenge = keyValues["challenge"];
                requiredValues++;
            }

            if (keyValues.ContainsKey("response"))
            {
                response = keyValues["response"];
                requiredValues++;
            }

            if (requiredValues != 2)
            {
                // if (requiredValues != 3)
                return(DataFunctions.StringToBytes(@"\error\\err\0\fatal\\errmsg\Invalid Query!\id\1\final\"));
            }

            var clientData = UsersDatabase.Instance.GetUserData(state.Name);

            if (clientData != null)
            {
                state.PasswordEncrypted = clientData.Passwordenc;

                var value          = GenerateResponseValue(ref state);
                var valueWithEmail = GenerateResponseValueWithEmail(ref state, ref clientData);

                if (response == value || response == valueWithEmail)
                {
                    ushort session;

                    if (response == value)
                    {
                        session = GenerateSession(state.Name);
                    }
                    else
                    {
                        session = GenerateSession(state.Name + "@" + (state.Email ?? clientData.Email));
                    }

                    string proofValue;

                    if (response == value)
                    {
                        proofValue = GenerateProofValue(state);
                    }
                    else
                    {
                        proofValue = GenerateProofValueWithEmail(state);
                    }

                    string proof = String.Format(@"\lc\2\sesskey\{0}\proof\{1}\userid\{2}\profileid\{3}\uniquenick\{4}\lt\{5}\id\1\final\",
                                                 session,
                                                 proofValue,
                                                 clientData.UserId,
                                                 clientData.ProfileId,
                                                 state.Name,
                                                 _random.GetString(22, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + "__");

                    /*state.Session = session.ToString();
                     *                  Dictionary<string, object> updateClientData = new Dictionary<string, object>() {
                     *                          { "session", session }
                     *                  };
                     *                  LoginDatabase.Instance.SetData(state.Name, updateClientData);*/

                    UsersDatabase.Instance.LogLogin(state.Name, ((IPEndPoint)state.Socket.RemoteEndPoint).Address);

                    state.State++;
                    return(DataFunctions.StringToBytes(proof));
                }
                else
                {
                    return(DataFunctions.StringToBytes(@"\error\\err\260\fatal\\errmsg\The password provided is incorrect.\id\1\final\"));
                }
            }
            else
            {
                return(DataFunctions.StringToBytes(String.Format(@"\error\\err\265\fatal\\errmsg\Username [{0}] doesn't exist!\id\1\final\", state.Name)));
            }
        }
예제 #20
0
        private void HandleClientManager(ref LoginSocketState state, string query, Dictionary <string, string> keyValues)
        {
            if (state == null || String.IsNullOrWhiteSpace(query) || keyValues == null)
            {
                return;
            }

            if (state.State >= 4)
            {
                state.Dispose();
            }
            else
            {
                switch (query)
                {
                case "login":
                    SendToClient(ref state, LoginServerMessages.SendProof(ref state, keyValues));
                    Users[state.ProfileId] = state;
                    state.StartKeepAlive(this);

                    break;

                case "newuser":
                    SendToClient(ref state, LoginServerMessages.NewUser(ref state, keyValues));
                    break;

                case "addbuddy":
                    // \\addbuddy\\\\sesskey\\51437\\newprofileid\\1\\reason\\just be my friend

                    var newFriendId = long.Parse(keyValues["newprofileid"]);

                    if (Database.MainDBInstance.AddFriend(state.ProfileId, newFriendId))
                    {
                        //var signature = (state.ProfileId.ToString() + newFriendId.ToString()).ToMD5();
                        // "\\bm\\%d\\f\\%d\\msg\\%s|signed|%s",GPI_BM_REQUEST,profileid,reason,signature);
                        //SendToClient(ref state, $@"\bm\2\f\{newFriendId}\msg\{keyValues["reason"]}|signed|{signature}".ToAssciiBytes());

                        if (Users.TryGetValue(newFriendId, out LoginSocketState friendState))
                        {
                            SendToClient(ref friendState, $@"\bm\100\f\{state.ProfileId}\msg\|s|{state.Status}{state.GetLSParameter()}|ss|{state.StatusString}\final\".ToAssciiBytes());
                            SendToClient(ref state, $@"\bm\100\f\{newFriendId}\msg\|s|{friendState.Status}{friendState.GetLSParameter()}|ss|{friendState.StatusString}\final\".ToAssciiBytes());
                        }
                        else
                        {
                            SendToClient(ref state, $@"\bm\100\f\{newFriendId}\msg\|s|0|ss|Offline\final\".ToAssciiBytes());
                        }
                    }
                    break;

                case "delbuddy":
                    // \delbuddy\\sesskey\51437\delprofileid\1
                    Database.MainDBInstance.RemoveFriend(state.ProfileId, long.Parse(keyValues["delprofileid"]));
                    break;

                case "getprofile":
                    SendToClient(ref state, LoginServerMessages.SendProfile(ref state, keyValues));
                    break;

                case "updatepro":
                    //LoginServerMessages.UpdateProfile(ref state, keyValues);
                    break;

                case "status":

                    var remoteEndPoint = ((IPEndPoint)state.Socket.RemoteEndPoint);

                    var profile = Database.MainDBInstance.GetProfileById(state.ProfileId);

                    if (profile == null)
                    {
                        return;
                    }

                    var friends = profile.Friends ?? new List <long>();

                    SendToClient(ref state, $@"\bdy\{friends.Count + 1}\list\{string.Join(",",friends.Concat(new long[] { profile.Id }))}\final\".ToAssciiBytes());

                    // var loopbackIp = (uint)IPAddress.NetworkToHostOrder((int)IPAddress.Loopback.Address);
                    // var loopbackIp = ReverseEndian32((uint)IPAddress.NetworkToHostOrder((int)IPAddress.Parse("192.168.159.128").Address));
                    // var port = ReverseEndian16(27900);

                    state.Status       = keyValues.GetOrDefault("status") ?? state.Status ?? "0";
                    state.StatusString = keyValues.GetOrDefault("statstring") ?? state.StatusString ?? "Offline";
                    state.LocString    = keyValues.GetOrDefault("locstring") ?? state.LocString ?? "-1";

                    //SendToClient(ref state, $@"\bm\100\f\{profile.Id}\msg\|s|{1}|ss|DXP{"|ls|"}{-1}|ip|{loopbackIp}|p|{port}|qm|{0}\final\".ToAssciiBytes());

                    var statusResult = $@"\bm\100\f\{profile.Id}\msg\|s|{state.Status}{state.GetLSParameter()}|ss|{state.StatusString}\final\".ToAssciiBytes();
                    SendToClient(ref state, statusResult);

                    for (int i = 0; i < friends.Count; i++)
                    {
                        var friendId = friends[i];

                        if (Users.TryGetValue(friendId, out LoginSocketState friendState))
                        {
                            SendToClient(ref friendState, statusResult);
                            //SendToClient(ref state, $@"\bm\100\f\{friendId}\msg\|s|{1}|ss|DXP|ls|-1\final\".ToAssciiBytes());
                            SendToClient(ref state, $@"\bm\100\f\{friendId}\msg\|s|{friendState.Status}{friendState.GetLSParameter()}|ss|{friendState.StatusString}\final\".ToAssciiBytes());
                        }
                        else
                        {
                            SendToClient(ref state, $@"\bm\100\f\{friendId}\msg\|s|0|ss|Offline\final\".ToAssciiBytes());
                        }
                    }

                    // \status\1\sesskey\17562\statstring\DXP\locstring\-1

                    // userid\200000003\profileid\100000003\uniquenick\Bambochuk

                    //sendBuddies()
                    // SendToClient(ref state, $@"\bdy\1\list\100000003\final\".ToAssciiBytes());
                    //SendToClient(ref state, $@"\bdy\0\list\\final\".ToAssciiBytes());

                    // TODO: sendAddRequests();

                    //sendStatusUpdateToBuddies(this);

                    // send self status
                    // |s|%d|ss|%s%s%s|ip|%d|p|%d|qm|%d

                    /*
                     * c->status,
                     *      c->statusstr,
                     *      c->locstr[0] != 0 ? "|ls|" : "",
                     *      c->locstr,
                     *      reverse_endian32(c->ip),
                     *      reverse_endian16(c->port),
                     *      c->quietflags
                     */

                    // SendToClient(ref state, $@"\bm\100\f\100000003\msg\|s|{2}|ss|DXP{"|ls|"}{-1}|ip|{(uint)IPAddress.NetworkToHostOrder((int)IPAddress.Loopback.Address)}|p|{ReverseEndian16(6500)}|qm|{0}\final\".ToAssciiBytes());
                    //SendToClient(ref state, $@"\bm\100\f\100000002\msg\|s|0|ss|Offline\final\".ToAssciiBytes());
                    //SendToClient(ref state, $@"\bm\100\f\100000001\msg\|s|{1}|ss|DXP{"|ls|"}{-1}|ip|{(uint)IPAddress.NetworkToHostOrder((int)remoteEndPoint.Address.Address)}|p|{ReverseEndian16(6500)}|qm|{0}\final\".ToAssciiBytes());



                    // send friend status



                    break;

                case "logout":
                    Users.TryRemove(state.ProfileId, out LoginSocketState removingState);
                    LoginServerMessages.Logout(ref state, keyValues);
                    break;

                case "registernick":
                    SendToClient(ref state, DataFunctions.StringToBytes(string.Format(@"\rn\{0}\id\{1}\final\", keyValues["uniquenick"], keyValues["id"])));
                    break;

                case "ka":
                    SendToClient(ref state, $@"\ka\\final\".ToAssciiBytes());
                    break;

                default:
                    break;
                }
            }
        }