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)); }
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; } }
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; } }
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); }
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(); } }
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()))); }
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(); } }
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(); } }
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))); } }
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; } } }