From 30abd30421289509cd3bd18a9114501afdc0fb7c Mon Sep 17 00:00:00 2001 From: stephentoub Date: Sun, 7 Feb 2016 10:40:27 -0500 Subject: [PATCH] Remove Client property from TcpClient and UdpClient The property leaks through the abstraction. It's rarely used. And it complicates things on Unix due to exposing the underlying socket instance combined with difficulties with multiple connect calls on a single socket instance. Until we have good reason to expose it in the contract, we're removing it from the contract before it's stable. --- .../System/Data/SqlClient/SNI/SNITcpHandle.cs | 93 +++++++++++++++---- .../ClientAsyncAuthenticateTest.cs | 5 +- .../ClientDefaultEncryptionTest.cs | 10 +- .../tests/FunctionalTests/DummyTcpServer.cs | 11 +-- .../ServerAllowNoEncryptionTest.cs | 15 ++- .../ServerAsyncAuthenticateTest.cs | 5 +- .../FunctionalTests/ServerNoEncryptionTest.cs | 10 +- .../ServerRequireEncryptionTest.cs | 10 +- .../FunctionalTests/AgnosticListenerTest.cs | 4 - .../tests/FunctionalTests/UdpClientTest.cs | 8 -- .../ref/System.Net.Sockets.cs | 2 - .../src/System/Net/Sockets/TCPClient.Unix.cs | 38 +------- .../System/Net/Sockets/TCPClient.Windows.cs | 15 +-- .../src/System/Net/Sockets/TCPClient.cs | 12 +-- .../src/System/Net/Sockets/UDPClient.cs | 55 +++++------ .../ArgumentValidationTests.cs | 22 ----- .../tests/FunctionalTests/SendReceive.cs | 85 ----------------- .../tests/FunctionalTests/TcpClientTest.cs | 2 - 18 files changed, 130 insertions(+), 272 deletions(-) diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNITcpHandle.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNITcpHandle.cs index edc12fcff897..1698209be2c8 100644 --- a/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNITcpHandle.cs +++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNITcpHandle.cs @@ -6,6 +6,8 @@ using System.Net; using System.Net.Security; using System.Net.Sockets; +using System.Runtime.ExceptionServices; +using System.Runtime.InteropServices; using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; using System.Threading.Tasks; @@ -25,7 +27,6 @@ internal class SNITCPHandle : SNIHandle private readonly TaskFactory _writeTaskFactory; private Stream _stream; - private TcpClient _tcpClient; private SslStream _sslStream; private SslOverTdsStream _sslOverTdsStream; private SNIAsyncCallback _receiveCallback; @@ -56,12 +57,6 @@ public override void Dispose() _sslStream.Dispose(); _sslStream = null; } - - if (_tcpClient != null) - { - _tcpClient.Dispose(); - _tcpClient = null; - } } } @@ -103,8 +98,6 @@ public SNITCPHandle(string serverName, int port, long timerExpire, object callba try { - _tcpClient = new TcpClient(); - TimeSpan ts; // In case the Timeout is Infinite, we will receive the max value of Int64 as the tick count @@ -116,7 +109,7 @@ public SNITCPHandle(string serverName, int port, long timerExpire, object callba ts = ts.Ticks < 0 ? TimeSpan.FromTicks(0) : ts; } - Task connectTask; + Task connectTask; if (parallel) { Task serverAddrTask = Dns.GetHostAddressesAsync(serverName); @@ -130,11 +123,11 @@ public SNITCPHandle(string serverName, int port, long timerExpire, object callba return; } - connectTask = _tcpClient.ConnectAsync(serverAddresses, port); + connectTask = ConnectAsync(serverAddresses, port); } else { - connectTask = _tcpClient.ConnectAsync(serverName, port); + connectTask = ConnectAsync(serverName, port); } if (!(isInfiniteTimeOut ? connectTask.Wait(-1) : connectTask.Wait(ts))) @@ -143,9 +136,9 @@ public SNITCPHandle(string serverName, int port, long timerExpire, object callba return; } - _tcpClient.NoDelay = true; - _tcpStream = _tcpClient.GetStream(); - _socket = _tcpClient.Client; + _socket = connectTask.Result; + _socket.NoDelay = true; + _tcpStream = new NetworkStream(_socket, true); _sslOverTdsStream = new SslOverTdsStream(_tcpStream); _sslStream = new SslStream(_sslOverTdsStream, true, new RemoteCertificateValidationCallback(ValidateServerCertificate), null); @@ -165,6 +158,70 @@ public SNITCPHandle(string serverName, int port, long timerExpire, object callba _status = TdsEnums.SNI_SUCCESS; } + private static async Task ConnectAsync(string serverName, int port) + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + await socket.ConnectAsync(serverName, port).ConfigureAwait(false); + return socket; + } + + // On unix we can't use the instance Socket methods that take multiple endpoints + + IPAddress[] addresses = await Dns.GetHostAddressesAsync(serverName).ConfigureAwait(false); + return await ConnectAsync(addresses, port).ConfigureAwait(false); + } + + private static async Task ConnectAsync(IPAddress[] serverAddresses, int port) + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + await socket.ConnectAsync(serverAddresses, port).ConfigureAwait(false); + return socket; + } + + // On unix we can't use the instance Socket methods that take multiple endpoints + + if (serverAddresses == null) + { + throw new ArgumentNullException("serverAddresses"); + } + if (serverAddresses.Length == 0) + { + throw new ArgumentOutOfRangeException("serverAddresses"); + } + + // Try each address in turn, and return the socket opened for the first one that works. + ExceptionDispatchInfo lastException = null; + foreach (IPAddress address in serverAddresses) + { + var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + try + { + await socket.ConnectAsync(address, port).ConfigureAwait(false); + return socket; + } + catch (Exception exc) + { + socket.Dispose(); + lastException = ExceptionDispatchInfo.Capture(exc); + } + } + + // Propagate the last failure that occurrred + if (lastException != null) + { + lastException.Throw(); + } + + // Should never get here. Either there will have been no addresses and we'll have thrown + // at the beginning, or one of the addresses will have worked and we'll have returned, or + // at least one of the addresses will failed, in which case we will have propagated that. + throw new ArgumentException(); + } + /// /// Enable SSL /// @@ -276,11 +333,11 @@ public override uint Receive(out SNIPacket packet, int timeoutInMilliseconds) { if (timeoutInMilliseconds > 0) { - _tcpClient.ReceiveTimeout = timeoutInMilliseconds; + _socket.ReceiveTimeout = timeoutInMilliseconds; } else if (timeoutInMilliseconds == -1) { // SqlCient internally represents infinite timeout by -1, and for TcpClient this is translated to a timeout of 0 - _tcpClient.ReceiveTimeout = 0; + _socket.ReceiveTimeout = 0; } else { @@ -320,7 +377,7 @@ public override uint Receive(out SNIPacket packet, int timeoutInMilliseconds) } finally { - _tcpClient.ReceiveTimeout = 0; + _socket.ReceiveTimeout = 0; } } } diff --git a/src/System.Net.Security/tests/FunctionalTests/ClientAsyncAuthenticateTest.cs b/src/System.Net.Security/tests/FunctionalTests/ClientAsyncAuthenticateTest.cs index 2c520290ca5e..e52dba0504cb 100644 --- a/src/System.Net.Security/tests/FunctionalTests/ClientAsyncAuthenticateTest.cs +++ b/src/System.Net.Security/tests/FunctionalTests/ClientAsyncAuthenticateTest.cs @@ -142,9 +142,8 @@ private async Task ClientAsyncSslHelper( Assert.True(((IAsyncResult)async).AsyncWaitHandle.WaitOne(TestConfiguration.PassingTestTimeoutMilliseconds), "Timed Out"); async.GetAwaiter().GetResult(); - _log.WriteLine("Client({0}) authenticated to server({1}) with encryption cipher: {2} {3}-bit strength", - client.Client.LocalEndPoint, client.Client.RemoteEndPoint, - sslStream.CipherAlgorithm, sslStream.CipherStrength); + _log.WriteLine("Client authenticated to server({0}) with encryption cipher: {1} {2}-bit strength", + server.RemoteEndPoint, sslStream.CipherAlgorithm, sslStream.CipherStrength); Assert.True(sslStream.CipherAlgorithm != CipherAlgorithmType.Null, "Cipher algorithm should not be NULL"); Assert.True(sslStream.CipherStrength > 0, "Cipher strength should be greater than 0"); } diff --git a/src/System.Net.Security/tests/FunctionalTests/ClientDefaultEncryptionTest.cs b/src/System.Net.Security/tests/FunctionalTests/ClientDefaultEncryptionTest.cs index a0462a54c5f8..99d72b89c589 100644 --- a/src/System.Net.Security/tests/FunctionalTests/ClientDefaultEncryptionTest.cs +++ b/src/System.Net.Security/tests/FunctionalTests/ClientDefaultEncryptionTest.cs @@ -45,9 +45,8 @@ public async Task ClientDefaultEncryption_ServerRequireEncryption_ConnectWithEnc using (var sslStream = new SslStream(client.GetStream(), false, AllowAnyServerCertificate, null)) { await sslStream.AuthenticateAsClientAsync("localhost", null, SslProtocolSupport.DefaultSslProtocols, false); - _log.WriteLine("Client({0}) authenticated to server({1}) with encryption cipher: {2} {3}-bit strength", - client.Client.LocalEndPoint, client.Client.RemoteEndPoint, - sslStream.CipherAlgorithm, sslStream.CipherStrength); + _log.WriteLine("Client authenticated to server({0}) with encryption cipher: {1} {2}-bit strength", + serverRequireEncryption.RemoteEndPoint, sslStream.CipherAlgorithm, sslStream.CipherStrength); Assert.True(sslStream.CipherAlgorithm != CipherAlgorithmType.Null, "Cipher algorithm should not be NULL"); Assert.True(sslStream.CipherStrength > 0, "Cipher strength should be greater than 0"); } @@ -66,9 +65,8 @@ public async Task ClientDefaultEncryption_ServerAllowNoEncryption_ConnectWithEnc using (var sslStream = new SslStream(client.GetStream(), false, AllowAnyServerCertificate, null)) { await sslStream.AuthenticateAsClientAsync("localhost", null, SslProtocolSupport.DefaultSslProtocols, false); - _log.WriteLine("Client({0}) authenticated to server({1}) with encryption cipher: {2} {3}-bit strength", - client.Client.LocalEndPoint, client.Client.RemoteEndPoint, - sslStream.CipherAlgorithm, sslStream.CipherStrength); + _log.WriteLine("Client authenticated to server({0}) with encryption cipher: {1} {2}-bit strength", + serverAllowNoEncryption.RemoteEndPoint, sslStream.CipherAlgorithm, sslStream.CipherStrength); Assert.True(sslStream.CipherAlgorithm != CipherAlgorithmType.Null, "Cipher algorithm should not be NULL"); Assert.True(sslStream.CipherStrength > 0, "Cipher strength should be greater than 0"); } diff --git a/src/System.Net.Security/tests/FunctionalTests/DummyTcpServer.cs b/src/System.Net.Security/tests/FunctionalTests/DummyTcpServer.cs index 41ef597996e6..a24d0358ff2c 100644 --- a/src/System.Net.Security/tests/FunctionalTests/DummyTcpServer.cs +++ b/src/System.Net.Security/tests/FunctionalTests/DummyTcpServer.cs @@ -96,8 +96,7 @@ private void OnAuthenticate(Task result, ClientState state) try { result.GetAwaiter().GetResult(); - _log.WriteLine("Server({0}) authenticated to client({1}) with encryption cipher: {2} {3}-bit strength", - state.TcpClient.Client.LocalEndPoint, state.TcpClient.Client.RemoteEndPoint, + _log.WriteLine("Server authenticated to client with encryption cipher: {0} {1}-bit strength", sslStream.CipherAlgorithm, sslStream.CipherStrength); // Start listening for data from the client connection. @@ -106,15 +105,13 @@ private void OnAuthenticate(Task result, ClientState state) catch (AuthenticationException authEx) { _log.WriteLine( - "Server({0}) disconnecting from client({1}) during authentication. No shared SSL/TLS algorithm. ({2})", - state.TcpClient.Client.LocalEndPoint, - state.TcpClient.Client.RemoteEndPoint, + "Server disconnecting from client during authentication. No shared SSL/TLS algorithm. ({0})", authEx); } catch (Exception ex) { - _log.WriteLine("Server({0}) disconnecting from client({1}) during authentication. Exception: {2}", - state.TcpClient.Client.LocalEndPoint, state.TcpClient.Client.RemoteEndPoint, ex.Message); + _log.WriteLine("Server disconnecting from client during authentication. Exception: {0}", + ex.Message); } finally { diff --git a/src/System.Net.Security/tests/FunctionalTests/ServerAllowNoEncryptionTest.cs b/src/System.Net.Security/tests/FunctionalTests/ServerAllowNoEncryptionTest.cs index d0a4b1b5ddde..917641f68306 100644 --- a/src/System.Net.Security/tests/FunctionalTests/ServerAllowNoEncryptionTest.cs +++ b/src/System.Net.Security/tests/FunctionalTests/ServerAllowNoEncryptionTest.cs @@ -44,9 +44,8 @@ public async Task ServerAllowNoEncryption_ClientRequireEncryption_ConnectWithEnc using (var sslStream = new SslStream(client.GetStream(), false, AllowAnyServerCertificate, null, EncryptionPolicy.RequireEncryption)) { await sslStream.AuthenticateAsClientAsync("localhost", null, SslProtocolSupport.DefaultSslProtocols, false); - _log.WriteLine("Client({0}) authenticated to server({1}) with encryption cipher: {2} {3}-bit strength", - client.Client.LocalEndPoint, client.Client.RemoteEndPoint, - sslStream.CipherAlgorithm, sslStream.CipherStrength); + _log.WriteLine("Client authenticated to server({0}) with encryption cipher: {1} {2}-bit strength", + serverAllowNoEncryption.RemoteEndPoint, sslStream.CipherAlgorithm, sslStream.CipherStrength); Assert.NotEqual(CipherAlgorithmType.Null, sslStream.CipherAlgorithm); Assert.True(sslStream.CipherStrength > 0); } @@ -65,9 +64,8 @@ public async Task ServerAllowNoEncryption_ClientAllowNoEncryption_ConnectWithEnc using (var sslStream = new SslStream(client.GetStream(), false, AllowAnyServerCertificate, null, EncryptionPolicy.AllowNoEncryption)) { await sslStream.AuthenticateAsClientAsync("localhost", null, SslProtocolSupport.DefaultSslProtocols, false); - _log.WriteLine("Client({0}) authenticated to server({1}) with encryption cipher: {2} {3}-bit strength", - client.Client.LocalEndPoint, client.Client.RemoteEndPoint, - sslStream.CipherAlgorithm, sslStream.CipherStrength); + _log.WriteLine("Client authenticated to server({0}) with encryption cipher: {1} {2}-bit strength", + serverAllowNoEncryption.RemoteEndPoint, sslStream.CipherAlgorithm, sslStream.CipherStrength); Assert.NotEqual(CipherAlgorithmType.Null, sslStream.CipherAlgorithm); Assert.True(sslStream.CipherStrength > 0, "Cipher strength should be greater than 0"); } @@ -87,9 +85,8 @@ public async Task ServerAllowNoEncryption_ClientNoEncryption_ConnectWithNoEncryp using (var sslStream = new SslStream(client.GetStream(), false, AllowAnyServerCertificate, null, EncryptionPolicy.NoEncryption)) { await sslStream.AuthenticateAsClientAsync("localhost", null, SslProtocolSupport.DefaultSslProtocols, false); - _log.WriteLine("Client({0}) authenticated to server({1}) with encryption cipher: {2} {3}-bit strength", - client.Client.LocalEndPoint, client.Client.RemoteEndPoint, - sslStream.CipherAlgorithm, sslStream.CipherStrength); + _log.WriteLine("Client authenticated to server({0}) with encryption cipher: {1} {2}-bit strength", + serverAllowNoEncryption.RemoteEndPoint, sslStream.CipherAlgorithm, sslStream.CipherStrength); CipherAlgorithmType expected = CipherAlgorithmType.Null; Assert.Equal(expected, sslStream.CipherAlgorithm); diff --git a/src/System.Net.Security/tests/FunctionalTests/ServerAsyncAuthenticateTest.cs b/src/System.Net.Security/tests/FunctionalTests/ServerAsyncAuthenticateTest.cs index 05cfdbbd8068..b423600e270d 100644 --- a/src/System.Net.Security/tests/FunctionalTests/ServerAsyncAuthenticateTest.cs +++ b/src/System.Net.Security/tests/FunctionalTests/ServerAsyncAuthenticateTest.cs @@ -171,9 +171,8 @@ private async Task ServerAsyncSslHelper( } _log.WriteLine( - "Server({0}) authenticated client({1}) with encryption cipher: {2} {3}-bit strength", - serverConnection.Client.LocalEndPoint, - serverConnection.Client.RemoteEndPoint, + "Server({0}) authenticated with encryption cipher: {1} {2}-bit strength", + serverEndPoint, sslServerStream.CipherAlgorithm, sslServerStream.CipherStrength); diff --git a/src/System.Net.Security/tests/FunctionalTests/ServerNoEncryptionTest.cs b/src/System.Net.Security/tests/FunctionalTests/ServerNoEncryptionTest.cs index b9a379c00593..f5ae12fddab1 100644 --- a/src/System.Net.Security/tests/FunctionalTests/ServerNoEncryptionTest.cs +++ b/src/System.Net.Security/tests/FunctionalTests/ServerNoEncryptionTest.cs @@ -63,9 +63,8 @@ public async Task ServerNoEncryption_ClientAllowNoEncryption_ConnectWithNoEncryp { await sslStream.AuthenticateAsClientAsync("localhost", null, SslProtocolSupport.DefaultSslProtocols, false); - _log.WriteLine("Client({0}) authenticated to server({1}) with encryption cipher: {2} {3}-bit strength", - client.Client.LocalEndPoint, client.Client.RemoteEndPoint, - sslStream.CipherAlgorithm, sslStream.CipherStrength); + _log.WriteLine("Client authenticated to server({0}) with encryption cipher: {1} {2}-bit strength", + serverNoEncryption.RemoteEndPoint, sslStream.CipherAlgorithm, sslStream.CipherStrength); CipherAlgorithmType expected = CipherAlgorithmType.Null; Assert.Equal(expected, sslStream.CipherAlgorithm); @@ -87,9 +86,8 @@ public async Task ServerNoEncryption_ClientNoEncryption_ConnectWithNoEncryption( using (var sslStream = new SslStream(client.GetStream(), false, AllowAnyServerCertificate, null, EncryptionPolicy.NoEncryption)) { await sslStream.AuthenticateAsClientAsync("localhost", null, SslProtocolSupport.DefaultSslProtocols, false); - _log.WriteLine("Client({0}) authenticated to server({1}) with encryption cipher: {2} {3}-bit strength", - client.Client.LocalEndPoint, client.Client.RemoteEndPoint, - sslStream.CipherAlgorithm, sslStream.CipherStrength); + _log.WriteLine("Client authenticated to server({0}) with encryption cipher: {1} {2}-bit strength", + serverNoEncryption.RemoteEndPoint, sslStream.CipherAlgorithm, sslStream.CipherStrength); CipherAlgorithmType expected = CipherAlgorithmType.Null; Assert.Equal(expected, sslStream.CipherAlgorithm); diff --git a/src/System.Net.Security/tests/FunctionalTests/ServerRequireEncryptionTest.cs b/src/System.Net.Security/tests/FunctionalTests/ServerRequireEncryptionTest.cs index e42b65f206ec..0114e9b1f5ee 100644 --- a/src/System.Net.Security/tests/FunctionalTests/ServerRequireEncryptionTest.cs +++ b/src/System.Net.Security/tests/FunctionalTests/ServerRequireEncryptionTest.cs @@ -44,9 +44,8 @@ public async Task ServerRequireEncryption_ClientRequireEncryption_ConnectWithEnc using (var sslStream = new SslStream(client.GetStream(), false, AllowAnyServerCertificate, null, EncryptionPolicy.RequireEncryption)) { await sslStream.AuthenticateAsClientAsync("localhost", null, SslProtocolSupport.DefaultSslProtocols, false); - _log.WriteLine("Client({0}) authenticated to server({1}) with encryption cipher: {2} {3}-bit strength", - client.Client.LocalEndPoint, client.Client.RemoteEndPoint, - sslStream.CipherAlgorithm, sslStream.CipherStrength); + _log.WriteLine("Client authenticated to server({0}) with encryption cipher: {1} {2}-bit strength", + serverRequireEncryption.RemoteEndPoint, sslStream.CipherAlgorithm, sslStream.CipherStrength); Assert.True(sslStream.CipherAlgorithm != CipherAlgorithmType.Null, "Cipher algorithm should not be NULL"); Assert.True(sslStream.CipherStrength > 0, "Cipher strength should be greater than 0"); } @@ -65,9 +64,8 @@ public async Task ServerRequireEncryption_ClientAllowNoEncryption_ConnectWithEnc using (var sslStream = new SslStream(client.GetStream(), false, AllowAnyServerCertificate, null, EncryptionPolicy.AllowNoEncryption)) { await sslStream.AuthenticateAsClientAsync("localhost", null, SslProtocolSupport.DefaultSslProtocols, false); - _log.WriteLine("Client({0}) authenticated to server({1}) with encryption cipher: {2} {3}-bit strength", - client.Client.LocalEndPoint, client.Client.RemoteEndPoint, - sslStream.CipherAlgorithm, sslStream.CipherStrength); + _log.WriteLine("Client authenticated to server({0}) with encryption cipher: {1} {2}-bit strength", + serverRequireEncryption.RemoteEndPoint, sslStream.CipherAlgorithm, sslStream.CipherStrength); Assert.True(sslStream.CipherAlgorithm != CipherAlgorithmType.Null, "Cipher algorithm should not be NULL"); Assert.True(sslStream.CipherStrength > 0, "Cipher strength should be greater than 0"); } diff --git a/src/System.Net.Sockets.Legacy/tests/FunctionalTests/AgnosticListenerTest.cs b/src/System.Net.Sockets.Legacy/tests/FunctionalTests/AgnosticListenerTest.cs index bc9d95b841d6..fb554d82df7b 100644 --- a/src/System.Net.Sockets.Legacy/tests/FunctionalTests/AgnosticListenerTest.cs +++ b/src/System.Net.Sockets.Legacy/tests/FunctionalTests/AgnosticListenerTest.cs @@ -73,8 +73,6 @@ public void ConnectWithV4AndV6_Success() v6Client.ConnectAsync(IPAddress.IPv6Loopback, port).GetAwaiter().GetResult(); TcpClient acceptedV6Client = listener.EndAcceptTcpClient(asyncResult); - Assert.Equal(AddressFamily.InterNetworkV6, acceptedV6Client.Client.RemoteEndPoint.AddressFamily); - Assert.Equal(AddressFamily.InterNetworkV6, v6Client.Client.RemoteEndPoint.AddressFamily); asyncResult = listener.BeginAcceptTcpClient(null, null); @@ -82,8 +80,6 @@ public void ConnectWithV4AndV6_Success() v4Client.ConnectAsync(IPAddress.Loopback, port).GetAwaiter().GetResult(); TcpClient acceptedV4Client = listener.EndAcceptTcpClient(asyncResult); - Assert.Equal(AddressFamily.InterNetworkV6, acceptedV4Client.Client.RemoteEndPoint.AddressFamily); - Assert.Equal(AddressFamily.InterNetwork, v4Client.Client.RemoteEndPoint.AddressFamily); v6Client.Dispose(); acceptedV6Client.Dispose(); diff --git a/src/System.Net.Sockets.Legacy/tests/FunctionalTests/UdpClientTest.cs b/src/System.Net.Sockets.Legacy/tests/FunctionalTests/UdpClientTest.cs index 934f28a8ef59..507c240ca5cb 100644 --- a/src/System.Net.Sockets.Legacy/tests/FunctionalTests/UdpClientTest.cs +++ b/src/System.Net.Sockets.Legacy/tests/FunctionalTests/UdpClientTest.cs @@ -55,14 +55,6 @@ public void BeginSend_AsyncOperationCompletes_Success() Assert.True(_waitHandle.WaitOne(Configuration.PassingTestTimeout), "Timed out while waiting for connection"); } - [ActiveIssue(4968)] - [Fact] - public void UdpClient_ConnectAsync_Success() - { - var c = new UdpClient(); - c.Client.ConnectAsync("114.114.114.114", 53).Wait(); - } - private void AsyncCompleted(IAsyncResult ar) { UdpClient udpService = (UdpClient)ar.AsyncState; diff --git a/src/System.Net.Sockets/ref/System.Net.Sockets.cs b/src/System.Net.Sockets/ref/System.Net.Sockets.cs index 04cfb222b7d2..519e8662ea00 100644 --- a/src/System.Net.Sockets/ref/System.Net.Sockets.cs +++ b/src/System.Net.Sockets/ref/System.Net.Sockets.cs @@ -417,7 +417,6 @@ public TcpClient() { } public TcpClient(System.Net.Sockets.AddressFamily family) { } protected bool Active { get { return default(bool); } set { } } public int Available { get { return default(int); } } - public System.Net.Sockets.Socket Client { get { return default(System.Net.Sockets.Socket); } set { } } public bool Connected { get { return default(bool); } } public bool ExclusiveAddressUse { get { return default(bool); } set { } } public System.Net.Sockets.LingerOption LingerState { get { return default(System.Net.Sockets.LingerOption); } set { } } @@ -458,7 +457,6 @@ public UdpClient(System.Net.IPEndPoint localEP) { } public UdpClient(System.Net.Sockets.AddressFamily family) { } protected bool Active { get { return default(bool); } set { } } public int Available { get { return default(int); } } - public System.Net.Sockets.Socket Client { get { return default(System.Net.Sockets.Socket); } set { } } public bool DontFragment { get { return default(bool); } set { } } public bool EnableBroadcast { get { return default(bool); } set { } } public bool ExclusiveAddressUse { get { return default(bool); } set { } } diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/TCPClient.Unix.cs b/src/System.Net.Sockets/src/System/Net/Sockets/TCPClient.Unix.cs index e4afe8bb2037..23e33035d613 100644 --- a/src/System.Net.Sockets/src/System/Net/Sockets/TCPClient.Unix.cs +++ b/src/System.Net.Sockets/src/System/Net/Sockets/TCPClient.Unix.cs @@ -51,7 +51,8 @@ private void InitializeClientSocket() // Nop. We want to lazily-allocate the socket. } - private Socket ClientCore + [DebuggerBrowsable(DebuggerBrowsableState.Never)] // TODO: Remove once https://github.com/dotnet/corefx/issues/5868 is addressed. + private Socket Client { get { @@ -73,19 +74,6 @@ private Socket ClientCore ExitClientLock(); } } - set - { - EnterClientLock(); - try - { - _clientSocket = value; - ClearInitializedValues(); - } - finally - { - ExitClientLock(); - } - } } private void ApplyInitializedOptionsToSocket(Socket socket) @@ -134,25 +122,6 @@ private void ApplyInitializedOptionsToSocket(Socket socket) } } - private void ClearInitializedValues() - { - ShadowOptions so = _shadowOptions; - if (so == null) - { - return; - } - - // Clear the initialized fields for all of our shadow properties. - so._exclusiveAddressUseInitialized = - so._receiveBufferSizeInitialized = - so._sendBufferSizeInitialized = - so._receiveTimeoutInitialized = - so._sendTimeoutInitialized = - so._lingerStateInitialized = - so._noDelayInitialized = - false; - } - private int AvailableCore { get @@ -249,9 +218,9 @@ private async Task ConnectAsyncCorePrivate(IPAddress[] addresses, int port) ExceptionDispatchInfo lastException = null; foreach (IPAddress address in addresses) { + Socket s = CreateSocket(); try { - Socket s = CreateSocket(); ApplyInitializedOptionsToSocket(s); await s.ConnectAsync(address, port).ConfigureAwait(false); @@ -262,6 +231,7 @@ private async Task ConnectAsyncCorePrivate(IPAddress[] addresses, int port) } catch (Exception exc) { + s.Dispose(); lastException = ExceptionDispatchInfo.Capture(exc); } } diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/TCPClient.Windows.cs b/src/System.Net.Sockets/src/System/Net/Sockets/TCPClient.Windows.cs index f731959ffa41..154e3a269009 100644 --- a/src/System.Net.Sockets/src/System/Net/Sockets/TCPClient.Windows.cs +++ b/src/System.Net.Sockets/src/System/Net/Sockets/TCPClient.Windows.cs @@ -10,21 +10,10 @@ partial class TcpClient { private void InitializeClientSocket() { - Client = CreateSocket(); + _clientSocket = CreateSocket(); } - // Used by the class to provide the underlying network socket. - private Socket ClientCore - { - get - { - return _clientSocket; - } - set - { - _clientSocket = value; - } - } + private Socket Client { get { return _clientSocket; } } private int AvailableCore { get { return _clientSocket.Available; } } diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/TCPClient.cs b/src/System.Net.Sockets/src/System/Net/Sockets/TCPClient.cs index 6b8c6ebb1657..fae1cd3adddf 100644 --- a/src/System.Net.Sockets/src/System/Net/Sockets/TCPClient.cs +++ b/src/System.Net.Sockets/src/System/Net/Sockets/TCPClient.cs @@ -63,14 +63,6 @@ internal TcpClient(Socket acceptedSocket) } } - // Used by the class to provide the underlying network socket. - [DebuggerBrowsable(DebuggerBrowsableState.Never)] // TODO: Remove once https://github.com/dotnet/corefx/issues/5868 is addressed. - public Socket Client - { - get { return ClientCore; } - set { ClientCore = value; } - } - // Used by the class to indicate that a connection has been made. protected bool Active { @@ -151,14 +143,14 @@ public NetworkStream GetStream() { throw new ObjectDisposedException(this.GetType().FullName); } - if (!Client.Connected) + if (!Connected) { throw new InvalidOperationException(SR.net_notconnected); } if (_dataStream == null) { - _dataStream = new NetworkStream(Client, true); + _dataStream = new NetworkStream(_clientSocket, true); } if (NetEventSource.Log.IsEnabled()) diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/UDPClient.cs b/src/System.Net.Sockets/src/System/Net/Sockets/UDPClient.cs index 58aeb7be2814..22c7ac49b46f 100644 --- a/src/System.Net.Sockets/src/System/Net/Sockets/UDPClient.cs +++ b/src/System.Net.Sockets/src/System/Net/Sockets/UDPClient.cs @@ -79,7 +79,7 @@ public UdpClient(int port, AddressFamily family) CreateClientSocket(); - Client.Bind(localEP); + _clientSocket.Bind(localEP); } // Creates a new instance of the UdpClient class that communicates on the @@ -98,20 +98,7 @@ public UdpClient(IPEndPoint localEP) CreateClientSocket(); - Client.Bind(localEP); - } - - // Used by the class to provide the underlying network socket. - public Socket Client - { - get - { - return _clientSocket; - } - set - { - _clientSocket = value; - } + _clientSocket.Bind(localEP); } // Used by the class to indicate that a connection to a remote host has been made. @@ -207,7 +194,7 @@ private void FreeResources() return; } - Socket chkClientSocket = Client; + Socket chkClientSocket = _clientSocket; if (chkClientSocket != null) { // If the NetworkStream wasn't retrieved, the Socket might @@ -215,7 +202,7 @@ private void FreeResources() // of the Bind() call and free the bound IPEndPoint. chkClientSocket.InternalShutdown(SocketShutdown.Both); chkClientSocket.Dispose(); - Client = null; + _clientSocket = null; } _cleanedUp = true; } @@ -247,12 +234,12 @@ private void CheckForBroadcast(IPAddress ipAddress) // and in that case we set SocketOptionName.Broadcast on the socket to allow its use. // if the user really wants complete control over Broadcast addresses he needs to // inherit from UdpClient and gain control over the Socket and do whatever is appropriate. - if (Client != null && !_isBroadcast && IsBroadcast(ipAddress)) + if (_clientSocket != null && !_isBroadcast && IsBroadcast(ipAddress)) { // We need to set the Broadcast socket option. // Note that once we set the option on the Socket we never reset it. _isBroadcast = true; - Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1); + _clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1); } } @@ -294,12 +281,12 @@ internal IAsyncResult BeginSend(byte[] datagram, int bytes, IPEndPoint endPoint, if (endPoint == null) { - return Client.BeginSend(datagram, 0, bytes, SocketFlags.None, requestCallback, state); + return _clientSocket.BeginSend(datagram, 0, bytes, SocketFlags.None, requestCallback, state); } CheckForBroadcast(endPoint.Address); - return Client.BeginSendTo(datagram, 0, bytes, SocketFlags.None, endPoint, requestCallback, state); + return _clientSocket.BeginSendTo(datagram, 0, bytes, SocketFlags.None, endPoint, requestCallback, state); } internal IAsyncResult BeginSend(byte[] datagram, int bytes, string hostname, int port, AsyncCallback requestCallback, object state) @@ -346,11 +333,11 @@ internal int EndSend(IAsyncResult asyncResult) if (_active) { - return Client.EndSend(asyncResult); + return _clientSocket.EndSend(asyncResult); } else { - return Client.EndSendTo(asyncResult); + return _clientSocket.EndSendTo(asyncResult); } } @@ -375,7 +362,7 @@ internal IAsyncResult BeginReceive(AsyncCallback requestCallback, object state) tempRemoteEP = IPEndPointStatics.IPv6Any; } - return Client.BeginReceiveFrom(_buffer, 0, MaxUDPSize, SocketFlags.None, ref tempRemoteEP, requestCallback, state); + return _clientSocket.BeginReceiveFrom(_buffer, 0, MaxUDPSize, SocketFlags.None, ref tempRemoteEP, requestCallback, state); } internal byte[] EndReceive(IAsyncResult asyncResult, ref IPEndPoint remoteEP) @@ -395,7 +382,7 @@ internal byte[] EndReceive(IAsyncResult asyncResult, ref IPEndPoint remoteEP) tempRemoteEP = IPEndPointStatics.IPv6Any; } - int received = Client.EndReceiveFrom(asyncResult, ref tempRemoteEP); + int received = _clientSocket.EndReceiveFrom(asyncResult, ref tempRemoteEP); remoteEP = (IPEndPoint)tempRemoteEP; // Because we don't return the actual length, we need to ensure the returned buffer @@ -435,7 +422,7 @@ public void JoinMulticastGroup(IPAddress multicastAddr) { MulticastOption mcOpt = new MulticastOption(multicastAddr); - Client.SetSocketOption( + _clientSocket.SetSocketOption( SocketOptionLevel.IP, SocketOptionName.AddMembership, mcOpt); @@ -444,7 +431,7 @@ public void JoinMulticastGroup(IPAddress multicastAddr) { IPv6MulticastOption mcOpt = new IPv6MulticastOption(multicastAddr); - Client.SetSocketOption( + _clientSocket.SetSocketOption( SocketOptionLevel.IPv6, SocketOptionName.AddMembership, mcOpt); @@ -466,7 +453,7 @@ public void JoinMulticastGroup(IPAddress multicastAddr, IPAddress localAddress) MulticastOption mcOpt = new MulticastOption(multicastAddr, localAddress); - Client.SetSocketOption( + _clientSocket.SetSocketOption( SocketOptionLevel.IP, SocketOptionName.AddMembership, mcOpt); @@ -500,7 +487,7 @@ public void JoinMulticastGroup(int ifindex, IPAddress multicastAddr) IPv6MulticastOption mcOpt = new IPv6MulticastOption(multicastAddr, ifindex); - Client.SetSocketOption( + _clientSocket.SetSocketOption( SocketOptionLevel.IPv6, SocketOptionName.AddMembership, mcOpt); @@ -527,7 +514,7 @@ public void JoinMulticastGroup(IPAddress multicastAddr, int timeToLive) JoinMulticastGroup(multicastAddr); // Set Time To Live (TTL). - Client.SetSocketOption( + _clientSocket.SetSocketOption( (_family == AddressFamily.InterNetwork) ? SocketOptionLevel.IP : SocketOptionLevel.IPv6, SocketOptionName.MulticastTimeToLive, timeToLive); @@ -557,7 +544,7 @@ public void DropMulticastGroup(IPAddress multicastAddr) { MulticastOption mcOpt = new MulticastOption(multicastAddr); - Client.SetSocketOption( + _clientSocket.SetSocketOption( SocketOptionLevel.IP, SocketOptionName.DropMembership, mcOpt); @@ -566,7 +553,7 @@ public void DropMulticastGroup(IPAddress multicastAddr) { IPv6MulticastOption mcOpt = new IPv6MulticastOption(multicastAddr); - Client.SetSocketOption( + _clientSocket.SetSocketOption( SocketOptionLevel.IPv6, SocketOptionName.DropMembership, mcOpt); @@ -601,7 +588,7 @@ public void DropMulticastGroup(IPAddress multicastAddr, int ifindex) IPv6MulticastOption mcOpt = new IPv6MulticastOption(multicastAddr, ifindex); - Client.SetSocketOption( + _clientSocket.SetSocketOption( SocketOptionLevel.IPv6, SocketOptionName.DropMembership, mcOpt); @@ -667,7 +654,7 @@ private void CreateClientSocket() // Common initialization code. // // IPv6 Changes: Use the AddressFamily of this class rather than hardcode. - Client = new Socket(_family, SocketType.Dgram, ProtocolType.Udp); + _clientSocket = new Socket(_family, SocketType.Dgram, ProtocolType.Udp); } } } diff --git a/src/System.Net.Sockets/tests/FunctionalTests/ArgumentValidationTests.cs b/src/System.Net.Sockets/tests/FunctionalTests/ArgumentValidationTests.cs index ad8a198d6fa4..b782ce83e2d0 100644 --- a/src/System.Net.Sockets/tests/FunctionalTests/ArgumentValidationTests.cs +++ b/src/System.Net.Sockets/tests/FunctionalTests/ArgumentValidationTests.cs @@ -758,27 +758,5 @@ public void Socket_ConnectAsync_MultipleAddresses_NotSupported() Assert.Throws(() => { s.ConnectAsync(new[] { IPAddress.Loopback }, 12345); }); } } - - [Fact] - [PlatformSpecific(PlatformID.AnyUnix)] - public void TcpClient_ConnectAsync_StringHost_NotSupportedAfterClientAccess() - { - using (TcpClient client = new TcpClient()) - { - var tmp = client.Client; - Assert.Throws(() => { client.ConnectAsync("localhost", 12345); }); - } - } - - [Fact] - [PlatformSpecific(PlatformID.AnyUnix)] - public void TcpClient_ConnectAsync_MultipleAddresses_NotSupportedAfterClientAccess() - { - using (TcpClient client = new TcpClient()) - { - var tmp = client.Client; - Assert.Throws(() => { client.ConnectAsync(new[] { IPAddress.Loopback }, 12345); }); - } - } } } diff --git a/src/System.Net.Sockets/tests/FunctionalTests/SendReceive.cs b/src/System.Net.Sockets/tests/FunctionalTests/SendReceive.cs index 7bb6b0dba6a0..562eafd195a7 100644 --- a/src/System.Net.Sockets/tests/FunctionalTests/SendReceive.cs +++ b/src/System.Net.Sockets/tests/FunctionalTests/SendReceive.cs @@ -126,77 +126,6 @@ private static void SendToRecvFromAsync_Datagram_UDP(IPAddress leftAddress, IPAd } } - private static void SendToRecvFromAsync_UdpClient_Datagram_UDP(IPAddress leftAddress, IPAddress rightAddress) - { - const int DatagramSize = 256; - const int DatagramsToSend = 256; - const int AckTimeout = 1000; - const int TestTimeout = 30000; - - var left = new UdpClient(new IPEndPoint(leftAddress, 0)); - var right = new UdpClient(new IPEndPoint(rightAddress, 0)); - - var leftEndpoint = (IPEndPoint)left.Client.LocalEndPoint; - var rightEndpoint = (IPEndPoint)right.Client.LocalEndPoint; - - var receiverAck = new ManualResetEventSlim(); - var senderAck = new ManualResetEventSlim(); - - var receivedChecksums = new uint?[DatagramsToSend]; - int receivedDatagrams = 0; - - Task receiverTask = Task.Run(async () => - { - for (; receivedDatagrams < DatagramsToSend; receivedDatagrams++) - { - UdpReceiveResult result = await left.ReceiveAsync(); - - receiverAck.Set(); - Assert.True(senderAck.Wait(AckTimeout)); - senderAck.Reset(); - - Assert.Equal(DatagramSize, result.Buffer.Length); - Assert.Equal(rightEndpoint, result.RemoteEndPoint); - - int datagramId = (int)result.Buffer[0]; - Assert.Null(receivedChecksums[datagramId]); - - receivedChecksums[datagramId] = Fletcher32.Checksum(result.Buffer, 0, result.Buffer.Length); - } - }); - - var sentChecksums = new uint[DatagramsToSend]; - int sentDatagrams = 0; - - Task senderTask = Task.Run(async () => - { - var random = new Random(); - var sendBuffer = new byte[DatagramSize]; - - for (; sentDatagrams < DatagramsToSend; sentDatagrams++) - { - random.NextBytes(sendBuffer); - sendBuffer[0] = (byte)sentDatagrams; - - int sent = await right.SendAsync(sendBuffer, DatagramSize, leftEndpoint); - - Assert.True(receiverAck.Wait(AckTimeout)); - receiverAck.Reset(); - senderAck.Set(); - - Assert.Equal(DatagramSize, sent); - sentChecksums[sentDatagrams] = Fletcher32.Checksum(sendBuffer, 0, sent); - } - }); - - Assert.True(Task.WaitAll(new[] { receiverTask, senderTask }, TestTimeout)); - for (int i = 0; i < DatagramsToSend; i++) - { - Assert.NotNull(receivedChecksums[i]); - Assert.Equal(sentChecksums[i], (uint)receivedChecksums[i]); - } - } - private static void SendRecvAsync_Stream_TCP(IPAddress listenAt, bool useMultipleBuffers) { const int BytesToSend = 123456; @@ -464,20 +393,6 @@ public void SendToRecvFromAsync_Single_Datagram_UDP_IPv4() SendToRecvFromAsync_Datagram_UDP(IPAddress.Loopback, IPAddress.Loopback); } - [ActiveIssue(5411, PlatformID.Windows)] - [Fact] - public void SendToRecvFromAsync_UdpClient_Single_Datagram_UDP_IPv6() - { - SendToRecvFromAsync_UdpClient_Datagram_UDP(IPAddress.IPv6Loopback, IPAddress.IPv6Loopback); - } - - [ActiveIssue(5411, PlatformID.Windows)] - [Fact] - public void SendToRecvFromAsync_UdpClient_Single_Datagram_UDP_IPv4() - { - SendToRecvFromAsync_UdpClient_Datagram_UDP(IPAddress.Loopback, IPAddress.Loopback); - } - [Fact] public void SendRecvAsync_Multiple_Stream_TCP_IPv6() { diff --git a/src/System.Net.Sockets/tests/FunctionalTests/TcpClientTest.cs b/src/System.Net.Sockets/tests/FunctionalTests/TcpClientTest.cs index 4538f890d7d5..0e5ac62979dc 100644 --- a/src/System.Net.Sockets/tests/FunctionalTests/TcpClientTest.cs +++ b/src/System.Net.Sockets/tests/FunctionalTests/TcpClientTest.cs @@ -46,8 +46,6 @@ public async Task Connect_DnsEndPoint_Success(int mode) } Assert.True(client.Connected); - Assert.NotNull(client.Client); - Assert.Same(client.Client, client.Client); using (NetworkStream s = client.GetStream()) {