/// <summary> /// Runs on a new client connection, and sets a client id and adds to list of clients. /// </summary> /// <param name="asyncResult">Result from connection containing socket to client</param> public static void ClientConnectCallback(IAsyncResult asyncResult) { try { Socket clientSocket = Globals.Listener.EndAccept(asyncResult); NetworkStream networkStream = new NetworkStream(clientSocket); SslStream sslStream = new SslStream(networkStream, false); // Authenticate the server but don't require the client to authenticate. try { sslStream.AuthenticateAsServer(Globals.ServerCertificate, false, true); // Display the properties and settings for the authenticated stream. HelperMethods.DisplaySecurityLevel(sslStream); HelperMethods.DisplaySecurityServices(sslStream); HelperMethods.DisplayCertificateInformation(sslStream); HelperMethods.DisplayStreamProperties(sslStream); // Set timeouts to 5 seconds. sslStream.ReadTimeout = 5000; sslStream.WriteTimeout = 5000; } catch (AuthenticationException e) { Console.WriteLine($"Exception: {e.Message}"); if (e.InnerException != null) { Console.WriteLine($"Inner exception: {e.InnerException.Message}"); } Console.WriteLine("Authentication failed - closing the connection."); sslStream.Close(); clientSocket.Close(); Globals.Listener.BeginAccept(ClientConnectCallback, null);// keep listening return; } catch (Exception e) { Console.WriteLine($"Exception: {e.Message}"); sslStream.Close(); clientSocket.Close(); Globals.Listener.BeginAccept(ClientConnectCallback, null);// keep listening return; } byte[] clientId = new byte[10]; Globals.Random.NextBytes(clientId); string idString = clientId.Aggregate("", (current, idByte) => current + idByte); // Keep trying until we get a username that isn't taken while (HelperMethods.UsernameTaken(idString)) { Globals.Random.NextBytes(clientId); idString = clientId.Aggregate("", (current, idByte) => current + idByte); } ClientInfo newClient = new ClientInfo(clientSocket, sslStream, networkStream); newClient.SetUsername(idString);// Set the default username to the randomly generated byte id Globals.ClientList.Add(newClient); Console.WriteLine($"Client {newClient.GetUsername()} connected"); newClient.BeginReceiveData(); Globals.Listener.BeginAccept(ClientConnectCallback, null); } catch (ObjectDisposedException) { Console.WriteLine("ClientConnectCallback(): Object already disposed"); } catch (SocketException se) { Console.WriteLine(se.Message); } }