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
            .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

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

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

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

            
106
impl<'a> ChanTarget for BridgeRelay<'a> {}
107

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

            
128
impl<'a> ChanTarget for BridgeRelayWithDesc<'a> {}
129

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

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