private async ValueTask <HttpConnection> CreateConnection(HttpRequestMessage request, HttpConnectionKey key, HttpConnectionPool pool) { Uri uri = request.RequestUri; Stream stream = await ConnectHelper.ConnectAsync(uri.IdnHost, uri.Port).ConfigureAwait(false); TransportContext transportContext = null; if (uri.Scheme == UriScheme.Https) { SslStream sslStream = await EstablishSslConnection(uri.IdnHost, request, stream).ConfigureAwait(false); stream = sslStream; transportContext = sslStream.TransportContext; } if (pool == null) { pool = _connectionPoolTable.GetOrAdd(key, _ => new HttpConnectionPool()); } var connection = new HttpConnection(pool, key, uri.IdnHost, stream, transportContext, false); return(connection); }
private async ValueTask <HttpConnection> CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken) { // If a non-infinite connect timeout has been set, create and use a new CancellationToken that'll be canceled // when either the original token is canceled or a connect timeout occurs. CancellationTokenSource cancellationWithConnectTimeout = null; if (Settings._connectTimeout != Timeout.InfiniteTimeSpan) { cancellationWithConnectTimeout = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, default); cancellationWithConnectTimeout.CancelAfter(Settings._connectTimeout); cancellationToken = cancellationWithConnectTimeout.Token; } try { Stream stream = await (_proxyUri == null ? ConnectHelper.ConnectAsync(_host, _port, cancellationToken) : (_sslOptions == null ? ConnectHelper.ConnectAsync(_proxyUri.IdnHost, _proxyUri.Port, cancellationToken) : EstablishProxyTunnel(cancellationToken))).ConfigureAwait(false); TransportContext transportContext = null; if (_sslOptions != null) { // TODO #25206 and #24430: Register/IsCancellationRequested should be removable once SslStream auth and sockets respect cancellation. CancellationTokenRegistration ctr = cancellationToken.Register(s => ((Stream)s).Dispose(), stream); try { SslStream sslStream = await ConnectHelper.EstablishSslConnectionAsync(_sslOptions, request, stream, cancellationToken).ConfigureAwait(false); stream = sslStream; transportContext = sslStream.TransportContext; cancellationToken.ThrowIfCancellationRequested(); // to handle race condition where stream is dispose of by cancellation after auth } catch (Exception exc) { stream.Dispose(); // in case cancellation occurs after successful SSL auth if (HttpConnection.ShouldWrapInOperationCanceledException(exc, cancellationToken)) { throw HttpConnection.CreateOperationCanceledException(exc, cancellationToken); } throw; } finally { ctr.Dispose(); } } return(_maxConnections == int.MaxValue ? new HttpConnection(this, stream, transportContext) : new HttpConnectionWithFinalizer(this, stream, transportContext)); // finalizer needed to signal the pool when a connection is dropped } finally { cancellationWithConnectTimeout?.Dispose(); } }
private ValueTask <HttpConnection> GetOrCreateConnection(HttpRequestMessage request, Uri proxyUri, CancellationToken cancellationToken) { var key = new HttpConnectionKey(proxyUri); HttpConnectionPool pool = _connectionPools.GetOrAddPool(key); return(pool.GetConnectionAsync(async(state, ct) => { Stream stream = await ConnectHelper.ConnectAsync(state.proxyUri.IdnHost, state.proxyUri.Port, ct).ConfigureAwait(false); return new HttpConnection(state.pool, state.key, null, stream, null, true); }, (pool: pool, key: key, request: request, proxyUri: proxyUri), cancellationToken)); }
private async ValueTask <HttpConnection> CreateConnection( HttpRequestMessage request, HttpConnectionKey key, HttpConnectionPool pool, CancellationToken cancellationToken) { Uri uri = request.RequestUri; Stream stream = await ConnectHelper.ConnectAsync(uri.IdnHost, uri.Port, cancellationToken).ConfigureAwait(false); TransportContext transportContext = null; if (uri.Scheme == UriScheme.Https) { // Get the appropriate host name to use for the SSL connection, allowing a host header to override. string host = request.Headers.Host; if (host == null) { // No host header, use the host from the Uri. host = uri.IdnHost; } else { // There is a host header. Use it, but first see if we need to trim off a port. int colonPos = host.IndexOf(':'); if (colonPos >= 0) { // There is colon, which could either be a port separator or a separator in // an IPv6 address. See if this is an IPv6 address; if it's not, use everything // before the colon as the host name, and if it is, use everything before the last // colon iff the last colon is after the end of the IPv6 address (otherwise it's a // part of the address). int ipV6AddressEnd = host.IndexOf(']'); if (ipV6AddressEnd == -1) { host = host.Substring(0, colonPos); } else { colonPos = host.LastIndexOf(':'); if (colonPos > ipV6AddressEnd) { host = host.Substring(0, colonPos); } } } } // Establish the connection using the parsed host name. SslStream sslStream = await EstablishSslConnection(host, request, stream, cancellationToken).ConfigureAwait(false); stream = sslStream; transportContext = sslStream.TransportContext; } return(new HttpConnection(pool, key, uri.IdnHost, stream, transportContext, false)); }
private async ValueTask <HttpConnection> CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken) { Stream stream = await ConnectHelper.ConnectAsync(_key, cancellationToken).ConfigureAwait(false); TransportContext transportContext = null; if (_key.IsSecure) { SslStream sslStream = await ConnectHelper.EstablishSslConnectionAsync(_pools.Settings, _key.SslHostName, request, stream, cancellationToken).ConfigureAwait(false); stream = sslStream; transportContext = sslStream.TransportContext; } return(new HttpConnection(this, stream, transportContext)); }
private async ValueTask <HttpConnection> CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken) { Stream stream = await ConnectHelper.ConnectAsync(_key, cancellationToken).ConfigureAwait(false); TransportContext transportContext = null; if (_key.IsSecure) { SslStream sslStream = await ConnectHelper.EstablishSslConnectionAsync(_sslOptions, request, stream, cancellationToken).ConfigureAwait(false); stream = sslStream; transportContext = sslStream.TransportContext; } return(_maxConnections == int.MaxValue ? new HttpConnection(this, stream, transportContext) : new HttpConnectionWithFinalizer(this, stream, transportContext)); // finalizer needed to signal the pool when a connection is dropped }
private async ValueTask <HttpConnection> CreateConnection(HttpRequestMessage request, HttpConnectionKey key, HttpConnectionPool pool) { Uri uri = request.RequestUri; Stream stream = await ConnectHelper.ConnectAsync(uri.IdnHost, uri.Port).ConfigureAwait(false); TransportContext transportContext = null; if (HttpUtilities.IsSupportedSecureScheme(uri.Scheme)) { SslStream sslStream = await EstablishSslConnection(uri.IdnHost, request, stream).ConfigureAwait(false); stream = sslStream; transportContext = sslStream.TransportContext; } return(new HttpConnection(pool, key, uri.IdnHost, stream, transportContext, false)); }
private async ValueTask <HttpConnection> CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken) { // If a non-infinite connect timeout has been set, create and use a new CancellationToken that'll be canceled // when either the original token is canceled or a connect timeout occurs. CancellationTokenSource cancellationWithConnectTimeout = null; if (Settings._connectTimeout != Timeout.InfiniteTimeSpan) { cancellationWithConnectTimeout = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, default); cancellationWithConnectTimeout.CancelAfter(Settings._connectTimeout); cancellationToken = cancellationWithConnectTimeout.Token; } try { Stream stream = await (_proxyUri == null ? ConnectHelper.ConnectAsync(_host, _port, cancellationToken) : (_sslOptions == null ? ConnectHelper.ConnectAsync(_proxyUri.IdnHost, _proxyUri.Port, cancellationToken) : EstablishProxyTunnel(cancellationToken))).ConfigureAwait(false); TransportContext transportContext = null; if (_sslOptions != null) { SslStream sslStream = await ConnectHelper.EstablishSslConnectionAsync(_sslOptions, request, stream, cancellationToken).ConfigureAwait(false); stream = sslStream; transportContext = sslStream.TransportContext; } return(_maxConnections == int.MaxValue ? new HttpConnection(this, stream, transportContext) : new HttpConnectionWithFinalizer(this, stream, transportContext)); // finalizer needed to signal the pool when a connection is dropped } finally { cancellationWithConnectTimeout?.Dispose(); } }
private async ValueTask <HttpConnection> GetOrCreateConnection(HttpRequestMessage request, Uri proxyUri) { HttpConnectionKey key = new HttpConnectionKey(proxyUri); HttpConnectionPool pool; if (_connectionPoolTable.TryGetValue(key, out pool)) { HttpConnection poolConnection = pool.GetConnection(); if (poolConnection != null) { return(poolConnection); } } Stream stream = await ConnectHelper.ConnectAsync(proxyUri.Host, proxyUri.Port).ConfigureAwait(false); if (pool == null) { pool = _connectionPoolTable.GetOrAdd(key, _ => new HttpConnectionPool()); } return(new HttpConnection(pool, key, stream, null, true)); }
private async ValueTask <(HttpConnection, HttpResponseMessage)> CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken) { // If a non-infinite connect timeout has been set, create and use a new CancellationToken that'll be canceled // when either the original token is canceled or a connect timeout occurs. CancellationTokenSource cancellationWithConnectTimeout = null; if (Settings._connectTimeout != Timeout.InfiniteTimeSpan) { cancellationWithConnectTimeout = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, default); cancellationWithConnectTimeout.CancelAfter(Settings._connectTimeout); cancellationToken = cancellationWithConnectTimeout.Token; } try { Socket socket = null; Stream stream = null; switch (_kind) { case HttpConnectionKind.Http: case HttpConnectionKind.Https: case HttpConnectionKind.ProxyConnect: (socket, stream) = await ConnectHelper.ConnectAsync(_host, _port, cancellationToken).ConfigureAwait(false); break; case HttpConnectionKind.Proxy: (socket, stream) = await ConnectHelper.ConnectAsync(_proxyUri.IdnHost, _proxyUri.Port, cancellationToken).ConfigureAwait(false); break; case HttpConnectionKind.ProxyTunnel: case HttpConnectionKind.SslProxyTunnel: HttpResponseMessage response; (stream, response) = await EstablishProxyTunnel(cancellationToken).ConfigureAwait(false); if (response != null) { // Return non-success response from proxy. response.RequestMessage = request; return(null, response); } break; } TransportContext transportContext = null; if (_sslOptions != null) { SslStream sslStream = await ConnectHelper.EstablishSslConnectionAsync(_sslOptions, request, stream, cancellationToken).ConfigureAwait(false); stream = sslStream; transportContext = sslStream.TransportContext; } HttpConnection connection = _maxConnections == int.MaxValue ? new HttpConnection(this, socket, stream, transportContext) : new HttpConnectionWithFinalizer(this, socket, stream, transportContext); // finalizer needed to signal the pool when a connection is dropped return(connection, null); } finally { cancellationWithConnectTimeout?.Dispose(); } }