use byteorder::{ByteOrder, BigEndian};
use std::borrow::Cow;
use std::str::FromStr;
use std::net;
pub mod no_auth;
pub use no_auth::TcpNoAuth;
#[repr(C)]
pub enum Command {
TcpConnectionEstablishment = 1,
TcpPortBinding,
UdpPortBinding
}
pub enum Destination {
Ipv4Addr(std::net::Ipv4Addr),
DomainName(Cow<'static, str>),
Ipv6Addr(std::net::Ipv6Addr)
}
impl Destination {
pub fn len_as_buffer(&self) -> usize {
match self {
Destination::Ipv4Addr(_) => 4 + 1,
Destination::DomainName(name) => name.len() + 2,
Destination::Ipv6Addr(_) => 16 + 1
}
}
fn extend_buffer(&mut self, buf: &mut [u8])
-> Result<(), ()>
{
match self {
Destination::Ipv4Addr(addr) => {
buf[0] = 0x01;
BigEndian::write_u32(&mut buf[1..5], addr.clone().into());
},
Destination::DomainName(name) => {
buf[0] = 0x03;
if name.len() > 255 {
return Err(())
}
buf[1] = name.len() as u8;
buf[2..].clone_from_slice(name.as_bytes());
},
Destination::Ipv6Addr(addr) => {
buf[0] = 0x04;
BigEndian::write_u128(&mut buf[1..17], addr.clone().into());
}
}
Ok(())
}
}
impl FromStr for Destination {
type Err = ();
fn from_str(s: &str) -> Result<Destination, Self::Err> {
let result = s.parse::<net::Ipv4Addr>();
if result.is_ok() {
return Ok(Destination::Ipv4Addr(result.unwrap()))
}
let result = s.parse::<net::Ipv6Addr>();
if result.is_ok() {
return Ok(Destination::Ipv6Addr(result.unwrap()))
}
webpki::DNSNameRef::try_from_ascii_str(s)
.map_err(|_| ())?;
Ok(Destination::DomainName(Cow::Owned(s.to_owned())))
}
}