cs_mwc_bch/messages/
node_addr.rs

1use byteorder::{BigEndian, LittleEndian, ReadBytesExt, WriteBytesExt};
2use std::io;
3use std::io::{Read, Write};
4use std::net::{IpAddr, Ipv6Addr};
5use util::{Result, Serializable};
6
7/// Network address for a node on the network
8#[derive(Debug, PartialEq, Eq, Hash, Clone)]
9pub struct NodeAddr {
10    /// Services flags for the node
11    pub services: u64,
12    /// IPV6 address for the node. IPV4 addresses may be used as IPV4-mapped IPV6 addresses.
13    pub ip: Ipv6Addr,
14    /// Port for Bitcoin P2P communication
15    pub port: u16,
16}
17
18impl NodeAddr {
19    /// Size of the NodeAddr in bytes
20    pub const SIZE: usize = 26;
21
22    /// Creates a NodeAddr from an IP address and port
23    pub fn new(ip: IpAddr, port: u16) -> NodeAddr {
24        NodeAddr {
25            services: 0,
26            ip: match ip {
27                IpAddr::V4(ipv4) => ipv4.to_ipv6_mapped(),
28                IpAddr::V6(ipv6) => ipv6,
29            },
30            port,
31        }
32    }
33
34    /// Returns the size of the address in bytes
35    pub fn size(&self) -> usize {
36        NodeAddr::SIZE
37    }
38}
39
40impl Serializable<NodeAddr> for NodeAddr {
41    fn read(reader: &mut dyn Read) -> Result<NodeAddr> {
42        let services = reader.read_u64::<LittleEndian>()?;
43        let mut ip = [0; 16];
44        reader.read(&mut ip)?;
45        let ip = Ipv6Addr::from(ip);
46        let port = reader.read_u16::<BigEndian>()?;
47        Ok(NodeAddr { services, ip, port })
48    }
49
50    fn write(&self, writer: &mut dyn Write) -> io::Result<()> {
51        writer.write_u64::<LittleEndian>(self.services)?;
52        writer.write(&self.ip.octets())?;
53        writer.write_u16::<BigEndian>(self.port)?;
54        Ok(())
55    }
56}
57
58impl Default for NodeAddr {
59    fn default() -> NodeAddr {
60        NodeAddr {
61            services: 0,
62            ip: Ipv6Addr::from([0; 16]),
63            port: 0,
64        }
65    }
66}
67
68#[cfg(test)]
69mod tests {
70    use super::*;
71    use hex;
72    use std::io::Cursor;
73
74    #[test]
75    fn read_bytes() {
76        let b =
77            hex::decode("250000000000000000000000000000000000ffff2d32bffbddd3".as_bytes()).unwrap();
78        let a = NodeAddr::read(&mut Cursor::new(&b)).unwrap();
79        assert!(a.services == 37);
80        assert!(a.ip.octets() == [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 45, 50, 191, 251]);
81        assert!(a.port == 56787);
82    }
83
84    #[test]
85    fn write_read() {
86        let mut v = Vec::new();
87        let a = NodeAddr {
88            services: 1,
89            ip: Ipv6Addr::from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]),
90            port: 123,
91        };
92        a.write(&mut v).unwrap();
93        assert!(v.len() == a.size());
94        assert!(NodeAddr::read(&mut Cursor::new(&v)).unwrap() == a);
95    }
96}