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 .iter()
58 .copied()
59 .chain(desc.iter().flat_map(|d| d.as_ref().or_ports()))
60 .unique()
61 .collect();
62
63 Self {
64 bridge_line,
65 desc,
66 addrs,
67 }
68 }
69
70 /// Return true if this BridgeRelay has a known descriptor and can be used for relays.
71 pub fn has_descriptor(&self) -> bool {
72 self.desc.is_some()
73 }
74
75 /// If we have enough information about this relay to build a circuit through it,
76 /// return a BridgeRelayWithDesc for it.
77 pub fn as_relay_with_desc(&self) -> Option<BridgeRelayWithDesc<'_>> {
78 self.desc.is_some().then_some(BridgeRelayWithDesc(self))
79 }
80}
81
82impl<'a> HasRelayIds for BridgeRelay<'a> {
83 fn identity(&self, key_type: RelayIdType) -> Option<RelayIdRef<'_>> {
84 self.bridge_line
85 .identity(key_type)
86 .or_else(|| self.desc.as_ref().and_then(|d| d.identity(key_type)))
87 }
88}
89
90impl<'a> HasAddrs for BridgeRelay<'a> {
91 /// Note: Remember (from the documentation at [`HasAddrs`]) that these are
92 /// not necessarily addresses _at which the Bridge can be reached_. For
93 /// those, use `chan_method`. These addresses are used for establishing
94 /// GeoIp and family info.
95 fn addrs(&self) -> &[std::net::SocketAddr] {
96 &self.addrs[..]
97 }
98}
99
100impl<'a> HasChanMethod for BridgeRelay<'a> {
101 fn chan_method(&self) -> tor_linkspec::ChannelMethod {
102 self.bridge_line.chan_method()
103 }
104}
105
106impl<'a> ChanTarget for BridgeRelay<'a> {}
107
108impl<'a> HasRelayIds for BridgeRelayWithDesc<'a> {
109 fn identity(&self, key_type: RelayIdType) -> Option<RelayIdRef<'_>> {
110 self.0.identity(key_type)
111 }
112}
113impl<'a> HasAddrs for BridgeRelayWithDesc<'a> {
114 /// Note: Remember (from the documentation at [`HasAddrs`]) that these are
115 /// not necessarily addresses _at which the Bridge can be reached_. For
116 /// those, use `chan_method`. These addresses are used for establishing
117 /// GeoIp and family info.
118 fn addrs(&self) -> &[std::net::SocketAddr] {
119 self.0.addrs()
120 }
121}
122impl<'a> HasChanMethod for BridgeRelayWithDesc<'a> {
123 fn chan_method(&self) -> tor_linkspec::ChannelMethod {
124 self.0.chan_method()
125 }
126}
127
128impl<'a> ChanTarget for BridgeRelayWithDesc<'a> {}
129
130impl<'a> BridgeRelayWithDesc<'a> {
131 /// Return a reference to the BridgeDesc in this reference.
132 fn desc(&self) -> &BridgeDesc {
133 self.0
134 .desc
135 .as_ref()
136 .expect("There was supposed to be a descriptor here")
137 }
138}
139
140impl<'a> CircTarget for BridgeRelayWithDesc<'a> {
141 fn ntor_onion_key(&self) -> &tor_llcrypto::pk::curve25519::PublicKey {
142 self.desc().as_ref().ntor_onion_key()
143 }
144
145 fn protovers(&self) -> &tor_protover::Protocols {
146 self.desc().as_ref().protocols()
147 }
148}