/// <summary> /// The server socket listener thread. Creates the server socket, creates the /// idle timeout Timer then loops accepting connections. When a client connects, /// creates the Session, optionally enables SSL/TLS 1.2, caches the Session and /// begins an asynchronous socket read operation. /// </summary> private void Run() { try { socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.ReceiveTimeout = ServerConfiguration.ReceiveTimeoutInMS; socket.SendTimeout = ServerConfiguration.SendTimeoutInMS; if (string.IsNullOrEmpty(ServerConfiguration.Host)) ServerConfiguration.Host = ServerConfiguration.DEFAULT_BIND_ADDRESS; socket.Bind(new IPEndPoint(IPAddress.Parse(ServerConfiguration.Host), ServerConfiguration.Port)); socket.Listen(64);//config value Logger.Log(Level.Info, string.Format("Listening on {0}:{1}...", ServerConfiguration.Host, ServerConfiguration.Port)); idleTimeoutTimer = new Timer(IdleTimeOutTimerCallback, null, TIMER_INTERVAL, TIMER_INTERVAL); while (!signalClose) { Socket client = socket.Accept(); string address = ((IPEndPoint)client.RemoteEndPoint).Address.ToString(); Session session = new Session( new NetworkStream(client), address, ServerConfiguration.TlsConfiguration, ProtocolConfigurations, Logger, UserData); if (ServerConfiguration.TlsConfiguration != null && ServerConfiguration.TlsConfiguration.Enabled) EnableTls(session); session.Log(Level.Info, "Connected."); lock (sessions) sessions.Add(session); session.BeginRead(); if (signalClose) break; } } catch (SocketException ex) { if (!signalClose) Logger.Log(Level.Error, ex.Message); } catch (Exception ex) { Logger.Log(Level.Error, ex.Message); } }
/// <summary> /// Connects to the server, creates a Session, optionally enables SSL/TLS 1.2 /// and begins an asynchronous socket read operation. /// </summary> public void Connect() { Close(); Logger.Log(Level.Info, string.Format("Connecting to {0}:{1}...", ServerConfiguration.Host, ServerConfiguration.Port)); Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); server.ReceiveTimeout = ServerConfiguration.ReceiveTimeoutInMS; server.SendTimeout = ServerConfiguration.SendTimeoutInMS; server.LingerState = new LingerOption(true, 10); server.NoDelay = true; if (string.IsNullOrEmpty(ServerConfiguration.Host)) ServerConfiguration.Host = ServerConfiguration.DEFAULT_HOST; server.Connect(ServerConfiguration.Host, ServerConfiguration.Port); string address = ((IPEndPoint)server.RemoteEndPoint).Address.ToString(); session = new Session( new NetworkStream(server), address, ServerConfiguration.TlsConfiguration, ProtocolConfigurations, Logger, UserData); session.OnConnectionLost += session_OnConnectionLost; if (ServerConfiguration.TlsConfiguration != null && ServerConfiguration.TlsConfiguration.Enabled) EnableTls(); Logger.Log(Level.Info, string.Format("Connected to {0}:{1}.", ServerConfiguration.Host, ServerConfiguration.Port)); session.BeginRead(); }
/// <summary> /// Enables SSL/TLS 1.2. /// </summary> /// <remarks> Registers the <see cref="Session.TlsCertificateValidationCallback"/> /// and <see cref="Session.TlsCertificateSelectionCallback"/> with the /// SslStream then authenticates the connection. </remarks> /// <param name="session">The Session object to enable TLS.</param> private void EnableTls(Session session) { RemoteCertificateValidationCallback validationCallback = new RemoteCertificateValidationCallback(session.TlsCertificateValidationCallback); LocalCertificateSelectionCallback selectionCallback = new LocalCertificateSelectionCallback(session.TlsCertificateSelectionCallback); SslStream sslStream = new SslStream( session.Stream, true, validationCallback, selectionCallback, EncryptionPolicy.AllowNoEncryption); session.Stream = sslStream; ((SslStream)session.Stream).AuthenticateAsServer( certificate, ServerConfiguration.TlsConfiguration.RequireRemoteCertificate, SslProtocols.Ssl3 | SslProtocols.Tls, ServerConfiguration.TlsConfiguration.CheckCertificateRevocation); }
/// <summary> /// Closes the <see cref="Session"/>. /// </summary> public void Close() { if (session != null) { session.Close(); session = null; } }