Merge branch 'main' into hyper-docs

This commit is contained in:
Ian Jackson 2022-03-01 11:02:46 +00:00
commit 5610cec095
8 changed files with 387 additions and 91 deletions

207
Cargo.lock generated
View File

@ -41,6 +41,15 @@ dependencies = [
"version_check",
]
[[package]]
name = "aho-corasick"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
"memchr",
]
[[package]]
name = "ansi_term"
version = "0.12.1"
@ -166,6 +175,8 @@ dependencies = [
"hyper",
"pin-project",
"thiserror",
"tls-api",
"tls-api-native-tls",
"tokio",
"tor-error",
"tor-rtcompat",
@ -323,7 +334,7 @@ checksum = "9c86f33abd5a4f3e2d6d9251a9e0c6a7e52eb1113caf893dae8429bf4a53f378"
dependencies = [
"futures-lite",
"rustls",
"webpki",
"webpki 0.21.4",
]
[[package]]
@ -971,6 +982,19 @@ version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
name = "env_logger"
version = "0.5.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38"
dependencies = [
"atty",
"humantime 1.3.0",
"log",
"regex",
"termcolor",
]
[[package]]
name = "event-listener"
version = "2.5.2"
@ -1103,6 +1127,12 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "fuchsia-zircon"
version = "0.3.3"
@ -1387,6 +1417,15 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
[[package]]
name = "humantime"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
dependencies = [
"quick-error",
]
[[package]]
name = "humantime"
version = "2.1.0"
@ -1399,7 +1438,7 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac34a56cfd4acddb469cc7fff187ed5ac36f498ba085caf8bbc725e3ff474058"
dependencies = [
"humantime",
"humantime 2.1.0",
"serde",
]
@ -1997,6 +2036,17 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
[[package]]
name = "pem"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd56cbd21fea48d0c440b41cd69c589faacade08c992d9a54e471b79d0fd13eb"
dependencies = [
"base64",
"once_cell",
"regex",
]
[[package]]
name = "pem-rfc7468"
version = "0.2.4"
@ -2166,6 +2216,12 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "quick-error"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]]
name = "quickcheck"
version = "1.0.3"
@ -2184,6 +2240,19 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
dependencies = [
"fuchsia-cprng",
"libc",
"rand_core 0.3.1",
"rdrand",
"winapi 0.3.9",
]
[[package]]
name = "rand"
version = "0.7.3"
@ -2228,6 +2297,21 @@ dependencies = [
"rand_core 0.6.3",
]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[package]]
name = "rand_core"
version = "0.5.1"
@ -2255,6 +2339,15 @@ dependencies = [
"rand_core 0.5.1",
]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "redox_syscall"
version = "0.2.10"
@ -2280,6 +2373,8 @@ version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
@ -2330,7 +2425,7 @@ dependencies = [
"libc",
"once_cell",
"spin",
"untrusted",
"untrusted 0.7.1",
"web-sys",
"winapi 0.3.9",
]
@ -2405,7 +2500,7 @@ dependencies = [
"log",
"ring",
"sct",
"webpki",
"webpki 0.21.4",
]
[[package]]
@ -2456,7 +2551,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce"
dependencies = [
"ring",
"untrusted",
"untrusted 0.7.1",
]
[[package]]
@ -2718,6 +2813,16 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "tempdir"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
dependencies = [
"rand 0.4.6",
"remove_dir_all",
]
[[package]]
name = "tempfile"
version = "3.3.0"
@ -2732,6 +2837,25 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "termcolor"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
dependencies = [
"winapi-util",
]
[[package]]
name = "test-cert-gen"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3208d0ae2e3736d4ac2f6ba2229c4d9bbd54080e228e662a7684eabcf13ff419"
dependencies = [
"pem",
"tempdir",
]
[[package]]
name = "textwrap"
version = "0.11.0"
@ -2804,6 +2928,53 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "tls-api"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7dded74ddc6d4a98f9f94f17f1c4d796e4af3cb5fba9e7655f157a036ee7de0"
dependencies = [
"anyhow",
"log",
"pem",
"tempdir",
"thiserror",
"tokio",
"void",
"webpki 0.22.0",
]
[[package]]
name = "tls-api-native-tls"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c547db405b51a4e549f803c980572f3cb3957dff153b04e3e7aebb1fc5f249b4"
dependencies = [
"anyhow",
"native-tls",
"thiserror",
"tls-api",
"tls-api-test",
"tokio",
]
[[package]]
name = "tls-api-test"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "344ab291be7ed9ab296fc28153fe3ac1e430f44c4dfb3f1324a3c09bbbb5f104"
dependencies = [
"anyhow",
"env_logger",
"log",
"pem",
"test-cert-gen",
"tls-api",
"tokio",
"untrusted 0.6.2",
"webpki 0.22.0",
]
[[package]]
name = "tokio"
version = "1.17.0"
@ -3480,6 +3651,12 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "untrusted"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f"
[[package]]
name = "untrusted"
version = "0.7.1"
@ -3532,6 +3709,12 @@ version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]]
name = "waker-fn"
version = "1.1.0"
@ -3666,7 +3849,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea"
dependencies = [
"ring",
"untrusted",
"untrusted 0.7.1",
]
[[package]]
name = "webpki"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
dependencies = [
"ring",
"untrusted 0.7.1",
]
[[package]]
@ -3792,7 +3985,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fb2bc2a902d992cd5f471ee3ab0ffd6603047a4207384562755b9d6de977518"
dependencies = [
"ring",
"untrusted",
"untrusted 0.7.1",
]
[[package]]

View File

@ -23,14 +23,16 @@ static = [ "arti-client/static" ]
experimental-api = []
[dependencies]
anyhow = "1.0.23"
arti-client = { path="../arti-client", version = "0.0.4"}
hyper = { version = "0.14", features = ["http1", "client", "runtime"] }
pin-project = "1"
tokio = { package = "tokio", version = "1.7", features = ["rt", "rt-multi-thread", "io-util", "net", "time", "macros" ] }
thiserror = "1"
tls-api = { version = "0.7" }
tls-api-native-tls = { version = "0.7.0" }
tor-error = { path="../tor-error", version = "0.0.1" }
tor-rtcompat = { path="../tor-rtcompat", version = "0.0.4", features=["tokio"] }
[dev-dependencies]
anyhow = "1.0.23"
tracing-subscriber = "0.3.0"

View File

@ -8,9 +8,7 @@ High-level layer for making http(s) requests the Tor network as a client.
Note that these APIs are NOT covered by semantic versioning guarantees:
we might break them or remove them between patch versions.
`error_detail` -- Make the `TorError` type transparent, and expose the `Error` within.
Note that the resulting APIs are not stable.
`native-tls` (default), `rustls` -- Select TLS libraries to support.
`native-tls` (default), `rustls` -- Select TLS libraries to use for Tor's purposes.
(The end-to-end TLS to the origin server is separate, and handled via `tls-api`.)
License: MIT OR Apache-2.0

View File

@ -1,10 +1,10 @@
/// TODO this ought to support https!
use arti_hyper::*;
use anyhow::Result;
use arti_client::{TorClient, TorClientConfig};
use hyper::Body;
use std::convert::TryInto;
use tls_api::{TlsConnector, TlsConnectorBuilder};
use tor_rtcompat::tokio::TokioNativeTlsRuntime;
#[tokio::main]
@ -34,8 +34,10 @@ async fn main() -> Result<()> {
// (This takes a while to gather the necessary consensus state, etc.)
let tor_client = TorClient::create_bootstrapped(rt, config).await?;
let tls_connector = tls_api_native_tls::TlsConnector::builder()?.build()?;
// The `ArtiHttpConnector` lets us make HTTP requests via the Tor network.
let tor_connector = ArtiHttpConnector::new(tor_client);
let tor_connector = ArtiHttpConnector::new(tor_client, tls_connector);
let http = hyper::Client::builder().build::<_, Body>(tor_connector);
// The rest is just standard usage of Hyper.

View File

@ -1,7 +1,4 @@
//! High-level layer for making http(s) requests the Tor network as a client.
//!
//! Work-in-progress.
//! This is **not suitable for use** right now because it does not support HTTPs.
#![deny(missing_docs)]
#![warn(noop_method_call)]
@ -11,7 +8,6 @@
#![deny(clippy::cargo_common_metadata)]
#![deny(clippy::cast_lossless)]
#![deny(clippy::checked_conversions)]
#![warn(clippy::clone_on_ref_ptr)]
#![warn(clippy::cognitive_complexity)]
#![deny(clippy::debug_assert_with_mut_call)]
#![deny(clippy::exhaustive_enums)]
@ -37,6 +33,7 @@
use std::future::Future;
use std::io::Error;
use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll};
use arti_client::{DataStream, IntoTorAddr, TorClient};
@ -46,6 +43,7 @@ use hyper::http::Uri;
use hyper::service::Service;
use pin_project::pin_project;
use thiserror::Error;
use tls_api::TlsConnector as TlsConn; // This is different from tor_rtompat::TlsConnector
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
use tor_rtcompat::Runtime;
@ -62,7 +60,7 @@ pub enum ConnectionError {
uri: Uri,
},
/// Unsupported URI scheme
/// Missing hostname
#[error("Missing hostname in {uri:?}")]
MissingHostname {
/// URI
@ -72,6 +70,10 @@ pub enum ConnectionError {
/// Tor connection failed
#[error("Tor connection failed")]
Arti(#[from] arti_client::Error),
/// TLS connection failed
#[error("TLS connection failed")]
TLS(#[source] Arc<anyhow::Error>),
}
/// We implement this for form's sake
@ -83,7 +85,8 @@ impl tor_error::HasKind for ConnectionError {
match self {
CE::UnsupportedUriScheme{..} => EK::NotImplemented,
CE::MissingHostname{..} => EK::BadApiUsage,
CE::Arti(e) => e.kind(),
CE::Arti(e) => e.kind(),
CE::TLS(_) => EK::RemoteProtocolFailed,
}
}
}
@ -91,29 +94,56 @@ impl tor_error::HasKind for ConnectionError {
/// A `hyper` connector to proxy HTTP connections via the Tor network, using Arti.
///
/// Only supports plaintext HTTP for now.
#[derive(Clone)]
pub struct ArtiHttpConnector<R: Runtime> {
///
/// TC is the TLS to used *across* Tor to connect to the origin server.
/// This is a different Rust type to the TLS used *by* Tor to connect to relays etc.
/// It might even be a different underlying TLS implementation
/// (although that is usually not a particularly good idea).
pub struct ArtiHttpConnector<R: Runtime, TC: TlsConn> {
/// The client
client: TorClient<R>,
/// TLS for using across Tor.
tls_conn: Arc<TC>,
}
impl<R: Runtime> ArtiHttpConnector<R> {
// #[derive(Clone)] infers a TC: Clone bound
impl<R: Runtime, TC: TlsConn> Clone for ArtiHttpConnector<R, TC> {
fn clone(&self) -> Self {
let client = self.client.clone();
let tls_conn = self.tls_conn.clone();
Self { client, tls_conn }
}
}
impl<R: Runtime, TC: TlsConn> ArtiHttpConnector<R, TC> {
/// Make a new `ArtiHttpConnector` using an Arti `TorClient` object.
pub fn new(client: TorClient<R>) -> Self {
Self { client }
pub fn new(client: TorClient<R>, tls_conn: TC) -> Self {
let tls_conn = tls_conn.into();
Self { client, tls_conn }
}
}
/// Wrapper type that makes an Arti `DataStream` implement necessary traits to be used as
/// a `hyper` connection object (mainly `Connection`).
#[pin_project]
pub struct ArtiHttpConnection {
pub struct ArtiHttpConnection<TC: TlsConn> {
/// The stream
#[pin]
inner: DataStream,
inner: MaybeHttpsStream<TC>,
}
impl Connection for ArtiHttpConnection {
/// The actual actual stream; might be TLS, might not
#[pin_project(project = MaybeHttpsStreamProj)]
enum MaybeHttpsStream<TC: TlsConn> {
/// http
Http(Pin<Box<DataStream>>), // Tc:TlsStream is generally boxed; box this one too
/// https
Https(#[pin] TC::TlsStream),
}
impl<TC: TlsConn> Connection for ArtiHttpConnection<TC> {
fn connected(&self) -> Connected {
Connected::new()
}
@ -121,50 +151,83 @@ impl Connection for ArtiHttpConnection {
// These trait implementations just defer to the inner `DataStream`; the wrapper type is just
// there to implement the `Connection` trait.
impl AsyncRead for ArtiHttpConnection {
impl<TC: TlsConn> AsyncRead for ArtiHttpConnection<TC> {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<Result<(), std::io::Error>> {
self.project().inner.poll_read(cx, buf)
match self.project().inner.project() {
MaybeHttpsStreamProj::Http(ds) => ds.as_mut().poll_read(cx, buf),
MaybeHttpsStreamProj::Https(t) => t.poll_read(cx, buf),
}
}
}
impl AsyncWrite for ArtiHttpConnection {
impl<TC: TlsConn> AsyncWrite for ArtiHttpConnection<TC> {
fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<Result<usize, Error>> {
self.project().inner.poll_write(cx, buf)
match self.project().inner.project() {
MaybeHttpsStreamProj::Http(ds) => ds.as_mut().poll_write(cx, buf),
MaybeHttpsStreamProj::Https(t) => t.poll_write(cx, buf),
}
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
self.project().inner.poll_flush(cx)
match self.project().inner.project() {
MaybeHttpsStreamProj::Http(ds) => ds.as_mut().poll_flush(cx),
MaybeHttpsStreamProj::Https(t) => t.poll_flush(cx),
}
}
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
self.project().inner.poll_shutdown(cx)
match self.project().inner.project() {
MaybeHttpsStreamProj::Http(ds) => ds.as_mut().poll_shutdown(cx),
MaybeHttpsStreamProj::Https(t) => t.poll_shutdown(cx),
}
}
}
/// Convert uri to host and port
fn uri_to_host_port(uri: Uri) -> Result<(String, u16), ConnectionError> {
if uri.scheme() != Some(&Scheme::HTTP) {
return Err(ConnectionError::UnsupportedUriScheme { uri });
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
/// Are we doing TLS?
enum UseTls {
/// No
Bare,
/// Yes
Tls,
}
/// Convert uri to http[s] host and port, and whether to do tls
fn uri_to_host_port_tls(uri: Uri) -> Result<(String, u16, UseTls), ConnectionError> {
let use_tls = {
// Scheme doesn't derive PartialEq so can't be matched on
let scheme = uri.scheme();
if scheme == Some(&Scheme::HTTP) {
UseTls::Bare
} else if scheme == Some(&Scheme::HTTPS) {
UseTls::Tls
} else {
return Err(ConnectionError::UnsupportedUriScheme { uri });
}
};
let host = match uri.host() {
Some(h) => h,
_ => return Err(ConnectionError::MissingHostname { uri }),
};
let port = uri.port().map(|x| x.as_u16()).unwrap_or(80);
let port = uri.port().map(|x| x.as_u16()).unwrap_or(match use_tls {
UseTls::Tls => 443,
UseTls::Bare => 80,
});
Ok((host.to_owned(), port))
Ok((host.to_owned(), port, use_tls))
}
impl<R: Runtime> Service<Uri> for ArtiHttpConnector<R> {
type Response = ArtiHttpConnection;
impl<R: Runtime, TC: TlsConn> Service<Uri> for ArtiHttpConnector<R, TC> {
type Response = ArtiHttpConnection<TC>;
type Error = ConnectionError;
#[allow(clippy::type_complexity)]
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
@ -178,15 +241,28 @@ impl<R: Runtime> Service<Uri> for ArtiHttpConnector<R> {
// underlying handles required to make Tor connections internally).
// We use this to avoid the returned future having to borrow `self`.
let client = self.client.clone();
let tls_conn = self.tls_conn.clone();
Box::pin(async move {
// Extract the host and port to connect to from the URI.
let (host, port) = uri_to_host_port(req)?;
let (host, port, use_tls) = uri_to_host_port_tls(req)?;
// Initiate a new Tor connection, producing a `DataStream` if successful.
let addr = (&host as &str, port)
.into_tor_addr()
.map_err(arti_client::Error::from)?;
let ds = client.connect(addr).await?;
Ok(ArtiHttpConnection { inner: ds })
let inner = match use_tls {
UseTls::Tls => {
let conn = tls_conn
.connect_impl_tls_stream(&host, ds)
.await
.map_err(|e| ConnectionError::TLS(e.into()))?;
MaybeHttpsStream::Https(conn)
}
UseTls::Bare => MaybeHttpsStream::Http(Box::new(ds).into()),
};
Ok(ArtiHttpConnection { inner })
})
}
}

View File

@ -936,7 +936,56 @@ impl<B: AbstractCircBuilder + 'static, R: Runtime> AbstractCircMgr<B, R> {
let mut retry_error = RetryError::in_attempt_to("wait for circuits");
while let Some((src, id)) = incoming.next().await {
let id = match id {
match id {
Ok(Ok(ref id)) => {
// Great, we have a circuit. See if we can use it!
let mut list = self.circs.lock().expect("poisoned lock");
if let Some(ent) = list.get_open_mut(id) {
let now = self.runtime.now();
match ent.restrict_mut(usage, now) {
Ok(()) => {
// Great, this will work. We drop the
// pending request now explicitly to remove
// it from the list.
drop(pending_request);
if matches!(ent.expiration, ExpirationInfo::Unused { .. }) {
// Since this circuit hasn't been used yet, schedule expiration task after `max_dirtiness` from now.
spawn_expiration_task(
&self.runtime,
Arc::downgrade(&self),
ent.circ.id(),
now + self.circuit_timing().max_dirtiness,
);
}
return Ok(ent.circ.clone());
}
Err(e) => {
// TODO: as below, improve this log message.
if src == streams::Source::Left {
info!(
"{:?} suggested we use {:?}, but restrictions failed: {:?}",
src, id, &e
);
} else {
debug!(
"{:?} suggested we use {:?}, but restrictions failed: {:?}",
src, id, &e
);
}
if src == streams::Source::Left {
retry_error.push(e);
}
continue;
}
}
}
}
Ok(Err(ref e)) => {
debug!("{:?} sent error {:?}", src, e);
if src == streams::Source::Left {
retry_error.push(e.clone());
}
}
Err(oneshot::Canceled) => {
debug!(
"{:?} went away (Canceled), quitting take_action right away",
@ -945,50 +994,6 @@ impl<B: AbstractCircBuilder + 'static, R: Runtime> AbstractCircMgr<B, R> {
retry_error.push(Error::PendingCanceled);
return Err(retry_error);
}
Ok(id) => id,
};
if let Ok(ref id) = id {
// Great, we have a circuit. See if we can use it!
let mut list = self.circs.lock().expect("poisoned lock");
if let Some(ent) = list.get_open_mut(id) {
let now = self.runtime.now();
match ent.restrict_mut(usage, now) {
Ok(()) => {
// Great, this will work. We drop the
// pending request now explicitly to remove
// it from the list.
drop(pending_request);
if matches!(ent.expiration, ExpirationInfo::Unused { .. }) {
// Since this circuit hasn't been used yet, schedule expiration task after `max_dirtiness` from now.
spawn_expiration_task(
&self.runtime,
Arc::downgrade(&self),
ent.circ.id(),
now + self.circuit_timing().max_dirtiness,
);
}
return Ok(ent.circ.clone());
}
Err(e) => {
// TODO: as below, improve this log message.
if src == streams::Source::Left {
info!(
"{:?} suggested we use {:?}, but restrictions failed: {:?}",
src, id, &e
);
} else {
debug!(
"{:?} suggested we use {:?}, but restrictions failed: {:?}",
src, id, &e
);
}
if src == streams::Source::Left {
retry_error.push(e);
}
continue;
}
}
}
}
// TODO: Improve this log message; using :? here will make it

View File

@ -424,6 +424,23 @@ pub enum ErrorKind {
#[display(fmt = "remote hostname lookup failure")]
RemoteHostNotFound,
/// Trouble involving a protocol we're using with a peer on the far side of the Tor network
///
/// We were using a higher-layer protocol over a Tor connection,
/// and something went wrong.
/// This might be an error reported by the remote host within that higher protocol,
/// or a problem detected locally but relating to that higher protocol.
///
/// The nature of the problem can vary:
/// examples could include:
/// failure to agree suitable parameters (incompatibility);
/// authentication problems (eg, TLS certificate trouble);
/// protocol violation by the peer;
/// peer refusing to provide service;
/// etc.
#[display(fmt = "remote protocol failed")]
RemoteProtocolFailed,
/// An operation failed, and the relay in question reported that it's too
/// busy to answer our request.
#[display(fmt = "relay too busy")]

View File

@ -9,4 +9,7 @@ cargo +nightly update -Z minimal-versions
cargo update \
-p crc32fast \
-p quote:0.6.3 \
-p synstructure:0.12.0
-p zeroize_derive:1.1.1 \
-p env_logger:0.5.0 \
-p synstructure:0.12.0 \
-p nix:0.4.2