Skip to content
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

Introducing type based Token parsing and processing #2758

Draft
wants to merge 6 commits into
base: feat/sqlclientx
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -923,6 +923,7 @@
<AutoGen>True</AutoGen>
<DependentUpon>Strings.resx</DependentUpon>
</Compile>
<Compile Include="Microsoft\Data\SqlClientX\IO\ByteBuffer.cs" />
<Compile Include="Microsoft\Data\SqlClientX\IO\TdsBufferManager.cs" />
<Compile Include="Microsoft\Data\SqlClientX\IO\TdsReader.cs" />
<Compile Include="Microsoft\Data\SqlClientX\IO\TdsWriter.cs" />
Expand Down Expand Up @@ -969,6 +970,66 @@
<Compile Include="Microsoft\Data\SqlClientX\SqlConnector.cs" />
<Compile Include="Microsoft\Data\SqlClientX\SqlDataSource.cs" />
<Compile Include="Microsoft\Data\SqlClientX\SqlDataSourceBuilder.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\State\TdsCommandContext.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\State\TdsConnectionState.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\State\TdsContext.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\State\TdsErrorWarningsState.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\State\TdsTransactionState.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\State\TdsSnapshotState.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\State\TdsTimeoutState.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\State\ITdsEventListener.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\TdsParserX.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\TdsUtils.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\DataClassification\DataClassificationToken.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\DataClassification\DataClassificationTokenParser.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\DoneInProc\DoneInProcToken.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\DoneInProc\DoneInProcTokenParser.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\DoneProc\DoneProcToken.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\DoneProc\DoneProcTokenParser.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\Done\DoneStatus.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\Done\DoneToken.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\Done\DoneTokenParser.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\EnvChange\CharsetEnvChangeToken.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\EnvChange\PromoteTransactionEnvChangeToken.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\EnvChange\TransactionEnvChangeToken.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\EnvChange\DatabaseEnvChangeToken.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\EnvChange\DatabaseMirroringPartnerEnvChangeToken.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\EnvChange\EnvChangeToken.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\EnvChange\EnvChangeTokenParser.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\EnvChange\EnvChangeTokenProcessor.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\EnvChange\EnvChangeTokenSubType.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\EnvChange\LanguageEnvChangeToken.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\EnvChange\PacketSizeEnvChangeToken.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\EnvChange\ResetConnectionEnvChangeToken.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\EnvChange\RoutingEnvChangeToken.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\EnvChange\RoutingInfo.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\EnvChange\SqlCollationEnvChangeToken.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\Error\ErrorToken.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\Error\ErrorTokenParser.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\Error\ErrorTokenProcessor.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\FeatureExtAck\FeatureExtAckToken.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\FeatureExtAck\FeatureExtAckTokenParser.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\FeatureExtAck\FeatureId.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\FedAuthInfo\FedAuthInfoId.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\FedAuthInfo\FedAuthInfoToken.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\FedAuthInfo\FedAuthInfoTokenParser.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\Info\InfoToken.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\Info\InfoTokenParser.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\Info\InfoTokenProcessor.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\LoginAck\LoginAckToken.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\LoginAck\LoginAckTokenParser.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\LoginAck\LoginAckTokenProcessor.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\LoginAck\ProgVersion.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\LoginAck\SqlInterfaceType.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\TdsVersion.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\ReturnStatus\ReturnStatusToken.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\ReturnStatus\ReturnStatusTokenParser.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\Token.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\TokenParser.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\TokenProcessingHandler.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\TokenProcessor.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\TokenStreamHandler.cs" />
<Compile Include="Microsoft\Data\SqlClientX\Tds\Tokens\TokenType.cs" />
<Compile Include="Microsoft\Data\SqlClientX\UnpooledDataSource.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="$(CommonSourceRoot)Resources\Strings.resx">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#if NET8_0_OR_GREATER

using System;
using System.Collections.Generic;
using System.IO;
Expand All @@ -13,13 +15,22 @@
using Microsoft.Data.SqlClient.SNI;
using Microsoft.Data.SqlClientX.Handlers.Connection.Login;
using Microsoft.Data.SqlClientX.IO;
using Microsoft.Data.SqlClientX.Tds;
using Microsoft.Data.SqlClientX.Tds.State;

namespace Microsoft.Data.SqlClientX.Handlers.Connection
{ /// <summary>
/// Class that contains all context data needed for various handlers.
/// </summary>
internal class ConnectionHandlerContext : HandlerRequest, ICloneable
{
private TdsStream _tdsStream;

/// <summary>
/// Tds Parser to be used for parsing login response.
/// </summary>
internal TdsParserX TdsParser { get; private set; }

// TODO: Decide if we need a default constructor depending on the latest design
/// <summary>
/// Stream used by readers.
Expand Down Expand Up @@ -57,10 +68,22 @@ internal class ConnectionHandlerContext : HandlerRequest, ICloneable
/// </summary>
public SslOverTdsStream SslOverTdsStream { get; internal set; }

/// <summary>
/// Event listener to capture Info and Error events
/// </summary>
public ITdsEventListener TdsEventListener { get; internal set; }

/// <summary>
/// The TdsStream to write Tds Packets to.
/// </summary>
public TdsStream TdsStream { get; internal set; }
public TdsStream TdsStream {
get => _tdsStream;
set
{
_tdsStream = value;
TdsParser = new TdsParserX(value, TdsEventListener);
}
}

/// <summary>
/// Whether the connection is capable of MARS
Expand Down Expand Up @@ -129,7 +152,8 @@ public object Clone()
ConnectionId = this.ConnectionId,
SslStream = this.SslStream,
SslOverTdsStream = this.SslOverTdsStream,
TdsStream = this.TdsStream,
TdsStream = this.TdsStream,
TdsEventListener = this.TdsEventListener,
IsMarsCapable = this.IsMarsCapable,
IsFedAuthNegotiatedInPrelogin = this.IsFedAuthNegotiatedInPrelogin,
AccessTokenInBytes = this.AccessTokenInBytes,
Expand Down Expand Up @@ -157,3 +181,5 @@ private void AddToRoutingHistory(ConnectionHandlerContext context)

}
}

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#if NET8_0_OR_GREATER

using System.Threading;
using System.Threading.Tasks;

Expand All @@ -22,7 +24,11 @@ public static ValueTask ProcessRequestAsync(ConnectionHandlerContext context, bo
NextHandler = new TransportCreationHandler()
{
NextHandler = new PreloginHandler()
{
NextHandler = new LoginHandler()
}
}
}.Handle(context, isAsync, ct);
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#if NET8_0_OR_GREATER

using System.Threading;
using System.Threading.Tasks;
using Microsoft.Data.SqlClient;
Expand All @@ -18,7 +20,7 @@ internal class DataSourceParsingHandler : ContextHandler<ConnectionHandlerContex
public override ValueTask Handle(ConnectionHandlerContext request, bool isAsync, CancellationToken ct)
{
ServerInfo serverInfo = request.ServerInfo;
string fullServerName = serverInfo.ExtendedServerName;
string fullServerName = serverInfo.ExtendedServerName ?? serverInfo.UserServerName;
string localDBDataSource = GetLocalDBDataSource(fullServerName, out bool errorWithLocalDBProcessing);

if (errorWithLocalDBProcessing)
Expand Down Expand Up @@ -80,3 +82,4 @@ private static string GetLocalDBDataSource(string fullServerName, out bool error
}
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#if NET8_0_OR_GREATER

using System;
using System.Diagnostics;
using System.Threading;
Expand Down Expand Up @@ -629,3 +631,4 @@ internal static bool ShouldRequest(LoginHandlerContext context)
}
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#if NET8_0_OR_GREATER

using System;
using System.Security;
using System.Threading;
Expand Down Expand Up @@ -188,3 +190,4 @@ public int CalculateLoginRecordLength()
}
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#if NET8_0_OR_GREATER

using System;
using System.Buffers;
using System.Diagnostics;
Expand Down Expand Up @@ -50,8 +52,7 @@ public override async ValueTask Handle(ConnectionHandlerContext context, bool is
LoginHandlerContext loginHandlerContext = new LoginHandlerContext(context);
await SendLogin(loginHandlerContext, isAsync, ct).ConfigureAwait(false);

// TODO: Complete the login by reading data.
// This requires parsing by reading token stream from TDS.
await context.TdsParser.RunAsync(RunBehavior.UntilDone, isAsync, ct);
}

private async ValueTask SendLogin(LoginHandlerContext context, bool isAsync, CancellationToken ct)
Expand All @@ -75,15 +76,15 @@ private async ValueTask TdsLogin(LoginHandlerContext context, bool isAsync, Canc
Debug.Assert(TdsEnums.MAXLEN_CLIENTINTERFACE >= context.ClientInterfaceName.Length, "cchCltIntName can specify at most 128 unicode characters. See Tds spec");

// Calculate the fixed length
length += context.CalculateLoginRecordLength();

length += context.CalculateLoginRecordLength();

string userName = context.UserName;
byte[] encryptedPassword = context.EncryptedPassword;
int encryptedPasswordLengthInBytes = encryptedPassword != null ? encryptedPassword.Length : 0;

PasswordChangeRequest passwordChangeRequest = context.PasswordChangeRequest;
byte[] encryptedChangePassword = passwordChangeRequest?.NewSecurePassword == null ? null: TdsParserStaticMethods.ObfuscatePassword(passwordChangeRequest.NewPassword);
byte[] encryptedChangePassword = passwordChangeRequest?.NewSecurePassword == null ? null : TdsParserStaticMethods.ObfuscatePassword(passwordChangeRequest.NewPassword);
int encryptedChangePasswordLength = encryptedChangePassword != null ? encryptedChangePassword.Length : 0;
int encryptedChangePasswordLengthInBytes = passwordChangeRequest?.NewSecurePassword != null ? passwordChangeRequest.NewSecurePassword.Length : encryptedChangePasswordLength;

Expand Down Expand Up @@ -140,7 +141,7 @@ await WriteLoginData(context,

TdsStream stream = context.TdsStream;
ct.ThrowIfCancellationRequested();

if (isAsync)
{
await stream.FlushAsync(ct).ConfigureAwait(false);
Expand Down Expand Up @@ -199,7 +200,7 @@ private int CalculateFeatureExtensionLength(LoginHandlerContext context)
}


private async ValueTask WriteLoginData(LoginHandlerContext context,
private async ValueTask WriteLoginData(LoginHandlerContext context,
SessionData recoverySessionData,
byte[] encryptedPassword,
byte[] encryptedChangePassword,
Expand Down Expand Up @@ -229,7 +230,7 @@ private async ValueTask WriteLoginData(LoginHandlerContext context,
if (recoverySessionData == null)
{
int protocolVersion = encrypt == SqlConnectionEncryptOption.Strict
? (TdsEnums.TDS8_MAJOR << 24) | (TdsEnums.TDS8_INCREMENT << 16) | TdsEnums.TDS8_MINOR
? (TdsEnums.TDS8_MAJOR << 24) | (TdsEnums.TDS8_INCREMENT << 16) | TdsEnums.TDS8_MINOR
: (TdsEnums.SQL2012_MAJOR << 24) | (TdsEnums.SQL2012_INCREMENT << 16) | TdsEnums.SQL2012_MINOR;
await writer.WriteIntAsync(protocolVersion, isAsync, ct).ConfigureAwait(false);
}
Expand All @@ -244,10 +245,10 @@ private async ValueTask WriteLoginData(LoginHandlerContext context,
await writer.WriteIntAsync(0, isAsync, ct).ConfigureAwait(false); // connectionID is unused

// Log7Flags (DWORD)

int log7Flags = CreateLogin7Flags(context);
await writer.WriteIntAsync(log7Flags, isAsync, ct).ConfigureAwait(false);

await writer.WriteIntAsync(0, isAsync, ct).ConfigureAwait(false); // ClientTimeZone is not used
await writer.WriteIntAsync(0, isAsync, ct).ConfigureAwait(false); // LCID is unused by server

Expand Down Expand Up @@ -318,7 +319,7 @@ private async ValueTask WriteLoginData(LoginHandlerContext context,
s_nicAddress = TdsParserStaticMethods.GetNetworkPhysicalAddressForTdsLoginOnly();

await stream.TdsWriter.WriteBytesAsync(s_nicAddress.AsMemory(), isAsync, ct).ConfigureAwait(false);

await writer.WriteShortAsync(offset, isAsync, ct).ConfigureAwait(false); // ibSSPI offset
if (context.UseSspi)
{
Expand Down Expand Up @@ -373,7 +374,7 @@ private async ValueTask WriteLoginData(LoginHandlerContext context,
await stream.WriteStringAsync(clientInterfaceName, isAsync, ct).ConfigureAwait(false);
await stream.WriteStringAsync(context.Language, isAsync, ct).ConfigureAwait(false);
await stream.WriteStringAsync(context.Database, isAsync, ct).ConfigureAwait(false);

// send over SSPI data if we are using SSPI
if (context.UseSspi)
{
Expand All @@ -395,8 +396,8 @@ private async ValueTask WriteLoginData(LoginHandlerContext context,
}
}

await SendFeatureExtensionData(context,
isAsync,
await SendFeatureExtensionData(context,
isAsync,
ct).ConfigureAwait(false);
}
catch (Exception e)
Expand Down Expand Up @@ -526,3 +527,4 @@ private static int CreateLogin7Flags(LoginHandlerContext context)
}
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#if NET8_0_OR_GREATER

using System.IO;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
Expand Down Expand Up @@ -145,3 +147,4 @@ public virtual IHandler<PreloginHandlerContext> CreateChain(PreloginHandlerConte
}
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#if NET8_0_OR_GREATER

using Microsoft.Data.SqlClient;

namespace Microsoft.Data.SqlClientX.Handlers.Connection.PreloginSubHandlers
Expand Down Expand Up @@ -120,3 +122,4 @@ public bool DoesClientNeedEncryption() =>

}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#if NET8_0_OR_GREATER

using System;
using System.Buffers.Binary;
using System.Diagnostics;
Expand Down Expand Up @@ -376,3 +378,4 @@ private static async Task CreatePreloginAndSend(PreloginHandlerContext context,
}
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
#if NET8_0_OR_GREATER

using System.Net.Security;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
Expand Down Expand Up @@ -81,3 +82,4 @@ private static SslClientAuthenticationOptions BuildClientAuthenticationOptions(P
}
}
}
#endif
Loading
Loading