private void FinishConnection( Stream stream )
        {
            Debug.Print( "ServerConnector.FinishConnection" );
            try {
                _protocolHandler.ConnectionReady( stream );
                _protocolHandler = null;
                TcpClient = null;

                var server = _server;
                _server = null;
                OnConnectionEstablished( server );
            }
            catch ( Exception e ) {
                Debug.Print( "ServerConnector.FinishConnection: caught exception:\n{0}", e );
            }
        }
        private void ConnectCallback( IAsyncResult ar )
        {
            bool retry = false;
            try {
                TcpClient.EndConnect( ar );
            }
            catch ( SocketException e ) {
                Debug.Print( "ServerConnector.ConnectCallback: TcpClient.EndConnect: caught SocketException, error code {0}:\n{1}", e.ErrorCode, e );
                OnConnectionAttemptFailed( CurrentEndPoint, e );
                retry = true;
            }
            catch ( Exception e ) {
                Debug.Print( "ServerConnector.ConnectCallback: TcpClient.EndConnect: caught exception:\n{0}", e );
                OnConnectionAttemptFailed( CurrentEndPoint, e );
                retry = true;
            }

            if ( retry ) {
                TryEstablishConnection( );
                return;
            }

            EndPointEnumerator.Dispose( );
            EndPoints = null;

            Debug.Print( "ServerConnector.ConnectCallback: Connected!" );
            SocketRegistry.Register( TcpClient.Client.LocalEndPoint as IPEndPoint, TcpClient.Client.RemoteEndPoint as IPEndPoint );

            Debug.Print( "ServerConnector.ConnectCallback: Constructing objects." );

            var selfUser = new SelfUser {
                NickName = Configuration.NickName,
                HostName = Configuration.LocalHostName,
                RealHostName = Configuration.LocalHostName,
                RealName = Configuration.RealName,
                UserName = Configuration.UserName,
                NickServUserName = Configuration.NickServUserName,
                NickServPassword = Configuration.NickServPassword,
            };

            _server = new Server {
                ServerEndPoint = CurrentEndPoint,
                SelfUser = selfUser,
                ServerHostName = Configuration.ServerHostName,
                ServerPassword = Configuration.Password,
            };
            _protocolHandler = new ProtocolHandler {
                TcpClient = TcpClient,
                SelfUser = selfUser,
                Server = _server,
            };
            _server.ProtocolHandler = _protocolHandler;

            selfUser.Server = _server;

            if ( CurrentEndPoint.UseSsl ) {
                Debug.Print( "ServerConnector.ConnectCallback: Starting SSL." );
                _sslStream = new SslStream( TcpClient.GetStream( ), true, ServerCertificateValidationCallback, LocalCertificateSelectionCallback, EncryptionPolicy.RequireEncryption );
                try {
                    _sslStream.BeginAuthenticateAsClient( Configuration.ServerHostName, CertificateCollection, SslProtocols.Default, true, AuthenticateAsClientCallback, null );
                }
                catch ( Exception e ) {
                    Debug.Print( "ServerConnector.ConnectCallback: Caught exception calling BeginAuthenticateAsClient:\n{0}", e );
                    throw;
                }
            } else {
                FinishConnection( TcpClient.GetStream( ) );
            }
        }
        private void ConnectCallback(IAsyncResult ar)
        {
            bool retry = false;

            try {
                TcpClient.EndConnect(ar);
            }
            catch (SocketException e) {
                Debug.Print("ServerConnector.ConnectCallback: TcpClient.EndConnect: caught SocketException, error code {0}:\n{1}", e.ErrorCode, e);
                OnConnectionAttemptFailed(CurrentEndPoint, e);
                retry = true;
            }
            catch (Exception e) {
                Debug.Print("ServerConnector.ConnectCallback: TcpClient.EndConnect: caught exception:\n{0}", e);
                OnConnectionAttemptFailed(CurrentEndPoint, e);
                retry = true;
            }

            if (retry)
            {
                TryEstablishConnection( );
                return;
            }

            EndPointEnumerator.Dispose( );
            EndPoints = null;

            Debug.Print("ServerConnector.ConnectCallback: Connected!");
            SocketRegistry.Register(TcpClient.Client.LocalEndPoint as IPEndPoint, TcpClient.Client.RemoteEndPoint as IPEndPoint);

            Debug.Print("ServerConnector.ConnectCallback: Constructing objects.");

            var selfUser = new SelfUser {
                NickName         = Configuration.NickName,
                HostName         = Configuration.LocalHostName,
                RealHostName     = Configuration.LocalHostName,
                RealName         = Configuration.RealName,
                UserName         = Configuration.UserName,
                NickServUserName = Configuration.NickServUserName,
                NickServPassword = Configuration.NickServPassword,
            };

            _server = new Server {
                ServerEndPoint = CurrentEndPoint,
                SelfUser       = selfUser,
                ServerHostName = Configuration.ServerHostName,
                ServerPassword = Configuration.Password,
            };
            _protocolHandler = new ProtocolHandler {
                TcpClient = TcpClient,
                SelfUser  = selfUser,
                Server    = _server,
            };
            _server.ProtocolHandler = _protocolHandler;

            selfUser.Server = _server;

            if (CurrentEndPoint.UseSsl)
            {
                Debug.Print("ServerConnector.ConnectCallback: Starting SSL.");
                _sslStream = new SslStream(TcpClient.GetStream( ), true, ServerCertificateValidationCallback, LocalCertificateSelectionCallback, EncryptionPolicy.RequireEncryption);
                try {
                    _sslStream.BeginAuthenticateAsClient(Configuration.ServerHostName, CertificateCollection, SslProtocols.Default, true, AuthenticateAsClientCallback, null);
                }
                catch (Exception e) {
                    Debug.Print("ServerConnector.ConnectCallback: Caught exception calling BeginAuthenticateAsClient:\n{0}", e);
                    throw;
                }
            }
            else
            {
                FinishConnection(TcpClient.GetStream( ));
            }
        }
        protected virtual void Dispose( bool disposing )
        {
            if ( disposing ) {
                ConnectionAttemptStarted = null;
                ConnectionAttemptFailed = null;
                ConnectionFailed = null;
                ConnectionEstablished = null;

                EndPoints = null;
                IPAddresses = null;
                CurrentEndPoint = null;
                CertificateCollection = null;
                Configuration = null;

                if ( null != EndPointEnumerator ) {
                    EndPointEnumerator.Dispose( );
                    EndPointEnumerator = null;
                }
                if ( null != TcpClient ) {
                    TcpClient.Close( );
                    TcpClient = null;
                }
                if ( null != _protocolHandler ) {
                    _protocolHandler.Dispose( );
                    _protocolHandler = null;
                }
                if ( null != _sslStream ) {
                    _sslStream.Dispose( );
                    _sslStream = null;
                }
            }
        }
        private void ConnectionEstablished( object sender, ConnectionEstablishedEventArgs ev ) {
            Console.WriteLine( "ConsoleHarness: ConnectionEstablished:" );
            Console.WriteLine( "+ remote end point: {0}", ev.Server.ServerEndPoint );
            Console.WriteLine( );

            _serverConnector = null;

            _server = ev.Server;
            _protocolHandler = _server.ProtocolHandler;
            _selfUser = _server.SelfUser;

            _selfUser.Error += HandleError;
            _selfUser.Quit += HandleSelfQuit;
            _server.Registered += HandleRegistered;
            _server.MotdComplete += HandleMotdComplete;

            _connected = true;
        }