1
//! Implementation code to make a bridge something that we can connect to and use to relay traffic.
2

            
3
use itertools::Itertools as _;
4
use tor_linkspec::{
5
    ChanTarget, CircTarget, HasAddrs, HasChanMethod, HasRelayIds, RelayIdRef, RelayIdType,
6
};
7

            
8
use 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)]
13
pub 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)]
47
pub struct BridgeRelayWithDesc<'a>(
48
    /// This will _always_ be a bridge relay with a non-None desc.
49
    &'a BridgeRelay<'a>,
50
);
51

            
52
impl<'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

            
80
impl<'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

            
88
impl<'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

            
98
impl<'a> HasChanMethod for BridgeRelay<'a> {
99
    fn chan_method(&self) -> tor_linkspec::ChannelMethod {
100
        self.bridge_line.chan_method()
101
    }
102
}
103

            
104
impl<'a> ChanTarget for BridgeRelay<'a> {}
105

            
106
impl<'a> HasRelayIds for BridgeRelayWithDesc<'a> {
107
    fn identity(&self, key_type: RelayIdType) -> Option<RelayIdRef<'_>> {
108
        self.0.identity(key_type)
109
    }
110
}
111
impl<'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
}
120
impl<'a> HasChanMethod for BridgeRelayWithDesc<'a> {
121
    fn chan_method(&self) -> tor_linkspec::ChannelMethod {
122
        self.0.chan_method()
123
    }
124
}
125

            
126
impl<'a> ChanTarget for BridgeRelayWithDesc<'a> {}
127

            
128
impl<'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

            
138
impl<'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
}