cuprate_wire/network_address/
epee_builder.rs
1use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
10
11use bytes::Buf;
12use thiserror::Error;
13
14use cuprate_epee_encoding::{epee_object, EpeeObjectBuilder};
15use cuprate_types::AddressType;
16
17use crate::NetworkAddress;
18
19use super::OnionAddr;
20
21#[derive(Default)]
24pub struct TaggedNetworkAddress {
26 ty: Option<AddressType>,
28 addr: Option<AllFieldsNetworkAddress>,
30}
31
32epee_object!(
33 TaggedNetworkAddress,
34 ty("type"): Option<AddressType>,
35 addr: Option<AllFieldsNetworkAddress>,
36);
37
38impl EpeeObjectBuilder<NetworkAddress> for TaggedNetworkAddress {
39 fn add_field<B: Buf>(&mut self, name: &str, b: &mut B) -> cuprate_epee_encoding::Result<bool> {
40 match name {
41 "type" => {
42 if self
43 .ty
44 .replace(cuprate_epee_encoding::read_epee_value(b)?)
45 .is_some()
46 {
47 return Err(cuprate_epee_encoding::Error::Format(
48 "Duplicate field in data.",
49 ));
50 }
51 Ok(true)
52 }
53 "addr" => {
54 if std::mem::replace(&mut self.addr, cuprate_epee_encoding::read_epee_value(b)?)
55 .is_some()
56 {
57 return Err(cuprate_epee_encoding::Error::Format(
58 "Duplicate field in data.",
59 ));
60 }
61 Ok(true)
62 }
63 _ => Ok(false),
64 }
65 }
66
67 fn finish(self) -> cuprate_epee_encoding::Result<NetworkAddress> {
68 self.try_into()
69 .map_err(|_| cuprate_epee_encoding::Error::Value("Invalid network address".to_string()))
70 }
71}
72
73#[derive(Error, Debug)]
74#[error("Invalid network address")]
75pub struct InvalidNetworkAddress;
76
77impl TryFrom<TaggedNetworkAddress> for NetworkAddress {
78 type Error = InvalidNetworkAddress;
79
80 fn try_from(value: TaggedNetworkAddress) -> Result<Self, Self::Error> {
81 value
82 .addr
83 .ok_or(InvalidNetworkAddress)?
84 .try_into_network_address(value.ty.ok_or(InvalidNetworkAddress)?)
85 .ok_or(InvalidNetworkAddress)
86 }
87}
88
89impl From<NetworkAddress> for TaggedNetworkAddress {
90 fn from(value: NetworkAddress) -> Self {
91 match value {
92 NetworkAddress::Clear(addr) => match addr {
93 SocketAddr::V4(addr) => Self {
94 ty: Some(AddressType::Ipv4),
95 addr: Some(AllFieldsNetworkAddress {
96 m_ip: Some(u32::from_le_bytes(addr.ip().octets())),
97 m_port: Some(addr.port()),
98 addr: None,
99 host: None,
100 port: None,
101 }),
102 },
103 SocketAddr::V6(addr) => Self {
104 ty: Some(AddressType::Ipv6),
105 addr: Some(AllFieldsNetworkAddress {
106 addr: Some(addr.ip().octets()),
107 m_port: Some(addr.port()),
108 m_ip: None,
109 host: None,
110 port: None,
111 }),
112 },
113 },
114 NetworkAddress::Tor(onion_addr) => Self {
115 ty: Some(AddressType::Tor),
116 addr: Some(AllFieldsNetworkAddress {
117 m_ip: None,
118 m_port: None,
119 addr: None,
120 host: Some(onion_addr.addr_string()),
121 port: Some(onion_addr.port()),
122 }),
123 },
124 }
125 }
126}
127
128#[derive(Default)]
129struct AllFieldsNetworkAddress {
133 m_ip: Option<u32>,
135 m_port: Option<u16>,
137
138 addr: Option<[u8; 16]>,
140
141 host: Option<String>,
143 port: Option<u16>,
145}
146
147epee_object!(
148 AllFieldsNetworkAddress,
149 m_ip: Option<u32>,
150 m_port: Option<u16>,
151 addr: Option<[u8; 16]>,
152 host: Option<String>,
153 port: Option<u16>,
154);
155
156impl AllFieldsNetworkAddress {
157 fn try_into_network_address(self, ty: AddressType) -> Option<NetworkAddress> {
158 Some(match ty {
159 AddressType::Ipv4 => NetworkAddress::from(SocketAddrV4::new(
160 Ipv4Addr::from(self.m_ip?.to_le_bytes()),
161 self.m_port?,
162 )),
163 AddressType::Ipv6 => NetworkAddress::from(SocketAddrV6::new(
164 Ipv6Addr::from(self.addr?),
165 self.m_port?,
166 0,
167 0,
168 )),
169 AddressType::Tor => {
170 NetworkAddress::from(OnionAddr::new(self.host?.as_str(), self.port?).ok()?)
171 }
172 _ => return None,
174 })
175 }
176}