use super::*;
use nom::{
switch,
value,
number::complete::{le_u8, be_u16}
};
use cookie_factory::{gen_if_else};
use std::net::{
IpAddr,
Ipv4Addr,
Ipv6Addr,
SocketAddr,
SocketAddrV4
};
use tox_binary_io::*;
use tox_crypto::*;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct PackedNode {
pub saddr: SocketAddr,
pub pk: PublicKey,
}
impl ToBytes for PackedNode {
fn to_bytes<'a>(&self, buf: (&'a mut [u8], usize)) -> Result<(&'a mut [u8], usize), GenError> {
do_gen!(buf,
gen_if_else!(self.saddr.is_ipv4(), gen_be_u8!(2), gen_be_u8!(10)) >>
gen_call!(|buf, addr| IpAddr::to_bytes(addr, buf), &self.saddr.ip()) >>
gen_be_u16!(self.saddr.port()) >>
gen_slice!(self.pk.as_ref())
)
}
}
impl FromBytes for PackedNode {
named!(from_bytes<PackedNode>, do_parse!(
addr: switch!(le_u8,
2 => map!(Ipv4Addr::from_bytes, IpAddr::V4) |
10 => map!(Ipv6Addr::from_bytes, IpAddr::V6)
) >>
port: be_u16 >>
saddr: value!(SocketAddr::new(addr, port)) >>
pk: call!(PublicKey::from_bytes) >>
(PackedNode::new(saddr, &pk))
));
}
impl PackedNode {
pub fn new(saddr: SocketAddr, pk: &PublicKey) -> Self {
PackedNode { saddr: PackedNode::ipv6_to_ipv4(saddr), pk: *pk }
}
fn ipv6_to_ipv4(saddr: SocketAddr) -> SocketAddr {
match saddr {
SocketAddr::V4(v4) => SocketAddr::V4(v4),
SocketAddr::V6(v6) => {
if let Some(converted_ip4) = v6.ip().to_ipv4() {
SocketAddr::V4(SocketAddrV4::new(converted_ip4, v6.port()))
} else {
SocketAddr::V6(v6)
}
},
}
}
pub fn to_tcp_bytes<'a>(&self, buf: (&'a mut [u8], usize)) -> Result<(&'a mut [u8], usize), GenError> {
do_gen!(buf,
gen_if_else!(self.saddr.is_ipv4(), gen_be_u8!(130), gen_be_u8!(138)) >>
gen_call!(|buf, addr| IpAddr::to_bytes(addr, buf), &self.saddr.ip()) >>
gen_be_u16!(self.saddr.port()) >>
gen_slice!(self.pk.as_ref())
)
}
named!(
#[allow(unused_variables)]
#[doc = "from_bytes for TCP."],
pub from_tcp_bytes<PackedNode>, do_parse!(
addr: switch!(le_u8,
130 => map!(Ipv4Addr::from_bytes, IpAddr::V4) |
138 => map!(Ipv6Addr::from_bytes, IpAddr::V6)
) >>
port: be_u16 >>
saddr: value!(SocketAddr::new(addr, port)) >>
pk: call!(PublicKey::from_bytes) >>
(PackedNode::new(saddr, &pk))
));
pub fn ip_type(&self) -> u8 {
if self.saddr.is_ipv4() {
2
}
else {
10
}
}
pub fn ip(&self) -> IpAddr {
self.saddr.ip()
}
pub fn socket_addr(&self) -> SocketAddr {
self.saddr
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn packed_node_new() {
crypto_init().unwrap();
let (pk, _sk) = gen_keypair();
let saddr = "1.2.3.4:12345".parse().unwrap();
let a = PackedNode::new(saddr, &pk);
let b = PackedNode {
saddr,
pk,
};
assert_eq!(a, b);
}
#[test]
fn packed_node_new_ipv4_mapped() {
crypto_init().unwrap();
let (pk, _sk) = gen_keypair();
let saddr_v6 = "[::ffff:1.2.3.4]:12345".parse().unwrap();
let saddr_v4 = "1.2.3.4:12345".parse().unwrap();
let a = PackedNode::new(saddr_v6, &pk);
let b = PackedNode {
saddr: saddr_v4,
pk,
};
assert_eq!(a, b);
}
#[test]
fn packed_node_ip_type_2() {
crypto_init().unwrap();
let (pk, _sk) = gen_keypair();
let saddr = "1.2.3.4:12345".parse().unwrap();
let node = PackedNode::new(saddr, &pk);
assert_eq!(node.ip_type(), 2);
}
#[test]
fn packed_node_ip_type_10() {
crypto_init().unwrap();
let (pk, _sk) = gen_keypair();
let saddr = "[::1234:4321]:12345".parse().unwrap();
let node = PackedNode::new(saddr, &pk);
assert_eq!(node.ip_type(), 2);
}
#[test]
fn packed_node_ip() {
crypto_init().unwrap();
let (pk, _sk) = gen_keypair();
let saddr = "1.2.3.4:12345".parse().unwrap();
let node = PackedNode::new(saddr, &pk);
assert_eq!(node.ip(), saddr.ip());
}
#[test]
fn packed_node_socket_addr() {
crypto_init().unwrap();
let (pk, _sk) = gen_keypair();
let saddr = "1.2.3.4:12345".parse().unwrap();
let node = PackedNode::new(saddr, &pk);
assert_eq!(node.socket_addr(), saddr);
}
}