use itertools::Itertools as _;
use tor_linkspec::{
ChanTarget, CircTarget, HasAddrs, HasChanMethod, HasRelayIds, RelayIdRef, RelayIdType,
};
use super::{BridgeConfig, BridgeDesc};
#[derive(Clone, Debug)]
pub struct BridgeRelay<'a> {
bridge_line: &'a BridgeConfig,
desc: Option<BridgeDesc>,
addrs: Vec<std::net::SocketAddr>,
}
#[derive(Clone, Debug)]
pub struct BridgeRelayWithDesc<'a>(
&'a BridgeRelay<'a>,
);
impl<'a> BridgeRelay<'a> {
pub(crate) fn new(bridge_line: &'a BridgeConfig, desc: Option<BridgeDesc>) -> Self {
let addrs = bridge_line
.addrs()
.chain(desc.iter().flat_map(|d| d.as_ref().or_ports()))
.unique()
.collect();
Self {
bridge_line,
desc,
addrs,
}
}
pub fn has_descriptor(&self) -> bool {
self.desc.is_some()
}
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> {
fn addrs(&self) -> impl Iterator<Item = std::net::SocketAddr> {
self.addrs.iter().copied()
}
}
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> {
fn addrs(&self) -> impl Iterator<Item = 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> {
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()
}
}