private SocksConnection ConnectToDestinationIfNotConnected(Uri uri) { uri = Util.StripPath(uri); using (_connectionsAsyncLock.Lock()) { if (_connections.TryGetValue(uri.AbsoluteUri, out SocksConnection connection)) { if (!_references.Contains(uri)) { connection.ReferenceCount++; _references.Add(uri); } return(connection); } connection = new SocksConnection { EndPoint = EndPoint, Destination = uri }; connection.ReferenceCount++; _references.Add(uri); _connections.TryAdd(uri.AbsoluteUri, connection); return(connection); } }
private SocksConnection ConnectToDestinationIfNotConnected(Uri uri) { uri = Util.StripPath(uri); lock (_Connections) { if (_Connections.TryGetValue(uri.AbsoluteUri, out SocksConnection connection)) { if (!_References.Contains(uri)) { connection.AddReference(); _References.Add(uri); } return(connection); } connection = new SocksConnection { EndPoint = EndPoint, Destination = uri }; connection.AddReference(); _References.Add(uri); _Connections.TryAdd(uri.AbsoluteUri, connection); return(connection); } }
protected override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken ctsToken) { await Util.Semaphore.WaitAsync().ConfigureAwait(false); try { SocksConnection connection = null; try { Retry.Do(() => { connection = ConnectToDestinationIfNotConnected(request.RequestUri); }, RetryInterval, MaxRetry); } catch (Exception ex) { throw new TorException("Failed to connect to the destination", ex); } ctsToken.ThrowIfCancellationRequested(); // https://tools.ietf.org/html/rfc7230#section-2.7.1 // A sender MUST NOT generate an "http" URI with an empty host identifier. if (request.RequestUri.DnsSafeHost == "") { throw new HttpRequestException("Host identifier is empty"); } // https://tools.ietf.org/html/rfc7230#section-2.6 // Intermediaries that process HTTP messages (i.e., all intermediaries // other than those acting as tunnels) MUST send their own HTTP - version // in forwarded messages. request.Version = Protocol.Version; try { return(await connection.SendRequestAsync(request, ctsToken).ConfigureAwait(false)); } catch (Exception ex) { if (ex is OperationCanceledException) { throw; } else { throw new TorException("Failed to send the request", ex); } } } finally { Util.Semaphore.Release(); } }
private HttpResponseMessage Send(HttpRequestMessage request) { SocksConnection connection = null; try { Retry.Do(() => { connection = ConnectToDestinationIfNotConnected(request.RequestUri); }, RetryInterval, MaxRetry); } catch (Exception ex) { throw new TorException("Failed to connect to the destination", ex); } Util.ValidateRequest(request); HttpResponseMessage message = connection.SendRequest(request, IgnoreSslCertification); return(message); }