diff --git a/Cargo.lock b/Cargo.lock index 0d127880f..edbc6657a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3704,6 +3704,7 @@ dependencies = [ "tor-netdoc", "tor-persist", "tor-proto", + "tor-protover", "tor-rtcompat", "tor-rtmock", "tor-units", diff --git a/crates/tor-guardmgr/Cargo.toml b/crates/tor-guardmgr/Cargo.toml index 34d5de39c..bae11c1bc 100644 --- a/crates/tor-guardmgr/Cargo.toml +++ b/crates/tor-guardmgr/Cargo.toml @@ -19,7 +19,7 @@ experimental = ["bridge-client"] # Support for using bridges as a client. Note that this is not the same as # the pt-client feature, since here we are not concerned with # pluggable transports necessarily. -bridge-client = ["tor-netdoc/routerdesc"] +bridge-client = ["tor-netdoc/routerdesc", "tor-protover"] # Support for pluggable transports. pt-client = ["bridge-client", "tor-linkspec/pt-client"] @@ -51,6 +51,7 @@ tor-netdir = { path = "../tor-netdir", version = "0.6.0" } tor-netdoc = { path = "../tor-netdoc", version = "0.5.2" } # for address pattern tor-persist = { path = "../tor-persist", version = "0.5.1" } tor-proto = { path = "../tor-proto", version = "0.7.0" } +tor-protover = { path = "../tor-protover", version = "0.3.2", optional = true } tor-rtcompat = { path = "../tor-rtcompat", version = "0.7.0" } tor-units = { path = "../tor-units", version = "0.3.1" } tracing = "0.1.18" diff --git a/crates/tor-guardmgr/src/bridge/relay.rs b/crates/tor-guardmgr/src/bridge/relay.rs index 21b1cfb41..dea6d6571 100644 --- a/crates/tor-guardmgr/src/bridge/relay.rs +++ b/crates/tor-guardmgr/src/bridge/relay.rs @@ -2,7 +2,7 @@ use std::sync::Arc; -use tor_linkspec::{HasRelayIds, RelayIdRef, RelayIdType}; +use tor_linkspec::{ChanTarget, CircTarget, HasAddrs, HasRelayIds, RelayIdRef, RelayIdType}; use super::{Bridge, BridgeDesc}; @@ -22,11 +22,26 @@ pub struct BridgeRelay { desc: Option, } +/// A BridgeRelay that is known to have its full information available, and +/// which is therefore usable for circuits. +#[derive(Clone, Debug)] +pub struct BridgeRelayWithDesc<'a>( + /// This will _always_ be a bridge relay with a non-None desc. + &'a BridgeRelay, +); + impl BridgeRelay { /// Return true if this BridgeRelay has a known descriptor and can be used for relays. pub fn has_descriptor(&self) -> bool { self.desc.is_some() } + + /// If we have enough information about this relay to build a circuit through it, + /// return a BridgeRelayWithDesc for it. + // TODO pt-client rename XXXX + pub fn for_circuit_usage(&self) -> Option> { + self.desc.is_some().then(|| BridgeRelayWithDesc(self)) + } } impl HasRelayIds for BridgeRelay { @@ -36,3 +51,43 @@ impl HasRelayIds for BridgeRelay { .or_else(|| self.desc.as_ref().and_then(|d| d.identity(key_type))) } } + +impl HasAddrs for BridgeRelay { + fn addrs(&self) -> &[std::net::SocketAddr] { + todo!() + } +} + +impl ChanTarget for BridgeRelay {} + +impl<'a> HasRelayIds for BridgeRelayWithDesc<'a> { + fn identity(&self, key_type: RelayIdType) -> Option> { + self.0.identity(key_type) + } +} +impl<'a> HasAddrs for BridgeRelayWithDesc<'a> { + fn addrs(&self) -> &[std::net::SocketAddr] { + self.0.addrs() + } +} +impl<'a> ChanTarget for BridgeRelayWithDesc<'a> {} + +impl<'a> BridgeRelayWithDesc<'a> { + /// Return a reference to the BridgeDesc in this reference. + fn desc(&self) -> &BridgeDesc { + self.0 + .desc + .as_ref() + .expect("There was supposed to be a descriptor here") + } +} + +impl<'a> CircTarget for BridgeRelayWithDesc<'a> { + fn ntor_onion_key(&self) -> &tor_llcrypto::pk::curve25519::PublicKey { + self.desc().as_ref().ntor_onion_key() + } + + fn protovers(&self) -> &tor_protover::Protocols { + self.desc().as_ref().protocols() + } +}