udp: New AddressPort used in cells
Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
parent
a591bf353a
commit
3da4b95434
|
@ -10,8 +10,55 @@ use std::str::FromStr;
|
||||||
use tor_bytes::{Error, Result};
|
use tor_bytes::{Error, Result};
|
||||||
use tor_bytes::{Readable, Reader, Writeable, Writer};
|
use tor_bytes::{Readable, Reader, Writeable, Writer};
|
||||||
|
|
||||||
|
/// Indicates the payload is a hostname.
|
||||||
|
const T_HOSTNAME: u8 = 0x01;
|
||||||
|
/// Indicates the payload is an IPv4.
|
||||||
|
const T_IPV4: u8 = 0x04;
|
||||||
|
/// Indicates the payload is an IPv6.
|
||||||
|
const T_IPV6: u8 = 0x06;
|
||||||
|
|
||||||
|
/// Maximum length of an Address::Hostname set at 255.
|
||||||
|
const MAX_HOSTNAME_LEN: usize = u8::MAX as usize;
|
||||||
|
|
||||||
/// Address contained in a ConnectUdp and ConnectedUdp cell which can
|
/// Address contained in a ConnectUdp and ConnectedUdp cell which can
|
||||||
/// represent a hostname, IPv4 or IPv6.
|
/// represent a hostname, IPv4 or IPv6 along a port number.
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub struct AddressPort {
|
||||||
|
/// Address.
|
||||||
|
addr: Address,
|
||||||
|
/// Port.
|
||||||
|
port: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Readable for AddressPort {
|
||||||
|
fn take_from(r: &mut Reader<'_>) -> Result<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
addr: r.extract()?,
|
||||||
|
port: r.take_u16()?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Writeable for AddressPort {
|
||||||
|
fn write_onto<B: Writer + ?Sized>(&self, w: &mut B) {
|
||||||
|
w.write(&self.addr);
|
||||||
|
w.write_u16(self.port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<(&str, u16)> for AddressPort {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn try_from(value: (&str, u16)) -> Result<Self> {
|
||||||
|
let addr = Address::from_str(value.0)?;
|
||||||
|
Ok(Self {
|
||||||
|
addr,
|
||||||
|
port: value.1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Address representing either a hostname, IPv4 or IPv6.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub enum Address {
|
pub enum Address {
|
||||||
|
@ -23,16 +70,6 @@ pub enum Address {
|
||||||
Ipv6(Ipv6Addr),
|
Ipv6(Ipv6Addr),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Indicates the payload is a hostname.
|
|
||||||
const T_HOSTNAME: u8 = 0x01;
|
|
||||||
/// Indicates the payload is an IPv4.
|
|
||||||
const T_IPV4: u8 = 0x04;
|
|
||||||
/// Indicates the payload is an IPv6.
|
|
||||||
const T_IPV6: u8 = 0x06;
|
|
||||||
|
|
||||||
/// Maximum length of an Address::Hostname set at 255.
|
|
||||||
const MAX_HOSTNAME_LEN: usize = u8::MAX as usize;
|
|
||||||
|
|
||||||
impl Address {
|
impl Address {
|
||||||
/// Return true iff this is a Hostname.
|
/// Return true iff this is a Hostname.
|
||||||
pub fn is_hostname(&self) -> bool {
|
pub fn is_hostname(&self) -> bool {
|
||||||
|
@ -147,9 +184,7 @@ pub struct ConnectUdp {
|
||||||
/// Same as Begin flags.
|
/// Same as Begin flags.
|
||||||
flags: msg::BeginFlags,
|
flags: msg::BeginFlags,
|
||||||
/// Address to connect to. Can be Hostname, IPv4 or IPv6.
|
/// Address to connect to. Can be Hostname, IPv4 or IPv6.
|
||||||
addr: Address,
|
addr: AddressPort,
|
||||||
/// Target port
|
|
||||||
port: u16,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConnectUdp {
|
impl ConnectUdp {
|
||||||
|
@ -159,8 +194,7 @@ impl ConnectUdp {
|
||||||
F: Into<msg::BeginFlags>,
|
F: Into<msg::BeginFlags>,
|
||||||
{
|
{
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
addr: Address::from_str(addr)?,
|
addr: (addr, port).try_into()?,
|
||||||
port,
|
|
||||||
flags: flags.into(),
|
flags: flags.into(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -174,19 +208,16 @@ impl msg::Body for ConnectUdp {
|
||||||
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
|
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
|
||||||
let flags = r.take_u32()?;
|
let flags = r.take_u32()?;
|
||||||
let addr = r.extract()?;
|
let addr = r.extract()?;
|
||||||
let port = r.take_u16()?;
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
flags: flags.into(),
|
flags: flags.into(),
|
||||||
addr,
|
addr,
|
||||||
port,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_onto(self, w: &mut Vec<u8>) {
|
fn encode_onto(self, w: &mut Vec<u8>) {
|
||||||
w.write_u32(self.flags.bits());
|
w.write_u32(self.flags.bits());
|
||||||
w.write(&self.addr);
|
w.write(&self.addr);
|
||||||
w.write_u16(self.port);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,17 +226,17 @@ impl msg::Body for ConnectUdp {
|
||||||
pub struct ConnectedUdp {
|
pub struct ConnectedUdp {
|
||||||
/// The address that the relay has bound locally of a ConnectUdp. Note
|
/// The address that the relay has bound locally of a ConnectUdp. Note
|
||||||
/// that this might not be the relay address from the descriptor.
|
/// that this might not be the relay address from the descriptor.
|
||||||
our_address: Address,
|
our_address: AddressPort,
|
||||||
/// The address that the stream is connected to.
|
/// The address that the stream is connected to.
|
||||||
their_address: Address,
|
their_address: AddressPort,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConnectedUdp {
|
impl ConnectedUdp {
|
||||||
/// Construct a new ConnectedUdp cell.
|
/// Construct a new ConnectedUdp cell.
|
||||||
pub fn new(our: IpAddr, their: IpAddr) -> Result<Self> {
|
pub fn new(our_address: AddressPort, their_address: AddressPort) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
our_address: our.into(),
|
our_address,
|
||||||
their_address: their.into(),
|
their_address,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -216,12 +247,12 @@ impl msg::Body for ConnectedUdp {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
|
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
|
||||||
let our_address: Address = r.extract()?;
|
let our_address: AddressPort = r.extract()?;
|
||||||
if our_address.is_hostname() {
|
if our_address.addr.is_hostname() {
|
||||||
return Err(Error::BadMessage("Our address is a Hostname"));
|
return Err(Error::BadMessage("Our address is a Hostname"));
|
||||||
}
|
}
|
||||||
let their_address: Address = r.extract()?;
|
let their_address: AddressPort = r.extract()?;
|
||||||
if their_address.is_hostname() {
|
if their_address.addr.is_hostname() {
|
||||||
return Err(Error::BadMessage("Their address is a Hostname"));
|
return Err(Error::BadMessage("Their address is a Hostname"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,6 @@ use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||||
|
|
||||||
use hex_literal::hex;
|
use hex_literal::hex;
|
||||||
|
|
||||||
#[cfg(feature = "experimental-udp")]
|
|
||||||
use std::str::FromStr;
|
|
||||||
#[cfg(feature = "experimental-udp")]
|
#[cfg(feature = "experimental-udp")]
|
||||||
use tor_cell::relaycell::udp;
|
use tor_cell::relaycell::udp;
|
||||||
|
|
||||||
|
@ -576,40 +574,40 @@ fn test_connected_udp() {
|
||||||
let cmd = RelayCmd::CONNECTED_UDP;
|
let cmd = RelayCmd::CONNECTED_UDP;
|
||||||
assert_eq!(Into::<u8>::into(cmd), 17_u8);
|
assert_eq!(Into::<u8>::into(cmd), 17_u8);
|
||||||
|
|
||||||
let a_ipv4 = IpAddr::from_str("1.2.3.4").unwrap();
|
let a_ipv4 = ("1.2.3.4", 80).try_into().unwrap();
|
||||||
let b_ipv4 = IpAddr::from_str("5.6.7.8").unwrap();
|
let b_ipv4 = ("5.6.7.8", 80).try_into().unwrap();
|
||||||
|
|
||||||
let a_ipv6 = IpAddr::from_str("2600::1").unwrap();
|
let a_ipv6 = ("2600::1", 80).try_into().unwrap();
|
||||||
let b_ipv6 = IpAddr::from_str("2700::1").unwrap();
|
let b_ipv6 = ("2700::1", 80).try_into().unwrap();
|
||||||
|
|
||||||
// Valid encoded message. Generated by hand with python.
|
// Valid encoded message. Generated by hand with python.
|
||||||
msg(
|
msg(
|
||||||
cmd,
|
cmd,
|
||||||
"04 04 01020304
|
"04 04 01020304 0050
|
||||||
04 04 05060708",
|
04 04 05060708 0050",
|
||||||
&udp::ConnectedUdp::new(a_ipv4, b_ipv4).unwrap().into(),
|
&udp::ConnectedUdp::new(a_ipv4, b_ipv4).unwrap().into(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Valid encoded message. Generated by hand with python.
|
// Valid encoded message. Generated by hand with python.
|
||||||
msg(
|
msg(
|
||||||
cmd,
|
cmd,
|
||||||
"06 10 26000000000000000000000000000001
|
"06 10 26000000000000000000000000000001 0050
|
||||||
06 10 27000000000000000000000000000001",
|
06 10 27000000000000000000000000000001 0050",
|
||||||
&udp::ConnectedUdp::new(a_ipv6, b_ipv6).unwrap().into(),
|
&udp::ConnectedUdp::new(a_ipv6, b_ipv6).unwrap().into(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Invalid our_address
|
// Invalid our_address
|
||||||
msg_error(
|
msg_error(
|
||||||
cmd,
|
cmd,
|
||||||
"01 04 01020304
|
"01 04 01020304 0050
|
||||||
04 04 05060708",
|
04 04 05060708 0050",
|
||||||
BytesError::BadMessage("Our address is a Hostname"),
|
BytesError::BadMessage("Our address is a Hostname"),
|
||||||
);
|
);
|
||||||
// Invalid their_address
|
// Invalid their_address
|
||||||
msg_error(
|
msg_error(
|
||||||
cmd,
|
cmd,
|
||||||
"04 04 01020304
|
"04 04 01020304 0050
|
||||||
01 04 05060708",
|
01 04 05060708 0050",
|
||||||
BytesError::BadMessage("Their address is a Hostname"),
|
BytesError::BadMessage("Their address is a Hostname"),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue