Lines
0 %
Functions
Branches
100 %
//! Implementation code to make a bridge something that we can connect to and use to relay traffic.
use itertools::Itertools as _;
use tor_linkspec::{
ChanTarget, CircTarget, HasAddrs, HasChanMethod, HasRelayIds, RelayIdRef, RelayIdType,
};
use super::{BridgeConfig, BridgeDesc};
/// The information about a Bridge that is necessary to connect to it and send
/// it traffic.
#[derive(Clone, Debug)]
pub struct BridgeRelay<'a> {
/// The local configurations for the bridge.
///
/// This is _always_ necessary, since it without it we can't know whether
/// any pluggable transports are needed.
bridge_line: &'a BridgeConfig,
/// A descriptor for the bridge.
/// If present, it MUST have every RelayId that the `bridge_line` does.
/// `BridgeDesc` is an `Arc<>` internally, so we aren't so worried about
/// having this be owned.
desc: Option<BridgeDesc>,
/// All the known addresses for the bridge.
/// This includes the contact addresses in `bridge_line`, plus any addresses
/// listed in `desc`.
/// TODO(nickm): I wish we didn't have to reallocate a for this, but the API
/// requires that we can return a reference to a slice of this.
/// TODO(nickm): perhaps, construct this lazily?
addrs: Vec<std::net::SocketAddr>,
}
/// A BridgeRelay that is known to have its full information available, and
/// which is therefore usable for multi-hop circuits.
/// (All bridges can be used for single-hop circuits, but we need to know the
/// bridge's descriptor in order to construct proper multi-hop circuits
/// with forward secrecy through it.)
pub struct BridgeRelayWithDesc<'a>(
/// This will _always_ be a bridge relay with a non-None desc.
&'a BridgeRelay<'a>,
);
impl<'a> BridgeRelay<'a> {
/// Construct a new BridgeRelay from its parts.
pub(crate) fn new(bridge_line: &'a BridgeConfig, desc: Option<BridgeDesc>) -> Self {
let addrs = bridge_line
.addrs()
.iter()
.copied()
.chain(desc.iter().flat_map(|d| d.as_ref().or_ports()))
.unique()
.collect();
Self {
bridge_line,
desc,
addrs,
/// 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.
pub fn as_relay_with_desc(&self) -> Option<BridgeRelayWithDesc<'_>> {
self.desc.is_some().then_some(BridgeRelayWithDesc(self))
impl<'a> HasRelayIds for BridgeRelay<'a> {
fn identity(&self, key_type: RelayIdType) -> Option<RelayIdRef<'_>> {
self.bridge_line
.identity(key_type)
.or_else(|| self.desc.as_ref().and_then(|d| d.identity(key_type)))
impl<'a> HasAddrs for BridgeRelay<'a> {
/// Note: Remember (from the documentation at [`HasAddrs`]) that these are
/// not necessarily addresses _at which the Bridge can be reached_. For
/// those, use `chan_method`. These addresses are used for establishing
/// GeoIp and family info.
fn addrs(&self) -> &[std::net::SocketAddr] {
&self.addrs[..]
impl<'a> HasChanMethod for BridgeRelay<'a> {
fn chan_method(&self) -> tor_linkspec::ChannelMethod {
self.bridge_line.chan_method()
impl<'a> ChanTarget for BridgeRelay<'a> {}
impl<'a> HasRelayIds for BridgeRelayWithDesc<'a> {
self.0.identity(key_type)
impl<'a> HasAddrs for BridgeRelayWithDesc<'a> {
self.0.addrs()
impl<'a> HasChanMethod for BridgeRelayWithDesc<'a> {
self.0.chan_method()
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()