Skip to content

Merge | TdsParserStateObject lifetime-related methods #3394

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 34 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
c79425e
Port PacketHandle to netfx
edwardneal May 16, 2025
e41cf0e
Remove PacketHandle alias shim
edwardneal May 16, 2025
b1a4413
Align netfx use of PacketHandle
edwardneal May 16, 2025
fc3c31e
Merge IsPacketEmpty
edwardneal May 17, 2025
c03e518
Merge ReleasePacket
edwardneal May 17, 2025
adc1dbf
Merge ReadAsync, ReadSyncOverAsync
edwardneal May 17, 2025
3b58d9b
Merge IsFailedHandle
edwardneal May 17, 2025
e06dba9
Merge SniPacketGetData
edwardneal May 17, 2025
1ee1a14
Merge EmptyReadPacket
edwardneal May 17, 2025
51903e6
Merge CheckPacket
edwardneal May 17, 2025
93311c9
Merge WritePacket, IsValidPacket
edwardneal May 17, 2025
95c8414
Merge GetResetWritePacket
edwardneal May 17, 2025
c21d451
Merge ClearAllWritePackets, AddPacketToPendingList, RemovePacketFromP…
edwardneal May 17, 2025
857afe6
Improve diff between versions of TdsParserStateObjectNative
edwardneal May 17, 2025
0767cd7
PR feedback from #3353 - format IsValidPacket
edwardneal May 21, 2025
86180f0
Merge main
edwardneal May 23, 2025
fe5d81c
Address merge conflicts
edwardneal May 23, 2025
bd5a153
Merge DisposePacketCache
edwardneal May 23, 2025
7daf3ab
Merge branch 'merge/packethandle-follow-up' into merge/tdsparserstate…
edwardneal May 28, 2025
469d840
Merge CreateSessionHandle
edwardneal May 29, 2025
596ee25
Move AssignPendingDNSInfo from TdsParser, merge
edwardneal May 29, 2025
3b8f850
Sync method signature for CreatePhysicalSNIHandle
edwardneal May 29, 2025
dfeb360
Port netcore _serverSpn array to netfx
edwardneal Jun 3, 2025
4ab9be1
Merge CreatePhysicalSNIHandle
edwardneal Jun 3, 2025
1e4724e
Refactor to insert FreeGcHandle
edwardneal Jun 3, 2025
f824db7
Move CreateConsumerInfo and _gcHandle to TdsParserStateObjectNative
edwardneal Jun 3, 2025
ab27513
Merge Dispose
edwardneal Jun 3, 2025
34be57d
Merge branch 'main' into merge/tdsparserstateobject-lifetimes
edwardneal Jun 3, 2025
ecd0dd4
Merge main
edwardneal Jun 5, 2025
95322d3
Merge branch 'main' into merge/tdsparserstateobject-lifetimes
benrr101 Jun 23, 2025
72d9c8d
Add region to both TdsParserStateObjectNative files
edwardneal Jun 23, 2025
76a97d3
Make public constructor internal
edwardneal Jun 23, 2025
49da161
Merge branch 'main' into merge/tdsparserstateobject-lifetimes
edwardneal Jul 2, 2025
879246a
Remove redundant assignment to _serverSpn
edwardneal Jul 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,6 @@ internal void Connect(ServerInfo serverInfo,
}
else
{
_serverSpn = null;
SqlClientEventSource.Log.TryTraceEvent("TdsParser.Connect | SEC | Connection Object Id {0}, Authentication Mode: {1}", _connHandler.ObjectID,
authType == SqlAuthenticationMethod.NotSpecified ? SqlAuthenticationMethod.SqlPassword.ToString() : authType.ToString());
}
Expand Down Expand Up @@ -450,6 +449,8 @@ internal void Connect(ServerInfo serverInfo,
false,
true,
fParallel,
TransparentNetworkResolutionState.DisabledMode,
-1,
_connHandler.ConnectionOptions.IPAddressPreference,
FQDNforDNSCache,
ref _connHandler.pendingSQLDNSObject,
Expand Down Expand Up @@ -550,6 +551,8 @@ internal void Connect(ServerInfo serverInfo,
true,
true,
fParallel,
TransparentNetworkResolutionState.DisabledMode,
-1,
_connHandler.ConnectionOptions.IPAddressPreference,
FQDNforDNSCache,
ref _connHandler.pendingSQLDNSObject,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ internal static void PrepareConstrainedRegions()
// Constructors //
//////////////////

internal TdsParserStateObject(TdsParser parser, TdsParserStateObject physicalConnection, bool async)
protected TdsParserStateObject(TdsParser parser, TdsParserStateObject physicalConnection, bool async)
{
// Construct a MARS session
Debug.Assert(parser != null, "no parser?");
Expand Down Expand Up @@ -67,42 +67,19 @@ internal TdsParserStateObject(TdsParser parser, TdsParserStateObject physicalCon
// General methods //
/////////////////////

internal abstract void CreatePhysicalSNIHandle(
string serverName,
TimeoutTimer timeout,
out byte[] instanceName,
ref string[] spns,
bool flushCache,
bool async,
bool fParallel,
SqlConnectionIPAddressPreference iPAddressPreference,
string cachedFQDN,
ref SQLDNSInfo pendingDNSInfo,
string serverSPN,
bool isIntegratedSecurity = false,
bool tlsFirst = false,
string hostNameInCertificate = "",
string serverCertificateFilename = "");

internal abstract void AssignPendingDNSInfo(string userProtocol, string DNSCacheKey, ref SQLDNSInfo pendingDNSInfo);

protected abstract void CreateSessionHandle(TdsParserStateObject physicalConnection, bool async);

protected abstract void FreeGcHandle(int remaining, bool release);

internal abstract uint EnableSsl(ref uint info, bool tlsFirst, string serverCertificateFilename);

internal abstract uint WaitForSSLHandShakeToComplete(out int protocolVersion);

internal abstract void Dispose();

internal abstract uint CheckConnection();

internal int DecrementPendingCallbacks(bool release)
{
int remaining = Interlocked.Decrement(ref _pendingCallbacks);
SqlClientEventSource.Log.TryAdvancedTraceEvent("TdsParserStateObject.DecrementPendingCallbacks | ADV | State Object Id {0}, after decrementing _pendingCallbacks: {1}", _objectID, _pendingCallbacks);

FreeGcHandle(remaining, release);

// NOTE: TdsParserSessionPool may call DecrementPendingCallbacks on a TdsParserStateObject which is already disposed
// This is not dangerous (since the stateObj is no longer in use), but we need to add a workaround in the assert for it
Debug.Assert((remaining == -1 && SessionHandle.IsNull) || (0 <= remaining && remaining < 3), $"_pendingCallbacks values is invalid after decrementing: {remaining}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ internal override void CreatePhysicalSNIHandle(
bool flushCache,
bool async,
bool parallel,
TransparentNetworkResolutionState transparentNetworkResolutionState,
int totalTimeout,
SqlConnectionIPAddressPreference iPAddressPreference,
string cachedFQDN,
ref SQLDNSInfo pendingDNSInfo,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,12 @@ internal TdsParserStateObjectNative(TdsParser parser, TdsParserStateObject physi
{
}

public TdsParserStateObjectNative(TdsParser parser)
internal TdsParserStateObjectNative(TdsParser parser)
: base(parser)
{
}

////////////////
// Properties //
////////////////
#region Properties

internal SNIHandle Handle => _sessionHandle;

Expand All @@ -71,6 +69,8 @@ public TdsParserStateObjectNative(TdsParser parser)

internal override Guid? SessionId => default;

#endregion

protected override void CreateSessionHandle(TdsParserStateObject physicalConnection, bool async)
{
Debug.Assert(physicalConnection is TdsParserStateObjectNative, "Expected a stateObject of type " + this.GetType());
Expand All @@ -83,6 +83,9 @@ protected override void CreateSessionHandle(TdsParserStateObject physicalConnect
_sessionHandle = new SNIHandle(myInfo, nativeSNIObject.Handle, _parser.Connection.ConnectionOptions.IPAddressPreference, cachedDNSInfo);
}

// Retrieve the IP and port number from native SNI for TCP protocol. The IP information is stored temporarily in the
// pendingSQLDNSObject but not in the DNS Cache at this point. We only add items to the DNS Cache after we receive the
// IsSupported flag as true in the feature ext ack from server.
internal override void AssignPendingDNSInfo(string userProtocol, string DNSCacheKey, ref SQLDNSInfo pendingDNSInfo)
{
uint result;
Expand Down Expand Up @@ -159,7 +162,9 @@ internal override void CreatePhysicalSNIHandle(
bool flushCache,
bool async,
bool fParallel,
SqlConnectionIPAddressPreference ipPreference,
TransparentNetworkResolutionState transparentNetworkResolutionState,
int totalTimeout,
SqlConnectionIPAddressPreference iPAddressPreference,
string cachedFQDN,
ref SQLDNSInfo pendingDNSInfo,
string serverSPN,
Expand Down Expand Up @@ -188,7 +193,7 @@ internal override void CreatePhysicalSNIHandle(
bool ret = SQLFallbackDNSCache.Instance.GetDNSInfo(cachedFQDN, out cachedDNSInfo);

_sessionHandle = new SNIHandle(myInfo, serverName, ref serverSPN, timeout.MillisecondsRemainingInt, out instanceName,
flushCache, !async, fParallel, ipPreference, cachedDNSInfo, hostNameInCertificate);
flushCache, !async, fParallel, iPAddressPreference, cachedDNSInfo, hostNameInCertificate);
spns = new[] { serverSPN.TrimEnd() };
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ internal sealed partial class TdsParser

private bool _is2022 = false;

private string _serverSpn = null;
private string[] _serverSpn = null;

// SqlStatistics
private SqlStatistics _statistics = null;
Expand Down Expand Up @@ -395,6 +395,11 @@ internal void Connect(ServerInfo serverInfo,
ThrowExceptionAndWarning(_physicalStateObj);
Debug.Fail("SNI returned status != success, but no error thrown?");
}
else
{
SqlClientEventSource.Log.TryTraceEvent("TdsParser.Connect | SEC | Connection Object Id {0}, Authentication Mode: {1}", _connHandler.ObjectID,
authType == SqlAuthenticationMethod.NotSpecified ? SqlAuthenticationMethod.SqlPassword.ToString() : authType.ToString());
}

//Create LocalDB instance if necessary
if (connHandler.ConnectionOptions.LocalDBInstance != null)
Expand All @@ -408,28 +413,17 @@ internal void Connect(ServerInfo serverInfo,
}
}

_serverSpn = null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duplicate of line 400

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks - removed from netfx and netcore.


// AD Integrated behaves like Windows integrated when connecting to a non-fedAuth server
if (integratedSecurity || authType == SqlAuthenticationMethod.ActiveDirectoryIntegrated)
{
_authenticationProvider = _physicalStateObj.CreateSspiContextProvider();

if (!string.IsNullOrEmpty(serverInfo.ServerSPN))
{
_serverSpn = serverInfo.ServerSPN;
SqlClientEventSource.Log.TryTraceEvent("<sc.TdsParser.Connect|SEC> Server SPN `{0}` from the connection string is used.", serverInfo.ServerSPN);
}
else
{
// Empty signifies to interop layer that SPN needs to be generated
_serverSpn = string.Empty;
}

SqlClientEventSource.Log.TryTraceEvent("<sc.TdsParser.Connect|SEC> SSPI or Active Directory Authentication Library for SQL Server based integrated authentication");
}
else
{
_authenticationProvider = null;
_serverSpn = null;

switch (authType)
{
Expand Down Expand Up @@ -516,7 +510,12 @@ internal void Connect(ServerInfo serverInfo,
totalTimeout,
_connHandler.ConnectionOptions.IPAddressPreference,
FQDNforDNSCache,
hostNameInCertificate);
ref _connHandler.pendingSQLDNSObject,
serverInfo.ServerSPN,
integratedSecurity || authType == SqlAuthenticationMethod.ActiveDirectoryIntegrated,
isTlsFirst,
hostNameInCertificate,
serverCertificateFilename);

_authenticationProvider?.Initialize(serverInfo, _physicalStateObj, this);

Expand Down Expand Up @@ -559,7 +558,7 @@ internal void Connect(ServerInfo serverInfo,
Debug.Assert(result == TdsEnums.SNI_SUCCESS, "Unexpected failure state upon calling SniGetConnectionId");

// for DNS Caching phase 1
AssignPendingDNSInfo(serverInfo.UserProtocol, FQDNforDNSCache);
_physicalStateObj.AssignPendingDNSInfo(serverInfo.UserProtocol, FQDNforDNSCache, ref _connHandler.pendingSQLDNSObject);

if (!ClientOSEncryptionSupport)
{
Expand Down Expand Up @@ -609,8 +608,13 @@ internal void Connect(ServerInfo serverInfo,
transparentNetworkResolutionState,
totalTimeout,
_connHandler.ConnectionOptions.IPAddressPreference,
serverInfo.ResolvedServerName,
hostNameInCertificate);
FQDNforDNSCache,
ref _connHandler.pendingSQLDNSObject,
serverInfo.ServerSPN,
integratedSecurity,
isTlsFirst,
hostNameInCertificate,
serverCertificateFilename);

_authenticationProvider?.Initialize(serverInfo, _physicalStateObj, this);

Expand All @@ -626,7 +630,7 @@ internal void Connect(ServerInfo serverInfo,
SqlClientEventSource.Log.TryTraceEvent("<sc.TdsParser.Connect|SEC> Sending prelogin handshake");

// for DNS Caching phase 1
AssignPendingDNSInfo(serverInfo.UserProtocol, FQDNforDNSCache);
_physicalStateObj.AssignPendingDNSInfo(serverInfo.UserProtocol, FQDNforDNSCache, ref _connHandler.pendingSQLDNSObject);

SendPreLoginHandshake(instanceName, encrypt, integratedSecurity, serverCertificateFilename);
status = ConsumePreLoginHandshake(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,61 +43,7 @@ internal void BestEffortCleanup()
}
}
}

// Retrieve the IP and port number from native SNI for TCP protocol. The IP information is stored temporarily in the
// pendingSQLDNSObject but not in the DNS Cache at this point. We only add items to the DNS Cache after we receive the
// IsSupported flag as true in the feature ext ack from server.
internal void AssignPendingDNSInfo(string userProtocol, string DNSCacheKey)
{
uint result;
ushort portFromSNI = 0;
string IPStringFromSNI = string.Empty;
IPAddress IPFromSNI;
isTcpProtocol = false;
Provider providerNumber = Provider.INVALID_PROV;

if (string.IsNullOrEmpty(userProtocol))
{

result = SniNativeWrapper.SniGetProviderNumber(_physicalStateObj.Handle, ref providerNumber);
Debug.Assert(result == TdsEnums.SNI_SUCCESS, "Unexpected failure state upon calling SniGetProviderNumber");
isTcpProtocol = (providerNumber == Provider.TCP_PROV);
}
else if (userProtocol == TdsEnums.TCP)
{
isTcpProtocol = true;
}

// serverInfo.UserProtocol could be empty
if (isTcpProtocol)
{
result = SniNativeWrapper.SniGetConnectionPort(_physicalStateObj.Handle, ref portFromSNI);
Debug.Assert(result == TdsEnums.SNI_SUCCESS, "Unexpected failure state upon calling SniGetConnectionPort");


result = SniNativeWrapper.SniGetConnectionIpString(_physicalStateObj.Handle, ref IPStringFromSNI);
Debug.Assert(result == TdsEnums.SNI_SUCCESS, "Unexpected failure state upon calling SniGetConnectionIPString");

_connHandler.pendingSQLDNSObject = new SQLDNSInfo(DNSCacheKey, null, null, portFromSNI.ToString());

if (IPAddress.TryParse(IPStringFromSNI, out IPFromSNI))
{
if (System.Net.Sockets.AddressFamily.InterNetwork == IPFromSNI.AddressFamily)
{
_connHandler.pendingSQLDNSObject.AddrIPv4 = IPStringFromSNI;
}
else if (System.Net.Sockets.AddressFamily.InterNetworkV6 == IPFromSNI.AddressFamily)
{
_connHandler.pendingSQLDNSObject.AddrIPv6 = IPStringFromSNI;
}
}
}
else
{
_connHandler.pendingSQLDNSObject = null;
}
}


// @TODO: Consider adopting this pattern for all usages of Run and rename to Run.
internal bool RunReliably(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
{
Expand Down
Loading
Loading