Skip to main content

tor_guardmgr/bridge/
relay.rs

1//! Implementation code to make a bridge something that we can connect to and use to relay traffic.
2
3use itertools::Itertools as _;
4use tor_linkspec::{
5    ChanTarget, CircTarget, HasAddrs, HasChanMethod, HasRelayIds, RelayIdRef, RelayIdType,
6};
7
8use super::{BridgeConfig, BridgeDesc};
9
10/// The information about a Bridge that is necessary to connect to it and send
11/// it traffic.
12#[derive(Clone, Debug)]
13pub struct BridgeRelay<'a> {
14    /// The local configurations for the bridge.
15    ///
16    /// This is _always_ necessary, since it without it we can't know whether
17    /// any pluggable transports are needed.
18    bridge_line: &'a BridgeConfig,
19
20    /// A descriptor for the bridge.
21    ///
22    /// If present, it MUST have every RelayId that the `bridge_line` does.
23    ///
24    /// `BridgeDesc` is an `Arc<>` internally, so we aren't so worried about
25    /// having this be owned.
26    desc: Option<BridgeDesc>,
27
28    /// All the known addresses for the bridge.
29    ///
30    /// This includes the contact addresses in `bridge_line`, plus any addresses
31    /// listed in `desc`.
32    ///
33    /// TODO(nickm): I wish we didn't have to reallocate a for this, but the API
34    /// requires that we can return a reference to a slice of this.
35    ///
36    /// TODO(nickm): perhaps, construct this lazily?
37    addrs: Vec<std::net::SocketAddr>,
38}
39
40/// A BridgeRelay that is known to have its full information available, and
41/// which is therefore usable for multi-hop circuits.
42///
43/// (All bridges can be used for single-hop circuits, but we need to know the
44/// bridge's descriptor in order to construct proper multi-hop circuits
45/// with forward secrecy through it.)
46#[derive(Clone, Debug)]
47pub struct BridgeRelayWithDesc<'a>(
48    /// This will _always_ be a bridge relay with a non-None desc.
49    &'a BridgeRelay<'a>,
50);
51
52impl<'a> BridgeRelay<'a> {
53    /// Construct a new BridgeRelay from its parts.
54    pub(crate) fn new(bridge_line: &'a BridgeConfig, desc: Option<BridgeDesc>) -> Self {
55        let addrs = bridge_line
56            .addrs()
57            .chain(desc.iter().flat_map(|d| d.as_ref().or_ports()))
58            .unique()
59            .collect();
60
61        Self {
62            bridge_line,
63            desc,
64            addrs,
65        }
66    }
67
68    /// Return true if this BridgeRelay has a known descriptor and can be used for relays.
69    pub fn has_descriptor(&self) -> bool {
70        self.desc.is_some()
71    }
72
73    /// If we have enough information about this relay to build a circuit through it,
74    /// return a BridgeRelayWithDesc for it.
75    pub fn as_relay_with_desc(&self) -> Option<BridgeRelayWithDesc<'_>> {
76        self.desc.is_some().then_some(BridgeRelayWithDesc(self))
77    }
78}
79
80impl<'a> HasRelayIds for BridgeRelay<'a> {
81    fn identity(&self, key_type: RelayIdType) -> Option<RelayIdRef<'_>> {
82        self.bridge_line
83            .identity(key_type)
84            .or_else(|| self.desc.as_ref().and_then(|d| d.identity(key_type)))
85    }
86}
87
88impl<'a> HasAddrs for BridgeRelay<'a> {
89    /// Note: Remember (from the documentation at [`HasAddrs`]) that these are
90    /// not necessarily addresses _at which the Bridge can be reached_. For
91    /// those, use `chan_method`.  These addresses are used for establishing
92    /// GeoIp and family info.
93    fn addrs(&self) -> impl Iterator<Item = std::net::SocketAddr> {
94        self.addrs.iter().copied()
95    }
96}
97
98impl<'a> HasChanMethod for BridgeRelay<'a> {
99    fn chan_method(&self) -> tor_linkspec::ChannelMethod {
100        self.bridge_line.chan_method()
101    }
102}
103
104impl<'a> ChanTarget for BridgeRelay<'a> {}
105
106impl<'a> HasRelayIds for BridgeRelayWithDesc<'a> {
107    fn identity(&self, key_type: RelayIdType) -> Option<RelayIdRef<'_>> {
108        self.0.identity(key_type)
109    }
110}
111impl<'a> HasAddrs for BridgeRelayWithDesc<'a> {
112    /// Note: Remember (from the documentation at [`HasAddrs`]) that these are
113    /// not necessarily addresses _at which the Bridge can be reached_. For
114    /// those, use `chan_method`.  These addresses are used for establishing
115    /// GeoIp and family info.
116    fn addrs(&self) -> impl Iterator<Item = std::net::SocketAddr> {
117        self.0.addrs()
118    }
119}
120impl<'a> HasChanMethod for BridgeRelayWithDesc<'a> {
121    fn chan_method(&self) -> tor_linkspec::ChannelMethod {
122        self.0.chan_method()
123    }
124}
125
126impl<'a> ChanTarget for BridgeRelayWithDesc<'a> {}
127
128impl<'a> BridgeRelayWithDesc<'a> {
129    /// Return a reference to the BridgeDesc in this reference.
130    fn desc(&self) -> &BridgeDesc {
131        self.0
132            .desc
133            .as_ref()
134            .expect("There was supposed to be a descriptor here")
135    }
136}
137
138impl<'a> CircTarget for BridgeRelayWithDesc<'a> {
139    fn ntor_onion_key(&self) -> &tor_llcrypto::pk::curve25519::PublicKey {
140        self.desc().as_ref().ntor_onion_key()
141    }
142
143    fn protovers(&self) -> &tor_protover::Protocols {
144        self.desc().as_ref().protocols()
145    }
146}