/// <summary> /// Returns a Tcp Connection back to cache for reuse by other requests /// </summary> /// <param name="connection"></param> /// <returns></returns> internal async Task ReleaseClient(TcpConnectionCache connection) { connection.LastAccess = DateTime.Now; var key = GetConnectionKey(connection.HostName, connection.port, connection.IsHttps, connection.Version); await connectionAccessLock.WaitAsync(); try { List <TcpConnectionCache> cachedConnections; connectionCache.TryGetValue(key, out cachedConnections); if (cachedConnections != null) { cachedConnections.Add(connection); } else { connectionCache.Add(key, new List <TcpConnectionCache>() { connection }); } } finally { connectionAccessLock.Release(); } }
/// <summary> /// Get a TcpConnection to the specified host, port optionally HTTPS and a particular HTTP version /// </summary> /// <param name="hostname"></param> /// <param name="port"></param> /// <param name="isHttps"></param> /// <param name="version"></param> /// <returns></returns> internal async Task <TcpConnectionCache> GetClient(string hostname, int port, bool isHttps, Version version, ExternalProxy upStreamHttpProxy, ExternalProxy upStreamHttpsProxy, int bufferSize, SslProtocols supportedSslProtocols, RemoteCertificateValidationCallback remoteCertificateValidationCallBack, LocalCertificateSelectionCallback localCertificateSelectionCallback) { List <TcpConnectionCache> cachedConnections = null; TcpConnectionCache cached = null; //Get a unique string to identify this connection var key = GetConnectionKey(hostname, port, isHttps, version); while (true) { await connectionAccessLock.WaitAsync(); try { connectionCache.TryGetValue(key, out cachedConnections); if (cachedConnections != null && cachedConnections.Count > 0) { cached = cachedConnections.First(); cachedConnections.Remove(cached); } else { cached = null; } } finally { connectionAccessLock.Release(); } if (cached != null && !cached.TcpClient.Client.IsConnected()) { cached.TcpClient.Client.Dispose(); cached.TcpClient.Close(); continue; } if (cached == null) { break; } } if (cached == null) { cached = await CreateClient(hostname, port, isHttps, version, upStreamHttpProxy, upStreamHttpsProxy, bufferSize, supportedSslProtocols, remoteCertificateValidationCallBack, localCertificateSelectionCallback); } if (cachedConnections == null || cachedConnections.Count() <= 2) { var task = CreateClient(hostname, port, isHttps, version, upStreamHttpProxy, upStreamHttpsProxy, bufferSize, supportedSslProtocols, remoteCertificateValidationCallBack, localCertificateSelectionCallback) .ContinueWith(async(x) => { if (x.Status == TaskStatus.RanToCompletion) { await ReleaseClient(x.Result); } }); } return(cached); }