public void sendNewPasswordInfo(String newPasswordInfoString)
        {
            UpdatePasswordMsg updatePasswordMsg = new UpdatePasswordMsg();

            updatePasswordMsg.msg = newPasswordInfoString;
            MemoryStream outStream = updatePasswordMsg.WriteData();

            m_Server.Send(outStream.GetBuffer());
        }
        static void SendUpdatePasswordMessage(Socket _s, String _msg)
        {
            UpdatePasswordMsg updatePasswordMsg = new UpdatePasswordMsg();

            updatePasswordMsg.msg = _msg;
            MemoryStream outStream = updatePasswordMsg.WriteData();

            try
            {
                _s.Send(outStream.GetBuffer());
            }
            catch (System.Exception) { }
        }
        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?
                }
            }
        }
        /*
         * Receive messages from the server
         */
        static void clientReceive(Object o)
        {
            Form1 form = (Form1)o;

            while (form.m_Connected == true)
            {
                try
                {
                    byte[] buffer = new byte[4096];

                    if (form.m_Server.Receive(buffer) > 0)
                    {
                        MemoryStream stream = new MemoryStream(buffer);
                        BinaryReader read   = new BinaryReader(stream);

                        Msg m = Msg.DecodeStream(read);

                        if (m != null)
                        {
                            switch (m.mID)
                            {
                            case ClientNameMsg.ID:
                            {
                                ClientNameMsg clientName = (ClientNameMsg)m;
                                form.SetClientName(clientName.name);
                            }
                            break;

                            case ActionMsg.ID:
                            {
                                ActionMsg actionMessage = (ActionMsg)m;
                                form.AddActionText(actionMessage.msg);
                            }
                            break;

                            case LoginMsg.ID:
                            {
                                LoginMsg recievedLoginMsg = (LoginMsg)m;
                                switch (recievedLoginMsg.msg.Split(' ')[0])
                                {
                                case "LoginAccepted":
                                    m_MainForm.Invoke(new MethodInvoker(delegate()
                                        {
                                            m_LoginForm.Close();
                                            m_MainForm.Enabled = true;
                                            m_MainForm.Show();
                                            m_MainForm.WindowState = FormWindowState.Normal;
                                        }));

                                    break;

                                case "LoginFailed":
                                    m_MainForm.Invoke(new MethodInvoker(delegate()
                                        {
                                            // Clear text boxes and display error message
                                            m_LoginForm.ClearTextBoxes("Incorrect login details");
                                        }));
                                    break;

                                case "UserAlreadyLoggedIn":
                                    m_MainForm.Invoke(new MethodInvoker(delegate()
                                        {
                                            // Clear text boxes and display error message
                                            m_LoginForm.ClearTextBoxes("User logged in already");
                                        }));
                                    break;

                                case "AuthenticateRequested":
                                    m_MainForm.Invoke(new MethodInvoker(delegate()
                                        {
                                            m_MainForm.ReenterLoginDetails();
                                        }));
                                    break;

                                case "Salt":
                                    // If not one of the above confirm/deny strings then the message is the password salt sent back from the server in order to compare password hashs.
                                    Byte[] salt = Convert.FromBase64String(recievedLoginMsg.msg.Split(' ')[1]);

                                    m_MainForm.Invoke(new MethodInvoker(delegate()
                                        {
                                            // Handing the salt back to the login form as we don't want to store the plaintext password anywhere, it is only ever read from the password box
                                            m_LoginForm.logInWithSaltedHash(salt);
                                        }));
                                    break;
                                }
                            }
                            break;

                            case CreateNewUserMsg.ID:
                            {
                                // Returned through new user creation process
                                CreateNewUserMsg recievedNameCheck = (CreateNewUserMsg)m;
                                switch (recievedNameCheck.msg)
                                {
                                case "NameAvailable":
                                    m_MainForm.Invoke(new MethodInvoker(delegate()
                                        {
                                            m_RegisterNewUserForm.UserNameAccepted();
                                        }));
                                    break;

                                case "NameTaken":
                                    m_MainForm.Invoke(new MethodInvoker(delegate()
                                        {
                                            m_RegisterNewUserForm.UserNameRejected();
                                        }));
                                    break;

                                case "Success":
                                    m_MainForm.Invoke(new MethodInvoker(delegate()
                                        {
                                            m_RegisterNewUserForm.Close();
                                        }));
                                    break;
                                }
                            }
                            break;

                            case UpdatePasswordMsg.ID:
                            {
                                UpdatePasswordMsg updatePasswordMsg = (UpdatePasswordMsg)m;
                                switch (updatePasswordMsg.msg)
                                {
                                case "UpdatePasswordRequired":
                                    m_MainForm.Invoke(new MethodInvoker(delegate()
                                        {
                                            m_MainForm.OpenUpdatePasswordForm();
                                        }));
                                    break;

                                case "SuccessUpdatedPassword":
                                    m_MainForm.Invoke(new MethodInvoker(delegate()
                                        {
                                            m_UpdatePasswordForm.Close();
                                        }));
                                    break;
                                }
                            }
                            break;
                            }
                        }
                    }
                }
                catch (Exception)
                {
                    form.m_Connected = false;
                    Console.WriteLine("Lost connection.");
                    try
                    {
                        m_MainForm.Enabled = false;

                        // if the login window is closed
                        if (m_LoginForm.Visible == false)
                        {
                            m_LoginForm.ShowDialog();
                        }

                        m_MainForm.Invoke(new MethodInvoker(delegate()
                        {
                            m_LoginForm.showDisconnectedMessage();
                            m_MainForm.Hide();
                        }));
                    }
                    catch { }
                }
            }
            Application.Restart();
        }