Skip to content

Commit de07449

Browse files
Implementing SNINetworkStream fixes issue 422 for non-encrypted TCP connections.
1 parent 3eaa757 commit de07449

File tree

3 files changed

+46
-3
lines changed

3 files changed

+46
-3
lines changed

src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@
442442
<Compile Include="Microsoft\Data\SqlClient\SNI\SNIPhysicalHandle.cs" />
443443
<Compile Include="Microsoft\Data\SqlClient\SNI\SNIProxy.cs" />
444444
<Compile Include="Microsoft\Data\SqlClient\SNI\SNITcpHandle.cs" />
445-
<Compile Include="Microsoft\Data\SqlClient\SNI\SNISslStream.cs" />
445+
<Compile Include="Microsoft\Data\SqlClient\SNI\SNIStreams.cs" />
446446
<Compile Include="Microsoft\Data\SqlClient\SNI\SslOverTdsStream.cs" />
447447
<Compile Include="Microsoft\Data\SqlClient\SNI\SNICommon.cs" />
448448
<Compile Include="Microsoft\Data\SqlClient\SNI\SspiClientContextStatus.cs" />

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNISslStream.cs src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIStreams.cs

+44-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.IO;
77
using System.Threading;
88
using System.Threading.Tasks;
9+
using System.Net.Sockets;
910

1011
namespace Microsoft.Data.SqlClient.SNI
1112
{
@@ -30,7 +31,49 @@ public override Task<int> ReadAsync(byte[] buffer, int offset, int count, Cancel
3031
try
3132
{
3233
return _readAsyncQueueSemaphore.WaitAsync()
33-
.ContinueWith<int>(_ => base.ReadAsync(buffer, offset, count, cancellationToken).GetAwaiter().GetResult());
34+
.ContinueWith(_ => base.ReadAsync(buffer, offset, count, cancellationToken).GetAwaiter().GetResult());
35+
}
36+
finally
37+
{
38+
_readAsyncQueueSemaphore.Release();
39+
}
40+
}
41+
42+
// Prevent the WriteAsync's collision by running task in Semaphore Slim
43+
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
44+
{
45+
try
46+
{
47+
return _writeAsyncQueueSemaphore.WaitAsync().ContinueWith(_ => base.WriteAsync(buffer, offset, count, cancellationToken));
48+
}
49+
finally
50+
{
51+
_writeAsyncQueueSemaphore.Release();
52+
}
53+
}
54+
}
55+
56+
/// <summary>
57+
/// This class extends NetworkStream to customize stream behavior for Managed SNI implementation.
58+
/// </summary>
59+
internal class SNINetworkStream : NetworkStream
60+
{
61+
private readonly ConcurrentQueueSemaphore _writeAsyncQueueSemaphore;
62+
private readonly ConcurrentQueueSemaphore _readAsyncQueueSemaphore;
63+
64+
public SNINetworkStream(Socket socket, bool ownsSocket) : base(socket, ownsSocket)
65+
{
66+
_writeAsyncQueueSemaphore = new ConcurrentQueueSemaphore(1);
67+
_readAsyncQueueSemaphore = new ConcurrentQueueSemaphore(1);
68+
}
69+
70+
// Prevent the ReadAsync's collision by running task in Semaphore Slim
71+
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
72+
{
73+
try
74+
{
75+
return _readAsyncQueueSemaphore.WaitAsync()
76+
.ContinueWith(_ => base.ReadAsync(buffer, offset, count, cancellationToken).GetAwaiter().GetResult());
3477
}
3578
finally
3679
{

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ public SNITCPHandle(string serverName, int port, long timerExpire, object callba
223223
}
224224

225225
_socket.NoDelay = true;
226-
_tcpStream = new NetworkStream(_socket, true);
226+
_tcpStream = new SNINetworkStream(_socket, true);
227227

228228
_sslOverTdsStream = new SslOverTdsStream(_tcpStream);
229229
_sslStream = new SNISslStream(_sslOverTdsStream, true, new RemoteCertificateValidationCallback(ValidateServerCertificate));

0 commit comments

Comments
 (0)