cuprate_wire/network_address/
epee_builder.rs
1use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
2
3use bytes::Buf;
4use thiserror::Error;
5
6use cuprate_epee_encoding::{epee_object, EpeeObjectBuilder};
7
8use crate::NetworkAddress;
9
10#[derive(Default)]
11pub struct TaggedNetworkAddress {
12 ty: Option<u8>,
13 addr: Option<AllFieldsNetworkAddress>,
14}
15
16epee_object!(
17 TaggedNetworkAddress,
18 ty("type"): Option<u8>,
19 addr: Option<AllFieldsNetworkAddress>,
20);
21
22impl EpeeObjectBuilder<NetworkAddress> for TaggedNetworkAddress {
23 fn add_field<B: Buf>(&mut self, name: &str, b: &mut B) -> cuprate_epee_encoding::Result<bool> {
24 match name {
25 "type" => {
26 if std::mem::replace(
27 &mut self.ty,
28 Some(cuprate_epee_encoding::read_epee_value(b)?),
29 )
30 .is_some()
31 {
32 return Err(cuprate_epee_encoding::Error::Format(
33 "Duplicate field in data.",
34 ));
35 }
36 Ok(true)
37 }
38 "addr" => {
39 if std::mem::replace(&mut self.addr, cuprate_epee_encoding::read_epee_value(b)?)
40 .is_some()
41 {
42 return Err(cuprate_epee_encoding::Error::Format(
43 "Duplicate field in data.",
44 ));
45 }
46 Ok(true)
47 }
48 _ => Ok(false),
49 }
50 }
51
52 fn finish(self) -> cuprate_epee_encoding::Result<NetworkAddress> {
53 self.try_into()
54 .map_err(|_| cuprate_epee_encoding::Error::Value("Invalid network address".to_string()))
55 }
56}
57
58#[derive(Error, Debug)]
59#[error("Invalid network address")]
60pub struct InvalidNetworkAddress;
61
62impl TryFrom<TaggedNetworkAddress> for NetworkAddress {
63 type Error = InvalidNetworkAddress;
64
65 fn try_from(value: TaggedNetworkAddress) -> Result<Self, Self::Error> {
66 value
67 .addr
68 .ok_or(InvalidNetworkAddress)?
69 .try_into_network_address(value.ty.ok_or(InvalidNetworkAddress)?)
70 .ok_or(InvalidNetworkAddress)
71 }
72}
73
74impl From<NetworkAddress> for TaggedNetworkAddress {
75 fn from(value: NetworkAddress) -> Self {
76 match value {
77 NetworkAddress::Clear(addr) => match addr {
78 SocketAddr::V4(addr) => Self {
79 ty: Some(1),
80 addr: Some(AllFieldsNetworkAddress {
81 m_ip: Some(u32::from_le_bytes(addr.ip().octets())),
82 m_port: Some(addr.port()),
83 addr: None,
84 }),
85 },
86 SocketAddr::V6(addr) => Self {
87 ty: Some(2),
88 addr: Some(AllFieldsNetworkAddress {
89 addr: Some(addr.ip().octets()),
90 m_port: Some(addr.port()),
91 m_ip: None,
92 }),
93 },
94 },
95 }
96 }
97}
98
99#[derive(Default)]
100struct AllFieldsNetworkAddress {
101 m_ip: Option<u32>,
102 m_port: Option<u16>,
103 addr: Option<[u8; 16]>,
104}
105
106epee_object!(
107 AllFieldsNetworkAddress,
108 m_ip: Option<u32>,
109 m_port: Option<u16>,
110 addr: Option<[u8; 16]>,
111);
112
113impl AllFieldsNetworkAddress {
114 fn try_into_network_address(self, ty: u8) -> Option<NetworkAddress> {
115 Some(match ty {
116 1 => NetworkAddress::from(SocketAddrV4::new(
117 Ipv4Addr::from(self.m_ip?.to_le_bytes()),
118 self.m_port?,
119 )),
120 2 => NetworkAddress::from(SocketAddrV6::new(
121 Ipv6Addr::from(self.addr?),
122 self.m_port?,
123 0,
124 0,
125 )),
126 _ => return None,
127 })
128 }
129}