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}