From 5c505a1955f2e2966f58bad32011348b2d9de143 Mon Sep 17 00:00:00 2001 From: Aris Rellegue Date: Thu, 8 Jun 2023 10:43:57 -0700 Subject: [PATCH 1/8] Add SqlConnectionEncryptOptionConverter class which is used to convert string Encrypt option into SqlConnectionEncryptionOption type. --- .../SqlConnectionEncryptOptionConverter.xml | 51 ++++++++++ src/Microsoft.Data.SqlClient.sln | 1 + .../src/Microsoft.Data.SqlClient.csproj | 3 + .../netfx/src/Microsoft.Data.SqlClient.csproj | 3 + .../SqlClient/SqlConnectionEncryptOption.cs | 2 + .../SqlConnectionEncryptOptionConverter.cs | 46 +++++++++ .../Microsoft.Data.SqlClient.Tests.csproj | 1 + .../SqlConnectionStringBuilderTest.cs | 93 +++++++++++++++++++ 8 files changed, 200 insertions(+) create mode 100644 doc/snippets/Microsoft.Data.SqlClient/SqlConnectionEncryptOptionConverter.xml create mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionEncryptOptionConverter.cs diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionEncryptOptionConverter.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionEncryptOptionConverter.xml new file mode 100644 index 0000000000..9f26bc71c7 --- /dev/null +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionEncryptOptionConverter.xml @@ -0,0 +1,51 @@ + + + + + Converts a string Sql Connection Encrypt option into SqlConnectionEncryptOption object + + + ## Remarks +Implicit conversions have been added to maintain backwards compatibility with boolean behahavior for the property. When converting from a boolean, a value of `true` converts to and a value of `false` converts to . When converting to a boolean, , , and `null` convert to `true` and converts `false`. + + + + + + If the source type is a string then conversion is allowed . + + A string containing the value to convert. + + if the parameter can be converted successfully; otherwise, . + + This method does not throw an exception. + + + + Converts the specified string representation of a logical value to its equivalent. + + A string containing the value to convert. + + An object that is equivalent to . + + + An object that is equivalent to with value of if conversion was successful; + otherwise, an exception is thrown. + + This method throws an exception if conversion fails. + + + + Converts an object value to its string representation. + + An object containing the value to convert. + + A string representation of the value of . + + + A string representation of the value of . + + This method does not throw an exception if conversion fails. + + + diff --git a/src/Microsoft.Data.SqlClient.sln b/src/Microsoft.Data.SqlClient.sln index c5b34945a0..a94447bf12 100644 --- a/src/Microsoft.Data.SqlClient.sln +++ b/src/Microsoft.Data.SqlClient.sln @@ -121,6 +121,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Microsoft.Data.SqlClient", ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionAttestationProtocol.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionAttestationProtocol.xml ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionColumnEncryptionSetting.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionColumnEncryptionSetting.xml ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionEncryptOption.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionEncryptOption.xml + ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionEncryptOptionConverter.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionEncryptOptionConverter.xml ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionStringBuilder.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionStringBuilder.xml ..\doc\snippets\Microsoft.Data.SqlClient\SqlCredential.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlCredential.xml ..\doc\snippets\Microsoft.Data.SqlClient\SqlDataAdapter.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlDataAdapter.xml diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj index be1eb19b17..41f8374191 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -330,6 +330,9 @@ Microsoft\Data\SqlClient\SqlConnectionEncryptOption.cs + + Microsoft\Data\SqlClient\SqlConnectionEncryptOptionConverter.cs + Microsoft\Data\SqlClient\SqlConnectionPoolGroupProviderInfo.cs diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj index 4492274116..675dd57fe6 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -422,6 +422,9 @@ Microsoft\Data\SqlClient\SqlConnectionEncryptOption.cs + + Microsoft\Data\SqlClient\SqlConnectionEncryptOptionConverter.cs + Microsoft\Data\SqlClient\SqlConnectionPoolGroupProviderInfo.cs diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionEncryptOption.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionEncryptOption.cs index ecabdb9f04..997833437f 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionEncryptOption.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionEncryptOption.cs @@ -3,11 +3,13 @@ // See the LICENSE file in the project root for more information. using System; +using System.ComponentModel; using Microsoft.Data.Common; namespace Microsoft.Data.SqlClient { /// + [TypeConverter(typeof(SqlConnectionEncryptOptionConverter))] public sealed class SqlConnectionEncryptOption { private const string TRUE = "True"; diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionEncryptOptionConverter.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionEncryptOptionConverter.cs new file mode 100644 index 0000000000..da5eb6f8a1 --- /dev/null +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionEncryptOptionConverter.cs @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// 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; +using System.ComponentModel; +using System.Globalization; +using System.Drawing; + +namespace Microsoft.Data.SqlClient +{ + /// + public class SqlConnectionEncryptOptionConverter : TypeConverter + { + // Overrides the CanConvertFrom method of TypeConverter. + // The ITypeDescriptorContext interface provides the context for the + // conversion. Typically, this interface is used at design time to + // provide information about the design-time container. + /// + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + { + if (sourceType == typeof(string)) + { + return true; + } + return base.CanConvertFrom(context, sourceType); + } + // Overrides the ConvertFrom method of TypeConverter. + /// + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + if (value is string) + { + return SqlConnectionEncryptOption.Parse(value.ToString()); + } + throw new Exception("Value to convert must be of string type!"); + } + // Overrides the ConvertTo method of TypeConverter. + /// + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + return base.ConvertTo(context, culture, value, destinationType); + } + } +} diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj index 9d1e8d5087..408d7ffa61 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj @@ -66,6 +66,7 @@ + diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionStringBuilderTest.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionStringBuilderTest.cs index 2bc842566a..591a426568 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionStringBuilderTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionStringBuilderTest.cs @@ -4,6 +4,12 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.IO; +using System.Text; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; using Xunit; namespace Microsoft.Data.SqlClient.Tests @@ -468,6 +474,36 @@ public void EncryptTryParseInvalidValuesReturnsFalse(string value) Assert.Null(result); } + [Theory] + [InlineData("false","False")] + [InlineData("true", "True")] + [InlineData("strict", "Strict")] + [InlineData("mandatory","True")] + [InlineData("optional", "False")] + [InlineData("yes", "True")] + [InlineData("no", "False")] + [InlineData("absolutely", "True")] + [InlineData("affirmative", "True")] + [InlineData("never", "True")] + [InlineData("always", "True")] + [InlineData("none", "True")] + public void ConnectionStringFromJsonTests(string value, string expectedValue) + { + ExecuteConnectionStringFromJsonTests(value, expectedValue); + } + + [Theory] + [InlineData("absolutely")] + [InlineData("affirmative")] + [InlineData("never")] + [InlineData("always")] + [InlineData("none")] + [InlineData(" for sure ")] + public void ConnectionStringFromJsonThrowsException(string value) + { + ExecuteConnectionStringFromJsonThrowsException(value); + } + internal void ExecuteConnectionStringTests(string connectionString) { SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectionString); @@ -495,5 +531,62 @@ internal static void CheckEncryptType(SqlConnectionStringBuilder builder, SqlCon Assert.IsType(builder.Encrypt); Assert.Equal(expectedValue, builder.Encrypt); } + + internal void ExecuteConnectionStringFromJsonTests(string encryptOption, string result) + { + var settings = LoadSettingsFromJsonStream(encryptOption); + var connectionString = settings!.UserDb!.ToString(); + Assert.Contains($"Encrypt={result}", connectionString, StringComparison.InvariantCultureIgnoreCase); + } + + internal void ExecuteConnectionStringFromJsonThrowsException(string encryptOption) + { + Assert.Throws(() => LoadSettingsFromJsonStream(encryptOption)); + } + + TSettings LoadSettingsFromJsonStream(string encryptOption) where TSettings : class + { + TSettings settingsOut = null; + + Host.CreateDefaultBuilder() + .ConfigureAppConfiguration((ctx, configBuilder) => + { + // Note: Inside string interpolation, a { should be {{ and a } should be }} + // First, declare a stringified JSON + var json = $"{{ \"UserDb\": {{ \"UserComponents\": {{ \"NetworkLibrary\": \"DBMSSOCN\", \"UserID\": \"user\", \"Password\": \"password\", \"DataSource\": \"localhost\", \"InitialCatalog\": \"catalog\", \"Encrypt\": \"{encryptOption}\" }}}}}}"; + + // Load the stringified JSON as a stream into the configuration builder + configBuilder.AddJsonStream(new MemoryStream(Encoding.ASCII.GetBytes(json))); + configBuilder.AddEnvironmentVariables(); + }) + .ConfigureServices((ctx, services) => + { + var configuration = ctx.Configuration; + services.AddOptions(); + services.Configure(ctx.Configuration); + settingsOut = configuration.Get(); + }) + .Build(); + + return settingsOut; + } + } + + // These 2 classes will be used by ConnectionStringFromJsonTests only + internal class UserDbConnectionStringSettings + { + [Required] + public UserSqlConnectionString UserDb { get; set; } + } + + internal class UserSqlConnectionString + { + public SqlConnectionStringBuilder UserComponents { get; set; } = new(); + + public override string ToString() + { + return UserComponents!.ConnectionString; + } } + } From cde043009d57f456b90e2b4fa4faf8f0c6dabefd Mon Sep 17 00:00:00 2001 From: v-arellegue Date: Tue, 13 Jun 2023 08:37:36 -0700 Subject: [PATCH 2/8] Fixed Issue #1126 .NET Core SqlConnection ConnectTimout 15 less than not work? --- build.proj | 2 +- .../Microsoft/Data/SqlClient/SNI/SNIProxy.cs | 2 - .../SqlClient/SqlInternalConnectionTds.cs | 4 -- .../src/Microsoft/Data/SqlClient/TdsParser.cs | 3 -- .../Data/SqlClient/TdsParserStateObject.cs | 1 - .../SqlClient/TdsParserStateObjectManaged.cs | 3 +- .../SqlClient/TdsParserStateObjectNative.cs | 3 +- .../Data/SqlClient/TdsParserStateObject.cs | 2 +- .../SqlClient/TdsParserSafeHandles.Windows.cs | 9 ---- .../SqlConnectionBasicTests.cs | 52 +++++++++++++++++++ 10 files changed, 56 insertions(+), 25 deletions(-) diff --git a/build.proj b/build.proj index 2e1ba19930..465f9264c3 100644 --- a/build.proj +++ b/build.proj @@ -105,7 +105,7 @@ - $(DotNetCmd) dotnet build -c Release -p:ReferenceType=$(ReferenceType)" + $(DotNetCmd) dotnet build -c Release -p:ReferenceType=$(ReferenceType) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs index ac4d3599dd..19659a2d93 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs @@ -130,7 +130,6 @@ private static bool IsErrorStatus(SecurityStatusPalErrorCode errorCode) /// Create a SNI connection handle /// /// Full server name from connection string - /// Ignore open timeout /// Timer expiration /// Instance name /// SPN @@ -148,7 +147,6 @@ private static bool IsErrorStatus(SecurityStatusPalErrorCode errorCode) /// SNI handle internal static SNIHandle CreateConnectionHandle( string fullServerName, - bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, ref byte[][] spnBuffer, diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs index 66631151c9..5e3a4ad25f 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs @@ -1538,7 +1538,6 @@ private void LoginNoFailover(ServerInfo serverInfo, AttemptOneLogin(serverInfo, newPassword, newSecurePassword, - !connectionOptions.MultiSubnetFailover, // ignore timeout for SniOpen call unless MSF connectionOptions.MultiSubnetFailover ? intervalTimer : timeout); if (connectionOptions.MultiSubnetFailover && null != ServerProvidedFailOverPartner) @@ -1777,7 +1776,6 @@ TimeoutTimer timeout currentServerInfo, newPassword, newSecurePassword, - false, // Use timeout in SniOpen intervalTimer, withFailover: true ); @@ -1905,7 +1903,6 @@ private void AttemptOneLogin( ServerInfo serverInfo, string newPassword, SecureString newSecurePassword, - bool ignoreSniOpenTimeout, TimeoutTimer timeout, bool withFailover = false) { @@ -1916,7 +1913,6 @@ private void AttemptOneLogin( _parser.Connect(serverInfo, this, - ignoreSniOpenTimeout, timeout.LegacyTimerExpire, ConnectionOptions, withFailover); diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs index c83587ab4c..e9e3388ef8 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs @@ -361,7 +361,6 @@ internal void ProcessPendingAck(TdsParserStateObject stateObj) internal void Connect( ServerInfo serverInfo, SqlInternalConnectionTds connHandler, - bool ignoreSniOpenTimeout, long timerExpire, SqlConnectionString connectionOptions, bool withFailover) @@ -445,7 +444,6 @@ internal void Connect( // AD Integrated behaves like Windows integrated when connecting to a non-fedAuth server _physicalStateObj.CreatePhysicalSNIHandle( serverInfo.ExtendedServerName, - ignoreSniOpenTimeout, timerExpire, out instanceName, ref _sniSpnBuffer, @@ -544,7 +542,6 @@ internal void Connect( _physicalStateObj.CreatePhysicalSNIHandle( serverInfo.ExtendedServerName, - ignoreSniOpenTimeout, timerExpire, out instanceName, ref _sniSpnBuffer, true, diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs index bc7cd362a8..dd37579205 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs @@ -197,7 +197,6 @@ private void ResetCancelAndProcessAttention() internal abstract void CreatePhysicalSNIHandle( string serverName, - bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, ref byte[][] spnBuffer, diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectManaged.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectManaged.cs index f219e75406..e0b4765b6b 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectManaged.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectManaged.cs @@ -77,7 +77,6 @@ protected override uint SNIPacketGetData(PacketHandle packet, byte[] inBuff, ref internal override void CreatePhysicalSNIHandle( string serverName, - bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, ref byte[][] spnBuffer, @@ -93,7 +92,7 @@ internal override void CreatePhysicalSNIHandle( string hostNameInCertificate, string serverCertificateFilename) { - SNIHandle? sessionHandle = SNIProxy.CreateConnectionHandle(serverName, ignoreSniOpenTimeout, timerExpire, out instanceName, ref spnBuffer, serverSPN, + SNIHandle? sessionHandle = SNIProxy.CreateConnectionHandle(serverName, timerExpire, out instanceName, ref spnBuffer, serverSPN, flushCache, async, parallel, isIntegratedSecurity, iPAddressPreference, cachedFQDN, ref pendingDNSInfo, tlsFirst, hostNameInCertificate, serverCertificateFilename); diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs index c17a6f9bd4..bf8337cacb 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs @@ -140,7 +140,6 @@ private SNINativeMethodWrapper.ConsumerInfo CreateConsumerInfo(bool async) internal override void CreatePhysicalSNIHandle( string serverName, - bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, ref byte[][] spnBuffer, @@ -199,7 +198,7 @@ internal override void CreatePhysicalSNIHandle( SQLDNSInfo cachedDNSInfo; bool ret = SQLFallbackDNSCache.Instance.GetDNSInfo(cachedFQDN, out cachedDNSInfo); - _sessionHandle = new SNIHandle(myInfo, serverName, spnBuffer[0], ignoreSniOpenTimeout, checked((int)timeout), out instanceName, + _sessionHandle = new SNIHandle(myInfo, serverName, spnBuffer[0], checked((int)timeout), out instanceName, flushCache, !async, fParallel, ipPreference, cachedDNSInfo, hostNameInCertificate); } diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs index 74427d732a..fb0533fd4a 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs @@ -319,7 +319,7 @@ internal void CreatePhysicalSNIHandle( _ = SQLFallbackDNSCache.Instance.GetDNSInfo(cachedFQDN, out SQLDNSInfo cachedDNSInfo); - _sessionHandle = new SNIHandle(myInfo, serverName, spnBuffer, ignoreSniOpenTimeout, checked((int)timeout), + _sessionHandle = new SNIHandle(myInfo, serverName, spnBuffer, checked((int)timeout), out instanceName, flushCache, !async, fParallel, transparentNetworkResolutionState, totalTimeout, ipPreference, cachedDNSInfo, hostNameInCertificate); } diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserSafeHandles.Windows.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserSafeHandles.Windows.cs index 21ae59c019..23f4be3504 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserSafeHandles.Windows.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserSafeHandles.Windows.cs @@ -150,7 +150,6 @@ internal SNIHandle( SNINativeMethodWrapper.ConsumerInfo myInfo, string serverName, byte[] spnBuffer, - bool ignoreSniOpenTimeout, int timeout, out byte[] instanceName, bool flushCache, @@ -174,14 +173,6 @@ internal SNIHandle( { _fSync = fSync; instanceName = new byte[256]; // Size as specified by netlibs. - if (ignoreSniOpenTimeout) - { - // UNDONE: ITEM12001110 (DB Mirroring Reconnect) Old behavior of not truly honoring timeout presevered - // for non-failover scenarios to avoid breaking changes as part of a QFE. Consider fixing timeout - // handling in next full release and removing ignoreSniOpenTimeout parameter. - timeout = Timeout.Infinite; // -1 == native SNIOPEN_TIMEOUT_VALUE / INFINITE - } - #if NETFRAMEWORK int transparentNetworkResolutionStateNo = (int)transparentNetworkResolutionState; _status = SNINativeMethodWrapper.SNIOpenSyncEx(myInfo, serverName, ref base.handle, diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionBasicTests.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionBasicTests.cs index 916cbf83b4..d35925aa03 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionBasicTests.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionBasicTests.cs @@ -248,5 +248,57 @@ public void ConnectionTestValidCredentialCombination() Assert.Equal(sqlCredential, conn.Credential); } + + [Theory] + [InlineData(60)] + [InlineData(30)] + [InlineData(15)] + [InlineData(10)] + [InlineData(5)] + [InlineData(1)] + public void ConnectionTimeoutTest(int timeout) + { + // Start a server with connection timeout from the inline data. + using TestTdsServer server = TestTdsServer.StartTestServer(false, false, timeout); + using SqlConnection connection = new SqlConnection(server.ConnectionString); + + // Dispose the server to force connection timeout + server.Dispose(); + + // Measure the actual time it took to timeout and compare it with configured timeout + var start = DateTime.Now; + var end = start; + + // Open a connection with the server disposed. + try + { + connection.Open(); + } + catch (Exception) + { + end = DateTime.Now; + } + + // Calculate actual duration of timeout + TimeSpan s = end - start; + // Did not time out? + if (s.TotalSeconds == 0) + Assert.True(s.TotalSeconds == 0); + + // Is actual time out the same as configured timeout or within an additional 3 second threshold because of overhead? + if (s.TotalSeconds > 0) + Assert.True(s.TotalSeconds <= timeout + 3); + } + + [Theory] + [InlineData(-5)] + public void ConnectionInvalidTimeoutTest(int timeout) + { + // Start a server with connection timeout from the inline data. + Assert.Throws(() => + { + using TestTdsServer server = TestTdsServer.StartTestServer(false, false, timeout); + }); + } } } From deac0685106822fb793c5ba295e22e61bad01632 Mon Sep 17 00:00:00 2001 From: v-arellegue Date: Fri, 16 Jun 2023 11:47:39 -0700 Subject: [PATCH 3/8] Revert "Add SqlConnectionEncryptOptionConverter class which is used to convert string Encrypt option into SqlConnectionEncryptionOption type." This reverts commit 5c505a1955f2e2966f58bad32011348b2d9de143. --- .../SqlConnectionEncryptOptionConverter.xml | 51 ---------- src/Microsoft.Data.SqlClient.sln | 1 - .../src/Microsoft.Data.SqlClient.csproj | 3 - .../netfx/src/Microsoft.Data.SqlClient.csproj | 3 - .../SqlClient/SqlConnectionEncryptOption.cs | 2 - .../SqlConnectionEncryptOptionConverter.cs | 46 --------- .../Microsoft.Data.SqlClient.Tests.csproj | 1 - .../SqlConnectionStringBuilderTest.cs | 93 ------------------- 8 files changed, 200 deletions(-) delete mode 100644 doc/snippets/Microsoft.Data.SqlClient/SqlConnectionEncryptOptionConverter.xml delete mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionEncryptOptionConverter.cs diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionEncryptOptionConverter.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionEncryptOptionConverter.xml deleted file mode 100644 index 9f26bc71c7..0000000000 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionEncryptOptionConverter.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - Converts a string Sql Connection Encrypt option into SqlConnectionEncryptOption object - - - ## Remarks -Implicit conversions have been added to maintain backwards compatibility with boolean behahavior for the property. When converting from a boolean, a value of `true` converts to and a value of `false` converts to . When converting to a boolean, , , and `null` convert to `true` and converts `false`. - - - - - - If the source type is a string then conversion is allowed . - - A string containing the value to convert. - - if the parameter can be converted successfully; otherwise, . - - This method does not throw an exception. - - - - Converts the specified string representation of a logical value to its equivalent. - - A string containing the value to convert. - - An object that is equivalent to . - - - An object that is equivalent to with value of if conversion was successful; - otherwise, an exception is thrown. - - This method throws an exception if conversion fails. - - - - Converts an object value to its string representation. - - An object containing the value to convert. - - A string representation of the value of . - - - A string representation of the value of . - - This method does not throw an exception if conversion fails. - - - diff --git a/src/Microsoft.Data.SqlClient.sln b/src/Microsoft.Data.SqlClient.sln index a94447bf12..c5b34945a0 100644 --- a/src/Microsoft.Data.SqlClient.sln +++ b/src/Microsoft.Data.SqlClient.sln @@ -121,7 +121,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Microsoft.Data.SqlClient", ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionAttestationProtocol.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionAttestationProtocol.xml ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionColumnEncryptionSetting.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionColumnEncryptionSetting.xml ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionEncryptOption.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionEncryptOption.xml - ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionEncryptOptionConverter.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionEncryptOptionConverter.xml ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionStringBuilder.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionStringBuilder.xml ..\doc\snippets\Microsoft.Data.SqlClient\SqlCredential.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlCredential.xml ..\doc\snippets\Microsoft.Data.SqlClient\SqlDataAdapter.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlDataAdapter.xml diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj index 90367cf55a..66791366f3 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -330,9 +330,6 @@ Microsoft\Data\SqlClient\SqlConnectionEncryptOption.cs - - Microsoft\Data\SqlClient\SqlConnectionEncryptOptionConverter.cs - Microsoft\Data\SqlClient\SqlConnectionPoolGroupProviderInfo.cs diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj index 675dd57fe6..4492274116 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -422,9 +422,6 @@ Microsoft\Data\SqlClient\SqlConnectionEncryptOption.cs - - Microsoft\Data\SqlClient\SqlConnectionEncryptOptionConverter.cs - Microsoft\Data\SqlClient\SqlConnectionPoolGroupProviderInfo.cs diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionEncryptOption.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionEncryptOption.cs index 997833437f..ecabdb9f04 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionEncryptOption.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionEncryptOption.cs @@ -3,13 +3,11 @@ // See the LICENSE file in the project root for more information. using System; -using System.ComponentModel; using Microsoft.Data.Common; namespace Microsoft.Data.SqlClient { /// - [TypeConverter(typeof(SqlConnectionEncryptOptionConverter))] public sealed class SqlConnectionEncryptOption { private const string TRUE = "True"; diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionEncryptOptionConverter.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionEncryptOptionConverter.cs deleted file mode 100644 index da5eb6f8a1..0000000000 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionEncryptOptionConverter.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// 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; -using System.ComponentModel; -using System.Globalization; -using System.Drawing; - -namespace Microsoft.Data.SqlClient -{ - /// - public class SqlConnectionEncryptOptionConverter : TypeConverter - { - // Overrides the CanConvertFrom method of TypeConverter. - // The ITypeDescriptorContext interface provides the context for the - // conversion. Typically, this interface is used at design time to - // provide information about the design-time container. - /// - public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) - { - if (sourceType == typeof(string)) - { - return true; - } - return base.CanConvertFrom(context, sourceType); - } - // Overrides the ConvertFrom method of TypeConverter. - /// - public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) - { - if (value is string) - { - return SqlConnectionEncryptOption.Parse(value.ToString()); - } - throw new Exception("Value to convert must be of string type!"); - } - // Overrides the ConvertTo method of TypeConverter. - /// - public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) - { - return base.ConvertTo(context, culture, value, destinationType); - } - } -} diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj index 408d7ffa61..9d1e8d5087 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj @@ -66,7 +66,6 @@ - diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionStringBuilderTest.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionStringBuilderTest.cs index 591a426568..2bc842566a 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionStringBuilderTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionStringBuilderTest.cs @@ -4,12 +4,6 @@ using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.IO; -using System.Text; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; using Xunit; namespace Microsoft.Data.SqlClient.Tests @@ -474,36 +468,6 @@ public void EncryptTryParseInvalidValuesReturnsFalse(string value) Assert.Null(result); } - [Theory] - [InlineData("false","False")] - [InlineData("true", "True")] - [InlineData("strict", "Strict")] - [InlineData("mandatory","True")] - [InlineData("optional", "False")] - [InlineData("yes", "True")] - [InlineData("no", "False")] - [InlineData("absolutely", "True")] - [InlineData("affirmative", "True")] - [InlineData("never", "True")] - [InlineData("always", "True")] - [InlineData("none", "True")] - public void ConnectionStringFromJsonTests(string value, string expectedValue) - { - ExecuteConnectionStringFromJsonTests(value, expectedValue); - } - - [Theory] - [InlineData("absolutely")] - [InlineData("affirmative")] - [InlineData("never")] - [InlineData("always")] - [InlineData("none")] - [InlineData(" for sure ")] - public void ConnectionStringFromJsonThrowsException(string value) - { - ExecuteConnectionStringFromJsonThrowsException(value); - } - internal void ExecuteConnectionStringTests(string connectionString) { SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectionString); @@ -531,62 +495,5 @@ internal static void CheckEncryptType(SqlConnectionStringBuilder builder, SqlCon Assert.IsType(builder.Encrypt); Assert.Equal(expectedValue, builder.Encrypt); } - - internal void ExecuteConnectionStringFromJsonTests(string encryptOption, string result) - { - var settings = LoadSettingsFromJsonStream(encryptOption); - var connectionString = settings!.UserDb!.ToString(); - Assert.Contains($"Encrypt={result}", connectionString, StringComparison.InvariantCultureIgnoreCase); - } - - internal void ExecuteConnectionStringFromJsonThrowsException(string encryptOption) - { - Assert.Throws(() => LoadSettingsFromJsonStream(encryptOption)); - } - - TSettings LoadSettingsFromJsonStream(string encryptOption) where TSettings : class - { - TSettings settingsOut = null; - - Host.CreateDefaultBuilder() - .ConfigureAppConfiguration((ctx, configBuilder) => - { - // Note: Inside string interpolation, a { should be {{ and a } should be }} - // First, declare a stringified JSON - var json = $"{{ \"UserDb\": {{ \"UserComponents\": {{ \"NetworkLibrary\": \"DBMSSOCN\", \"UserID\": \"user\", \"Password\": \"password\", \"DataSource\": \"localhost\", \"InitialCatalog\": \"catalog\", \"Encrypt\": \"{encryptOption}\" }}}}}}"; - - // Load the stringified JSON as a stream into the configuration builder - configBuilder.AddJsonStream(new MemoryStream(Encoding.ASCII.GetBytes(json))); - configBuilder.AddEnvironmentVariables(); - }) - .ConfigureServices((ctx, services) => - { - var configuration = ctx.Configuration; - services.AddOptions(); - services.Configure(ctx.Configuration); - settingsOut = configuration.Get(); - }) - .Build(); - - return settingsOut; - } - } - - // These 2 classes will be used by ConnectionStringFromJsonTests only - internal class UserDbConnectionStringSettings - { - [Required] - public UserSqlConnectionString UserDb { get; set; } - } - - internal class UserSqlConnectionString - { - public SqlConnectionStringBuilder UserComponents { get; set; } = new(); - - public override string ToString() - { - return UserComponents!.ConnectionString; - } } - } From bf788581498f2646582ec3a255f411b557c3dc44 Mon Sep 17 00:00:00 2001 From: v-arellegue Date: Fri, 16 Jun 2023 11:58:18 -0700 Subject: [PATCH 4/8] Revert "Add SqlConnectionEncryptOptionConverter class which is used to convert string Encrypt option into SqlConnectionEncryptionOption type." This reverts commit 5c505a1955f2e2966f58bad32011348b2d9de143. --- .../SqlConnectionEncryptOptionConverter.xml | 51 ---------- src/Microsoft.Data.SqlClient.sln | 1 - .../src/Microsoft.Data.SqlClient.csproj | 3 - .../netfx/src/Microsoft.Data.SqlClient.csproj | 3 - .../SqlClient/SqlConnectionEncryptOption.cs | 2 - .../SqlConnectionEncryptOptionConverter.cs | 46 --------- .../Microsoft.Data.SqlClient.Tests.csproj | 1 - .../SqlConnectionStringBuilderTest.cs | 93 ------------------- 8 files changed, 200 deletions(-) delete mode 100644 doc/snippets/Microsoft.Data.SqlClient/SqlConnectionEncryptOptionConverter.xml delete mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionEncryptOptionConverter.cs diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionEncryptOptionConverter.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionEncryptOptionConverter.xml deleted file mode 100644 index 9f26bc71c7..0000000000 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlConnectionEncryptOptionConverter.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - Converts a string Sql Connection Encrypt option into SqlConnectionEncryptOption object - - - ## Remarks -Implicit conversions have been added to maintain backwards compatibility with boolean behahavior for the property. When converting from a boolean, a value of `true` converts to and a value of `false` converts to . When converting to a boolean, , , and `null` convert to `true` and converts `false`. - - - - - - If the source type is a string then conversion is allowed . - - A string containing the value to convert. - - if the parameter can be converted successfully; otherwise, . - - This method does not throw an exception. - - - - Converts the specified string representation of a logical value to its equivalent. - - A string containing the value to convert. - - An object that is equivalent to . - - - An object that is equivalent to with value of if conversion was successful; - otherwise, an exception is thrown. - - This method throws an exception if conversion fails. - - - - Converts an object value to its string representation. - - An object containing the value to convert. - - A string representation of the value of . - - - A string representation of the value of . - - This method does not throw an exception if conversion fails. - - - diff --git a/src/Microsoft.Data.SqlClient.sln b/src/Microsoft.Data.SqlClient.sln index a94447bf12..c5b34945a0 100644 --- a/src/Microsoft.Data.SqlClient.sln +++ b/src/Microsoft.Data.SqlClient.sln @@ -121,7 +121,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Microsoft.Data.SqlClient", ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionAttestationProtocol.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionAttestationProtocol.xml ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionColumnEncryptionSetting.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionColumnEncryptionSetting.xml ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionEncryptOption.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionEncryptOption.xml - ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionEncryptOptionConverter.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionEncryptOptionConverter.xml ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionStringBuilder.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlConnectionStringBuilder.xml ..\doc\snippets\Microsoft.Data.SqlClient\SqlCredential.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlCredential.xml ..\doc\snippets\Microsoft.Data.SqlClient\SqlDataAdapter.xml = ..\doc\snippets\Microsoft.Data.SqlClient\SqlDataAdapter.xml diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj index 90367cf55a..66791366f3 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -330,9 +330,6 @@ Microsoft\Data\SqlClient\SqlConnectionEncryptOption.cs - - Microsoft\Data\SqlClient\SqlConnectionEncryptOptionConverter.cs - Microsoft\Data\SqlClient\SqlConnectionPoolGroupProviderInfo.cs diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj index 675dd57fe6..4492274116 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -422,9 +422,6 @@ Microsoft\Data\SqlClient\SqlConnectionEncryptOption.cs - - Microsoft\Data\SqlClient\SqlConnectionEncryptOptionConverter.cs - Microsoft\Data\SqlClient\SqlConnectionPoolGroupProviderInfo.cs diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionEncryptOption.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionEncryptOption.cs index 997833437f..ecabdb9f04 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionEncryptOption.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionEncryptOption.cs @@ -3,13 +3,11 @@ // See the LICENSE file in the project root for more information. using System; -using System.ComponentModel; using Microsoft.Data.Common; namespace Microsoft.Data.SqlClient { /// - [TypeConverter(typeof(SqlConnectionEncryptOptionConverter))] public sealed class SqlConnectionEncryptOption { private const string TRUE = "True"; diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionEncryptOptionConverter.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionEncryptOptionConverter.cs deleted file mode 100644 index da5eb6f8a1..0000000000 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionEncryptOptionConverter.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// 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; -using System.ComponentModel; -using System.Globalization; -using System.Drawing; - -namespace Microsoft.Data.SqlClient -{ - /// - public class SqlConnectionEncryptOptionConverter : TypeConverter - { - // Overrides the CanConvertFrom method of TypeConverter. - // The ITypeDescriptorContext interface provides the context for the - // conversion. Typically, this interface is used at design time to - // provide information about the design-time container. - /// - public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) - { - if (sourceType == typeof(string)) - { - return true; - } - return base.CanConvertFrom(context, sourceType); - } - // Overrides the ConvertFrom method of TypeConverter. - /// - public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) - { - if (value is string) - { - return SqlConnectionEncryptOption.Parse(value.ToString()); - } - throw new Exception("Value to convert must be of string type!"); - } - // Overrides the ConvertTo method of TypeConverter. - /// - public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) - { - return base.ConvertTo(context, culture, value, destinationType); - } - } -} diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj index 408d7ffa61..9d1e8d5087 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj @@ -66,7 +66,6 @@ - diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionStringBuilderTest.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionStringBuilderTest.cs index 591a426568..2bc842566a 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionStringBuilderTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionStringBuilderTest.cs @@ -4,12 +4,6 @@ using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.IO; -using System.Text; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; using Xunit; namespace Microsoft.Data.SqlClient.Tests @@ -474,36 +468,6 @@ public void EncryptTryParseInvalidValuesReturnsFalse(string value) Assert.Null(result); } - [Theory] - [InlineData("false","False")] - [InlineData("true", "True")] - [InlineData("strict", "Strict")] - [InlineData("mandatory","True")] - [InlineData("optional", "False")] - [InlineData("yes", "True")] - [InlineData("no", "False")] - [InlineData("absolutely", "True")] - [InlineData("affirmative", "True")] - [InlineData("never", "True")] - [InlineData("always", "True")] - [InlineData("none", "True")] - public void ConnectionStringFromJsonTests(string value, string expectedValue) - { - ExecuteConnectionStringFromJsonTests(value, expectedValue); - } - - [Theory] - [InlineData("absolutely")] - [InlineData("affirmative")] - [InlineData("never")] - [InlineData("always")] - [InlineData("none")] - [InlineData(" for sure ")] - public void ConnectionStringFromJsonThrowsException(string value) - { - ExecuteConnectionStringFromJsonThrowsException(value); - } - internal void ExecuteConnectionStringTests(string connectionString) { SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectionString); @@ -531,62 +495,5 @@ internal static void CheckEncryptType(SqlConnectionStringBuilder builder, SqlCon Assert.IsType(builder.Encrypt); Assert.Equal(expectedValue, builder.Encrypt); } - - internal void ExecuteConnectionStringFromJsonTests(string encryptOption, string result) - { - var settings = LoadSettingsFromJsonStream(encryptOption); - var connectionString = settings!.UserDb!.ToString(); - Assert.Contains($"Encrypt={result}", connectionString, StringComparison.InvariantCultureIgnoreCase); - } - - internal void ExecuteConnectionStringFromJsonThrowsException(string encryptOption) - { - Assert.Throws(() => LoadSettingsFromJsonStream(encryptOption)); - } - - TSettings LoadSettingsFromJsonStream(string encryptOption) where TSettings : class - { - TSettings settingsOut = null; - - Host.CreateDefaultBuilder() - .ConfigureAppConfiguration((ctx, configBuilder) => - { - // Note: Inside string interpolation, a { should be {{ and a } should be }} - // First, declare a stringified JSON - var json = $"{{ \"UserDb\": {{ \"UserComponents\": {{ \"NetworkLibrary\": \"DBMSSOCN\", \"UserID\": \"user\", \"Password\": \"password\", \"DataSource\": \"localhost\", \"InitialCatalog\": \"catalog\", \"Encrypt\": \"{encryptOption}\" }}}}}}"; - - // Load the stringified JSON as a stream into the configuration builder - configBuilder.AddJsonStream(new MemoryStream(Encoding.ASCII.GetBytes(json))); - configBuilder.AddEnvironmentVariables(); - }) - .ConfigureServices((ctx, services) => - { - var configuration = ctx.Configuration; - services.AddOptions(); - services.Configure(ctx.Configuration); - settingsOut = configuration.Get(); - }) - .Build(); - - return settingsOut; - } - } - - // These 2 classes will be used by ConnectionStringFromJsonTests only - internal class UserDbConnectionStringSettings - { - [Required] - public UserSqlConnectionString UserDb { get; set; } - } - - internal class UserSqlConnectionString - { - public SqlConnectionStringBuilder UserComponents { get; set; } = new(); - - public override string ToString() - { - return UserComponents!.ConnectionString; - } } - } From 2028759dec35f61a043df1a09ecd7f1135194f83 Mon Sep 17 00:00:00 2001 From: v-arellegue Date: Fri, 16 Jun 2023 13:33:01 -0700 Subject: [PATCH 5/8] Revert "Fixed Issue #1126 .NET Core SqlConnection ConnectTimout 15 less than not work?" This reverts commit cde043009d57f456b90e2b4fa4faf8f0c6dabefd. --- build.proj | 2 +- .../Microsoft/Data/SqlClient/SNI/SNIProxy.cs | 2 + .../SqlClient/SqlInternalConnectionTds.cs | 4 ++ .../src/Microsoft/Data/SqlClient/TdsParser.cs | 3 ++ .../Data/SqlClient/TdsParserStateObject.cs | 1 + .../SqlClient/TdsParserStateObjectManaged.cs | 3 +- .../SqlClient/TdsParserStateObjectNative.cs | 3 +- .../Data/SqlClient/TdsParserStateObject.cs | 2 +- .../SqlClient/TdsParserSafeHandles.Windows.cs | 9 ++++ .../SqlConnectionBasicTests.cs | 52 ------------------- 10 files changed, 25 insertions(+), 56 deletions(-) diff --git a/build.proj b/build.proj index 465f9264c3..2e1ba19930 100644 --- a/build.proj +++ b/build.proj @@ -105,7 +105,7 @@ - $(DotNetCmd) dotnet build -c Release -p:ReferenceType=$(ReferenceType) + $(DotNetCmd) dotnet build -c Release -p:ReferenceType=$(ReferenceType)" diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs index 19659a2d93..ac4d3599dd 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs @@ -130,6 +130,7 @@ private static bool IsErrorStatus(SecurityStatusPalErrorCode errorCode) /// Create a SNI connection handle /// /// Full server name from connection string + /// Ignore open timeout /// Timer expiration /// Instance name /// SPN @@ -147,6 +148,7 @@ private static bool IsErrorStatus(SecurityStatusPalErrorCode errorCode) /// SNI handle internal static SNIHandle CreateConnectionHandle( string fullServerName, + bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, ref byte[][] spnBuffer, diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs index 5e3a4ad25f..66631151c9 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs @@ -1538,6 +1538,7 @@ private void LoginNoFailover(ServerInfo serverInfo, AttemptOneLogin(serverInfo, newPassword, newSecurePassword, + !connectionOptions.MultiSubnetFailover, // ignore timeout for SniOpen call unless MSF connectionOptions.MultiSubnetFailover ? intervalTimer : timeout); if (connectionOptions.MultiSubnetFailover && null != ServerProvidedFailOverPartner) @@ -1776,6 +1777,7 @@ TimeoutTimer timeout currentServerInfo, newPassword, newSecurePassword, + false, // Use timeout in SniOpen intervalTimer, withFailover: true ); @@ -1903,6 +1905,7 @@ private void AttemptOneLogin( ServerInfo serverInfo, string newPassword, SecureString newSecurePassword, + bool ignoreSniOpenTimeout, TimeoutTimer timeout, bool withFailover = false) { @@ -1913,6 +1916,7 @@ private void AttemptOneLogin( _parser.Connect(serverInfo, this, + ignoreSniOpenTimeout, timeout.LegacyTimerExpire, ConnectionOptions, withFailover); diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs index e9e3388ef8..c83587ab4c 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs @@ -361,6 +361,7 @@ internal void ProcessPendingAck(TdsParserStateObject stateObj) internal void Connect( ServerInfo serverInfo, SqlInternalConnectionTds connHandler, + bool ignoreSniOpenTimeout, long timerExpire, SqlConnectionString connectionOptions, bool withFailover) @@ -444,6 +445,7 @@ internal void Connect( // AD Integrated behaves like Windows integrated when connecting to a non-fedAuth server _physicalStateObj.CreatePhysicalSNIHandle( serverInfo.ExtendedServerName, + ignoreSniOpenTimeout, timerExpire, out instanceName, ref _sniSpnBuffer, @@ -542,6 +544,7 @@ internal void Connect( _physicalStateObj.CreatePhysicalSNIHandle( serverInfo.ExtendedServerName, + ignoreSniOpenTimeout, timerExpire, out instanceName, ref _sniSpnBuffer, true, diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs index dd37579205..bc7cd362a8 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs @@ -197,6 +197,7 @@ private void ResetCancelAndProcessAttention() internal abstract void CreatePhysicalSNIHandle( string serverName, + bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, ref byte[][] spnBuffer, diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectManaged.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectManaged.cs index e0b4765b6b..f219e75406 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectManaged.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectManaged.cs @@ -77,6 +77,7 @@ protected override uint SNIPacketGetData(PacketHandle packet, byte[] inBuff, ref internal override void CreatePhysicalSNIHandle( string serverName, + bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, ref byte[][] spnBuffer, @@ -92,7 +93,7 @@ internal override void CreatePhysicalSNIHandle( string hostNameInCertificate, string serverCertificateFilename) { - SNIHandle? sessionHandle = SNIProxy.CreateConnectionHandle(serverName, timerExpire, out instanceName, ref spnBuffer, serverSPN, + SNIHandle? sessionHandle = SNIProxy.CreateConnectionHandle(serverName, ignoreSniOpenTimeout, timerExpire, out instanceName, ref spnBuffer, serverSPN, flushCache, async, parallel, isIntegratedSecurity, iPAddressPreference, cachedFQDN, ref pendingDNSInfo, tlsFirst, hostNameInCertificate, serverCertificateFilename); diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs index bf8337cacb..c17a6f9bd4 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs @@ -140,6 +140,7 @@ private SNINativeMethodWrapper.ConsumerInfo CreateConsumerInfo(bool async) internal override void CreatePhysicalSNIHandle( string serverName, + bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, ref byte[][] spnBuffer, @@ -198,7 +199,7 @@ internal override void CreatePhysicalSNIHandle( SQLDNSInfo cachedDNSInfo; bool ret = SQLFallbackDNSCache.Instance.GetDNSInfo(cachedFQDN, out cachedDNSInfo); - _sessionHandle = new SNIHandle(myInfo, serverName, spnBuffer[0], checked((int)timeout), out instanceName, + _sessionHandle = new SNIHandle(myInfo, serverName, spnBuffer[0], ignoreSniOpenTimeout, checked((int)timeout), out instanceName, flushCache, !async, fParallel, ipPreference, cachedDNSInfo, hostNameInCertificate); } diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs index fb0533fd4a..74427d732a 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs @@ -319,7 +319,7 @@ internal void CreatePhysicalSNIHandle( _ = SQLFallbackDNSCache.Instance.GetDNSInfo(cachedFQDN, out SQLDNSInfo cachedDNSInfo); - _sessionHandle = new SNIHandle(myInfo, serverName, spnBuffer, checked((int)timeout), + _sessionHandle = new SNIHandle(myInfo, serverName, spnBuffer, ignoreSniOpenTimeout, checked((int)timeout), out instanceName, flushCache, !async, fParallel, transparentNetworkResolutionState, totalTimeout, ipPreference, cachedDNSInfo, hostNameInCertificate); } diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserSafeHandles.Windows.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserSafeHandles.Windows.cs index 23f4be3504..21ae59c019 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserSafeHandles.Windows.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserSafeHandles.Windows.cs @@ -150,6 +150,7 @@ internal SNIHandle( SNINativeMethodWrapper.ConsumerInfo myInfo, string serverName, byte[] spnBuffer, + bool ignoreSniOpenTimeout, int timeout, out byte[] instanceName, bool flushCache, @@ -173,6 +174,14 @@ internal SNIHandle( { _fSync = fSync; instanceName = new byte[256]; // Size as specified by netlibs. + if (ignoreSniOpenTimeout) + { + // UNDONE: ITEM12001110 (DB Mirroring Reconnect) Old behavior of not truly honoring timeout presevered + // for non-failover scenarios to avoid breaking changes as part of a QFE. Consider fixing timeout + // handling in next full release and removing ignoreSniOpenTimeout parameter. + timeout = Timeout.Infinite; // -1 == native SNIOPEN_TIMEOUT_VALUE / INFINITE + } + #if NETFRAMEWORK int transparentNetworkResolutionStateNo = (int)transparentNetworkResolutionState; _status = SNINativeMethodWrapper.SNIOpenSyncEx(myInfo, serverName, ref base.handle, diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionBasicTests.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionBasicTests.cs index d35925aa03..916cbf83b4 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionBasicTests.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionBasicTests.cs @@ -248,57 +248,5 @@ public void ConnectionTestValidCredentialCombination() Assert.Equal(sqlCredential, conn.Credential); } - - [Theory] - [InlineData(60)] - [InlineData(30)] - [InlineData(15)] - [InlineData(10)] - [InlineData(5)] - [InlineData(1)] - public void ConnectionTimeoutTest(int timeout) - { - // Start a server with connection timeout from the inline data. - using TestTdsServer server = TestTdsServer.StartTestServer(false, false, timeout); - using SqlConnection connection = new SqlConnection(server.ConnectionString); - - // Dispose the server to force connection timeout - server.Dispose(); - - // Measure the actual time it took to timeout and compare it with configured timeout - var start = DateTime.Now; - var end = start; - - // Open a connection with the server disposed. - try - { - connection.Open(); - } - catch (Exception) - { - end = DateTime.Now; - } - - // Calculate actual duration of timeout - TimeSpan s = end - start; - // Did not time out? - if (s.TotalSeconds == 0) - Assert.True(s.TotalSeconds == 0); - - // Is actual time out the same as configured timeout or within an additional 3 second threshold because of overhead? - if (s.TotalSeconds > 0) - Assert.True(s.TotalSeconds <= timeout + 3); - } - - [Theory] - [InlineData(-5)] - public void ConnectionInvalidTimeoutTest(int timeout) - { - // Start a server with connection timeout from the inline data. - Assert.Throws(() => - { - using TestTdsServer server = TestTdsServer.StartTestServer(false, false, timeout); - }); - } } } From 64ece1d4ddc6f2a1ad60d6f21ec7d73a3a99003d Mon Sep 17 00:00:00 2001 From: v-arellegue Date: Mon, 19 Jun 2023 16:27:08 -0700 Subject: [PATCH 6/8] Removed ignoreSniOpenTimeout in Connect function chain of calls. Added Unit Test to prove that the ignore timeout has been removed. --- .../Microsoft/Data/SqlClient/SNI/SNIProxy.cs | 2 - .../SqlClient/SqlInternalConnectionTds.cs | 4 - .../src/Microsoft/Data/SqlClient/TdsParser.cs | 3 - .../Data/SqlClient/TdsParserStateObject.cs | 1 - .../SqlClient/TdsParserStateObjectManaged.cs | 3 +- .../SqlClient/TdsParserStateObjectNative.cs | 3 +- .../Data/SqlClient/TdsParserStateObject.cs | 2 +- .../SqlClient/TdsParserSafeHandles.Windows.cs | 16 ++-- .../SqlConnectionBasicTests.cs | 92 +++++++++++++++++++ 9 files changed, 103 insertions(+), 23 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs index ac4d3599dd..19659a2d93 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs @@ -130,7 +130,6 @@ private static bool IsErrorStatus(SecurityStatusPalErrorCode errorCode) /// Create a SNI connection handle /// /// Full server name from connection string - /// Ignore open timeout /// Timer expiration /// Instance name /// SPN @@ -148,7 +147,6 @@ private static bool IsErrorStatus(SecurityStatusPalErrorCode errorCode) /// SNI handle internal static SNIHandle CreateConnectionHandle( string fullServerName, - bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, ref byte[][] spnBuffer, diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs index 66631151c9..5e3a4ad25f 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs @@ -1538,7 +1538,6 @@ private void LoginNoFailover(ServerInfo serverInfo, AttemptOneLogin(serverInfo, newPassword, newSecurePassword, - !connectionOptions.MultiSubnetFailover, // ignore timeout for SniOpen call unless MSF connectionOptions.MultiSubnetFailover ? intervalTimer : timeout); if (connectionOptions.MultiSubnetFailover && null != ServerProvidedFailOverPartner) @@ -1777,7 +1776,6 @@ TimeoutTimer timeout currentServerInfo, newPassword, newSecurePassword, - false, // Use timeout in SniOpen intervalTimer, withFailover: true ); @@ -1905,7 +1903,6 @@ private void AttemptOneLogin( ServerInfo serverInfo, string newPassword, SecureString newSecurePassword, - bool ignoreSniOpenTimeout, TimeoutTimer timeout, bool withFailover = false) { @@ -1916,7 +1913,6 @@ private void AttemptOneLogin( _parser.Connect(serverInfo, this, - ignoreSniOpenTimeout, timeout.LegacyTimerExpire, ConnectionOptions, withFailover); diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs index c83587ab4c..e9e3388ef8 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs @@ -361,7 +361,6 @@ internal void ProcessPendingAck(TdsParserStateObject stateObj) internal void Connect( ServerInfo serverInfo, SqlInternalConnectionTds connHandler, - bool ignoreSniOpenTimeout, long timerExpire, SqlConnectionString connectionOptions, bool withFailover) @@ -445,7 +444,6 @@ internal void Connect( // AD Integrated behaves like Windows integrated when connecting to a non-fedAuth server _physicalStateObj.CreatePhysicalSNIHandle( serverInfo.ExtendedServerName, - ignoreSniOpenTimeout, timerExpire, out instanceName, ref _sniSpnBuffer, @@ -544,7 +542,6 @@ internal void Connect( _physicalStateObj.CreatePhysicalSNIHandle( serverInfo.ExtendedServerName, - ignoreSniOpenTimeout, timerExpire, out instanceName, ref _sniSpnBuffer, true, diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs index bc7cd362a8..dd37579205 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs @@ -197,7 +197,6 @@ private void ResetCancelAndProcessAttention() internal abstract void CreatePhysicalSNIHandle( string serverName, - bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, ref byte[][] spnBuffer, diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectManaged.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectManaged.cs index f219e75406..e0b4765b6b 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectManaged.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectManaged.cs @@ -77,7 +77,6 @@ protected override uint SNIPacketGetData(PacketHandle packet, byte[] inBuff, ref internal override void CreatePhysicalSNIHandle( string serverName, - bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, ref byte[][] spnBuffer, @@ -93,7 +92,7 @@ internal override void CreatePhysicalSNIHandle( string hostNameInCertificate, string serverCertificateFilename) { - SNIHandle? sessionHandle = SNIProxy.CreateConnectionHandle(serverName, ignoreSniOpenTimeout, timerExpire, out instanceName, ref spnBuffer, serverSPN, + SNIHandle? sessionHandle = SNIProxy.CreateConnectionHandle(serverName, timerExpire, out instanceName, ref spnBuffer, serverSPN, flushCache, async, parallel, isIntegratedSecurity, iPAddressPreference, cachedFQDN, ref pendingDNSInfo, tlsFirst, hostNameInCertificate, serverCertificateFilename); diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs index c17a6f9bd4..bf8337cacb 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs @@ -140,7 +140,6 @@ private SNINativeMethodWrapper.ConsumerInfo CreateConsumerInfo(bool async) internal override void CreatePhysicalSNIHandle( string serverName, - bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, ref byte[][] spnBuffer, @@ -199,7 +198,7 @@ internal override void CreatePhysicalSNIHandle( SQLDNSInfo cachedDNSInfo; bool ret = SQLFallbackDNSCache.Instance.GetDNSInfo(cachedFQDN, out cachedDNSInfo); - _sessionHandle = new SNIHandle(myInfo, serverName, spnBuffer[0], ignoreSniOpenTimeout, checked((int)timeout), out instanceName, + _sessionHandle = new SNIHandle(myInfo, serverName, spnBuffer[0], checked((int)timeout), out instanceName, flushCache, !async, fParallel, ipPreference, cachedDNSInfo, hostNameInCertificate); } diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs index 74427d732a..fb0533fd4a 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs @@ -319,7 +319,7 @@ internal void CreatePhysicalSNIHandle( _ = SQLFallbackDNSCache.Instance.GetDNSInfo(cachedFQDN, out SQLDNSInfo cachedDNSInfo); - _sessionHandle = new SNIHandle(myInfo, serverName, spnBuffer, ignoreSniOpenTimeout, checked((int)timeout), + _sessionHandle = new SNIHandle(myInfo, serverName, spnBuffer, checked((int)timeout), out instanceName, flushCache, !async, fParallel, transparentNetworkResolutionState, totalTimeout, ipPreference, cachedDNSInfo, hostNameInCertificate); } diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserSafeHandles.Windows.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserSafeHandles.Windows.cs index 21ae59c019..8d276cd285 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserSafeHandles.Windows.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserSafeHandles.Windows.cs @@ -150,7 +150,6 @@ internal SNIHandle( SNINativeMethodWrapper.ConsumerInfo myInfo, string serverName, byte[] spnBuffer, - bool ignoreSniOpenTimeout, int timeout, out byte[] instanceName, bool flushCache, @@ -174,13 +173,14 @@ internal SNIHandle( { _fSync = fSync; instanceName = new byte[256]; // Size as specified by netlibs. - if (ignoreSniOpenTimeout) - { - // UNDONE: ITEM12001110 (DB Mirroring Reconnect) Old behavior of not truly honoring timeout presevered - // for non-failover scenarios to avoid breaking changes as part of a QFE. Consider fixing timeout - // handling in next full release and removing ignoreSniOpenTimeout parameter. - timeout = Timeout.Infinite; // -1 == native SNIOPEN_TIMEOUT_VALUE / INFINITE - } + // Option ignoreSniOpenTimeout is no longer available + //if (ignoreSniOpenTimeout) + //{ + // // UNDONE: ITEM12001110 (DB Mirroring Reconnect) Old behavior of not truly honoring timeout presevered + // // for non-failover scenarios to avoid breaking changes as part of a QFE. Consider fixing timeout + // // handling in next full release and removing ignoreSniOpenTimeout parameter. + // timeout = Timeout.Infinite; // -1 == native SNIOPEN_TIMEOUT_VALUE / INFINITE + //} #if NETFRAMEWORK int transparentNetworkResolutionStateNo = (int)transparentNetworkResolutionState; diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionBasicTests.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionBasicTests.cs index 916cbf83b4..f1a392dca9 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionBasicTests.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionBasicTests.cs @@ -248,5 +248,97 @@ public void ConnectionTestValidCredentialCombination() Assert.Equal(sqlCredential, conn.Credential); } + + [Theory] + [InlineData(60)] + [InlineData(30)] + [InlineData(15)] + [InlineData(10)] + [InlineData(5)] + [InlineData(1)] + public void ConnectionTimeoutTest(int timeout) + { + // Start a server with connection timeout from the inline data. + using TestTdsServer server = TestTdsServer.StartTestServer(false, false, timeout); + using SqlConnection connection = new SqlConnection(server.ConnectionString); + + // Dispose the server to force connection timeout + server.Dispose(); + + // Measure the actual time it took to timeout and compare it with configured timeout + var start = DateTime.Now; + var end = start; + + // Open a connection with the server disposed. + try + { + connection.Open(); + } + catch (Exception) + { + end = DateTime.Now; + } + + // Calculate actual duration of timeout + TimeSpan s = end - start; + // Did not time out? + if (s.TotalSeconds == 0) + Assert.True(s.TotalSeconds == 0); + + // Is actual time out the same as configured timeout or within an additional 3 second threshold because of overhead? + if (s.TotalSeconds > 0) + Assert.True(s.TotalSeconds <= timeout + 3); + } + + [Theory] + [InlineData(60)] + [InlineData(30)] + [InlineData(15)] + [InlineData(10)] + [InlineData(5)] + [InlineData(1)] + public async void ConnectionTimeoutTestAsync(int timeout) + { + // Start a server with connection timeout from the inline data. + using TestTdsServer server = TestTdsServer.StartTestServer(false, false, timeout); + using SqlConnection connection = new SqlConnection(server.ConnectionString); + + // Dispose the server to force connection timeout + server.Dispose(); + + // Measure the actual time it took to timeout and compare it with configured timeout + var start = DateTime.Now; + var end = start; + + // Open a connection with the server disposed. + try + { + await connection.OpenAsync(); + } + catch (Exception) + { + end = DateTime.Now; + } + + // Calculate actual duration of timeout + TimeSpan s = end - start; + // Did not time out? + if (s.TotalSeconds == 0) + Assert.True(s.TotalSeconds == 0); + + // Is actual time out the same as configured timeout or within an additional 3 second threshold because of overhead? + if (s.TotalSeconds > 0) + Assert.True(s.TotalSeconds <= timeout + 3); + } + + [Fact] + public void ConnectionInvalidTimeoutTest() + { + // Start a server with connection timeout from the inline data. + Assert.Throws(() => + { + using TestTdsServer server = TestTdsServer.StartTestServer(false, false, -5); + }); + } } } From f4538d39fa109b97c89d80e7464dacb13e4f28c4 Mon Sep 17 00:00:00 2001 From: v-arellegue Date: Tue, 11 Jul 2023 17:06:24 -0700 Subject: [PATCH 7/8] Put back missing } after resolving conflict so project will build. --- .../tests/FunctionalTests/SqlConnectionBasicTests.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionBasicTests.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionBasicTests.cs index 30c9ce9f2e..547c92118b 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionBasicTests.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionBasicTests.cs @@ -343,6 +343,8 @@ public void ConnectionInvalidTimeoutTest() using TestTdsServer server = TestTdsServer.StartTestServer(false, false, -5); }); + } + [Fact] public void ConnectionTestWithCultureTH() { From e76d99f28889e8583b8503c292fc6986af807de9 Mon Sep 17 00:00:00 2001 From: v-arellegue Date: Tue, 11 Jul 2023 18:07:02 -0700 Subject: [PATCH 8/8] Remove ignoreSniOpenTimeout from .NetFx too. --- .../Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs | 6 +----- .../netfx/src/Microsoft/Data/SqlClient/TdsParser.cs | 3 --- .../src/Microsoft/Data/SqlClient/TdsParserStateObject.cs | 1 - .../tests/FunctionalTests/SqlConnectionBasicTests.cs | 1 - 4 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs index 501c2072ca..aa6a670021 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs @@ -1861,7 +1861,6 @@ private void LoginNoFailover(ServerInfo serverInfo, string newPassword, SecureSt AttemptOneLogin(serverInfo, newPassword, newSecurePassword, - !isParallel, // ignore timeout for SniOpen call unless MSF , and TNIR attemptOneLoginTimeout, isFirstTransparentAttempt: isFirstTransparentAttempt, disableTnir: disableTnir); @@ -2137,7 +2136,6 @@ TimeoutTimer timeout currentServerInfo, newPassword, newSecurePassword, - false, // Use timeout in SniOpen intervalTimer, withFailover: true ); @@ -2175,7 +2173,6 @@ TimeoutTimer timeout currentServerInfo, newPassword, newSecurePassword, - false, // Use timeout in SniOpen intervalTimer, withFailover: true ); @@ -2293,7 +2290,7 @@ private void ResolveExtendedServerName(ServerInfo serverInfo, bool aliasLookup, } // 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, bool disableTnir = false) + private void AttemptOneLogin(ServerInfo serverInfo, string newPassword, SecureString newSecurePassword, TimeoutTimer timeout, bool withFailover = false, bool isFirstTransparentAttempt = true, bool disableTnir = false) { SqlClientEventSource.Log.TryAdvancedTraceEvent(" {0}, timout={1}[msec], server={2}", ObjectID, timeout.MillisecondsRemaining, serverInfo.ExtendedServerName); @@ -2303,7 +2300,6 @@ private void AttemptOneLogin(ServerInfo serverInfo, string newPassword, SecureSt _parser.Connect(serverInfo, this, - ignoreSniOpenTimeout, timeout.LegacyTimerExpire, ConnectionOptions, withFailover, diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs index 1d29e89fd0..21abbab757 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs @@ -494,7 +494,6 @@ internal void ProcessPendingAck(TdsParserStateObject stateObj) internal void Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, - bool ignoreSniOpenTimeout, long timerExpire, SqlConnectionString connectionOptions, bool withFailover, @@ -640,7 +639,6 @@ internal void Connect(ServerInfo serverInfo, _physicalStateObj.CreatePhysicalSNIHandle( serverInfo.ExtendedServerName, - ignoreSniOpenTimeout, timerExpire, out instanceName, _sniSpnBuffer, @@ -746,7 +744,6 @@ internal void Connect(ServerInfo serverInfo, _physicalStateObj.SniContext = SniContext.Snix_Connect; _physicalStateObj.CreatePhysicalSNIHandle( serverInfo.ExtendedServerName, - ignoreSniOpenTimeout, timerExpire, out instanceName, _sniSpnBuffer, diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs index 1e70699324..5d5ade91f4 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs @@ -279,7 +279,6 @@ private SNINativeMethodWrapper.ConsumerInfo CreateConsumerInfo(bool async) internal void CreatePhysicalSNIHandle( string serverName, - bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, byte[] spnBuffer, diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionBasicTests.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionBasicTests.cs index 547c92118b..66dc223c4b 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionBasicTests.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionBasicTests.cs @@ -337,7 +337,6 @@ public async void ConnectionTimeoutTestAsync(int timeout) [Fact] public void ConnectionInvalidTimeoutTest() { - // Start a server with connection timeout from the inline data. Assert.Throws(() => { using TestTdsServer server = TestTdsServer.StartTestServer(false, false, -5);