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
//! Declare the TargetPort type.
use serde::{Deserialize, Serialize};
use std::fmt;
/// A port that we want to connect to as a client.
///
/// Ordinarily, this is a TCP port, plus a flag to indicate whether we
/// must support IPv4 or IPv6.
#[derive(
Clone, Copy, Debug, Deserialize, Eq, PartialEq, Hash, PartialOrd, Ord, Serialize, Default,
)]
#[non_exhaustive]
pub struct TargetPort {
/// True if this is a request to connect to an IPv6 address
pub ipv6: bool,
/// The port that the client wants to connect to
pub port: u16,
}
impl TargetPort {
/// Create a request to make sure that a circuit supports a given
/// ipv4 exit port.
pub fn ipv4(port: u16) -> TargetPort {
TargetPort { ipv6: false, port }
}
/// Create a request to make sure that a circuit supports a given
/// ipv6 exit port.
pub fn ipv6(port: u16) -> TargetPort {
TargetPort { ipv6: true, port }
}
/// Return true if this port is supported by the provided Relay.
pub fn is_supported_by(&self, r: &tor_netdir::details::RelayDetails<'_>) -> bool {
if self.ipv6 {
r.supports_exit_port_ipv6(self.port)
} else {
r.supports_exit_port_ipv4(self.port)
}
}
}
impl fmt::Display for TargetPort {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}{}", self.port, if self.ipv6 { "v6" } else { "v4" })
}
}