From a6ad4e178755833fc5cce15ac95241e3a1203a80 Mon Sep 17 00:00:00 2001 From: Geoffrey Kizer Date: Sun, 30 Aug 2020 18:04:47 -0700 Subject: [PATCH 1/4] remove System.Net.Connections and related features --- src/libraries/NetCoreAppLibrary.props | 2 - .../ref/System.Net.Connections.cs | 21 + .../src/System.Net.Connections.csproj | 4 +- .../src/System/Net/NetworkError.cs | 0 .../src/System/Net/NetworkException.cs | 13 +- .../Sockets/SocketsConnectionFactoryTests.cs | 30 - .../System.Net.Connections.Tests.csproj | 4 + .../System.Net.Http/ref/System.Net.Http.cs | 2 - .../ref/System.Net.Http.csproj | 1 - .../src/System.Net.Http.csproj | 602 ++++++------------ .../BrowserHttpHandler/SocketsHttpHandler.cs | 13 - .../Http/SocketsHttpHandler/ConnectHelper.cs | 21 +- .../DnsEndPointWithProperties.cs | 31 - .../SocketsHttpHandler/Http2Connection.cs | 9 +- .../Http/SocketsHttpHandler/HttpConnection.cs | 17 +- .../SocketsHttpHandler/HttpConnectionPool.cs | 72 +-- .../HttpConnectionSettings.cs | 6 - .../SocketsConnectionFactory.cs | 106 +++ .../SocketsHttpHandler/SocketsHttpHandler.cs | 28 - .../HttpClientHandlerTest.Http2.cs | 2 +- .../FunctionalTests/SocketsHttpHandlerTest.cs | 105 --- .../System.Net.Http.Functional.Tests.csproj | 1 - .../ref/System.Net.Primitives.cs | 18 - .../src/Resources/Strings.resx | 24 - .../src/System.Net.Primitives.csproj | 2 - ...tem.Net.Primitives.Functional.Tests.csproj | 1 - .../src/System/Net/WebException.cs | 9 +- .../src/System.Net.Sockets.csproj | 2 - .../src/System/Net/Sockets/NetworkStream.cs | 63 +- .../src/System/Net/Sockets/Socket.Tasks.cs | 14 +- .../FunctionalTests/NetworkStreamTest.cs | 38 +- src/libraries/pkg/baseline/packageIndex.json | 5 +- 32 files changed, 450 insertions(+), 816 deletions(-) rename src/libraries/{System.Net.Primitives => System.Net.Connections}/src/System/Net/NetworkError.cs (100%) rename src/libraries/{System.Net.Primitives => System.Net.Connections}/src/System/Net/NetworkException.cs (76%) delete mode 100644 src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/DnsEndPointWithProperties.cs create mode 100644 src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SocketsConnectionFactory.cs diff --git a/src/libraries/NetCoreAppLibrary.props b/src/libraries/NetCoreAppLibrary.props index 0fd6812ef3c1b..0b19bb845e5a7 100644 --- a/src/libraries/NetCoreAppLibrary.props +++ b/src/libraries/NetCoreAppLibrary.props @@ -48,7 +48,6 @@ System.IO.FileSystem.Watcher; System.IO.IsolatedStorage; System.IO.MemoryMappedFiles; - System.IO.Pipelines; System.IO.Pipes; System.IO.Pipes.AccessControl; System.IO.UnmanagedMemoryStream; @@ -57,7 +56,6 @@ System.Linq.Parallel; System.Linq.Queryable; System.Memory; - System.Net.Connections; System.Net.Http; System.Net.Http.Json; System.Net.HttpListener; diff --git a/src/libraries/System.Net.Connections/ref/System.Net.Connections.cs b/src/libraries/System.Net.Connections/ref/System.Net.Connections.cs index 1e8e72cd28eb5..feca258c46ce2 100644 --- a/src/libraries/System.Net.Connections/ref/System.Net.Connections.cs +++ b/src/libraries/System.Net.Connections/ref/System.Net.Connections.cs @@ -79,3 +79,24 @@ public SocketsConnectionFactory(System.Net.Sockets.SocketType socketType, System protected virtual System.Net.Sockets.Socket CreateSocket(System.Net.Sockets.AddressFamily addressFamily, System.Net.Sockets.SocketType socketType, System.Net.Sockets.ProtocolType protocolType, System.Net.EndPoint? endPoint, System.Net.Connections.IConnectionProperties? options) { throw null; } } } +namespace System.Net +{ + public enum NetworkError : int + { + Other = 0, + EndPointInUse, + HostNotFound, + TimedOut, + ConnectionRefused, + OperationAborted, + ConnectionAborted, + ConnectionReset, + } + public class NetworkException : System.IO.IOException + { + public NetworkException(NetworkError error, Exception? innerException = null) { } + public NetworkException(string message, NetworkError error, Exception? innerException = null) { } + protected NetworkException(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) { } + public NetworkError NetworkError { get { throw null; } } + } +} diff --git a/src/libraries/System.Net.Connections/src/System.Net.Connections.csproj b/src/libraries/System.Net.Connections/src/System.Net.Connections.csproj index cf6682f2cd821..055eaef1b57e6 100644 --- a/src/libraries/System.Net.Connections/src/System.Net.Connections.csproj +++ b/src/libraries/System.Net.Connections/src/System.Net.Connections.csproj @@ -6,6 +6,8 @@ + + @@ -20,13 +22,13 @@ + - diff --git a/src/libraries/System.Net.Primitives/src/System/Net/NetworkError.cs b/src/libraries/System.Net.Connections/src/System/Net/NetworkError.cs similarity index 100% rename from src/libraries/System.Net.Primitives/src/System/Net/NetworkError.cs rename to src/libraries/System.Net.Connections/src/System/Net/NetworkError.cs diff --git a/src/libraries/System.Net.Primitives/src/System/Net/NetworkException.cs b/src/libraries/System.Net.Connections/src/System/Net/NetworkException.cs similarity index 76% rename from src/libraries/System.Net.Primitives/src/System/Net/NetworkException.cs rename to src/libraries/System.Net.Connections/src/System/Net/NetworkException.cs index 37855524415c3..ef99bd835c3a5 100644 --- a/src/libraries/System.Net.Primitives/src/System/Net/NetworkException.cs +++ b/src/libraries/System.Net.Connections/src/System/Net/NetworkException.cs @@ -38,16 +38,7 @@ public override void GetObjectData(SerializationInfo serializationInfo, Streamin /// Returns the specific kind of error. public NetworkError NetworkError { get; } - private static string GetExceptionMessage(NetworkError error) => error switch - { - NetworkError.EndPointInUse => SR.networkerror_addressinuse, - NetworkError.TimedOut => SR.networkerror_timedout, - NetworkError.HostNotFound => SR.networkerror_hostnotfound, - NetworkError.ConnectionRefused => SR.networkerror_connectionrefused, - NetworkError.ConnectionAborted => SR.networkerror_connectionaborted, - NetworkError.ConnectionReset => SR.networkerror_connectionreset, - NetworkError.OperationAborted => SR.networkerror_operationaborted, - _ => SR.networkerror_other - }; + // TODO: Better exception messages + private static string GetExceptionMessage(NetworkError error) => $"A network error occurred: {error}"; } } diff --git a/src/libraries/System.Net.Connections/tests/System.Net.Connections.Tests/Sockets/SocketsConnectionFactoryTests.cs b/src/libraries/System.Net.Connections/tests/System.Net.Connections.Tests/Sockets/SocketsConnectionFactoryTests.cs index 9215042fe8e5d..683f1b970eb91 100644 --- a/src/libraries/System.Net.Connections/tests/System.Net.Connections.Tests/Sockets/SocketsConnectionFactoryTests.cs +++ b/src/libraries/System.Net.Connections/tests/System.Net.Connections.Tests/Sockets/SocketsConnectionFactoryTests.cs @@ -225,36 +225,6 @@ public async Task Connection_Pipe_ReadWrite_Success(EndPoint endPoint, SocketTyp Assert.True(rr.Buffer.FirstSpan.SequenceEqual(sendData)); } - [Fact] - public async Task Connection_Stream_FailingOperation_ThowsNetworkException() - { - using var server = SocketTestServer.SocketTestServerFactory(SocketImplementationType.Async, IPAddress.Loopback); - using SocketsConnectionFactory factory = new SocketsConnectionFactory(SocketType.Stream, ProtocolType.Tcp); - using Connection connection = await factory.ConnectAsync(server.EndPoint); - - connection.ConnectionProperties.TryGet(out Socket socket); - Stream stream = connection.Stream; - socket.Dispose(); - - Assert.Throws(() => stream.Read(new byte[1], 0, 1)); - Assert.Throws(() => stream.Write(new byte[1], 0, 1)); - } - - [Fact] - public async Task Connection_Pipe_FailingOperation_ThowsNetworkException() - { - using var server = SocketTestServer.SocketTestServerFactory(SocketImplementationType.Async, IPAddress.Loopback); - using SocketsConnectionFactory factory = new SocketsConnectionFactory(SocketType.Stream, ProtocolType.Tcp); - using Connection connection = await factory.ConnectAsync(server.EndPoint); - - connection.ConnectionProperties.TryGet(out Socket socket); - IDuplexPipe pipe = connection.Pipe; - socket.Dispose(); - - await Assert.ThrowsAsync(() => pipe.Input.ReadAsync().AsTask()); - await Assert.ThrowsAsync(() => pipe.Output.WriteAsync(new byte[1]).AsTask()); - } - [Theory] [InlineData(false, false)] [InlineData(false, true)] diff --git a/src/libraries/System.Net.Connections/tests/System.Net.Connections.Tests/System.Net.Connections.Tests.csproj b/src/libraries/System.Net.Connections/tests/System.Net.Connections.Tests/System.Net.Connections.Tests.csproj index 6426b8ea3149b..7ddfadfd04df2 100644 --- a/src/libraries/System.Net.Connections/tests/System.Net.Connections.Tests/System.Net.Connections.Tests.csproj +++ b/src/libraries/System.Net.Connections/tests/System.Net.Connections.Tests/System.Net.Connections.Tests.csproj @@ -30,5 +30,9 @@ + + + + diff --git a/src/libraries/System.Net.Http/ref/System.Net.Http.cs b/src/libraries/System.Net.Http/ref/System.Net.Http.cs index 85997fa96cc5c..cc6c8995ac954 100644 --- a/src/libraries/System.Net.Http/ref/System.Net.Http.cs +++ b/src/libraries/System.Net.Http/ref/System.Net.Http.cs @@ -331,7 +331,6 @@ public SocketsHttpHandler() { } public static bool IsSupported { get { throw null; } } public bool AllowAutoRedirect { get { throw null; } set { } } public System.Net.DecompressionMethods AutomaticDecompression { get { throw null; } set { } } - public System.Net.Connections.ConnectionFactory? ConnectionFactory { get { throw null; } set { } } public System.TimeSpan ConnectTimeout { get { throw null; } set { } } [System.Diagnostics.CodeAnalysis.AllowNullAttribute] public System.Net.CookieContainer CookieContainer { get { throw null; } set { } } @@ -345,7 +344,6 @@ public SocketsHttpHandler() { } public int MaxConnectionsPerServer { get { throw null; } set { } } public int MaxResponseDrainSize { get { throw null; } set { } } public int MaxResponseHeadersLength { get { throw null; } set { } } - public System.Func>? PlaintextFilter { get { throw null; } set { } } public System.TimeSpan PooledConnectionIdleTimeout { get { throw null; } set { } } public System.TimeSpan PooledConnectionLifetime { get { throw null; } set { } } public bool PreAuthenticate { get { throw null; } set { } } diff --git a/src/libraries/System.Net.Http/ref/System.Net.Http.csproj b/src/libraries/System.Net.Http/ref/System.Net.Http.csproj index 296b6c0cdb1b5..0e6cf82734dc7 100644 --- a/src/libraries/System.Net.Http/ref/System.Net.Http.csproj +++ b/src/libraries/System.Net.Http/ref/System.Net.Http.csproj @@ -10,7 +10,6 @@ - diff --git a/src/libraries/System.Net.Http/src/System.Net.Http.csproj b/src/libraries/System.Net.Http/src/System.Net.Http.csproj index 3f2923fec0418..2d341bca21f68 100644 --- a/src/libraries/System.Net.Http/src/System.Net.Http.csproj +++ b/src/libraries/System.Net.Http/src/System.Net.Http.csproj @@ -1,4 +1,4 @@ - + win true @@ -60,6 +60,7 @@ + @@ -106,28 +107,16 @@ - - - - - - - - - - - + + + + + + + + + + @@ -177,105 +166,55 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -357,43 +296,29 @@ - + - + - - - - - - - - - - - - + + + + + + + + + + + + @@ -402,275 +327,150 @@ - - - - - - - - - - - - + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + @@ -686,9 +486,7 @@ - - diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/SocketsHttpHandler.cs b/src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/SocketsHttpHandler.cs index 214f5621415eb..1d7ae3a03813c 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/SocketsHttpHandler.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/SocketsHttpHandler.cs @@ -6,7 +6,6 @@ using System.Threading; using System.Threading.Tasks; using System.Diagnostics.CodeAnalysis; -using System.Net.Connections; namespace System.Net.Http { @@ -149,18 +148,6 @@ public HttpKeepAlivePingPolicy KeepAlivePingPolicy set => throw new PlatformNotSupportedException(); } - public ConnectionFactory? ConnectionFactory - { - get => throw new PlatformNotSupportedException(); - set => throw new PlatformNotSupportedException(); - } - - public Func>? PlaintextFilter - { - get => throw new PlatformNotSupportedException(); - set => throw new PlatformNotSupportedException(); - } - public IDictionary Properties => throw new PlatformNotSupportedException(); public HeaderEncodingSelector? RequestHeaderEncodingSelector diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectHelper.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectHelper.cs index 726b8ba4bfba3..931b8887fac03 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectHelper.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectHelper.cs @@ -3,12 +3,9 @@ using System.Diagnostics; using System.IO; -using System.IO.Pipelines; -using System.Net.Connections; using System.Net.Quic; using System.Net.Security; using System.Net.Sockets; -using System.Runtime.ExceptionServices; using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; @@ -34,11 +31,11 @@ public CertificateCallbackMapper(Func ConnectAsync(ConnectionFactory factory, DnsEndPoint endPoint, IConnectionProperties? options, CancellationToken cancellationToken) + public static async ValueTask ConnectAsync(SocketsConnectionFactory factory, DnsEndPoint endPoint, CancellationToken cancellationToken) { try { - return await factory.ConnectAsync(endPoint, options, cancellationToken).ConfigureAwait(false); + return await factory.ConnectAsync(endPoint, cancellationToken).ConfigureAwait(false); } catch (OperationCanceledException ex) when (ex.CancellationToken == cancellationToken) { @@ -50,7 +47,7 @@ public static async ValueTask ConnectAsync(ConnectionFactory factory } } - public static Connection Connect(string host, int port, CancellationToken cancellationToken) + public static Stream Connect(string host, int port, CancellationToken cancellationToken) { // For synchronous connections, we can just create a socket and make the connection. cancellationToken.ThrowIfCancellationRequested(); @@ -63,17 +60,7 @@ public static Connection Connect(string host, int port, CancellationToken cancel socket.Connect(new DnsEndPoint(host, port)); } - // Since we only do GracefulShutdown in SocketsHttpHandler code, Connection.FromStream() should match SocketConnection's behavior: - return Connection.FromStream(new NetworkStream(socket, ownsSocket: true), localEndPoint: socket.LocalEndPoint, remoteEndPoint: socket.RemoteEndPoint); - } - catch (SocketException se) - { - socket.Dispose(); - - // SocketConnectionFactory wraps SocketException in NetworkException. Do the same here. - NetworkException ne = NetworkErrorHelper.MapSocketException(se); - - throw CreateWrappedException(ne, host, port, cancellationToken); + return new NetworkStream(socket, ownsSocket: true); } catch (Exception e) { diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/DnsEndPointWithProperties.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/DnsEndPointWithProperties.cs deleted file mode 100644 index ef4ee0b510297..0000000000000 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/DnsEndPointWithProperties.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics.CodeAnalysis; -using System.Net.Connections; - -namespace System.Net.Http -{ - // Passed to a connection factory, merges allocations for the DnsEndPoint and connection properties. - internal sealed class DnsEndPointWithProperties : DnsEndPoint, IConnectionProperties - { - private readonly HttpRequestMessage _initialRequest; - - public DnsEndPointWithProperties(string host, int port, HttpRequestMessage initialRequest) : base(host, port) - { - _initialRequest = initialRequest; - } - - bool IConnectionProperties.TryGet(Type propertyKey, [NotNullWhen(true)] out object? property) - { - if (propertyKey == typeof(HttpRequestMessage)) - { - property = _initialRequest; - return true; - } - - property = null; - return false; - } - } -} diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs index 7d1dc3ec96242..bfbcdc1797ec1 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs @@ -7,7 +7,6 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; -using System.Net.Connections; using System.Net.Http.Headers; using System.Net.Http.HPack; using System.Net.Security; @@ -24,7 +23,6 @@ internal sealed partial class Http2Connection : HttpConnectionBase, IDisposable { private readonly HttpConnectionPool _pool; private readonly Stream _stream; - private readonly Connection _connection; // NOTE: These are mutable structs; do not make these readonly. private ArrayBuffer _incomingBuffer; @@ -119,11 +117,10 @@ internal enum KeepAliveState private long _keepAlivePingTimeoutTimestamp; private volatile KeepAliveState _keepAliveState; - public Http2Connection(HttpConnectionPool pool, Connection connection) + public Http2Connection(HttpConnectionPool pool, Stream stream) { _pool = pool; - _stream = connection.Stream; - _connection = connection; + _stream = stream; _incomingBuffer = new ArrayBuffer(InitialConnectionBufferSize); _outgoingBuffer = new ArrayBuffer(InitialConnectionBufferSize); @@ -1698,7 +1695,7 @@ private void CheckForShutdown() GC.SuppressFinalize(this); // Do shutdown. - _connection.Dispose(); + _stream.Dispose(); _connectionWindow.Dispose(); _concurrentStreams.Dispose(); diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs index 54e38fd591737..6e9a1b2b476dc 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs @@ -10,7 +10,6 @@ using System.Net.Http.Headers; using System.Net.Security; using System.Net.Sockets; -using System.Net.Connections; using System.Runtime.CompilerServices; using System.Text; using System.Threading; @@ -46,7 +45,6 @@ internal partial class HttpConnection : HttpConnectionBase, IDisposable private readonly HttpConnectionPool _pool; private readonly Socket? _socket; // used for polling; _stream should be used for all reading/writing. _stream owns disposal. private readonly Stream _stream; - private readonly Connection _connection; private readonly TransportContext? _transportContext; private readonly WeakReference _weakThisRef; @@ -73,16 +71,19 @@ internal partial class HttpConnection : HttpConnectionBase, IDisposable public HttpConnection( HttpConnectionPool pool, - Connection connection, + Stream stream, TransportContext? transportContext) { Debug.Assert(pool != null); - Debug.Assert(connection != null); + Debug.Assert(stream != null); _pool = pool; - connection.ConnectionProperties.TryGet(out _socket); // may be null in cases where we couldn't easily get the underlying socket - _stream = connection.Stream; - _connection = connection; + _stream = stream; + if (stream is NetworkStream networkStream) + { + _socket = networkStream.Socket; + } + _transportContext = transportContext; _writeBuffer = new byte[InitialWriteBufferSize]; @@ -125,7 +126,7 @@ protected void Dispose(bool disposing) if (disposing) { GC.SuppressFinalize(this); - _connection.Dispose(); + _stream.Dispose(); // Eat any exceptions from the read-ahead task. We don't need to log, as we expect // failures from this task due to closing the connection while a read is in progress. diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs index fdfbaf999af66..df4332c1d8254 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs @@ -6,7 +6,6 @@ using System.Diagnostics; using System.Globalization; using System.IO; -using System.Net.Connections; using System.Net.Http.Headers; using System.Net.Http.HPack; using System.Net.Http.QPack; @@ -577,7 +576,7 @@ public byte[] Http2AltSvcOriginUri } // Try to establish an HTTP2 connection - Connection? connection = null; + Stream? stream = null; SslStream? sslStream = null; TransportContext? transportContext = null; @@ -601,7 +600,7 @@ public byte[] Http2AltSvcOriginUri HttpResponseMessage? failureResponse; - (connection, transportContext, failureResponse) = + (stream, transportContext, failureResponse) = await ConnectAsync(request, async, cancellationToken).ConfigureAwait(false); if (failureResponse != null) @@ -609,18 +608,13 @@ public byte[] Http2AltSvcOriginUri return (null, true, failureResponse); } - Debug.Assert(connection != null); + Debug.Assert(stream != null); - sslStream = connection.Stream as SslStream; - - if (Settings._plaintextFilter != null) - { - connection = await Settings._plaintextFilter(request, connection, cancellationToken).ConfigureAwait(false); - } + sslStream = stream as SslStream; if (_kind == HttpConnectionKind.Http) { - http2Connection = new Http2Connection(this, connection); + http2Connection = new Http2Connection(this, stream); await http2Connection.SetupAsync().ConfigureAwait(false); AddHttp2Connection(http2Connection); @@ -644,7 +638,7 @@ public byte[] Http2AltSvcOriginUri throw new HttpRequestException(SR.Format(SR.net_ssl_http2_requires_tls12, sslStream.SslProtocol)); } - http2Connection = new Http2Connection(this, connection); + http2Connection = new Http2Connection(this, stream); await http2Connection.SetupAsync().ConfigureAwait(false); AddHttp2Connection(http2Connection); @@ -701,7 +695,7 @@ public byte[] Http2AltSvcOriginUri if (canUse) { - return (ConstructHttp11Connection(connection!, transportContext), true, null); + return (ConstructHttp11Connection(stream!, transportContext), true, null); } else { @@ -710,7 +704,7 @@ public byte[] Http2AltSvcOriginUri Trace("Discarding downgraded HTTP/1.1 connection because connection limit is exceeded"); } - await connection!.CloseAsync(ConnectionCloseMethod.GracefulShutdown, cancellationToken).ConfigureAwait(false); + stream!.Dispose(); } } @@ -1233,7 +1227,7 @@ public ValueTask SendAsync(HttpRequestMessage request, bool return SendWithProxyAuthAsync(request, async, doRequestAuth, cancellationToken); } - private async ValueTask<(Connection?, TransportContext?, HttpResponseMessage?)> ConnectAsync(HttpRequestMessage request, bool async, CancellationToken cancellationToken) + private async ValueTask<(Stream?, TransportContext?, HttpResponseMessage?)> ConnectAsync(HttpRequestMessage request, bool async, CancellationToken cancellationToken) { // If a non-infinite connect timeout has been set, create and use a new CancellationToken that will be canceled // when either the original token is canceled or a connect timeout occurs. @@ -1247,24 +1241,24 @@ public ValueTask SendAsync(HttpRequestMessage request, bool try { - Connection? connection = null; + Stream? stream = null; switch (_kind) { case HttpConnectionKind.Http: case HttpConnectionKind.Https: case HttpConnectionKind.ProxyConnect: Debug.Assert(_originAuthority != null); - connection = await ConnectToTcpHostAsync(_originAuthority.IdnHost, _originAuthority.Port, request, async, cancellationToken).ConfigureAwait(false); + stream = await ConnectToTcpHostAsync(_originAuthority.IdnHost, _originAuthority.Port, request, async, cancellationToken).ConfigureAwait(false); break; case HttpConnectionKind.Proxy: - connection = await ConnectToTcpHostAsync(_proxyUri!.IdnHost, _proxyUri.Port, request, async, cancellationToken).ConfigureAwait(false); + stream = await ConnectToTcpHostAsync(_proxyUri!.IdnHost, _proxyUri.Port, request, async, cancellationToken).ConfigureAwait(false); break; case HttpConnectionKind.ProxyTunnel: case HttpConnectionKind.SslProxyTunnel: HttpResponseMessage? response; - (connection, response) = await EstablishProxyTunnel(async, request.HasHeaders ? request.Headers : null, cancellationToken).ConfigureAwait(false); + (stream, response) = await EstablishProxyTunnel(async, request.HasHeaders ? request.Headers : null, cancellationToken).ConfigureAwait(false); if (response != null) { // Return non-success response from proxy. @@ -1274,17 +1268,17 @@ public ValueTask SendAsync(HttpRequestMessage request, bool break; } - Debug.Assert(connection != null); + Debug.Assert(stream != null); TransportContext? transportContext = null; if (IsSecure) { - SslStream sslStream = await ConnectHelper.EstablishSslConnectionAsync(GetSslOptionsForRequest(request), request, async, connection.Stream, cancellationToken).ConfigureAwait(false); - connection = Connection.FromStream(sslStream, leaveOpen: false, connection.ConnectionProperties, connection.LocalEndPoint, connection.RemoteEndPoint); + SslStream sslStream = await ConnectHelper.EstablishSslConnectionAsync(GetSslOptionsForRequest(request), request, async, stream, cancellationToken).ConfigureAwait(false); transportContext = sslStream.TransportContext; + stream = sslStream; } - return (connection, transportContext, null); + return (stream, transportContext, null); } finally { @@ -1294,37 +1288,31 @@ public ValueTask SendAsync(HttpRequestMessage request, bool private static readonly SocketsConnectionFactory s_defaultConnectionFactory = new SocketsConnectionFactory(SocketType.Stream, ProtocolType.Tcp); - private ValueTask ConnectToTcpHostAsync(string host, int port, HttpRequestMessage initialRequest, bool async, CancellationToken cancellationToken) + private ValueTask ConnectToTcpHostAsync(string host, int port, HttpRequestMessage initialRequest, bool async, CancellationToken cancellationToken) { if (async) { - ConnectionFactory connectionFactory = Settings._connectionFactory ?? s_defaultConnectionFactory; + SocketsConnectionFactory connectionFactory = s_defaultConnectionFactory; - var endPoint = new DnsEndPointWithProperties(host, port, initialRequest); - return ConnectHelper.ConnectAsync(connectionFactory, endPoint, endPoint, cancellationToken); + var endPoint = new DnsEndPoint(host, port); + return ConnectHelper.ConnectAsync(connectionFactory, endPoint, cancellationToken); } // Synchronous path. - if (Settings._connectionFactory != null) - { - // connection factories only support async. - throw new HttpRequestException(); - } - try { - return new ValueTask(ConnectHelper.Connect(host, port, cancellationToken)); + return new ValueTask(ConnectHelper.Connect(host, port, cancellationToken)); } catch (Exception ex) { - return ValueTask.FromException(ex); + return ValueTask.FromException(ex); } } internal async ValueTask<(HttpConnection?, HttpResponseMessage?)> CreateHttp11ConnectionAsync(HttpRequestMessage request, bool async, CancellationToken cancellationToken) { - (Connection? connection, TransportContext? transportContext, HttpResponseMessage? failureResponse) = + (Stream? stream, TransportContext? transportContext, HttpResponseMessage? failureResponse) = await ConnectAsync(request, async, cancellationToken).ConfigureAwait(false); if (failureResponse != null) @@ -1332,7 +1320,7 @@ private ValueTask ConnectToTcpHostAsync(string host, int port, HttpR return (null, failureResponse); } - return (ConstructHttp11Connection(connection!, transportContext), null); + return (ConstructHttp11Connection(stream!, transportContext), null); } private SslClientAuthenticationOptions GetSslOptionsForRequest(HttpRequestMessage request) @@ -1352,13 +1340,13 @@ private SslClientAuthenticationOptions GetSslOptionsForRequest(HttpRequestMessag return _sslOptionsHttp11!; } - private HttpConnection ConstructHttp11Connection(Connection connection, TransportContext? transportContext) + private HttpConnection ConstructHttp11Connection(Stream stream, TransportContext? transportContext) { - return new HttpConnection(this, connection, transportContext); + return new HttpConnection(this, stream, transportContext); } // Returns the established stream or an HttpResponseMessage from the proxy indicating failure. - private async ValueTask<(Connection?, HttpResponseMessage?)> EstablishProxyTunnel(bool async, HttpRequestHeaders? headers, CancellationToken cancellationToken) + private async ValueTask<(Stream?, HttpResponseMessage?)> EstablishProxyTunnel(bool async, HttpRequestHeaders? headers, CancellationToken cancellationToken) { Debug.Assert(_originAuthority != null); // Send a CONNECT request to the proxy server to establish a tunnel. @@ -1380,9 +1368,7 @@ private HttpConnection ConstructHttp11Connection(Connection connection, Transpor Stream stream = tunnelResponse.Content.ReadAsStream(cancellationToken); EndPoint remoteEndPoint = new DnsEndPoint(_originAuthority.IdnHost, _originAuthority.Port); - // TODO: the Socket from the response can be funneled into a connection property here. - - return (Connection.FromStream(stream, remoteEndPoint: remoteEndPoint), null); + return (stream, null); } /// Enqueues a waiter to the waiters list. diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionSettings.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionSettings.cs index 3eefbd35f300d..177d8bc4884d0 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionSettings.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionSettings.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; -using System.Net.Connections; using System.Net.Security; using System.Threading; using System.Threading.Tasks; @@ -56,9 +55,6 @@ internal sealed class HttpConnectionSettings internal bool _enableMultipleHttp2Connections; - internal ConnectionFactory? _connectionFactory; - internal Func>? _plaintextFilter; - internal IDictionary? _properties; public HttpConnectionSettings() @@ -112,8 +108,6 @@ public HttpConnectionSettings CloneAndNormalize() _requestHeaderEncodingSelector = _requestHeaderEncodingSelector, _responseHeaderEncodingSelector = _responseHeaderEncodingSelector, _enableMultipleHttp2Connections = _enableMultipleHttp2Connections, - _connectionFactory = _connectionFactory, - _plaintextFilter = _plaintextFilter }; } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SocketsConnectionFactory.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SocketsConnectionFactory.cs new file mode 100644 index 0000000000000..98c8e89915164 --- /dev/null +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SocketsConnectionFactory.cs @@ -0,0 +1,106 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; +using System.Net.Sockets; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Net.Http +{ + /// + /// A factory to establish socket-based connections. + /// + /// + /// When constructed with , this factory will create connections with enabled. + /// In case of IPv6 sockets is also enabled. + /// + internal sealed class SocketsConnectionFactory + { + private readonly AddressFamily _addressFamily; + private readonly SocketType _socketType; + private readonly ProtocolType _protocolType; + + /// + /// Initializes a new instance of the class. + /// + /// The to forward to the socket. + /// The to forward to the socket. + /// The to forward to the socket. + public SocketsConnectionFactory( + AddressFamily addressFamily, + SocketType socketType, + ProtocolType protocolType) + { + _addressFamily = addressFamily; + _socketType = socketType; + _protocolType = protocolType; + } + + /// + /// Initializes a new instance of the class + /// that will forward to the Socket constructor. + /// + /// The to forward to the socket. + /// The to forward to the socket. + /// The created socket will be an IPv6 socket with enabled. + public SocketsConnectionFactory(SocketType socketType, ProtocolType protocolType) + : this(AddressFamily.InterNetworkV6, socketType, protocolType) + { + } + + public async ValueTask ConnectAsync( + EndPoint? endPoint, + CancellationToken cancellationToken = default) + { + if (endPoint == null) throw new ArgumentNullException(nameof(endPoint)); + cancellationToken.ThrowIfCancellationRequested(); + + Socket socket = CreateSocket(_addressFamily, _socketType, _protocolType, endPoint); + + try + { + await socket.ConnectAsync(endPoint, cancellationToken).ConfigureAwait(false); + return new NetworkStream(socket, true); + } + catch + { + socket.Dispose(); + throw; + } + } + + /// + /// Creates the socket that shall be used with the connection. + /// + /// The to forward to the socket. + /// The to forward to the socket. + /// The to forward to the socket. + /// The this socket will be connected to. + /// A new unconnected . + /// + /// In case of TCP sockets, the default implementation of this method will create a socket with enabled. + /// In case of IPv6 sockets is also be enabled. + /// + private Socket CreateSocket( + AddressFamily addressFamily, + SocketType socketType, + ProtocolType protocolType, + EndPoint? endPoint) + { + Socket socket = new Socket(addressFamily, socketType, protocolType); + + if (protocolType == ProtocolType.Tcp) + { + socket.NoDelay = true; + } + + if (addressFamily == AddressFamily.InterNetworkV6) + { + socket.DualMode = true; + } + + return socket; + } + } +} diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SocketsHttpHandler.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SocketsHttpHandler.cs index dbe8388b05c98..978e94a12d49e 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SocketsHttpHandler.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SocketsHttpHandler.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Diagnostics; -using System.Net.Connections; using System.Net.Security; using System.Threading; using System.Threading.Tasks; @@ -363,33 +362,6 @@ public bool EnableMultipleHttp2Connections internal bool SupportsProxy => true; internal bool SupportsRedirectConfiguration => true; - /// - /// When non-null, a custom factory used to open new TCP connections. - /// When null, a will be used. - /// - public ConnectionFactory? ConnectionFactory - { - get => _settings._connectionFactory; - set - { - CheckDisposedOrStarted(); - _settings._connectionFactory = value; - } - } - - /// - /// When non-null, a connection filter that is applied prior to any TLS encryption. - /// - public Func>? PlaintextFilter - { - get => _settings._plaintextFilter; - set - { - CheckDisposedOrStarted(); - _settings._plaintextFilter = value; - } - } - public IDictionary Properties => _settings._properties ?? (_settings._properties = new Dictionary()); diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http2.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http2.cs index cea66090d91d3..040558f36bfcd 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http2.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http2.cs @@ -1740,7 +1740,7 @@ await Http2LoopbackServer.CreateClientAndServerAsync( // Send response and close the stream. if (expectRequestFail) { - await Assert.ThrowsAsync(() => connection.SendDefaultResponseAsync(streamId2)); + await Assert.ThrowsAsync(() => connection.SendDefaultResponseAsync(streamId2)); // As stream is closed we don't want to continue with sending data. return; } diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs index fa0746865eb39..5dc9d3bba738e 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs @@ -5,7 +5,6 @@ using System.Diagnostics; using System.IO; using System.Linq; -using System.Net.Connections; using System.Net.Quic; using System.Net.Security; using System.Net.Sockets; @@ -106,110 +105,6 @@ private sealed class SetOnFinalized } } - public class SocketsHttpHandler_ConnectionFactoryTest : HttpClientHandlerTestBase - { - public SocketsHttpHandler_ConnectionFactoryTest(ITestOutputHelper output) : base(output) { } - - [Fact] - public async Task CustomConnectionFactory_AsyncRequest_Success() - { - await using ConnectionListenerFactory listenerFactory = new VirtualNetworkConnectionListenerFactory(); - await using ConnectionListener listener = await listenerFactory.ListenAsync(endPoint: null); - await using ConnectionFactory connectionFactory = VirtualNetworkConnectionListenerFactory.GetConnectionFactory(listener); - - var options = new GenericLoopbackOptions(); - - Task serverTask = Task.Run(async () => - { - await using Connection serverConnection = await listener.AcceptAsync(); - using GenericLoopbackConnection loopbackConnection = await LoopbackServerFactory.CreateConnectionAsync(socket: null, serverConnection.Stream, options); - - await loopbackConnection.InitializeConnectionAsync(); - - HttpRequestData requestData = await loopbackConnection.ReadRequestDataAsync(); - await loopbackConnection.SendResponseAsync(content: "foo"); - - Assert.Equal("/foo", requestData.Path); - }); - - Task clientTask = Task.Run(async () => - { - using HttpClientHandler handler = CreateHttpClientHandler(); - handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates; - - var socketsHandler = (SocketsHttpHandler)GetUnderlyingSocketsHttpHandler(handler); - socketsHandler.ConnectionFactory = connectionFactory; - - using HttpClient client = CreateHttpClient(handler); - - string response = await client.GetStringAsync($"{(options.UseSsl ? "https" : "http")}://{Guid.NewGuid():N}.com/foo"); - Assert.Equal("foo", response); - }); - - await new[] { serverTask, clientTask }.WhenAllOrAnyFailed(60_000); - } - - [Fact] - public async Task CustomConnectionFactory_SyncRequest_Fails() - { - await using ConnectionFactory connectionFactory = new SocketsConnectionFactory(SocketType.Stream, ProtocolType.Tcp); - using SocketsHttpHandler handler = new SocketsHttpHandler - { - ConnectionFactory = connectionFactory - }; - - using HttpClient client = CreateHttpClient(handler); - - HttpRequestException e = await Assert.ThrowsAnyAsync(() => client.GetStringAsync($"http://{Guid.NewGuid():N}.com/foo")); - Assert.IsType(e.InnerException); - } - - class CustomConnectionFactory : SocketsConnectionFactory - { - public CustomConnectionFactory() : base(SocketType.Stream, ProtocolType.Tcp) { } - - public HttpRequestMessage LastHttpRequestMessage { get; private set; } - - public override ValueTask ConnectAsync(EndPoint endPoint, IConnectionProperties options = null, CancellationToken cancellationToken = default) - { - if (options.TryGet(out HttpRequestMessage message)) - { - LastHttpRequestMessage = message; - } - - return base.ConnectAsync(endPoint, options, cancellationToken); - } - } - - [Fact] - public Task CustomConnectionFactory_ConnectAsync_CanCaptureHttpRequestMessage() - { - return LoopbackServer.CreateClientAndServerAsync(async uri => - { - using var connectionFactory = new CustomConnectionFactory(); - using var handler = new SocketsHttpHandler() - { - ConnectionFactory = connectionFactory - }; - using HttpClient client = CreateHttpClient(handler); - - using var request = new HttpRequestMessage(HttpMethod.Get, uri); - - using HttpResponseMessage response = await client.SendAsync(request); - string content = await response.Content.ReadAsStringAsync(); - - Assert.Equal("OK", content); - Assert.Same(request, connectionFactory.LastHttpRequestMessage); - }, server => server.HandleRequestAsync(content: "OK")); - } - } - - public sealed class SocketsHttpHandler_ConnectionFactoryTest_Http2 : SocketsHttpHandler_ConnectionFactoryTest - { - public SocketsHttpHandler_ConnectionFactoryTest_Http2(ITestOutputHelper output) : base(output) { } - protected override Version UseVersion => HttpVersion.Version20; - } - public sealed class SocketsHttpHandler_HttpProtocolTests : HttpProtocolTests { public SocketsHttpHandler_HttpProtocolTests(ITestOutputHelper output) : base(output) { } diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj b/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj index baea536e52cbf..75b93f333b7b0 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj @@ -237,7 +237,6 @@ - diff --git a/src/libraries/System.Net.Primitives/ref/System.Net.Primitives.cs b/src/libraries/System.Net.Primitives/ref/System.Net.Primitives.cs index 4abc120c3831f..899fa7d7d68e5 100644 --- a/src/libraries/System.Net.Primitives/ref/System.Net.Primitives.cs +++ b/src/libraries/System.Net.Primitives/ref/System.Net.Primitives.cs @@ -322,24 +322,6 @@ public abstract partial class TransportContext protected TransportContext() { } public abstract System.Security.Authentication.ExtendedProtection.ChannelBinding? GetChannelBinding(System.Security.Authentication.ExtendedProtection.ChannelBindingKind kind); } - public enum NetworkError : int - { - Other = 0, - EndPointInUse, - HostNotFound, - TimedOut, - ConnectionRefused, - OperationAborted, - ConnectionAborted, - ConnectionReset, - } - public class NetworkException : System.IO.IOException - { - public NetworkException(NetworkError error, Exception? innerException = null) { } - public NetworkException(string message, NetworkError error, Exception? innerException = null) { } - protected NetworkException(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) { } - public NetworkError NetworkError { get { throw null; } } - } } namespace System.Net.Cache { diff --git a/src/libraries/System.Net.Primitives/src/Resources/Strings.resx b/src/libraries/System.Net.Primitives/src/Resources/Strings.resx index 71c69951284b6..d95ea7484aace 100644 --- a/src/libraries/System.Net.Primitives/src/Resources/Strings.resx +++ b/src/libraries/System.Net.Primitives/src/Resources/Strings.resx @@ -114,28 +114,4 @@ An invalid IPEndPoint was specified. - - A network error has occured, see InnerException for more details. - - - The requested EndPoint is already in use. - - - No connection could be made because the remote host actively refused it. - - - No such host is known. - - - The operation was aborted by the user. - - - The connection was aborted by the local host. - - - The connection was forcibly closed by the remote host. - - - The connection attempt has timed out. - diff --git a/src/libraries/System.Net.Primitives/src/System.Net.Primitives.csproj b/src/libraries/System.Net.Primitives/src/System.Net.Primitives.csproj index 413d76f6925cb..07f176ab3ad64 100644 --- a/src/libraries/System.Net.Primitives/src/System.Net.Primitives.csproj +++ b/src/libraries/System.Net.Primitives/src/System.Net.Primitives.csproj @@ -34,8 +34,6 @@ - - diff --git a/src/libraries/System.Net.Primitives/tests/FunctionalTests/System.Net.Primitives.Functional.Tests.csproj b/src/libraries/System.Net.Primitives/tests/FunctionalTests/System.Net.Primitives.Functional.Tests.csproj index 215b3411c287d..26cd2568e1570 100644 --- a/src/libraries/System.Net.Primitives/tests/FunctionalTests/System.Net.Primitives.Functional.Tests.csproj +++ b/src/libraries/System.Net.Primitives/tests/FunctionalTests/System.Net.Primitives.Functional.Tests.csproj @@ -20,7 +20,6 @@ - diff --git a/src/libraries/System.Net.Requests/src/System/Net/WebException.cs b/src/libraries/System.Net.Requests/src/System/Net/WebException.cs index 9810108b83484..06f2207308a6b 100644 --- a/src/libraries/System.Net.Requests/src/System/Net/WebException.cs +++ b/src/libraries/System.Net.Requests/src/System/Net/WebException.cs @@ -96,17 +96,18 @@ internal static Exception CreateCompatibleException(Exception exception) private static WebExceptionStatus GetStatusFromExceptionHelper(HttpRequestException ex) { - NetworkException? networkException = ex.InnerException as NetworkException; + SocketException? socketException = ex.InnerException as SocketException; - if (networkException is null) + if (socketException is null) { return WebExceptionStatus.UnknownError; } WebExceptionStatus status; - switch (networkException.NetworkError) + switch (socketException.SocketErrorCode) { - case NetworkError.HostNotFound: + case SocketError.NoData: + case SocketError.HostNotFound: status = WebExceptionStatus.NameResolutionFailure; break; default: diff --git a/src/libraries/System.Net.Sockets/src/System.Net.Sockets.csproj b/src/libraries/System.Net.Sockets/src/System.Net.Sockets.csproj index 4d39c2d94a77b..ae0f96d5351e8 100644 --- a/src/libraries/System.Net.Sockets/src/System.Net.Sockets.csproj +++ b/src/libraries/System.Net.Sockets/src/System.Net.Sockets.csproj @@ -95,8 +95,6 @@ Link="Common\System\Net\Sockets\ProtocolType.cs" /> - diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/NetworkStream.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/NetworkStream.cs index 2eb6a180b7ac4..7ee46c5546819 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/NetworkStream.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/NetworkStream.cs @@ -50,15 +50,15 @@ public NetworkStream(Socket socket, FileAccess access, bool ownsSocket) // allowing non-blocking sockets could result in non-deterministic failures from those // operations. A developer that requires using NetworkStream with a non-blocking socket can // temporarily flip Socket.Blocking as a workaround. - throw GetCustomNetworkException(SR.net_sockets_blocking); + throw GetCustomException(SR.net_sockets_blocking); } if (!socket.Connected) { - throw GetCustomNetworkException(SR.net_notconnected); + throw GetCustomException(SR.net_notconnected); } if (socket.SocketType != SocketType.Stream) { - throw GetCustomNetworkException(SR.net_notstream); + throw GetCustomException(SR.net_notstream); } _streamSocket = socket; @@ -243,11 +243,11 @@ public override int Read(byte[] buffer, int offset, int size) } catch (SocketException socketException) { - throw NetworkErrorHelper.MapSocketException(socketException); + throw GetExceptionFromSocketException(SR.Format(SR.net_io_readfailure, socketException.Message), socketException); } catch (Exception exception) when (!(exception is OutOfMemoryException)) { - throw GetCustomNetworkException(SR.Format(SR.net_io_readfailure, exception.Message), exception); + throw GetCustomException(SR.Format(SR.net_io_readfailure, exception.Message), exception); } } @@ -267,8 +267,8 @@ public override int Read(Span buffer) int bytesRead = _streamSocket.Receive(buffer, SocketFlags.None, out SocketError errorCode); if (errorCode != SocketError.Success) { - var exception = new SocketException((int)errorCode); - throw NetworkErrorHelper.MapSocketException(exception); + var socketException = new SocketException((int)errorCode); + throw GetExceptionFromSocketException(SR.Format(SR.net_io_readfailure, socketException.Message), socketException); } return bytesRead; } @@ -326,11 +326,11 @@ public override void Write(byte[] buffer, int offset, int size) } catch (SocketException socketException) { - throw NetworkErrorHelper.MapSocketException(socketException); + throw GetExceptionFromSocketException(SR.Format(SR.net_io_writefailure, socketException.Message), socketException); } catch (Exception exception) when (!(exception is OutOfMemoryException)) { - throw GetCustomNetworkException(SR.Format(SR.net_io_writefailure, exception.Message), exception); + throw GetCustomException(SR.Format(SR.net_io_writefailure, exception.Message), exception); } } @@ -351,8 +351,8 @@ public override void Write(ReadOnlySpan buffer) _streamSocket.Send(buffer, SocketFlags.None, out SocketError errorCode); if (errorCode != SocketError.Success) { - var exception = new SocketException((int)errorCode); - throw NetworkErrorHelper.MapSocketException(exception); + var socketException = new SocketException((int)errorCode); + throw GetExceptionFromSocketException(SR.Format(SR.net_io_writefailure, socketException.Message), socketException); } } @@ -449,11 +449,11 @@ public override IAsyncResult BeginRead(byte[] buffer, int offset, int size, Asyn } catch (SocketException socketException) { - throw NetworkErrorHelper.MapSocketException(socketException); + throw GetExceptionFromSocketException(SR.Format(SR.net_io_readfailure, socketException.Message), socketException); } catch (Exception exception) when (!(exception is OutOfMemoryException)) { - throw GetCustomNetworkException(SR.Format(SR.net_io_readfailure, exception.Message), exception); + throw GetCustomException(SR.Format(SR.net_io_readfailure, exception.Message), exception); } } @@ -481,11 +481,11 @@ public override int EndRead(IAsyncResult asyncResult) } catch (SocketException socketException) { - throw NetworkErrorHelper.MapSocketException(socketException); + throw GetExceptionFromSocketException(SR.Format(SR.net_io_readfailure, socketException.Message), socketException); } catch (Exception exception) when (!(exception is OutOfMemoryException)) { - throw GetCustomNetworkException(SR.Format(SR.net_io_readfailure, exception.Message), exception); + throw GetCustomException(SR.Format(SR.net_io_readfailure, exception.Message), exception); } } @@ -539,11 +539,11 @@ public override IAsyncResult BeginWrite(byte[] buffer, int offset, int size, Asy } catch (SocketException socketException) { - throw NetworkErrorHelper.MapSocketException(socketException); + throw GetExceptionFromSocketException(SR.Format(SR.net_io_writefailure, socketException.Message), socketException); } catch (Exception exception) when (!(exception is OutOfMemoryException)) { - throw GetCustomNetworkException(SR.Format(SR.net_io_writefailure, exception.Message), exception); + throw GetCustomException(SR.Format(SR.net_io_writefailure, exception.Message), exception); } } @@ -567,11 +567,11 @@ public override void EndWrite(IAsyncResult asyncResult) } catch (SocketException socketException) { - throw NetworkErrorHelper.MapSocketException(socketException); + throw GetExceptionFromSocketException(SR.Format(SR.net_io_writefailure, socketException.Message), socketException); } catch (Exception exception) when (!(exception is OutOfMemoryException)) { - throw GetCustomNetworkException(SR.Format(SR.net_io_writefailure, exception.Message), exception); + throw GetCustomException(SR.Format(SR.net_io_writefailure, exception.Message), exception); } } @@ -623,11 +623,11 @@ public override Task ReadAsync(byte[] buffer, int offset, int size, Cancell } catch (SocketException socketException) { - throw NetworkErrorHelper.MapSocketException(socketException); + throw GetExceptionFromSocketException(SR.Format(SR.net_io_readfailure, socketException.Message), socketException); } catch (Exception exception) when (!(exception is OutOfMemoryException)) { - throw GetCustomNetworkException(SR.Format(SR.net_io_readfailure, exception.Message), exception); + throw GetCustomException(SR.Format(SR.net_io_readfailure, exception.Message), exception); } } @@ -650,11 +650,11 @@ public override ValueTask ReadAsync(Memory buffer, CancellationToken } catch (SocketException socketException) { - throw NetworkErrorHelper.MapSocketException(socketException); + throw GetExceptionFromSocketException(SR.Format(SR.net_io_readfailure, socketException.Message), socketException); } catch (Exception exception) when (!(exception is OutOfMemoryException)) { - throw GetCustomNetworkException(SR.Format(SR.net_io_readfailure, exception.Message), exception); + throw GetCustomException(SR.Format(SR.net_io_readfailure, exception.Message), exception); } } @@ -705,11 +705,11 @@ public override Task WriteAsync(byte[] buffer, int offset, int size, Cancellatio } catch (SocketException socketException) { - throw NetworkErrorHelper.MapSocketException(socketException); + throw GetExceptionFromSocketException(SR.Format(SR.net_io_writefailure, socketException.Message), socketException); } catch (Exception exception) when (!(exception is OutOfMemoryException)) { - throw GetCustomNetworkException(SR.Format(SR.net_io_writefailure, exception.Message), exception); + throw GetCustomException(SR.Format(SR.net_io_writefailure, exception.Message), exception); } } @@ -731,11 +731,11 @@ public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationTo } catch (SocketException socketException) { - throw NetworkErrorHelper.MapSocketException(socketException); + throw GetExceptionFromSocketException(SR.Format(SR.net_io_writefailure, socketException.Message), socketException); } catch (Exception exception) when (!(exception is OutOfMemoryException)) { - throw GetCustomNetworkException(SR.Format(SR.net_io_writefailure, exception.Message), exception); + throw GetCustomException(SR.Format(SR.net_io_writefailure, exception.Message), exception); } } @@ -793,9 +793,14 @@ private void ThrowIfDisposed() void ThrowObjectDisposedException() => throw new ObjectDisposedException(GetType().FullName); } - private static NetworkException GetCustomNetworkException(string message, Exception? innerException = null) + private static IOException GetExceptionFromSocketException(string message, SocketException innerException) { - return new NetworkException(message, NetworkError.Other, innerException); + return new IOException(message, innerException); + } + + private static IOException GetCustomException(string message, Exception? innerException = null) + { + return new IOException(message, innerException); } } } diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs index 83b8e3e4bb737..89d53627a5e67 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs @@ -195,7 +195,7 @@ internal ValueTask ReceiveAsync(Memory buffer, SocketFlags socketFlag Debug.Assert(saea.BufferList == null); saea.SetBuffer(buffer); saea.SocketFlags = socketFlags; - saea.WrapExceptionsInNetworkExceptions = fromNetworkStream; + saea.WrapExceptionsForNetworkStream = fromNetworkStream; return saea.ReceiveAsync(this, cancellationToken); } @@ -278,7 +278,7 @@ internal ValueTask SendAsync(ReadOnlyMemory buffer, SocketFlags socke Debug.Assert(saea.BufferList == null); saea.SetBuffer(MemoryMarshal.AsMemory(buffer)); saea.SocketFlags = socketFlags; - saea.WrapExceptionsInNetworkExceptions = false; + saea.WrapExceptionsForNetworkStream = false; return saea.SendAsync(this, cancellationToken); } @@ -296,7 +296,7 @@ internal ValueTask SendAsyncForNetworkStream(ReadOnlyMemory buffer, Socket Debug.Assert(saea.BufferList == null); saea.SetBuffer(MemoryMarshal.AsMemory(buffer)); saea.SocketFlags = socketFlags; - saea.WrapExceptionsInNetworkExceptions = true; + saea.WrapExceptionsForNetworkStream = true; return saea.SendAsyncForNetworkStream(this, cancellationToken); } @@ -618,7 +618,7 @@ public AwaitableSocketAsyncEventArgs(Socket owner, bool isReceiveForCaching) : _isReadForCaching = isReceiveForCaching; } - public bool WrapExceptionsInNetworkExceptions { get; set; } + public bool WrapExceptionsForNetworkStream { get; set; } private void Release() { @@ -926,8 +926,10 @@ private Exception CreateException(SocketError error, bool forAsyncThrow = true) e = ExceptionDispatchInfo.SetCurrentStackTrace(e); } - return WrapExceptionsInNetworkExceptions ? - NetworkErrorHelper.MapSocketException((SocketException)e) : + return WrapExceptionsForNetworkStream ? + (_isReadForCaching ? + new IOException(SR.Format(SR.net_io_readfailure, e.Message), e) : + new IOException(SR.Format(SR.net_io_writefailure, e.Message), e)) : e; } } diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs index fb29385985418..da51240e0f8b2 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs @@ -25,25 +25,25 @@ public void Ctor_NullSocket_ThrowsArgumentNullExceptions() } [Fact] - public void Ctor_NotConnected_ThrowsNetworkException() + public void Ctor_NotConnected_Throws() { - Assert.Throws(() => new NetworkStream(new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))); + Assert.Throws(() => new NetworkStream(new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))); } [Fact] - public async Task Ctor_NotStream_ThrowsNetworkException() + public async Task Ctor_NotStream_Throws() { using (Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)) using (Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)) { listener.Bind(new IPEndPoint(IPAddress.Loopback, 0)); await client.ConnectAsync(new IPEndPoint(IPAddress.Loopback, ((IPEndPoint)listener.LocalEndPoint).Port)); - Assert.Throws(() => new NetworkStream(client)); + Assert.Throws(() => new NetworkStream(client)); } } [Fact] - public async Task Ctor_NonBlockingSocket_ThrowsNetworkException() + public async Task Ctor_NonBlockingSocket_Throws() { using (Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) using (Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) @@ -56,7 +56,7 @@ public async Task Ctor_NonBlockingSocket_ThrowsNetworkException() using (Socket server = await acceptTask) { server.Blocking = false; - Assert.Throws(() => new NetworkStream(server)); + Assert.Throws(() => new NetworkStream(server)); } } } @@ -186,7 +186,7 @@ public async Task Ctor_SocketBool_CanReadAndWrite(bool ownsSocket) } else if (ownsSocket) { - Assert.IsType(e); + Assert.IsType(e); } else { @@ -317,14 +317,14 @@ public async Task DisposeSocketDirectly_ReadWriteThrowNetworkException() { serverSocket.Dispose(); - Assert.Throws(() => server.Read(new byte[1], 0, 1)); - Assert.Throws(() => server.Write(new byte[1], 0, 1)); + Assert.Throws(() => server.Read(new byte[1], 0, 1)); + Assert.Throws(() => server.Write(new byte[1], 0, 1)); - Assert.Throws(() => server.BeginRead(new byte[1], 0, 1, null, null)); - Assert.Throws(() => server.BeginWrite(new byte[1], 0, 1, null, null)); + Assert.Throws(() => server.BeginRead(new byte[1], 0, 1, null, null)); + Assert.Throws(() => server.BeginWrite(new byte[1], 0, 1, null, null)); - Assert.Throws(() => { server.ReadAsync(new byte[1], 0, 1); }); - Assert.Throws(() => { server.WriteAsync(new byte[1], 0, 1); }); + Assert.Throws(() => { server.ReadAsync(new byte[1], 0, 1); }); + Assert.Throws(() => { server.WriteAsync(new byte[1], 0, 1); }); } } } @@ -334,8 +334,8 @@ public async Task InvalidIAsyncResult_EndReadWriteThrows() { await RunWithConnectedNetworkStreamsAsync((server, _) => { - Assert.Throws(() => server.EndRead(Task.CompletedTask)); - Assert.Throws(() => server.EndWrite(Task.CompletedTask)); + Assert.Throws(() => server.EndRead(Task.CompletedTask)); + Assert.Throws(() => server.EndWrite(Task.CompletedTask)); return Task.CompletedTask; }); } @@ -579,14 +579,14 @@ await RunWithConnectedNetworkStreamsAsync(async (server, client) => [OuterLoop("Timeouts")] [Fact] - public async Task ReadTimeout_Expires_ThrowsSocketException() + public async Task ReadTimeout_Expires_Throws() { await RunWithConnectedNetworkStreamsAsync((server, client) => { Assert.Equal(-1, server.ReadTimeout); server.ReadTimeout = 1; - Assert.ThrowsAny(() => server.Read(new byte[1], 0, 1)); + Assert.ThrowsAny(() => server.Read(new byte[1], 0, 1)); return Task.CompletedTask; }); @@ -713,8 +713,8 @@ await RunWithConnectedNetworkStreamsAsync(async (stream, _) => // before that takes effect, it may also complete as aborted. bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); Assert.True( - (isWindows && e is NetworkException) || - (!isWindows && (e == null || e is NetworkException)), + (isWindows && e is IOException) || + (!isWindows && (e == null || e is IOException)), $"Got unexpected exception: {e?.ToString() ?? "(null)"}"); // Copying after disposing the stream diff --git a/src/libraries/pkg/baseline/packageIndex.json b/src/libraries/pkg/baseline/packageIndex.json index 6457475b075e0..4dfe9a9b48fb5 100644 --- a/src/libraries/pkg/baseline/packageIndex.json +++ b/src/libraries/pkg/baseline/packageIndex.json @@ -3354,9 +3354,7 @@ "4.6.0" ], "BaselineVersion": "6.0.0", - "InboxOn": { - "net5.0": "5.0.0.0" - }, + "InboxOn": {}, "AssemblyVersionInPackageVersion": { "4.0.0.0": "4.5.0", "4.0.0.1": "4.5.2", @@ -4102,6 +4100,7 @@ "xamarinios10": "Any", "xamarinmac20": "Any", "xamarintvos10": "Any", + "xamarinwatchos10": "Any" } }, From 96134da42448c31cca3e337d55fc7c0bede58c0d Mon Sep 17 00:00:00 2001 From: Geoffrey Kizer Date: Tue, 1 Sep 2020 08:41:19 -0700 Subject: [PATCH 2/4] cleanup csproj changes --- .../src/System.Net.Http.csproj | 598 ++++++++++++------ 1 file changed, 398 insertions(+), 200 deletions(-) diff --git a/src/libraries/System.Net.Http/src/System.Net.Http.csproj b/src/libraries/System.Net.Http/src/System.Net.Http.csproj index 2d341bca21f68..1badaad9ca3c4 100644 --- a/src/libraries/System.Net.Http/src/System.Net.Http.csproj +++ b/src/libraries/System.Net.Http/src/System.Net.Http.csproj @@ -1,4 +1,4 @@ - + win true @@ -60,7 +60,6 @@ - @@ -107,16 +106,26 @@ - - - - - - - - - - + + + + + + + + + + @@ -164,57 +173,107 @@ + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -296,29 +355,43 @@ - + - + - - - - - - - - - - - - + + + + + + + + + + + + @@ -327,150 +400,275 @@ - - - - - - - - - - - - + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + From 6574ac6813847f533e004d6d7000f7a23e31d0f5 Mon Sep 17 00:00:00 2001 From: Geoff Kizer Date: Tue, 1 Sep 2020 15:31:56 -0700 Subject: [PATCH 3/4] Update src/libraries/pkg/baseline/packageIndex.json Co-authored-by: Cory Nelson --- src/libraries/pkg/baseline/packageIndex.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libraries/pkg/baseline/packageIndex.json b/src/libraries/pkg/baseline/packageIndex.json index 4dfe9a9b48fb5..49b7804ca3983 100644 --- a/src/libraries/pkg/baseline/packageIndex.json +++ b/src/libraries/pkg/baseline/packageIndex.json @@ -4100,7 +4100,6 @@ "xamarinios10": "Any", "xamarinmac20": "Any", "xamarintvos10": "Any", - "xamarinwatchos10": "Any" } }, @@ -7322,4 +7321,4 @@ "System.Xml.XDocument" ] } -} \ No newline at end of file +} From 779502ae08c2ea12d98bd557e2e35e8978583b29 Mon Sep 17 00:00:00 2001 From: Geoff Kizer Date: Tue, 1 Sep 2020 15:32:27 -0700 Subject: [PATCH 4/4] Update src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs Co-authored-by: Cory Nelson --- .../System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs index 89d53627a5e67..5388df7411d2b 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs @@ -927,9 +927,7 @@ private Exception CreateException(SocketError error, bool forAsyncThrow = true) } return WrapExceptionsForNetworkStream ? - (_isReadForCaching ? - new IOException(SR.Format(SR.net_io_readfailure, e.Message), e) : - new IOException(SR.Format(SR.net_io_writefailure, e.Message), e)) : + new IOException(SR.Format(_isReadForCaching ? SR.net_io_readfailure : SR.net_io_writefailure, e.Message), e) : e; } }