private void TryEstablishConnection( )
        {
            if (null == TcpClient)
            {
                TcpClient = new TcpClient( );
            }

            while (EndPointEnumerator.MoveNext( ))
            {
                CurrentEndPoint = EndPointEnumerator.Current;
                Debug.Print("ServerConnector.TryEstablishConnection: trying {0}", CurrentEndPoint);
                OnConnectionAttemptStarted(CurrentEndPoint);

                try {
                    TcpClient.BeginConnect(CurrentEndPoint.Address, CurrentEndPoint.Port, ConnectCallback, null);
                    return;
                }
                catch (NotSupportedException e) {
                    Debug.Print("ServerConnector.TryEstablishConnection: TcpClient.BeginConnect: caught NotSupportedException:\n{0}", e);
                }
                catch (Exception e) {
                    Debug.Print("ServerConnector.TryEstablishConnection: TcpClient.BeginConnect: caught exception:\n{0}", e);
                }
            }

            if (null != TcpClient)
            {
                SocketRegistry.Unregister(TcpClient.Client.LocalEndPoint as IPEndPoint);
                TcpClient.Close( );
                TcpClient = null;
            }

            EndPointEnumerator.Dispose( );
            EndPoints = null;

            OnConnectionFailed(new Exception("Ran out of IP addresses and ports to try."));
        }
        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( ));
            }
        }