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