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 6ca0ed87edf4c9..c8bfc919e9cf5d 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 @@ -71,6 +71,7 @@ internal partial class HttpConnection : HttpConnectionBase, IDisposable public HttpConnection( HttpConnectionPool pool, + Socket? socket, Stream stream, TransportContext? transportContext) { @@ -78,11 +79,8 @@ public HttpConnection( Debug.Assert(stream != null); _pool = pool; + _socket = socket; _stream = stream; - if (stream is NetworkStream networkStream) - { - _socket = networkStream.Socket; - } _transportContext = transportContext; 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 715cab8a7deb69..19aeeeeec7cd63 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 @@ -576,6 +576,7 @@ public byte[] Http2AltSvcOriginUri } // Try to establish an HTTP2 connection + Socket? socket = null; Stream? stream = null; SslStream? sslStream = null; TransportContext? transportContext = null; @@ -600,7 +601,7 @@ public byte[] Http2AltSvcOriginUri HttpResponseMessage? failureResponse; - (stream, transportContext, failureResponse) = + (socket, stream, transportContext, failureResponse) = await ConnectAsync(request, async, cancellationToken).ConfigureAwait(false); if (failureResponse != null) @@ -690,7 +691,7 @@ public byte[] Http2AltSvcOriginUri if (canUse) { - return (await ConstructHttp11Connection(stream!, transportContext, request, cancellationToken).ConfigureAwait(false), true, null); + return (await ConstructHttp11Connection(socket, stream!, transportContext, request, cancellationToken).ConfigureAwait(false), true, null); } else { @@ -1222,7 +1223,7 @@ public ValueTask SendAsync(HttpRequestMessage request, bool return SendWithProxyAuthAsync(request, async, doRequestAuth, cancellationToken); } - private async ValueTask<(Stream?, TransportContext?, HttpResponseMessage?)> ConnectAsync(HttpRequestMessage request, bool async, CancellationToken cancellationToken) + private async ValueTask<(Socket?, 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. @@ -1258,13 +1259,15 @@ public ValueTask SendAsync(HttpRequestMessage request, bool { // Return non-success response from proxy. response.RequestMessage = request; - return (null, null, response); + return (null, null, null, response); } break; } Debug.Assert(stream != null); + Socket? socket = (stream as NetworkStream)?.Socket; + TransportContext? transportContext = null; if (IsSecure) { @@ -1273,7 +1276,7 @@ public ValueTask SendAsync(HttpRequestMessage request, bool stream = sslStream; } - return (stream, transportContext, null); + return (socket, stream, transportContext, null); } finally { @@ -1329,7 +1332,7 @@ private ValueTask ConnectToTcpHostAsync(string host, int port, HttpReque internal async ValueTask<(HttpConnection?, HttpResponseMessage?)> CreateHttp11ConnectionAsync(HttpRequestMessage request, bool async, CancellationToken cancellationToken) { - (Stream? stream, TransportContext? transportContext, HttpResponseMessage? failureResponse) = + (Socket? socket, Stream? stream, TransportContext? transportContext, HttpResponseMessage? failureResponse) = await ConnectAsync(request, async, cancellationToken).ConfigureAwait(false); if (failureResponse != null) @@ -1337,7 +1340,7 @@ private ValueTask ConnectToTcpHostAsync(string host, int port, HttpReque return (null, failureResponse); } - return (await ConstructHttp11Connection(stream!, transportContext, request, cancellationToken).ConfigureAwait(false), null); + return (await ConstructHttp11Connection(socket, stream!, transportContext, request, cancellationToken).ConfigureAwait(false), null); } private SslClientAuthenticationOptions GetSslOptionsForRequest(HttpRequestMessage request) @@ -1384,10 +1387,17 @@ private async ValueTask ApplyPlaintextFilter(Stream stream, Version http return newStream; } - private async ValueTask ConstructHttp11Connection(Stream stream, TransportContext? transportContext, HttpRequestMessage request, CancellationToken cancellationToken) + private async ValueTask ConstructHttp11Connection(Socket? socket, Stream stream, TransportContext? transportContext, HttpRequestMessage request, CancellationToken cancellationToken) { - stream = await ApplyPlaintextFilter(stream, HttpVersion.Version11, request, cancellationToken).ConfigureAwait(false); - return new HttpConnection(this, stream, transportContext); + Stream newStream = await ApplyPlaintextFilter(stream, HttpVersion.Version11, request, cancellationToken).ConfigureAwait(false); + + if (newStream != stream) + { + // If a plaintext filter created a new stream, we can't trust that the socket is still applicable. + socket = null; + } + + return new HttpConnection(this, socket, newStream, transportContext); } private async ValueTask ConstructHttp2Connection(Stream stream, HttpRequestMessage request, CancellationToken cancellationToken)