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

[Release 2.1] Fix missing error messages in Managed SNI #883

Merged
merged 4 commits into from
Jan 18, 2021
Merged
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 @@ -88,6 +88,25 @@ internal static uint MapLocalDBErrorStateToCode(LocalDBErrorState errorState)
}
}

internal static string MapLocalDBErrorStateToErrorMessage(LocalDBErrorState errorState)
{
switch (errorState)
{
case LocalDBErrorState.NO_INSTALLATION:
return Strings.SNI_ERROR_52;
case LocalDBErrorState.INVALID_CONFIG:
return Strings.SNI_ERROR_53;
case LocalDBErrorState.NO_SQLUSERINSTANCEDLL_PATH:
return Strings.SNI_ERROR_54;
case LocalDBErrorState.INVALID_SQLUSERINSTANCEDLL_PATH:
return Strings.SNI_ERROR_55;
case LocalDBErrorState.NONE:
return Strings.SNI_ERROR_50;
default:
return Strings.SNI_ERROR_53;
}
}

/// <summary>
/// Loads the User Instance dll.
/// </summary>
Expand Down Expand Up @@ -117,15 +136,15 @@ private bool LoadUserInstanceDll()
// If there was no DLL path found, then there is an error.
if (dllPath == null)
{
SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.INVALID_PROV, 0, MapLocalDBErrorStateToCode(registryQueryErrorState), string.Empty);
SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.INVALID_PROV, 0, MapLocalDBErrorStateToCode(registryQueryErrorState), MapLocalDBErrorStateToErrorMessage(registryQueryErrorState));
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.LocalDB.Windows.LoadUserInstanceDll |SNI|ERR >User instance DLL path is null.");
return false;
}

// In case the registry had an empty path for dll
if (string.IsNullOrWhiteSpace(dllPath))
{
SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.INVALID_PROV, 0, SNICommon.LocalDBInvalidSqlUserInstanceDllPath, string.Empty);
SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.INVALID_PROV, 0, SNICommon.LocalDBInvalidSqlUserInstanceDllPath, Strings.SNI_ERROR_55);
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.LocalDB.Windows.LoadUserInstanceDll |SNI|ERR > User instance DLL path is invalid. DLL path ={0}", dllPath);
return false;
}
Expand All @@ -135,7 +154,7 @@ private bool LoadUserInstanceDll()

if (libraryHandle.IsInvalid)
{
SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.INVALID_PROV, 0, SNICommon.LocalDBFailedToLoadDll, string.Empty);
SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.INVALID_PROV, 0, SNICommon.LocalDBFailedToLoadDll, Strings.SNI_ERROR_56);
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.LocalDB.Windows.LoadUserInstanceDll |SNI|ERR > Library Handle is invalid. Could not load the dll.");
libraryHandle.Dispose();
return false;
Expand All @@ -146,7 +165,7 @@ private bool LoadUserInstanceDll()

if (_startInstanceHandle == IntPtr.Zero)
{
SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.INVALID_PROV, 0, SNICommon.LocalDBBadRuntime, string.Empty);
SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.INVALID_PROV, 0, SNICommon.LocalDBBadRuntime, Strings.SNI_ERROR_57);
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.LocalDB.Windows.LoadUserInstanceDll |SNI|ERR > Was not able to load the PROC from DLL. Bad Runtime.");
libraryHandle.Dispose();
return false;
Expand All @@ -157,7 +176,7 @@ private bool LoadUserInstanceDll()

if (localDBStartInstanceFunc == null)
{
SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.INVALID_PROV, 0, SNICommon.LocalDBBadRuntime, string.Empty);
SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.INVALID_PROV, 0, SNICommon.LocalDBBadRuntime, Strings.SNI_ERROR_57);
libraryHandle.Dispose();
_startInstanceHandle = IntPtr.Zero;
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public uint StartReceive()
return TdsEnums.SNI_SUCCESS_IO_PENDING;
}
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.SNIMarsConnection.StartReceive |SNI|ERR> Connection not useable.");
return SNICommon.ReportSNIError(SNIProviders.SMUX_PROV, 0, SNICommon.ConnNotUsableError, string.Empty);
return SNICommon.ReportSNIError(SNIProviders.SMUX_PROV, 0, SNICommon.ConnNotUsableError, Strings.SNI_ERROR_19);
}
finally
{
Expand Down Expand Up @@ -293,7 +293,7 @@ public void HandleReceiveComplete(SNIPacket packet, uint sniErrorCode)

if (!_sessions.ContainsKey(_currentHeader.sessionId))
{
SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.SMUX_PROV, 0, SNICommon.InvalidParameterError, string.Empty);
SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.SMUX_PROV, 0, SNICommon.InvalidParameterError, Strings.SNI_ERROR_5);
HandleReceiveError(packet);
_lowerHandle.Dispose();
_lowerHandle = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ public override uint Receive(out SNIPacket packet, int timeoutInMilliseconds)

if (!_packetEvent.Wait(timeoutInMilliseconds))
{
SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.SMUX_PROV, 0, SNICommon.ConnTimeoutError, string.Empty);
SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.SMUX_PROV, 0, SNICommon.ConnTimeoutError, Strings.SNI_ERROR_11);
return TdsEnums.SNI_WAIT_TIMEOUT;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ internal sealed class SNINpHandle : SNIPhysicalHandle
private const int MAX_PIPE_INSTANCES = 255;

private readonly string _targetServer;
private readonly object _callbackObject;
private readonly object _sendSync;

private Stream _stream;
Expand All @@ -38,15 +37,14 @@ internal sealed class SNINpHandle : SNIPhysicalHandle
private int _bufferSize = TdsEnums.DEFAULT_LOGIN_PACKET_SIZE;
private readonly Guid _connectionId = Guid.NewGuid();

public SNINpHandle(string serverName, string pipeName, long timerExpire, object callbackObject)
public SNINpHandle(string serverName, string pipeName, long timerExpire)
{
long scopeID = SqlClientEventSource.Log.TrySNIScopeEnterEvent("<sc.SNI.SNINpHandle.SNINpHandle |SNI|INFO|SCOPE> Constructor");
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.SNINpHandle.SNINpHandle |SNI|INFO> Constructor. server name = {0}, pipe name = {1}", serverName, pipeName);
try
{
_sendSync = new object();
_targetServer = serverName;
_callbackObject = callbackObject;

try
{
Expand Down Expand Up @@ -86,7 +84,7 @@ public SNINpHandle(string serverName, string pipeName, long timerExpire, object

if (!_pipeStream.IsConnected || !_pipeStream.CanWrite || !_pipeStream.CanRead)
{
SNICommon.ReportSNIError(SNIProviders.NP_PROV, 0, SNICommon.ConnOpenFailedError, string.Empty);
SNICommon.ReportSNIError(SNIProviders.NP_PROV, 0, SNICommon.ConnOpenFailedError, Strings.SNI_ERROR_40);
_status = TdsEnums.SNI_ERROR;
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.SNINpHandle.SNINpHandle |SNI|ERR> Pipe stream is not connected or cannot write or read to/from it.");
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ private void ReadFromStreamAsyncContinuation(Task<int> t, object state)

if (_dataLength == 0)
{
SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.TCP_PROV, 0, SNICommon.ConnTerminatedError, string.Empty);
SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.TCP_PROV, 0, SNICommon.ConnTerminatedError, Strings.SNI_ERROR_2);
error = true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,6 @@ internal uint WritePacket(SNIHandle handle, SNIPacket packet, bool sync)
/// <summary>
/// Create a SNI connection handle
/// </summary>
/// <param name="callbackObject">Asynchronous I/O callback object</param>
/// <param name="fullServerName">Full server name from connection string</param>
/// <param name="ignoreSniOpenTimeout">Ignore open timeout</param>
/// <param name="timerExpire">Timer expiration</param>
Expand All @@ -254,7 +253,7 @@ internal uint WritePacket(SNIHandle handle, SNIPacket packet, bool sync)
/// <param name="cachedFQDN">Used for DNS Cache</param>
/// <param name="pendingDNSInfo">Used for DNS Cache</param>
/// <returns>SNI handle</returns>
internal SNIHandle CreateConnectionHandle(object callbackObject, string fullServerName, bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, ref byte[] spnBuffer, bool flushCache, bool async, bool parallel, bool isIntegratedSecurity, string cachedFQDN, ref SQLDNSInfo pendingDNSInfo)
internal SNIHandle CreateConnectionHandle(string fullServerName, bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, ref byte[] spnBuffer, bool flushCache, bool async, bool parallel, bool isIntegratedSecurity, string cachedFQDN, ref SQLDNSInfo pendingDNSInfo)
{
instanceName = new byte[1];

Expand All @@ -281,10 +280,10 @@ internal SNIHandle CreateConnectionHandle(object callbackObject, string fullServ
case DataSource.Protocol.Admin:
case DataSource.Protocol.None: // default to using tcp if no protocol is provided
case DataSource.Protocol.TCP:
sniHandle = CreateTcpHandle(details, timerExpire, callbackObject, parallel, cachedFQDN, ref pendingDNSInfo);
sniHandle = CreateTcpHandle(details, timerExpire, parallel, cachedFQDN, ref pendingDNSInfo);
break;
case DataSource.Protocol.NP:
sniHandle = CreateNpHandle(details, timerExpire, callbackObject, parallel);
sniHandle = CreateNpHandle(details, timerExpire, parallel);
break;
default:
Debug.Fail($"Unexpected connection protocol: {details._connectionProtocol}");
Expand Down Expand Up @@ -365,12 +364,11 @@ private static byte[] GetSqlServerSPN(string hostNameOrAddress, string portOrIns
/// </summary>
/// <param name="details">Data source</param>
/// <param name="timerExpire">Timer expiration</param>
/// <param name="callbackObject">Asynchronous I/O callback object</param>
/// <param name="parallel">Should MultiSubnetFailover be used</param>
/// <param name="cachedFQDN">Key for DNS Cache</param>
/// <param name="pendingDNSInfo">Used for DNS Cache</param>
/// <returns>SNITCPHandle</returns>
private SNITCPHandle CreateTcpHandle(DataSource details, long timerExpire, object callbackObject, bool parallel, string cachedFQDN, ref SQLDNSInfo pendingDNSInfo)
private SNITCPHandle CreateTcpHandle(DataSource details, long timerExpire, bool parallel, string cachedFQDN, ref SQLDNSInfo pendingDNSInfo)
{
// TCP Format:
// tcp:<host name>\<instance name>
Expand All @@ -379,7 +377,7 @@ private SNITCPHandle CreateTcpHandle(DataSource details, long timerExpire, objec
string hostName = details.ServerName;
if (string.IsNullOrWhiteSpace(hostName))
{
SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.TCP_PROV, 0, SNICommon.InvalidConnStringError, string.Empty);
SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.TCP_PROV, 0, SNICommon.InvalidConnStringError, Strings.SNI_ERROR_25);
return null;
}

Expand Down Expand Up @@ -408,7 +406,7 @@ private SNITCPHandle CreateTcpHandle(DataSource details, long timerExpire, objec
port = isAdminConnection ? DefaultSqlServerDacPort : DefaultSqlServerPort;
}

return new SNITCPHandle(hostName, port, timerExpire, callbackObject, parallel, cachedFQDN, ref pendingDNSInfo);
return new SNITCPHandle(hostName, port, timerExpire, parallel, cachedFQDN, ref pendingDNSInfo);
}


Expand All @@ -418,17 +416,17 @@ private SNITCPHandle CreateTcpHandle(DataSource details, long timerExpire, objec
/// </summary>
/// <param name="details">Data source</param>
/// <param name="timerExpire">Timer expiration</param>
/// <param name="callbackObject">Asynchronous I/O callback object</param>
/// <param name="parallel">Should MultiSubnetFailover be used. Only returns an error for named pipes.</param>
/// <returns>SNINpHandle</returns>
private SNINpHandle CreateNpHandle(DataSource details, long timerExpire, object callbackObject, bool parallel)
private SNINpHandle CreateNpHandle(DataSource details, long timerExpire, bool parallel)
{
if (parallel)
{
SNICommon.ReportSNIError(SNIProviders.NP_PROV, 0, SNICommon.MultiSubnetFailoverWithNonTcpProtocol, string.Empty);
// Connecting to a SQL Server instance using the MultiSubnetFailover connection option is only supported when using the TCP protocol
SNICommon.ReportSNIError(SNIProviders.NP_PROV, 0, SNICommon.MultiSubnetFailoverWithNonTcpProtocol, Strings.SNI_ERROR_49);
return null;
}
return new SNINpHandle(details.PipeHostName, details.PipeName, timerExpire, callbackObject);
return new SNINpHandle(details.PipeHostName, details.PipeName, timerExpire);
}

/// <summary>
Expand Down Expand Up @@ -632,7 +630,7 @@ internal static string GetLocalDBInstance(string dataSource, out bool error)
}
else
{
SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.INVALID_PROV, 0, SNICommon.LocalDBNoInstanceName, string.Empty);
SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.INVALID_PROV, 0, SNICommon.LocalDBNoInstanceName, Strings.SNI_ERROR_51);
error = true;
return null;
}
Expand Down Expand Up @@ -758,7 +756,7 @@ private bool InferConnectionDetails()

private void ReportSNIError(SNIProviders provider)
{
SNILoadHandle.SingletonInstance.LastError = new SNIError(provider, 0, SNICommon.InvalidConnStringError, string.Empty);
SNILoadHandle.SingletonInstance.LastError = new SNIError(provider, 0, SNICommon.InvalidConnStringError, Strings.SNI_ERROR_25);
IsBadDataSource = true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ namespace Microsoft.Data.SqlClient.SNI
internal sealed class SNITCPHandle : SNIPhysicalHandle
{
private readonly string _targetServer;
private readonly object _callbackObject;
private readonly object _sendSync;
private readonly Socket _socket;
private NetworkStream _tcpStream;
Expand Down Expand Up @@ -114,13 +113,11 @@ public override int ProtocolVersion
/// <param name="serverName">Server name</param>
/// <param name="port">TCP port number</param>
/// <param name="timerExpire">Connection timer expiration</param>
/// <param name="callbackObject">Callback object</param>
/// <param name="parallel">Parallel executions</param>
/// <param name="cachedFQDN">Key for DNS Cache</param>
/// <param name="pendingDNSInfo">Used for DNS Cache</param>
public SNITCPHandle(string serverName, int port, long timerExpire, object callbackObject, bool parallel, string cachedFQDN, ref SQLDNSInfo pendingDNSInfo)
public SNITCPHandle(string serverName, int port, long timerExpire, bool parallel, string cachedFQDN, ref SQLDNSInfo pendingDNSInfo)
{
_callbackObject = callbackObject;
_targetServer = serverName;
_sendSync = new object();

Expand Down Expand Up @@ -217,7 +214,7 @@ public SNITCPHandle(string serverName, int port, long timerExpire, object callba

if (reportError)
{
ReportTcpSNIError(0, SNICommon.ConnOpenFailedError, string.Empty);
ReportTcpSNIError(0, SNICommon.ConnOpenFailedError, Strings.SNI_ERROR_40);
}
return;
}
Expand Down Expand Up @@ -259,7 +256,7 @@ private Socket TryConnectParallel(string hostName, int port, TimeSpan ts, bool i
{
// Fail if above 64 to match legacy behavior
callerReportError = false;
ReportTcpSNIError(0, SNICommon.MultiSubnetFailoverWithMoreThan64IPs, string.Empty);
ReportTcpSNIError(0, SNICommon.MultiSubnetFailoverWithMoreThan64IPs, Strings.SNI_ERROR_47);
return availableSocket;
}

Expand Down Expand Up @@ -288,7 +285,7 @@ private Socket TryConnectParallel(string hostName, int port, TimeSpan ts, bool i
if (!(isInfiniteTimeOut ? connectTask.Wait(-1) : connectTask.Wait(ts)))
{
callerReportError = false;
ReportTcpSNIError(0, SNICommon.ConnOpenFailedError, string.Empty);
ReportTcpSNIError(0, SNICommon.ConnOpenFailedError, Strings.SNI_ERROR_40);
return availableSocket;
}

Expand Down Expand Up @@ -644,7 +641,7 @@ public override uint Receive(out SNIPacket packet, int timeoutInMilliseconds)
else
{
// otherwise it is timeout for 0 or less than -1
ReportTcpSNIError(0, SNICommon.ConnTimeoutError, string.Empty);
ReportTcpSNIError(0, SNICommon.ConnTimeoutError, Strings.SNI_ERROR_11);
return TdsEnums.SNI_WAIT_TIMEOUT;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ protected override uint SNIPacketGetData(PacketHandle packet, byte[] _inBuff, re

internal override void CreatePhysicalSNIHandle(string serverName, bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, ref byte[] spnBuffer, bool flushCache, bool async, bool parallel, string cachedFQDN, ref SQLDNSInfo pendingDNSInfo, bool isIntegratedSecurity)
{
_sessionHandle = SNIProxy.GetInstance().CreateConnectionHandle(this, serverName, ignoreSniOpenTimeout, timerExpire, out instanceName, ref spnBuffer, flushCache, async, parallel, isIntegratedSecurity, cachedFQDN, ref pendingDNSInfo);
_sessionHandle = SNIProxy.GetInstance().CreateConnectionHandle(serverName, ignoreSniOpenTimeout, timerExpire, out instanceName, ref spnBuffer, flushCache, async, parallel, isIntegratedSecurity, cachedFQDN, ref pendingDNSInfo);
if (_sessionHandle == null)
{
_parser.ProcessSNIError(this);
Expand Down