internal void Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, bool ignoreSniOpenTimeout, long timerExpire, bool encrypt, bool trustServerCert, bool integratedSecurity, bool withFailover)
{
if (_state != TdsParserState.Closed)
{
Debug.Assert(false, "TdsParser.Connect called on non-closed connection!");
return;
}
_connHandler = connHandler;
_loginWithFailover = withFailover;
uint sniStatus = SNILoadHandle.SingletonInstance.Status;
if (sniStatus != TdsEnums.SNI_SUCCESS)
{
_physicalStateObj.AddError(ProcessSNIError(_physicalStateObj));
_physicalStateObj.Dispose();
ThrowExceptionAndWarning(_physicalStateObj);
Debug.Assert(false, "SNI returned status != success, but no error thrown?");
}
#if !MANAGED_SNI
if (integratedSecurity)
{
LoadSSPILibrary();
// now allocate proper length of buffer
_sniSpnBuffer = new byte[SNINativeMethodWrapper.SniMaxComposedSpnLength];
}
else
{
_sniSpnBuffer = null;
}
#endif // MANAGED_SNI
byte[] instanceName = null;
Debug.Assert(_connHandler != null, "SqlConnectionInternalTds handler can not be null at this point.");
_connHandler.TimeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.PreLoginBegin);
_connHandler.TimeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.InitializeConnection);
bool fParallel = _connHandler.ConnectionOptions.MultiSubnetFailover;
#if MANAGED_SNI
_physicalStateObj.CreateConnectionHandle(serverInfo.ExtendedServerName, ignoreSniOpenTimeout, timerExpire,
out instanceName, _sniSpnBuffer, false, true, fParallel);
#else
_physicalStateObj.CreatePhysicalSNIHandle(serverInfo.ExtendedServerName, ignoreSniOpenTimeout, timerExpire,
out instanceName, _sniSpnBuffer, false, true, fParallel);
#endif // MANAGED_SNI
if (TdsEnums.SNI_SUCCESS != _physicalStateObj.Status)
{
_physicalStateObj.AddError(ProcessSNIError(_physicalStateObj));
// Since connect failed, free the unmanaged connection memory.
// HOWEVER - only free this after the netlib error was processed - if you
// don't, the memory for the connection object might not be accurate and thus
// a bad error could be returned (as it was when it was freed to early for me).
_physicalStateObj.Dispose();
ThrowExceptionAndWarning(_physicalStateObj);
Debug.Assert(false, "SNI returned status != success, but no error thrown?");
}
_server = serverInfo.ResolvedServerName;
if (null != connHandler.PoolGroupProviderInfo)
{
// If we are pooling, check to see if we were processing an
// alias which has changed, which means we need to clean out
// the pool. See Webdata 104293.
// This should not apply to routing, as it is not an alias change, routed connection
// should still use VNN of AlwaysOn cluster as server for pooling purposes.
connHandler.PoolGroupProviderInfo.AliasCheck(serverInfo.PreRoutingServerName == null ?
serverInfo.ResolvedServerName : serverInfo.PreRoutingServerName);
}
_state = TdsParserState.OpenNotLoggedIn;
_physicalStateObj.SniContext = SniContext.Snix_PreLoginBeforeSuccessfullWrite;
_physicalStateObj.TimeoutTime = timerExpire;
bool marsCapable = false;
_connHandler.TimeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.InitializeConnection);
_connHandler.TimeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.SendPreLoginHandshake);
#if MANAGED_SNI
UInt32 result = SNIProxy.Singleton.GetConnectionId(_physicalStateObj.Handle, ref _connHandler._clientConnectionId);
#else
UInt32 result = SNINativeMethodWrapper.SniGetConnectionId(_physicalStateObj.Handle, ref _connHandler._clientConnectionId);
#endif // MANAGED_SNI
Debug.Assert(result == TdsEnums.SNI_SUCCESS, "Unexpected failure state upon calling SniGetConnectionId");
SendPreLoginHandshake(instanceName, encrypt);
_connHandler.TimeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.SendPreLoginHandshake);
_connHandler.TimeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.ConsumePreLoginHandshake);
_physicalStateObj.SniContext = SniContext.Snix_PreLogin;
PreLoginHandshakeStatus status = ConsumePreLoginHandshake(encrypt, trustServerCert, integratedSecurity, out marsCapable);
if (status == PreLoginHandshakeStatus.InstanceFailure)
{
_physicalStateObj.Dispose(); // Close previous connection
// On Instance failure re-connect and flush SNI named instance cache.
_physicalStateObj.SniContext = SniContext.Snix_Connect;
#if MANAGED_SNI
_physicalStateObj.CreateConnectionHandle(serverInfo.ExtendedServerName, ignoreSniOpenTimeout, timerExpire, out instanceName, _sniSpnBuffer, true, true, fParallel);
#else
_physicalStateObj.CreatePhysicalSNIHandle(serverInfo.ExtendedServerName, ignoreSniOpenTimeout, timerExpire, out instanceName, _sniSpnBuffer, true, true, fParallel);
#endif // MANAGED_SNI
if (TdsEnums.SNI_SUCCESS != _physicalStateObj.Status)
{
_physicalStateObj.AddError(ProcessSNIError(_physicalStateObj));
ThrowExceptionAndWarning(_physicalStateObj);
}
#if MANAGED_SNI
UInt32 retCode = SNIProxy.Singleton.GetConnectionId(_physicalStateObj.Handle, ref _connHandler._clientConnectionId);
#else
UInt32 retCode = SNINativeMethodWrapper.SniGetConnectionId(_physicalStateObj.Handle, ref _connHandler._clientConnectionId);
#endif // MANAGED_SNI
Debug.Assert(retCode == TdsEnums.SNI_SUCCESS, "Unexpected failure state upon calling SniGetConnectionId");
SendPreLoginHandshake(instanceName, encrypt);
status = ConsumePreLoginHandshake(encrypt, trustServerCert, integratedSecurity, out marsCapable);
// Don't need to check for Sphinx failure, since we've already consumed
// one pre-login packet and know we are connecting to Shiloh.
if (status == PreLoginHandshakeStatus.InstanceFailure)
{
throw SQL.InstanceFailure();
}
}
if (_fMARS && marsCapable)
{
// if user explicitly disables mars or mars not supported, don't create the session pool
_sessionPool = new TdsParserSessionPool(this);
}
else
{
_fMARS = false;
}
return;
}