Skip to content

Commit

Permalink
fix (#2)
Browse files Browse the repository at this point in the history
native sni
managed sni unicode
  • Loading branch information
DavoudEshtehari committed Mar 2, 2022
1 parent 67f0bbf commit d93127c
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 91 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,11 @@ internal enum SniSpecialErrors : uint
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SNIServerEnumCloseWrapper")]
internal static extern void SNIServerEnumClose([In] IntPtr packet);

[DllImport(SNI, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SNIServerEnumReadWrapper")]
internal static extern int SNIServerEnumRead([In] IntPtr packet, [In, Out] char[] readBuffer, int bufferLength, out bool more);
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SNIServerEnumReadWrapper", CharSet = CharSet.Unicode)]
internal static extern int SNIServerEnumRead([In] IntPtr packet,
[In][MarshalAs(UnmanagedType.LPArray)] char[] readBuffer,
[In] int bufferLength,
[MarshalAs(UnmanagedType.Bool)] out bool more);

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

namespace Microsoft.Data.SqlClient.SNI
{
internal class SSRP
internal sealed class SSRP
{
private const char SemicolonSeparator = ';';
private const int SqlServerBrowserPort = 1434; //port SQL Server Browser
Expand Down Expand Up @@ -78,11 +78,11 @@ private static byte[] CreateInstanceInfoRequest(string instanceName)
{
const byte ClntUcastInst = 0x04;
instanceName += char.MinValue;
int byteCount = Encoding.ASCII.GetByteCount(instanceName);
int byteCount = Encoding.UTF7.GetByteCount(instanceName);

byte[] requestPacket = new byte[byteCount + 1];
requestPacket[0] = ClntUcastInst;
Encoding.ASCII.GetBytes(instanceName, 0, instanceName.Length, requestPacket, 1);
Encoding.UTF7.GetBytes(instanceName, 0, instanceName.Length, requestPacket, 1);

return requestPacket;
}
Expand Down Expand Up @@ -127,12 +127,12 @@ private static byte[] CreateDacPortInfoRequest(string instanceName)
const byte ClntUcastDac = 0x0F;
const byte ProtocolVersion = 0x01;
instanceName += char.MinValue;
int byteCount = Encoding.ASCII.GetByteCount(instanceName);
int byteCount = Encoding.UTF7.GetByteCount(instanceName);

byte[] requestPacket = new byte[byteCount + 2];
requestPacket[0] = ClntUcastDac;
requestPacket[1] = ProtocolVersion;
Encoding.ASCII.GetBytes(instanceName, 0, instanceName.Length, requestPacket, 2);
Encoding.UTF7.GetBytes(instanceName, 0, instanceName.Length, requestPacket, 2);

return requestPacket;
}
Expand Down Expand Up @@ -184,7 +184,9 @@ internal static string SendBroadcastUDPRequest()
{
StringBuilder response = new StringBuilder();
byte[] CLNT_BCAST_EX_Request = new byte[1] { CLNT_BCAST_EX }; //0x02
int currentTimeOut = FirstTimeoutForCLNT_BCAST_EX; //wait 5 secs for first response and every 1 sec upto 15 secs (https://docs.microsoft.com/en-us/openspecs/windows_protocols/mc-sqlr/f2640a2d-3beb-464b-a443-f635842ebc3e#Appendix_A_3)
// Waits 5 seconds for the first response and every 1 second up to 15 seconds
// https://docs.microsoft.com/en-us/openspecs/windows_protocols/mc-sqlr/f2640a2d-3beb-464b-a443-f635842ebc3e#Appendix_A_3
int currentTimeOut = FirstTimeoutForCLNT_BCAST_EX;

using (TrySNIEventScope.Create(nameof(SSRP)))
{
Expand All @@ -203,7 +205,7 @@ internal static string SendBroadcastUDPRequest()
SqlClientEventSource.Log.TrySNITraceEvent(nameof(SSRP), EventType.INFO, "Received instnace info from UDP Client.");
if (receiveTask.Result.Buffer.Length < ValidResponseSizeForCLNT_BCAST_EX) //discard invalid response
{
response.Append(Encoding.ASCII.GetString(receiveTask.Result.Buffer, ServerResponseHeaderSizeForCLNT_BCAST_EX, receiveTask.Result.Buffer.Length - ServerResponseHeaderSizeForCLNT_BCAST_EX)); //RESP_DATA(VARIABLE) - 3 (RESP_SIZE + SVR_RESP)
response.Append(Encoding.UTF7.GetString(receiveTask.Result.Buffer, ServerResponseHeaderSizeForCLNT_BCAST_EX, receiveTask.Result.Buffer.Length - ServerResponseHeaderSizeForCLNT_BCAST_EX)); //RESP_DATA(VARIABLE) - 3 (RESP_SIZE + SVR_RESP)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,10 @@ internal static extern unsafe uint SNISecGenClientContextWrapper(
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SNIServerEnumCloseWrapper")]
internal static extern void SNIServerEnumClose([In] IntPtr packet);

[DllImport(SNI, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SNIServerEnumReadWrapper")]
internal static extern int SNIServerEnumRead([In] IntPtr packet, [In, Out] char[] readBuffer, int bufferLength, out bool more);
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SNIServerEnumReadWrapper", CharSet = CharSet.Unicode)]
internal static extern int SNIServerEnumRead([In] IntPtr packet,
[In, Out][MarshalAs(UnmanagedType.LPArray)] char[] readBuffer,
[In] int bufferLength,
[MarshalAs(UnmanagedType.Bool)] out bool more);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,10 @@ internal static extern unsafe uint SNISecGenClientContextWrapper(
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SNIServerEnumCloseWrapper")]
internal static extern void SNIServerEnumClose([In] IntPtr packet);

[DllImport(SNI, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SNIServerEnumReadWrapper")]
internal static extern int SNIServerEnumRead([In] IntPtr packet, [In, Out] char[] readBuffer, int bufferLength, out bool more);
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SNIServerEnumReadWrapper", CharSet = CharSet.Unicode)]
internal static extern int SNIServerEnumRead([In] IntPtr packet,
[In, Out][MarshalAs(UnmanagedType.LPArray)] char[] readBuffer,
[In] int bufferLength,
[MarshalAs(UnmanagedType.Bool)] out bool more);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
// 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.Collections.Generic;
using System.Data;
using System.Globalization;
using Microsoft.Data.Sql;
using Microsoft.Data.SqlClient.SNI;

Expand All @@ -13,36 +11,31 @@ namespace Microsoft.Data.SqlClient.Server
/// <summary>
/// Provides a mechanism for enumerating all available instances of SQL Server within the local network
/// </summary>
internal static class SqlDataSourceEnumeratorManagedHelper
internal static class SqlDataSourceEnumeratorManagedHelper
{
/// <summary>
/// Provides a mechanism for enumerating all available instances of SQL Server within the local network.
/// </summary>
/// <returns>DataTable with ServerName,InstanceName,IsClustered and Version</returns>
internal static DataTable GetDataSources()
{
{
return ParseServerEnumString(SSRP.SendBroadcastUDPRequest());
}

static private System.Data.DataTable ParseServerEnumString(string serverInstances)
private static DataTable ParseServerEnumString(string serverInstances)
{
DataTable dataTable = new("SqlDataSources")
{
Locale = CultureInfo.InvariantCulture
};
dataTable.Columns.Add(SqlDataSourceEnumeratorUtil.ServerName, typeof(string));
dataTable.Columns.Add(SqlDataSourceEnumeratorUtil.InstanceName, typeof(string));
dataTable.Columns.Add(SqlDataSourceEnumeratorUtil.IsClustered, typeof(string));
dataTable.Columns.Add(SqlDataSourceEnumeratorUtil.Version, typeof(string));
System.Console.WriteLine(serverInstances);
DataTable dataTable = SqlDataSourceEnumeratorUtil.PrepareDataTable();
DataRow dataRow;

if (serverInstances.Length == 0)
{
return dataTable;
}

string[] numOfServerInstances = serverInstances.Split(new[] { SqlDataSourceEnumeratorUtil.EndOfServerInstanceDelimiterManaged }, StringSplitOptions.None);
SqlClientEventSource.Log.TryTraceEvent("<sc.SqlDataSourceEnumeratorManagedHelper.ParseServerEnumString|INFO> Number of server instances results recieved are {0}", numOfServerInstances.Length);
string[] numOfServerInstances = serverInstances.Split(SqlDataSourceEnumeratorUtil.s_endOfServerInstanceDelimiter_Managed, System.StringSplitOptions.None);
SqlClientEventSource.Log.TryTraceEvent("<sc.{0}.{1}|INFO> Number of recieved server instances are {2}",
nameof(SqlDataSourceEnumeratorManagedHelper), nameof(ParseServerEnumString), numOfServerInstances.Length);

foreach (string currentServerInstance in numOfServerInstances)
{
Expand All @@ -65,24 +58,19 @@ static private System.Data.DataTable ParseServerEnumString(string serverInstance
if (InstanceDetails.Count > 0)
{
dataRow = dataTable.NewRow();
dataRow[0] = InstanceDetails.ContainsKey(SqlDataSourceEnumeratorUtil.ServerName) == true ?
InstanceDetails[SqlDataSourceEnumeratorUtil.ServerName] : string.Empty;
dataRow[1] = InstanceDetails.ContainsKey(SqlDataSourceEnumeratorUtil.InstanceName) == true ?
InstanceDetails[SqlDataSourceEnumeratorUtil.InstanceName] : string.Empty;
dataRow[2] = InstanceDetails.ContainsKey(SqlDataSourceEnumeratorUtil.IsClustered) == true ?
InstanceDetails[SqlDataSourceEnumeratorUtil.IsClustered] : string.Empty;
dataRow[3] = InstanceDetails.ContainsKey(SqlDataSourceEnumeratorUtil.Version) == true ?
InstanceDetails[SqlDataSourceEnumeratorUtil.Version] : string.Empty;
dataRow[0] = InstanceDetails.ContainsKey(SqlDataSourceEnumeratorUtil.ServerNameCol) == true ?
InstanceDetails[SqlDataSourceEnumeratorUtil.ServerNameCol] : string.Empty;
dataRow[1] = InstanceDetails.ContainsKey(SqlDataSourceEnumeratorUtil.InstanceNameCol) == true ?
InstanceDetails[SqlDataSourceEnumeratorUtil.InstanceNameCol] : string.Empty;
dataRow[2] = InstanceDetails.ContainsKey(SqlDataSourceEnumeratorUtil.IsClusteredCol) == true ?
InstanceDetails[SqlDataSourceEnumeratorUtil.IsClusteredCol] : string.Empty;
dataRow[3] = InstanceDetails.ContainsKey(SqlDataSourceEnumeratorUtil.VersionNameCol) == true ?
InstanceDetails[SqlDataSourceEnumeratorUtil.VersionNameCol] : string.Empty;

dataTable.Rows.Add(dataRow);
}
}

foreach (DataColumn column in dataTable.Columns)
{
column.ReadOnly = true;
}
return dataTable;
return dataTable.SetColumnsReadOnly();
}
}
}
Loading

0 comments on commit d93127c

Please sign in to comment.