use nom::{le_u8, be_u16};
use std::net::{
IpAddr,
Ipv4Addr,
Ipv6Addr,
SocketAddr,
};
use toxcore::binary_io::*;
use toxcore::crypto_core::*;
#[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 { saddr, pk })
));
}
impl PackedNode {
pub fn new(udp: bool, saddr: SocketAddr, pk: &PublicKey) -> Self {
debug!(target: "PackedNode", "Creating new PackedNode.");
trace!(target: "PackedNode", "With args: udp: {}, saddr: {:?}, PK: {:?}",
udp, &saddr, pk);
PackedNode { saddr, pk: *pk }
}
pub fn ip_type(&self) -> u8 {
trace!(target: "PackedNode", "Getting IP type from PackedNode.");
trace!("With address: {:?}", self);
if self.saddr.is_ipv4() {
2
}
else {
10
}
}
pub fn ip(&self) -> IpAddr {
trace!(target: "PackedNode", "Getting IP address from PackedNode.");
trace!("With address: {:?}", self);
self.saddr.ip()
}
pub fn socket_addr(&self) -> SocketAddr {
trace!(target: "PackedNode", "Getting Socket address from PackedNode.");
trace!("With address: {:?}", self);
self.saddr
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::net::{SocketAddrV4, SocketAddrV6};
use quickcheck::{Arbitrary, Gen, quickcheck};
impl Arbitrary for PackedNode {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
let ipv4: bool = g.gen();
let mut pk_bytes = [0; PUBLICKEYBYTES];
g.fill_bytes(&mut pk_bytes);
let pk = PublicKey(pk_bytes);
if ipv4 {
let addr = Ipv4Addr::new(g.gen(), g.gen(), g.gen(), g.gen());
let saddr = SocketAddrV4::new(addr, g.gen());
PackedNode::new(g.gen(), SocketAddr::V4(saddr), &pk)
} else {
let addr = Ipv6Addr::new(g.gen(), g.gen(), g.gen(), g.gen(),
g.gen(), g.gen(), g.gen(), g.gen());
let saddr = SocketAddrV6::new(addr, g.gen(), 0, 0);
PackedNode::new(g.gen(), SocketAddr::V6(saddr), &pk)
}
}
}
#[test]
fn packed_node_new_test() {
fn with_params(saddr: SocketAddr) {
let (pk, _sk) = gen_keypair();
let a = PackedNode::new(true, saddr, &pk);
let b = PackedNode {
saddr,
pk,
};
assert_eq!(a, b);
}
quickcheck(with_params as fn(SocketAddr));
}
#[test]
fn packed_node_ip_type_test() {
fn with_packed_node(pnode: PackedNode) {
let a = pnode.ip_type();
let b =
if pnode.saddr.is_ipv4() {
2
} else {
10
};
assert_eq!(a, b);
}
quickcheck(with_packed_node as fn(PackedNode));
}
#[test]
fn packed_node_ip_test() {
fn with_packed_node(pnode: PackedNode) {
let a = pnode.ip();
let b = pnode.saddr.ip();
assert_eq!(a, b);
}
quickcheck(with_packed_node as fn(PackedNode));
}
#[test]
fn packed_node_socket_addr_test() {
fn with_packed_node(pnode: PackedNode) {
let a = pnode.socket_addr();
let b = pnode.saddr;
assert_eq!(a, b);
}
quickcheck(with_packed_node as fn(PackedNode));
}
}