static void Main(string[] args) { if (File.Exists("database.db")) { m_Database = new SQLDatabase("database.db", true); m_LoginsTable = m_Database.getLoginTable("logins"); m_UserTable = m_Database.getUsersTable("users"); m_IDTable = m_Database.getIdTable("ID"); } else { m_Database = new SQLDatabase("database.db"); m_LoginsTable = m_Database.addLoginTable("logins", "name varchar(20) NOT NULL, " + "passwordHash varchar(512) NOT NULL, " + "passwordSalt varchar(512) NOT NULL, " + "passwordRenewalDate varchar(128) NOT NULL, " + "isLoggedIn varchar(8), " + "id int NOT NULL"); m_UserTable = m_Database.addUsersTable("users", "name varchar(24) NOT NULL, " + "id int NOT NULL, " + "securityLevel int NOT NULL"); m_IDTable = m_Database.addIDTable("ID", "name varchar(24) NOT NULL, " + "nextID int"); m_LoginsTable.AddEntry(new string[] { "admin", "J1NF8m6ZRuDcx/5038/xP/zVdHPwg2YEdpOZvEVRFCw=", "IxBicNFzHtBa5GBFOuZTatjPTmVvgQ0JQ5NHwp+BOTI=", DateTime.MaxValue.Date.ToShortDateString(), "false", "0" }); m_UserTable.AddEntry(new string[] { "admin", "0", "999" }); m_IDTable.AddIDEntry("next", 1); } controls = new Controls(m_UserTable, m_LoginsTable); Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // Local address serverSocket.Bind(new IPEndPoint(IPAddress.Parse(serverIPAddress), 8500)); serverSocket.Listen(32); bool bQuit = false; Console.WriteLine("This is the server!"); while (!bQuit) { // When there is a new connection, create a new socket reference Socket serverClient = serverSocket.Accept(); // Start a new thread assigned to this socket Thread myThread = new Thread(ReceiveClientProcess); myThread.Start(serverClient); Thread.Sleep(500); // Perform any new connection actions. Log timestamp etc } }
static void ReceiveClientProcess(Object _socket) { bool bQuit = false; Socket clientSocket = (Socket)_socket; Console.WriteLine("client receive new user thread"); String sendMsg = ""; while (bQuit == false) { try { byte[] buffer = new byte[4096]; int result; result = clientSocket.Receive(buffer); if (result > 0) { MemoryStream stream = new MemoryStream(buffer); BinaryReader read = new BinaryReader(stream); Msg message = Msg.DecodeStream(read); if (message != null) { Console.Write("Client action: " + clientSocket + ": " + message.ToString() + "\r\n"); switch (message.mID) { case ActionMsg.ID: { ActionMsg actionMessage = (ActionMsg)message; String formattedMsg = actionMessage.msg; String clientName = GetNameFromSocket(clientSocket); lock (m_UserSocketDictionary) { String thisUserName = GetNameFromSocket(clientSocket); sendMsg = controls.Update(clientName, formattedMsg); Console.WriteLine(sendMsg); try { if (sendMsg.Substring(0, 23) == "<AuthenticateRequested>") { SendLoginMessage(clientSocket, "AuthenticateRequested"); break; } } catch { } // If sendMsg conditions have not returned true for any of the above specific cases, then send the message back to the player socket SendActionMessage(clientSocket, "", sendMsg); } } break; case CreateNewUserMsg.ID: { CreateNewUserMsg createNewUserMessage = (CreateNewUserMsg)message; String newLoginInfo = createNewUserMessage.msg; // Safe to split with this as no spaces allowed in username or password String[] processedLoginInfo = newLoginInfo.Split(' '); // If length == 1 then the client is performing a username availability check on the database if (processedLoginInfo.Length == 1) { if (m_LoginsTable.queryExists(processedLoginInfo[0], "name")) { SendNewUserMessage(clientSocket, "NameTaken"); } else { SendNewUserMessage(clientSocket, "NameAvailable"); } } else { // The position of the user name in the message String userName = processedLoginInfo[0]; // Someone else may have taken the userName since it was checked last so do one more quick check if (m_LoginsTable.queryExists(userName, "name")) { SendNewUserMessage(clientSocket, "NameTaken"); } else { // Tells the client to close it's 'registerNewUser' window SendNewUserMessage(clientSocket, "Success"); // Get the unique id first so as to use the same ID in the user table and the login table to link them together String uniqueID = GetNextUniqueID().ToString(); // Add the new user details to the logins table m_LoginsTable.AddEntry(new string[] { // Starting values userName, // name processedLoginInfo[1], // password processedLoginInfo[2], // salt DateTime.Today.AddMonths(passwordRenewalNumberOfMonths).ToShortDateString(), // password renewal date "false", // is logged in uniqueID // Id (not currently used as each name is unique) }); // Add the new user details to the users table m_UserTable.AddEntry(new string[] { userName, // name uniqueID, // Id (the same one as used in the login table) "0" // Security level }); } } } break; case LoginMsg.ID: LoginMsg loginAttempt = (LoginMsg)message; String loginAttemptMessage = loginAttempt.msg; String[] processedLoginMessage = loginAttemptMessage.Split(' '); // The position of the user name in the message String submittedUserName = processedLoginMessage[0]; // First check is whether the logins table contains a record of this username if (!m_LoginsTable.queryExists(submittedUserName, "name")) { SendLoginMessage(clientSocket, "LoginFailed"); } // Else if client is requesting salt else if (processedLoginMessage[1] == "RequestSalt") { if (true) //m_LoginsTable.getStringFieldFromName(submittedUserName, "isLoggedIn") == "false") { String salt = m_LoginsTable.getStringFieldFromName(submittedUserName, "passwordSalt"); SendLoginMessage(clientSocket, "Salt " + salt); } else { SendLoginMessage(clientSocket, "UserAlreadyLoggedIn"); } } else { DateTime.TryParse(m_LoginsTable.getStringFieldFromName(submittedUserName, "passwordRenewalDate"), out DateTime dtRenewDate); if (DateTime.Today.CompareTo(dtRenewDate) >= 0) { SendUpdatePasswordMessage(clientSocket, "UpdatePasswordRequired"); break; } // Get the database copy of the hashed salted password String databaseHash = m_LoginsTable.getStringFieldFromName(submittedUserName, "passwordHash"); // Compare against the hashed salted password sent in the login message if (processedLoginMessage[1] == databaseHash) { SendLoginMessage(clientSocket, "LoginAccepted"); m_UserSocketDictionary[submittedUserName] = clientSocket; m_LoginsTable.setFieldFromName(submittedUserName, "true", "isLoggedIn"); // Initial message to client SendActionMessage(clientSocket, "", "Welcome user"); } else { SendLoginMessage(clientSocket, "LoginFailed"); } } break; case UpdatePasswordMsg.ID: { UpdatePasswordMsg UpdatePasswordMsg = (UpdatePasswordMsg)message; String updatePasswordInfo = UpdatePasswordMsg.msg; String[] processedPasswordInfo = updatePasswordInfo.Split(' '); // Add the new user details to the logins table m_LoginsTable.UpdatePassword(new string[] { // Starting values processedPasswordInfo[0], // name processedPasswordInfo[1], // password processedPasswordInfo[2], // salt DateTime.Today.AddMonths(passwordRenewalNumberOfMonths).ToShortDateString(), // password renewal date }); // Tells the client to close it's window SendUpdatePasswordMessage(clientSocket, "SuccessUpdatedPassword"); } break; case LogoutMsg.ID: throw new Exception(); } } } } // Remove user from process catch (Exception) { bQuit = true; String output = "Lost client: " + GetNameFromSocket(clientSocket); Console.WriteLine(output); // Log user disconnected? // Try to adjust the isLoggedIn field as the client may disconnect before they have logged in successfully try { // Allow the client to log back in if disconnected m_LoginsTable.setFieldFromName(GetNameFromSocket(clientSocket), "false", "isLoggedIn"); } catch { } lock (m_UserSocketDictionary) { try { // Sanity check, then remove player information from playerDictionary if (m_UserSocketDictionary.ContainsKey(GetNameFromSocket(clientSocket))) { m_UserSocketDictionary.Remove(GetNameFromSocket(clientSocket)); } } catch (Exception) { } } // Log action? } } }