diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNIProxy.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNIProxy.cs index 6880bc187321..26b590c8f17a 100644 --- a/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNIProxy.cs +++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNIProxy.cs @@ -2,7 +2,6 @@ // 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.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net; @@ -10,9 +9,7 @@ using System.Net.Sockets; using System.Text; using System.Threading.Tasks; -using System; -using System.Threading; -using System.Collections; +using System.IO; namespace System.Data.SqlClient.SNI { @@ -575,7 +572,6 @@ internal class DataSource private const char CommaSeparator = ','; private const char BackSlashSeparator = '\\'; - private const char ForwardSlashSeparator = '/'; private const string DefaultHostName = "localhost"; private const string DefaultSqlServerInstanceName = "mssqlserver"; private const string PipeBeginning = @"\\"; @@ -786,32 +782,44 @@ private bool InferNamedPipesInformation() try { - Uri uri = new Uri(_dataSourceAfterTrimmingProtocol); - if (string.IsNullOrEmpty(uri.Host)) + string[] tokensByBackSlash = _dataSourceAfterTrimmingProtocol.Split(BackSlashSeparator); + + // The datasource is of the format \\host\pipe\sql\query [0]\[1]\[2]\[3]\[4]\[5] + // It would at least have 6 parts. + // Another valid Sql named pipe for an named instance is \\.\pipe\MSSQL$MYINSTANCE\sql\query + if (tokensByBackSlash.Length < 6) { ReportSNIError(SNIProviders.NP_PROV); return false; } - string[] absolutePathParts = uri.AbsolutePath.Split(ForwardSlashSeparator); + string host = tokensByBackSlash[2]; - //Check if the "pipe" keyword is the first part of path - if (PipeToken.CompareTo(absolutePathParts[1]) != 0) + if (string.IsNullOrEmpty(host)) { ReportSNIError(SNIProviders.NP_PROV); return false; } - // There should be at least 4 parts in the pipename e.g /pipe/sql/query [0]/[1]/[2]/[3] - // Another valid Sql named pipe for an named instance is \\.\pipe\MSSQL$MYINSTANCE\sql\query - if (absolutePathParts.Length < 4) + //Check if the "pipe" keyword is the first part of path + if (!PipeToken.Equals(tokensByBackSlash[3])) { ReportSNIError(SNIProviders.NP_PROV); return false; } - PipeName = uri.AbsolutePath.Substring(PipeToken.Length + 2); - ServerName = IsLocalHost(uri.Host) ? Environment.MachineName : uri.Host; + StringBuilder pipeNameBuilder = new StringBuilder(); + + for ( int i = 4; i < tokensByBackSlash.Length-1; i++) + { + pipeNameBuilder.Append(tokensByBackSlash[i]); + pipeNameBuilder.Append(Path.PathSeparator); + } + // Append the last part without a "/" + pipeNameBuilder.Append(tokensByBackSlash[tokensByBackSlash.Length - 1]); + + PipeName = pipeNameBuilder.ToString(); + ServerName = IsLocalHost(host) ? Environment.MachineName : host; } catch (UriFormatException) { @@ -820,7 +828,7 @@ private bool InferNamedPipesInformation() } // DataSource is something like "\\pipename" - if (ConnectionProtocol != DataSource.Protocol.None) + if (ConnectionProtocol == DataSource.Protocol.None) { ConnectionProtocol = DataSource.Protocol.NP; } diff --git a/src/System.Data.SqlClient/tests/FunctionalTests/ExceptionTest.cs b/src/System.Data.SqlClient/tests/FunctionalTests/ExceptionTest.cs index f0e72bdc85b3..5d30613835fc 100644 --- a/src/System.Data.SqlClient/tests/FunctionalTests/ExceptionTest.cs +++ b/src/System.Data.SqlClient/tests/FunctionalTests/ExceptionTest.cs @@ -76,6 +76,27 @@ public void IndependentConnectionExceptionTestExecuteReader() } } + [Theory] + [InlineData(@"np:\\.\pipe\sqlbad\query")] + [InlineData(@"np:\\.\pipe\MSSQL$NonExistentInstance\sql\query")] + [InlineData(@"\\.\pipe\sqlbad\query")] + [InlineData(@"\\.\pipe\MSSQL$NonExistentInstance\sql\query")] + [InlineData(@"np:\\localhost\pipe\sqlbad\query")] + [InlineData(@"np:\\localhost\pipe\MSSQL$NonExistentInstance\sqlbad\query")] + [InlineData(@"\\localhost\pipe\sqlbad\query")] + [InlineData(@"\\localhost\pipe\MSSQL$NonExistentInstance\sqlbad\query")] + [PlatformSpecific(TestPlatforms.Windows)] // Named pipes with the given input strings are not supported on Unix + public void NamedPipeTest(string dataSource) + { + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(); + builder.DataSource = dataSource; + builder.ConnectTimeout = 1; + using(SqlConnection connection = new SqlConnection(builder.ConnectionString)) + { + VerifyConnectionFailure(() => connection.Open(), "(provider: Named Pipes Provider, error: 11 - Timeout error)"); + } + } + private void GenerateConnectionException(string connectionString) { using (SqlConnection sqlConnection = new SqlConnection(connectionString))