示例#1
0
        internal static TimeoutTimer StartSecondsTimeout(int seconds)
        {
            TimeoutTimer timer = new TimeoutTimer();

            timer.SetTimeoutSeconds(seconds);
            return(timer);
        }
示例#2
0
        //-------------------
        // Timeout-setting methods
        //-------------------

        // Get a new timer that will expire in the given number of seconds
        //  For input, a value of zero seconds indicates infinite timeout
        internal static TimeoutTimer StartSecondsTimeout(int seconds)
        {
            //--------------------
            // Preconditions: None (seconds must conform to SetTimeoutSeconds requirements)

            //--------------------
            // Method body
            var timeout = new TimeoutTimer();
            timeout.SetTimeoutSeconds(seconds);

            //---------------------
            // Postconditions
            Debug.Assert(timeout != null); // Need a valid timeouttimer if no error

            return timeout;
        }
示例#3
0
        //-------------------
        // Timeout-setting methods
        //-------------------

        // Get a new timer that will expire in the given number of seconds
        //  For input, a value of zero seconds indicates infinite timeout
        internal static TimeoutTimer StartSecondsTimeout(int seconds)
        {
            //--------------------
            // Preconditions: None (seconds must conform to SetTimeoutSeconds requirements)

            //--------------------
            // Method body
            var timeout = new TimeoutTimer();

            timeout.SetTimeoutSeconds(seconds);

            //---------------------
            // Postconditions
            Debug.Assert(timeout != null); // Need a valid timeouttimer if no error

            return(timeout);
        }
示例#4
0
        // Get a new timer that will expire in the given number of milliseconds
        //  No current need to support infinite milliseconds timeout
        internal static TimeoutTimer StartMillisecondsTimeout(long milliseconds)
        {
            //--------------------
            // Preconditions
            Debug.Assert(0 <= milliseconds);

            //--------------------
            // Method body
            var timeout = new TimeoutTimer();
            timeout._timerExpire = checked(ADP.TimerCurrent() + (milliseconds * TimeSpan.TicksPerMillisecond));
            timeout._isInfiniteTimeout = false;

            //---------------------
            // Postconditions
            Debug.Assert(timeout != null); // Need a valid timeouttimer if no error

            return timeout;
        }
示例#5
0
        // Get a new timer that will expire in the given number of milliseconds
        //  No current need to support infinite milliseconds timeout
        internal static TimeoutTimer StartMillisecondsTimeout(long milliseconds)
        {
            //--------------------
            // Preconditions
            Debug.Assert(0 <= milliseconds);

            //--------------------
            // Method body
            var timeout = new TimeoutTimer();

            timeout._timerExpire       = checked (ADP.TimerCurrent() + (milliseconds * TimeSpan.TicksPerMillisecond));
            timeout._isInfiniteTimeout = false;

            //---------------------
            // Postconditions
            Debug.Assert(timeout != null); // Need a valid timeouttimer if no error

            return(timeout);
        }
 private void AttemptOneLogin(ServerInfo serverInfo, string newPassword, bool ignoreSniOpenTimeout, TimeoutTimer timeout, SqlConnection owningObject)
 {
     if (Bid.AdvancedOn)
     {
         Bid.Trace("<sc.SqlInternalConnectionTds.AttemptOneLogin|ADV> %d#, timout=%I64d{msec}, server=", base.ObjectID, timeout.MillisecondsRemaining);
         Bid.PutStr(serverInfo.ExtendedServerName);
         Bid.Trace("\n");
     }
     this._routingInfo = null;
     this._parser._physicalStateObj.SniContext = SniContext.Snix_Connect;
     this._parser.Connect(serverInfo, this, ignoreSniOpenTimeout, timeout.LegacyTimerExpire, base.ConnectionOptions.Encrypt, base.ConnectionOptions.TrustServerCertificate, base.ConnectionOptions.IntegratedSecurity);
     this._parser._physicalStateObj.SniContext = SniContext.Snix_Login;
     this.Login(serverInfo, timeout, newPassword);
     this.CompleteLogin(!base.ConnectionOptions.Pooling);
 }
 private void LoginWithFailover(bool useFailoverHost, ServerInfo primaryServerInfo, string failoverHost, string newPassword, bool redirectedUserInstance, SqlConnection owningObject, SqlConnectionString connectionOptions, TimeoutTimer timeout)
 {
     long num5;
     if (Bid.AdvancedOn)
     {
         Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, useFailover=%d{bool}, primary=", base.ObjectID, useFailoverHost);
         Bid.PutStr(primaryServerInfo.UserServerName);
         Bid.PutStr(", failover=");
         Bid.PutStr(failoverHost);
         Bid.PutStr("\n");
     }
     int num = 100;
     string networkLibrary = base.ConnectionOptions.NetworkLibrary;
     ServerInfo serverInfo = new ServerInfo(connectionOptions, failoverHost);
     this.ResolveExtendedServerName(primaryServerInfo, !redirectedUserInstance, owningObject);
     if (this.ServerProvidedFailOverPartner == null)
     {
         this.ResolveExtendedServerName(serverInfo, !redirectedUserInstance && (failoverHost != primaryServerInfo.UserServerName), owningObject);
     }
     if (timeout.IsInfinite)
     {
         ADP.TimerFromSeconds(15);
         num5 = 0L;
     }
     else
     {
         num5 = (long) (0.08f * timeout.MillisecondsRemaining);
     }
     bool flag = false;
     int num2 = 0;
     while (true)
     {
         ServerInfo info2;
         long milliseconds = num5 * ((num2 / 2) + 1);
         long millisecondsRemaining = timeout.MillisecondsRemaining;
         if (milliseconds > millisecondsRemaining)
         {
             milliseconds = millisecondsRemaining;
         }
         TimeoutTimer timer = TimeoutTimer.StartMillisecondsTimeout(milliseconds);
         if (this._parser != null)
         {
             this._parser.Disconnect();
         }
         this._parser = new TdsParser(base.ConnectionOptions.MARS, base.ConnectionOptions.Asynchronous);
         if (useFailoverHost)
         {
             if (!flag)
             {
                 this.FailoverPermissionDemand();
                 flag = true;
             }
             if ((this.ServerProvidedFailOverPartner != null) && (serverInfo.ResolvedServerName != this.ServerProvidedFailOverPartner))
             {
                 if (Bid.AdvancedOn)
                 {
                     Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, new failover partner=%ls\n", base.ObjectID, this.ServerProvidedFailOverPartner);
                 }
                 serverInfo.SetDerivedNames(networkLibrary, this.ServerProvidedFailOverPartner);
             }
             info2 = serverInfo;
         }
         else
         {
             info2 = primaryServerInfo;
         }
         try
         {
             this.AttemptOneLogin(info2, newPassword, false, timer, owningObject);
             if (this._routingInfo != null)
             {
                 Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover> Routed to %ls", this._routingInfo.ServerName);
                 throw SQL.ROR_UnexpectedRoutingInfo();
             }
             break;
         }
         catch (SqlException exception)
         {
             if (this.IsDoNotRetryConnectError(exception) || timeout.IsExpired)
             {
                 throw;
             }
             if (base.IsConnectionDoomed)
             {
                 throw;
             }
             if ((1 == (num2 % 2)) && (timeout.MillisecondsRemaining <= num))
             {
                 throw;
             }
         }
         if (1 == (num2 % 2))
         {
             if (Bid.AdvancedOn)
             {
                 Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, sleeping %d{milisec}\n", base.ObjectID, num);
             }
             Thread.Sleep(num);
             num = (num < 500) ? (num * 2) : 0x3e8;
         }
         num2++;
         useFailoverHost = !useFailoverHost;
     }
     if (useFailoverHost && (this.ServerProvidedFailOverPartner == null))
     {
         throw SQL.InvalidPartnerConfiguration(failoverHost, base.CurrentDatabase);
     }
     if (this.PoolGroupProviderInfo != null)
     {
         this.PoolGroupProviderInfo.FailoverCheck(this, useFailoverHost, connectionOptions, this.ServerProvidedFailOverPartner);
     }
     base.CurrentDataSource = useFailoverHost ? failoverHost : primaryServerInfo.UserServerName;
 }
 private void LoginNoFailover(ServerInfo serverInfo, string newPassword, bool redirectedUserInstance, SqlConnection owningObject, SqlConnectionString connectionOptions, TimeoutTimer timeout)
 {
     int num2 = 0;
     ServerInfo info = serverInfo;
     if (Bid.AdvancedOn)
     {
         Bid.Trace("<sc.SqlInternalConnectionTds.LoginNoFailover|ADV> %d#, host=%ls\n", base.ObjectID, serverInfo.UserServerName);
     }
     int num = 100;
     this.ResolveExtendedServerName(serverInfo, !redirectedUserInstance, owningObject);
 Label_0032:
     if (this._parser != null)
     {
         this._parser.Disconnect();
     }
     this._parser = new TdsParser(base.ConnectionOptions.MARS, base.ConnectionOptions.Asynchronous);
     try
     {
         this.AttemptOneLogin(serverInfo, newPassword, true, timeout, owningObject);
         if (connectionOptions.MultiSubnetFailover && (this.ServerProvidedFailOverPartner != null))
         {
             bool serverProvidedFailoverPartner = true;
             throw SQL.MultiSubnetFailoverWithFailoverPartner(serverProvidedFailoverPartner);
         }
         if (this._routingInfo == null)
         {
             if (this.PoolGroupProviderInfo != null)
             {
                 this.PoolGroupProviderInfo.FailoverCheck(this, false, connectionOptions, this.ServerProvidedFailOverPartner);
             }
             base.CurrentDataSource = info.UserServerName;
             return;
         }
         Bid.Trace("<sc.SqlInternalConnectionTds.LoginNoFailover> Routed to %ls", serverInfo.ExtendedServerName);
         if (num2 > 0)
         {
             throw SQL.ROR_RecursiveRoutingNotSupported();
         }
         if (timeout.IsExpired)
         {
             throw SQL.ROR_TimeoutAfterRoutingInfo();
         }
         serverInfo = new ServerInfo(base.ConnectionOptions, this._routingInfo, serverInfo.ResolvedServerName);
         this._currentPacketSize = base.ConnectionOptions.PacketSize;
         this._currentLanguage = this._originalLanguage = base.ConnectionOptions.CurrentLanguage;
         base.CurrentDatabase = this._originalDatabase = base.ConnectionOptions.InitialCatalog;
         this._currentFailoverPartner = null;
         this._instanceName = string.Empty;
         num2++;
         goto Label_0032;
     }
     catch (SqlException exception)
     {
         if (((this._parser == null) || (this._parser.State != TdsParserState.Closed)) || (this.IsDoNotRetryConnectError(exception) || timeout.IsExpired))
         {
             throw;
         }
         if (timeout.MillisecondsRemaining <= num)
         {
             throw;
         }
     }
     if (this.ServerProvidedFailOverPartner != null)
     {
         if (connectionOptions.MultiSubnetFailover)
         {
             bool flag = true;
             throw SQL.MultiSubnetFailoverWithFailoverPartner(flag);
         }
         this.LoginWithFailover(true, serverInfo, this.ServerProvidedFailOverPartner, newPassword, redirectedUserInstance, owningObject, connectionOptions, timeout);
     }
     else
     {
         if (Bid.AdvancedOn)
         {
             Bid.Trace("<sc.SqlInternalConnectionTds.LoginNoFailover|ADV> %d#, sleeping %d{milisec}\n", base.ObjectID, num);
         }
         Thread.Sleep(num);
         num = (num < 500) ? (num * 2) : 0x3e8;
         goto Label_0032;
     }
 }
    // Common code path for making one attempt to establish a connection and log in to server.
    private void AttemptOneLogin(ServerInfo serverInfo, string newPassword, SecureString newSecurePassword, bool ignoreSniOpenTimeout, TimeoutTimer timeout, bool withFailover = false, bool isFirstTransparentAttempt = true) {
        if (Bid.AdvancedOn) {
            Bid.Trace("<sc.SqlInternalConnectionTds.AttemptOneLogin|ADV> %d#, timout=%I64d{msec}, server=", ObjectID, timeout.MillisecondsRemaining);
            Bid.PutStr(serverInfo.ExtendedServerName);
            Bid.Trace("\n");
        }

        _routingInfo = null; // forget routing information 

        _parser._physicalStateObj.SniContext = SniContext.Snix_Connect;

        _parser.Connect(serverInfo,
                        this,
                        ignoreSniOpenTimeout,
                        timeout.LegacyTimerExpire,
                        ConnectionOptions.Encrypt,
                        ConnectionOptions.TrustServerCertificate,
                        ConnectionOptions.IntegratedSecurity,
                        withFailover,
                        isFirstTransparentAttempt,
                        ConnectionOptions.Authentication);

        timeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.ConsumePreLoginHandshake);
        timeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.LoginBegin);

        _parser._physicalStateObj.SniContext = SniContext.Snix_Login;
        this.Login(serverInfo, timeout, newPassword, newSecurePassword);

        timeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.ProcessConnectionAuth);
        timeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.PostLogin);

        CompleteLogin(!ConnectionOptions.Pooling);

        timeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.PostLogin);
    }
        // although the new password is generally not used it must be passed to the c'tor
        // the new Login7 packet will always write out the new password (or a length of zero and no bytes if not present)
        //
        internal SqlInternalConnectionTds(
                DbConnectionPoolIdentity    identity, 
                SqlConnectionString         connectionOptions,
                SqlCredential               credential,
                object                      providerInfo, 
                string                      newPassword,
                SecureString                newSecurePassword,
                bool                        redirectedUserInstance,
                SqlConnectionString         userConnectionOptions = null, // NOTE: userConnectionOptions may be different to connectionOptions if the connection string has been expanded (see SqlConnectionString.Expand)
                SessionData                 reconnectSessionData = null,
                DbConnectionPool            pool = null,
                string                      accessToken = null,
                bool applyTransientFaultHandling = false
                ) : base(connectionOptions) {

#if DEBUG
            if (reconnectSessionData != null) {
                reconnectSessionData._debugReconnectDataApplied = true;
            }
            try { // use this to help validate this object is only created after the following permission has been previously demanded in the current codepath
                if (userConnectionOptions != null) {
                    // As mentioned above, userConnectionOptions may be different to connectionOptions, so we need to demand on the correct connection string
                    userConnectionOptions.DemandPermission();
                }
                else {
                    connectionOptions.DemandPermission();
                }
            }
            catch(System.Security.SecurityException) {
                System.Diagnostics.Debug.Assert(false, "unexpected SecurityException for current codepath");
                throw;
            }
#endif
            Debug.Assert(reconnectSessionData == null || connectionOptions.ConnectRetryCount > 0, "Reconnect data supplied with CR turned off");

            _dbConnectionPool = pool;
  
            if (connectionOptions.ConnectRetryCount > 0) {
                _recoverySessionData = reconnectSessionData;          
                if (reconnectSessionData == null) {
                    _currentSessionData = new SessionData();
                }
                else {
                    _currentSessionData = new SessionData(_recoverySessionData);
                    _originalDatabase = _recoverySessionData._initialDatabase;
                    _originalLanguage = _recoverySessionData._initialLanguage;
                }
            }
          
            if (connectionOptions.UserInstance && InOutOfProcHelper.InProc) {
                throw SQL.UserInstanceNotAvailableInProc();
            }

            if (accessToken != null) {
                _accessTokenInBytes = System.Text.Encoding.Unicode.GetBytes(accessToken);
            }

            _identity = identity;
            Debug.Assert(newSecurePassword != null || newPassword != null, "cannot have both new secure change password and string based change password to be null");
            Debug.Assert(credential == null || (String.IsNullOrEmpty(connectionOptions.UserID) && String.IsNullOrEmpty(connectionOptions.Password)), "cannot mix the new secure password system and the connection string based password");

            Debug.Assert(credential == null || !connectionOptions.IntegratedSecurity, "Cannot use SqlCredential and Integrated Security");
            Debug.Assert(credential == null || !connectionOptions.ContextConnection, "Cannot use SqlCredential with context connection");

            _poolGroupProviderInfo = (SqlConnectionPoolGroupProviderInfo)providerInfo;
            _fResetConnection = connectionOptions.ConnectionReset;
            if (_fResetConnection && _recoverySessionData == null) {
                _originalDatabase = connectionOptions.InitialCatalog;
                _originalLanguage = connectionOptions.CurrentLanguage;
            }

            timeoutErrorInternal = new SqlConnectionTimeoutErrorInternal();
            _credential = credential;

            _parserLock.Wait(canReleaseFromAnyThread:false);
            ThreadHasParserLockForClose = true;   // In case of error, let ourselves know that we already own the parser lock
            RuntimeHelpers.PrepareConstrainedRegions();
            try {
#if DEBUG
                TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection();

                RuntimeHelpers.PrepareConstrainedRegions();
                try {
                    tdsReliabilitySection.Start();
#else
                {
#endif //DEBUG
                    _timeout = TimeoutTimer.StartSecondsTimeout(connectionOptions.ConnectTimeout);

                    // If transient fault handling is enabled then we can retry the login upto the ConnectRetryCount.
                    int connectionEstablishCount = applyTransientFaultHandling ? connectionOptions.ConnectRetryCount + 1 : 1;
                    int transientRetryIntervalInMilliSeconds = connectionOptions.ConnectRetryInterval * 1000; // Max value of transientRetryInterval is 60*1000 ms. The max value allowed for ConnectRetryInterval is 60
                    for (int i = 0; i < connectionEstablishCount; i++)
                    {
                        try
                        {
                            OpenLoginEnlist(_timeout, connectionOptions, credential, newPassword, newSecurePassword, redirectedUserInstance);
                            break;
                        }
                        catch (SqlException sqlex)
                        {
                            if (i + 1 == connectionEstablishCount 
                                || !applyTransientFaultHandling
                                || _timeout.IsExpired
                                || _timeout.MillisecondsRemaining < transientRetryIntervalInMilliSeconds
                                || !IsTransientError(sqlex))
                            {
                                throw sqlex;
                            }
                            else
                            {
                                Thread.Sleep(transientRetryIntervalInMilliSeconds);
                            }
                        }
                    }
                }
#if DEBUG
                finally {
                    tdsReliabilitySection.Stop();
                }
#endif //DEBUG
            }
            catch (System.OutOfMemoryException) {
                DoomThisConnection();
                throw;
            }
            catch (System.StackOverflowException) {
                DoomThisConnection();
                throw;
            }
            catch (System.Threading.ThreadAbortException) {
                DoomThisConnection();
                throw;
            }
            finally {
                ThreadHasParserLockForClose = false;
                _parserLock.Release();
            }
            if (Bid.AdvancedOn) {
                Bid.Trace("<sc.SqlInternalConnectionTds.ctor|ADV> %d#, constructed new TDS internal connection\n", ObjectID);
            }
        }
    // Attempt to login to a host that does not have a failover partner
    //
    //  Will repeatedly attempt to connect, but back off between each attempt so as not to clog the network.
    //  Back off period increases for first few failures: 100ms, 200ms, 400ms, 800ms, then 1000ms for subsequent attempts
    //
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    //  DEVNOTE: The logic in this method is paralleled by the logic in LoginWithFailover.
    //           Changes to either one should be examined to see if they need to be reflected in the other
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    private void LoginNoFailover(ServerInfo serverInfo, string newPassword, SecureString newSecurePassword, bool redirectedUserInstance, 
                SqlConnectionString connectionOptions, SqlCredential credential, TimeoutTimer timeout) {

        Debug.Assert(object.ReferenceEquals(connectionOptions, this.ConnectionOptions), "ConnectionOptions argument and property must be the same"); // consider removing the argument
        int routingAttempts = 0;
        ServerInfo originalServerInfo = serverInfo; // serverInfo may end up pointing to new object due to routing, original object is used to set CurrentDatasource

        if (Bid.AdvancedOn) {
            Bid.Trace("<sc.SqlInternalConnectionTds.LoginNoFailover|ADV> %d#, host=%ls\n", ObjectID, serverInfo.UserServerName);
        }
        int  sleepInterval = 100;  //milliseconds to sleep (back off) between attempts.

        ResolveExtendedServerName(serverInfo, !redirectedUserInstance, connectionOptions);

        long timeoutUnitInterval = 0;
        Boolean isParallel = connectionOptions.MultiSubnetFailover || connectionOptions.TransparentNetworkIPResolution;

        if(isParallel) {
            // Determine unit interval
            if (timeout.IsInfinite) {
                timeoutUnitInterval = checked((long)(ADP.FailoverTimeoutStep * (1000L * ADP.DefaultConnectionTimeout)));
            }
            else {
                timeoutUnitInterval = checked((long)(ADP.FailoverTimeoutStep * timeout.MillisecondsRemaining));
            }
        }
        // Only three ways out of this loop:
        //  1) Successfully connected
        //  2) Parser threw exception while main timer was expired
        //  3) Parser threw logon failure-related exception 
        //  4) Parser threw exception in post-initial connect code,
        //      such as pre-login handshake or during actual logon. (parser state != Closed)
        //
        //  Of these methods, only #1 exits normally. This preserves the call stack on the exception 
        //  back into the parser for the error cases.
        int attemptNumber = 0;
        TimeoutTimer intervalTimer = null;
        TimeoutTimer firstTransparentAttemptTimeout = TimeoutTimer.StartMillisecondsTimeout(ADP.FirstTransparentAttemptTimeout);
        TimeoutTimer attemptOneLoginTimeout = timeout;
        while(true) {

            if(isParallel) {
                attemptNumber++;
                // Set timeout for this attempt, but don't exceed original timer                
                long nextTimeoutInterval = checked(timeoutUnitInterval * attemptNumber);
                long milliseconds = timeout.MillisecondsRemaining;
                if (nextTimeoutInterval > milliseconds) {
                    nextTimeoutInterval = milliseconds;
                }
                intervalTimer = TimeoutTimer.StartMillisecondsTimeout(nextTimeoutInterval);
            }

            // Re-allocate parser each time to make sure state is known
            // RFC 50002652 - if parser was created by previous attempt, dispose it to properly close the socket, if created
            if (_parser != null)
                _parser.Disconnect();
 
            _parser = new TdsParser(ConnectionOptions.MARS, ConnectionOptions.Asynchronous);
            Debug.Assert(SniContext.Undefined== Parser._physicalStateObj.SniContext, String.Format((IFormatProvider)null, "SniContext should be Undefined; actual Value: {0}", Parser._physicalStateObj.SniContext));

            try {
                // 


                Boolean isFirstTransparentAttempt =  connectionOptions.TransparentNetworkIPResolution && attemptNumber == 1;

                if(isFirstTransparentAttempt) {
                    attemptOneLoginTimeout = firstTransparentAttemptTimeout;
                }
                else {
                    if(isParallel) {
                        attemptOneLoginTimeout = intervalTimer;
                    }
                }
                
                AttemptOneLogin(    serverInfo, 
                                    newPassword,
                                    newSecurePassword,
                                    !isParallel,    // ignore timeout for SniOpen call unless MSF , and TNIR
                                    attemptOneLoginTimeout,
                                    isFirstTransparentAttempt:isFirstTransparentAttempt);
                
                if (connectionOptions.MultiSubnetFailover && null != ServerProvidedFailOverPartner) {
                    // connection succeeded: trigger exception if server sends failover partner and MultiSubnetFailover is used.
                    throw SQL.MultiSubnetFailoverWithFailoverPartner(serverProvidedFailoverPartner: true, internalConnection: this);
                }

                if (_routingInfo != null) {
                    Bid.Trace("<sc.SqlInternalConnectionTds.LoginNoFailover> Routed to %ls", serverInfo.ExtendedServerName);

                    if (routingAttempts > 0) {
                        throw SQL.ROR_RecursiveRoutingNotSupported(this);
                    }

                    if (timeout.IsExpired) {
                        throw SQL.ROR_TimeoutAfterRoutingInfo(this);
                    }                    

                    serverInfo = new ServerInfo(ConnectionOptions, _routingInfo, serverInfo.ResolvedServerName);
                    timeoutErrorInternal.SetInternalSourceType(SqlConnectionInternalSourceType.RoutingDestination);
                    _originalClientConnectionId = _clientConnectionId;
                    _routingDestination = serverInfo.UserServerName;

                    // restore properties that could be changed by the environment tokens
                    _currentPacketSize = ConnectionOptions.PacketSize;
                    _currentLanguage = _originalLanguage = ConnectionOptions.CurrentLanguage;
                    CurrentDatabase = _originalDatabase = ConnectionOptions.InitialCatalog;
                    _currentFailoverPartner = null;
                    _instanceName = String.Empty;

                    routingAttempts++;

                    continue; // repeat the loop, but skip code reserved for failed connections (after the catch)
                }
                else {
                    break; // leave the while loop -- we've successfully connected
                }
            }
            catch (SqlException sqlex) {
                if (null == _parser
                    || TdsParserState.Closed != _parser.State
                    || IsDoNotRetryConnectError(sqlex)
                    || timeout.IsExpired) {       // no more time to try again
                    throw;  // Caller will call LoginFailure()
                }

                // Check sleep interval to make sure we won't exceed the timeout
                //  Do this in the catch block so we can re-throw the current exception
                if (timeout.MillisecondsRemaining <= sleepInterval) {
                    throw;
                }

                // 
            }

            // We only get here when we failed to connect, but are going to re-try

            // Switch to failover logic if the server provided a partner
            if (null != ServerProvidedFailOverPartner) {
                if (connectionOptions.MultiSubnetFailover) {
                    // connection failed: do not allow failover to server-provided failover partner if MultiSubnetFailover is set
                    throw SQL.MultiSubnetFailoverWithFailoverPartner(serverProvidedFailoverPartner: true, internalConnection: this);
                }
                Debug.Assert(ConnectionOptions.ApplicationIntent != ApplicationIntent.ReadOnly, "FAILOVER+AppIntent=RO: Should already fail (at LOGSHIPNODE in OnEnvChange)");

                timeoutErrorInternal.ResetAndRestartPhase();
                timeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.PreLoginBegin);
                timeoutErrorInternal.SetInternalSourceType(SqlConnectionInternalSourceType.Failover);
                timeoutErrorInternal.SetFailoverScenario(true); // this is a failover scenario
                LoginWithFailover(
                            true,   // start by using failover partner, since we already failed to connect to the primary
                            serverInfo,
                            ServerProvidedFailOverPartner,
                            newPassword,
                            newSecurePassword,
                            redirectedUserInstance,
                            connectionOptions,
                            credential,
                            timeout);
                return; // LoginWithFailover successfully connected and handled entire connection setup
            }

            // Sleep for a bit to prevent clogging the network with requests, 
            //  then update sleep interval for next iteration (max 1 second interval)
            if (Bid.AdvancedOn) {
                Bid.Trace("<sc.SqlInternalConnectionTds.LoginNoFailover|ADV> %d#, sleeping %d{milisec}\n", ObjectID, sleepInterval);
            }
            Thread.Sleep(sleepInterval);
            sleepInterval = (sleepInterval < 500) ? sleepInterval * 2 : 1000;
        }

        if (null != PoolGroupProviderInfo) {
            // We must wait for CompleteLogin to finish for to have the
            // env change from the server to know its designated failover 
            // partner; save this information in _currentFailoverPartner.
            PoolGroupProviderInfo.FailoverCheck(this, false, connectionOptions, ServerProvidedFailOverPartner);
        }
        CurrentDataSource = originalServerInfo.UserServerName;
    }
    // Attempt to login to a host that has a failover partner
    //
    // Connection & timeout sequence is
    //      First target, timeout = interval * 1
    //      second target, timeout = interval * 1
    //      sleep for 100ms
    //      First target, timeout = interval * 2
    //      Second target, timeout = interval * 2
    //      sleep for 200ms
    //      First Target, timeout = interval * 3
    //      etc.
    //
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    //  DEVNOTE: The logic in this method is paralleled by the logic in LoginNoFailover.
    //           Changes to either one should be examined to see if they need to be reflected in the other
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    private void LoginWithFailover(
            bool                useFailoverHost, 
            ServerInfo          primaryServerInfo, 
            string              failoverHost, 
            string              newPassword,
            SecureString        newSecurePassword,
            bool                redirectedUserInstance, 
            SqlConnectionString connectionOptions,
            SqlCredential       credential,
            TimeoutTimer        timeout
        ) {

        Debug.Assert(!connectionOptions.MultiSubnetFailover, "MultiSubnetFailover should not be set if failover partner is used");

        if (Bid.AdvancedOn) {
            Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, useFailover=%d{bool}, primary=", ObjectID, useFailoverHost);
            Bid.PutStr(primaryServerInfo.UserServerName);
            Bid.PutStr(", failover=");
            Bid.PutStr(failoverHost);
            Bid.PutStr("\n");
        }
        int  sleepInterval = 100;  //milliseconds to sleep (back off) between attempts.
        long timeoutUnitInterval;

        string     protocol = ConnectionOptions.NetworkLibrary;
        ServerInfo failoverServerInfo = new ServerInfo(connectionOptions, failoverHost);

        ResolveExtendedServerName(primaryServerInfo, !redirectedUserInstance, connectionOptions);
        if (null == ServerProvidedFailOverPartner) {// No point in resolving the failover partner when we're going to override it below
            // Don't resolve aliases if failover == primary // 
            ResolveExtendedServerName(failoverServerInfo, !redirectedUserInstance && failoverHost != primaryServerInfo.UserServerName, connectionOptions);
        }

        // Determine unit interval
        if (timeout.IsInfinite) {
            timeoutUnitInterval = checked((long) ADP.FailoverTimeoutStep * ADP.TimerFromSeconds(ADP.DefaultConnectionTimeout));
        }
        else {
            timeoutUnitInterval = checked((long) (ADP.FailoverTimeoutStep * timeout.MillisecondsRemaining));
        }

        // Initialize loop variables
        bool failoverDemandDone = false; // have we demanded for partner information yet (as necessary)?
        int attemptNumber = 0;

        // Only three ways out of this loop:
        //  1) Successfully connected
        //  2) Parser threw exception while main timer was expired
        //  3) Parser threw logon failure-related exception (LOGON_FAILED, PASSWORD_EXPIRED, etc)
        //
        //  Of these methods, only #1 exits normally. This preserves the call stack on the exception 
        //  back into the parser for the error cases.
        while (true) {
            // Set timeout for this attempt, but don't exceed original timer
            long nextTimeoutInterval = checked(timeoutUnitInterval * ((attemptNumber / 2) + 1));
            long milliseconds = timeout.MillisecondsRemaining;
            if (nextTimeoutInterval > milliseconds) {
                nextTimeoutInterval = milliseconds;
            }

            TimeoutTimer intervalTimer = TimeoutTimer.StartMillisecondsTimeout(nextTimeoutInterval);

            // Re-allocate parser each time to make sure state is known
            // RFC 50002652 - if parser was created by previous attempt, dispose it to properly close the socket, if created
            if (_parser != null)
                _parser.Disconnect();

            _parser = new TdsParser(ConnectionOptions.MARS, ConnectionOptions.Asynchronous);
            Debug.Assert(SniContext.Undefined== Parser._physicalStateObj.SniContext, String.Format((IFormatProvider)null, "SniContext should be Undefined; actual Value: {0}", Parser._physicalStateObj.SniContext));

            ServerInfo currentServerInfo;
            if (useFailoverHost) {
                if (!failoverDemandDone) {
                    FailoverPermissionDemand();
                    failoverDemandDone = true;
                }

                // Primary server may give us a different failover partner than the connection string indicates.  Update it
                if (null != ServerProvidedFailOverPartner && failoverServerInfo.ResolvedServerName != ServerProvidedFailOverPartner) {
                    if (Bid.AdvancedOn) {
                        Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, new failover partner=%ls\n", ObjectID, ServerProvidedFailOverPartner);
                    }
                    failoverServerInfo.SetDerivedNames(protocol, ServerProvidedFailOverPartner);
                }
                currentServerInfo = failoverServerInfo;
                timeoutErrorInternal.SetInternalSourceType(SqlConnectionInternalSourceType.Failover);
            }
            else {
                currentServerInfo = primaryServerInfo;
                timeoutErrorInternal.SetInternalSourceType(SqlConnectionInternalSourceType.Principle);
            }

            try {
                // Attempt login.  Use timerInterval for attempt timeout unless infinite timeout was requested.
                AttemptOneLogin(
                        currentServerInfo,
                        newPassword,
                        newSecurePassword,
                        false,          // Use timeout in SniOpen
                        intervalTimer,
                        withFailover:true
                        );

                if (_routingInfo != null) {
                    // We are in login with failover scenation and server sent routing information
                    // If it is read-only routing - we did not supply AppIntent=RO (it should be checked before)
                    // If it is something else, not known yet (future server) - this client is not designed to support this.                    
                    // In any case, server should not have sent the routing info.
                    Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover> Routed to %ls", _routingInfo.ServerName);
                    throw SQL.ROR_UnexpectedRoutingInfo(this);
                }

                break; // leave the while loop -- we've successfully connected
            }
            catch (SqlException sqlex) {
                if (IsDoNotRetryConnectError(sqlex)
                        || timeout.IsExpired) 
                {       // no more time to try again
                    throw;  // Caller will call LoginFailure()
                }

                if (IsConnectionDoomed) {
                    throw;
                }

                if (1 == attemptNumber % 2) {
                    // Check sleep interval to make sure we won't exceed the original timeout
                    //  Do this in the catch block so we can re-throw the current exception
                    if (timeout.MillisecondsRemaining <= sleepInterval) {
                        throw;
                    }
                }

                // 
            }

            // We only get here when we failed to connect, but are going to re-try

            // After trying to connect to both servers fails, sleep for a bit to prevent clogging 
            //  the network with requests, then update sleep interval for next iteration (max 1 second interval)
            if (1 == attemptNumber % 2) {
                if (Bid.AdvancedOn) {
                    Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, sleeping %d{milisec}\n", ObjectID, sleepInterval);
                }
                Thread.Sleep(sleepInterval);
                sleepInterval = (sleepInterval < 500) ? sleepInterval * 2 : 1000;
            }

            // Update attempt number and target host
            attemptNumber++;
            useFailoverHost = !useFailoverHost;
        }

        // If we get here, connection/login succeeded!  Just a few more checks & record-keeping

        // if connected to failover host, but said host doesn't have DbMirroring set up, throw an error
        if (useFailoverHost && null == ServerProvidedFailOverPartner) {
            throw SQL.InvalidPartnerConfiguration(failoverHost, CurrentDatabase);
        }

        if (null != PoolGroupProviderInfo) {
            // We must wait for CompleteLogin to finish for to have the
            // env change from the server to know its designated failover 
            // partner; save this information in _currentFailoverPartner.
            PoolGroupProviderInfo.FailoverCheck(this, useFailoverHost, connectionOptions, ServerProvidedFailOverPartner);
        }
        CurrentDataSource = (useFailoverHost ? failoverHost : primaryServerInfo.UserServerName);
    }
        private void Login(ServerInfo server, TimeoutTimer timeout, string newPassword, SecureString newSecurePassword) {
            // create a new login record
            SqlLogin login = new SqlLogin();

            // gather all the settings the user set in the connection string or
            // properties and do the login
            CurrentDatabase   = server.ResolvedDatabaseName;
            _currentPacketSize = ConnectionOptions.PacketSize;
            _currentLanguage   = ConnectionOptions.CurrentLanguage;

            int timeoutInSeconds = 0;

            // If a timeout tick value is specified, compute the timeout based
            // upon the amount of time left in seconds.
            if (!timeout.IsInfinite)
            {
                long t = timeout.MillisecondsRemaining/1000;
                if ((long)Int32.MaxValue > t)
                {
                    timeoutInSeconds = (int)t;
                }
            }

            login.authentication = ConnectionOptions.Authentication;
            login.timeout = timeoutInSeconds;
            login.userInstance     = ConnectionOptions.UserInstance;
            login.hostName         = ConnectionOptions.ObtainWorkstationId();
            login.userName         = ConnectionOptions.UserID;
            login.password         = ConnectionOptions.Password;
            login.applicationName  = ConnectionOptions.ApplicationName;

            login.language         = _currentLanguage;
            if (!login.userInstance) { // Do not send attachdbfilename or database to SSE primary instance
                login.database         = CurrentDatabase;;
                login.attachDBFilename = ConnectionOptions.AttachDBFilename;
            }

            // VSTS#795621 - Ensure ServerName is Sent During TdsLogin To Enable Sql Azure Connectivity.
            // Using server.UserServerName (versus ConnectionOptions.DataSource) since TdsLogin requires 
            // serverName to always be non-null.
            login.serverName = server.UserServerName;

            login.useReplication   = ConnectionOptions.Replication;
            login.useSSPI          = ConnectionOptions.IntegratedSecurity 
                                     || (ConnectionOptions.Authentication == SqlAuthenticationMethod.ActiveDirectoryIntegrated && !_fedAuthRequired);
            login.packetSize       = _currentPacketSize;
            login.newPassword      = newPassword;
            login.readOnlyIntent   = ConnectionOptions.ApplicationIntent == ApplicationIntent.ReadOnly;
            login.credential       = _credential;
            if (newSecurePassword != null) {
                login.newSecurePassword = newSecurePassword;
            }

            TdsEnums.FeatureExtension requestedFeatures = TdsEnums.FeatureExtension.None;
            if (ConnectionOptions.ConnectRetryCount>0) {
                requestedFeatures |= TdsEnums.FeatureExtension.SessionRecovery;
                _sessionRecoveryRequested = true;
            }

            // If the workflow being used is Active Directory Password or Active Directory Integrated and server's prelogin response
            // for FEDAUTHREQUIRED option indicates Federated Authentication is required, we have to insert FedAuth Feature Extension
            // in Login7, indicating the intent to use Active Directory Authentication Library for SQL Server.
            if (ConnectionOptions.Authentication == SqlAuthenticationMethod.ActiveDirectoryPassword
                || (ConnectionOptions.Authentication == SqlAuthenticationMethod.ActiveDirectoryIntegrated && _fedAuthRequired)) {
                requestedFeatures |= TdsEnums.FeatureExtension.FedAuth;
                _federatedAuthenticationInfoRequested = true;
                _fedAuthFeatureExtensionData = 
                    new FederatedAuthenticationFeatureExtensionData { 
                        libraryType = TdsEnums.FedAuthLibrary.ADAL,
                        authentication = ConnectionOptions.Authentication,
                        fedAuthRequiredPreLoginResponse = _fedAuthRequired
                    };
            }
            if (_accessTokenInBytes != null) {
                requestedFeatures |= TdsEnums.FeatureExtension.FedAuth;
                _fedAuthFeatureExtensionData = new FederatedAuthenticationFeatureExtensionData {
                        libraryType = TdsEnums.FedAuthLibrary.SecurityToken,
                        fedAuthRequiredPreLoginResponse = _fedAuthRequired,
                        accessToken = _accessTokenInBytes
                    };
                // No need any further info from the server for token based authentication. So set _federatedAuthenticationRequested to true
                _federatedAuthenticationRequested = true;
            }

            // The TCE and GLOBALTRANSACTIONS feature are implicitly requested
            requestedFeatures |= TdsEnums.FeatureExtension.Tce | TdsEnums.FeatureExtension.GlobalTransactions;
            _parser.TdsLogin(login, requestedFeatures, _recoverySessionData, _fedAuthFeatureExtensionData);
        }
        private void OpenLoginEnlist(TimeoutTimer timeout, SqlConnectionString connectionOptions, SqlCredential credential,
                    string newPassword, SecureString newSecurePassword, bool redirectedUserInstance) {
            bool useFailoverPartner; // should we use primary or secondary first
            ServerInfo dataSource = new ServerInfo(connectionOptions);
            string failoverPartner;

            if (null != PoolGroupProviderInfo) {
                useFailoverPartner = PoolGroupProviderInfo.UseFailoverPartner;
                failoverPartner = PoolGroupProviderInfo.FailoverPartner;
            }
            else {
                // Only ChangePassword or SSE User Instance comes through this code path.
                useFailoverPartner = false;
                failoverPartner = ConnectionOptions.FailoverPartner; 
            }

            timeoutErrorInternal.SetInternalSourceType(useFailoverPartner ? SqlConnectionInternalSourceType.Failover : SqlConnectionInternalSourceType.Principle);

            bool hasFailoverPartner = !ADP.IsEmpty(failoverPartner);

            // Open the connection and Login
            try {
                timeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.PreLoginBegin);
                if (hasFailoverPartner) {
                    timeoutErrorInternal.SetFailoverScenario(true); // this is a failover scenario
                    LoginWithFailover(
                                useFailoverPartner, 
                                dataSource, 
                                failoverPartner, 
                                newPassword,
                                newSecurePassword,
                                redirectedUserInstance, 
                                connectionOptions,
                                credential,
                                timeout);
                }
                else {
                    timeoutErrorInternal.SetFailoverScenario(false); // not a failover scenario
                    LoginNoFailover(dataSource, newPassword, newSecurePassword, redirectedUserInstance, 
                            connectionOptions, credential, timeout);
                }
                timeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.PostLogin);
            }
            catch (Exception e) {
                // 
                if (ADP.IsCatchableExceptionType(e)) {
                    LoginFailure();
                }
                throw;
            }
            timeoutErrorInternal.SetAllCompleteMarker();

#if DEBUG
            _parser._physicalStateObj.InvalidateDebugOnlyCopyOfSniContext();
#endif
        }
 private void Login(ServerInfo server, TimeoutTimer timeout, string newPassword)
 {
     SqlLogin rec = new SqlLogin();
     base.CurrentDatabase = server.ResolvedDatabaseName;
     this._currentPacketSize = base.ConnectionOptions.PacketSize;
     this._currentLanguage = base.ConnectionOptions.CurrentLanguage;
     int num2 = 0;
     if (!timeout.IsInfinite)
     {
         long num = timeout.MillisecondsRemaining / 0x3e8L;
         if (0x7fffffffL > num)
         {
             num2 = (int) num;
         }
     }
     rec.timeout = num2;
     rec.userInstance = base.ConnectionOptions.UserInstance;
     rec.hostName = base.ConnectionOptions.ObtainWorkstationId();
     rec.userName = base.ConnectionOptions.UserID;
     rec.password = base.ConnectionOptions.Password;
     rec.applicationName = base.ConnectionOptions.ApplicationName;
     rec.language = this._currentLanguage;
     if (!rec.userInstance)
     {
         rec.database = base.CurrentDatabase;
         rec.attachDBFilename = base.ConnectionOptions.AttachDBFilename;
     }
     rec.serverName = server.UserServerName;
     rec.useReplication = base.ConnectionOptions.Replication;
     rec.useSSPI = base.ConnectionOptions.IntegratedSecurity;
     rec.packetSize = this._currentPacketSize;
     rec.newPassword = newPassword;
     rec.readOnlyIntent = base.ConnectionOptions.ApplicationIntent == ApplicationIntent.ReadOnly;
     this._parser.TdsLogin(rec);
 }
 private void OpenLoginEnlist(SqlConnection owningObject, TimeoutTimer timeout, SqlConnectionString connectionOptions, string newPassword, bool redirectedUserInstance)
 {
     string failoverPartner;
     bool useFailoverPartner;
     ServerInfo primaryServerInfo = new ServerInfo(connectionOptions);
     if (this.PoolGroupProviderInfo != null)
     {
         useFailoverPartner = this.PoolGroupProviderInfo.UseFailoverPartner;
         failoverPartner = this.PoolGroupProviderInfo.FailoverPartner;
     }
     else
     {
         useFailoverPartner = false;
         failoverPartner = base.ConnectionOptions.FailoverPartner;
     }
     bool flag2 = !ADP.IsEmpty(failoverPartner);
     try
     {
         if (flag2)
         {
             this.LoginWithFailover(useFailoverPartner, primaryServerInfo, failoverPartner, newPassword, redirectedUserInstance, owningObject, connectionOptions, timeout);
         }
         else
         {
             this.LoginNoFailover(primaryServerInfo, newPassword, redirectedUserInstance, owningObject, connectionOptions, timeout);
         }
     }
     catch (Exception exception)
     {
         if (ADP.IsCatchableExceptionType(exception))
         {
             this.LoginFailure();
         }
         throw;
     }
 }
        private void Login(ServerInfo server, TimeoutTimer timeout)
        {
            // create a new login record
            SqlLogin login = new SqlLogin();

            // gather all the settings the user set in the connection string or
            // properties and do the login
            CurrentDatabase = server.ResolvedDatabaseName;
            _currentPacketSize = ConnectionOptions.PacketSize;
            _currentLanguage = ConnectionOptions.CurrentLanguage;

            int timeoutInSeconds = 0;

            // If a timeout tick value is specified, compute the timeout based
            // upon the amount of time left in seconds.
            if (!timeout.IsInfinite)
            {
                long t = timeout.MillisecondsRemaining / 1000;
                if ((long)Int32.MaxValue > t)
                {
                    timeoutInSeconds = (int)t;
                }
            }

            login.timeout = timeoutInSeconds;
            login.userInstance = ConnectionOptions.UserInstance;
            login.hostName = ConnectionOptions.ObtainWorkstationId();
            login.userName = ConnectionOptions.UserID;
            login.password = ConnectionOptions.Password;
            login.applicationName = ConnectionOptions.ApplicationName;

            login.language = _currentLanguage;
            if (!login.userInstance)
            { // Do not send attachdbfilename or database to SSE primary instance
                login.database = CurrentDatabase; ;
                login.attachDBFilename = ConnectionOptions.AttachDBFilename;
            }

            // VSTS#795621 - Ensure ServerName is Sent During TdsLogin To Enable Sql Azure Connectivity.
            // Using server.UserServerName (versus ConnectionOptions.DataSource) since TdsLogin requires 
            // serverName to always be non-null.
            login.serverName = server.UserServerName;

            login.useReplication = ConnectionOptions.Replication;
            login.useSSPI = ConnectionOptions.IntegratedSecurity;
            login.packetSize = _currentPacketSize;
            login.readOnlyIntent = ConnectionOptions.ApplicationIntent == ApplicationIntent.ReadOnly;

            TdsEnums.FeatureExtension requestedFeatures = TdsEnums.FeatureExtension.None;
            if (ConnectionOptions.ConnectRetryCount > 0)
            {
                requestedFeatures |= TdsEnums.FeatureExtension.SessionRecovery;
                _sessionRecoveryRequested = true;
            }

            _parser.TdsLogin(login, requestedFeatures, _recoverySessionData);
        }
        // Common code path for making one attempt to establish a connection and log in to server.
        private void AttemptOneLogin(ServerInfo serverInfo,
                                bool ignoreSniOpenTimeout,
                                    TimeoutTimer timeout,
                                    bool withFailover = false)
        {
            _routingInfo = null; // forget routing information 

            _parser._physicalStateObj.SniContext = SniContext.Snix_Connect;

            _parser.Connect(serverInfo,
                            this,
                            ignoreSniOpenTimeout,
                            timeout.LegacyTimerExpire,
                            ConnectionOptions.Encrypt,
                            ConnectionOptions.TrustServerCertificate,
                            ConnectionOptions.IntegratedSecurity,
                            withFailover);

            _timeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.ConsumePreLoginHandshake);
            _timeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.LoginBegin);

            _parser._physicalStateObj.SniContext = SniContext.Snix_Login;
            this.Login(serverInfo, timeout);

            _timeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.ProcessConnectionAuth);
            _timeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.PostLogin);

            CompleteLogin(!ConnectionOptions.Pooling);

            _timeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.PostLogin);
        }
 internal static TimeoutTimer StartSecondsTimeout(int seconds)
 {
     TimeoutTimer timer = new TimeoutTimer();
     timer.SetTimeoutSeconds(seconds);
     return timer;
 }