emissary_core/primitives/
router_address.rs1use crate::{
20 crypto::{base64_encode, StaticPrivateKey},
21 error::parser::RouterAddressParseError,
22 primitives::{Date, Mapping, Str},
23};
24
25use bytes::{BufMut, BytesMut};
26use nom::{number::complete::be_u8, Err, IResult};
27
28use alloc::{string::ToString, vec::Vec};
29use core::{
30 net::{IpAddr, Ipv4Addr, SocketAddr},
31 str::FromStr,
32};
33
34#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
36pub enum TransportKind {
37 Ntcp2,
39
40 Ssu2,
42}
43
44impl TryFrom<Str> for TransportKind {
45 type Error = ();
46
47 fn try_from(value: Str) -> Result<Self, Self::Error> {
48 if value.starts_with("SSU") {
49 return Ok(TransportKind::Ssu2);
50 }
51
52 if value.starts_with("NTCP2") {
53 return Ok(TransportKind::Ntcp2);
54 }
55
56 Err(())
57 }
58}
59
60impl TransportKind {
61 fn serialize(&self) -> Vec<u8> {
63 match self {
64 Self::Ntcp2 => Str::from("NTCP2").serialize(),
65 Self::Ssu2 => Str::from("SSU2").serialize(),
66 }
67 }
68}
69
70#[derive(Debug, Clone)]
72pub struct RouterAddress {
73 pub cost: u8,
75
76 pub expires: Date,
78
79 pub transport: TransportKind,
81
82 pub options: Mapping,
84
85 pub socket_address: Option<SocketAddr>,
87}
88
89impl RouterAddress {
90 pub fn new_unpublished_ntcp2(key: [u8; 32], port: u16) -> Self {
92 let static_key = StaticPrivateKey::from(key).public();
93 let key = base64_encode(&static_key);
94
95 let mut options = Mapping::default();
96 options.insert("v".into(), "2".into());
97 options.insert("s".into(), key.into());
98
99 Self {
100 cost: 14,
101 expires: Date::new(0),
102 transport: TransportKind::Ntcp2,
103 socket_address: Some(SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), port)),
104 options,
105 }
106 }
107
108 pub fn new_published_ntcp2(key: [u8; 32], iv: [u8; 16], port: u16, host: Ipv4Addr) -> Self {
110 let static_key = StaticPrivateKey::from(key).public();
111
112 let mut options = Mapping::default();
113 options.insert(Str::from("v"), Str::from("2"));
114 options.insert(Str::from("s"), Str::from(base64_encode(&static_key)));
115 options.insert(Str::from("host"), Str::from(host.to_string()));
116 options.insert(Str::from("port"), Str::from(port.to_string()));
117 options.insert(Str::from("i"), Str::from(base64_encode(iv)));
118
119 Self {
120 cost: 3,
121 expires: Date::new(0),
122 transport: TransportKind::Ntcp2,
123 options,
124 socket_address: Some(SocketAddr::new(IpAddr::V4(host), port)),
125 }
126 }
127
128 pub fn new_unpublished_ssu2(static_key: [u8; 32], intro_key: [u8; 32], port: u16) -> Self {
130 let static_key = {
131 let static_key = StaticPrivateKey::from(static_key).public();
132 base64_encode(&static_key)
133 };
134 let intro_key = base64_encode(intro_key);
135
136 let mut options = Mapping::default();
137 options.insert(Str::from_str("v").unwrap(), Str::from_str("2").unwrap());
138 options.insert(
139 Str::from_str("s").unwrap(),
140 Str::from_str(&static_key).unwrap(),
141 );
142 options.insert(
143 Str::from_str("i").unwrap(),
144 Str::from_str(&intro_key).unwrap(),
145 );
146
147 Self {
148 cost: 14,
149 expires: Date::new(0),
150 transport: TransportKind::Ssu2,
151 socket_address: Some(SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), port)),
152 options,
153 }
154 }
155
156 pub fn new_published_ssu2(
158 static_key: [u8; 32],
159 intro_key: [u8; 32],
160 port: u16,
161 host: Ipv4Addr,
162 ) -> Self {
163 let static_key = {
164 let static_key = StaticPrivateKey::from(static_key).public();
165 base64_encode(&static_key)
166 };
167 let intro_key = base64_encode(intro_key);
168
169 let mut options = Mapping::default();
170 options.insert(Str::from("v"), Str::from("2"));
171 options.insert(
172 Str::from_str("s").unwrap(),
173 Str::from_str(&static_key).unwrap(),
174 );
175 options.insert(
176 Str::from_str("i").unwrap(),
177 Str::from_str(&intro_key).unwrap(),
178 );
179 options.insert(Str::from("host"), Str::from(host.to_string()));
180 options.insert(Str::from("port"), Str::from(port.to_string()));
181
182 Self {
183 cost: 8,
184 expires: Date::new(0),
185 transport: TransportKind::Ssu2,
186 options,
187 socket_address: Some(SocketAddr::new(IpAddr::V4(host), port)),
188 }
189 }
190
191 pub fn parse_frame(input: &[u8]) -> IResult<&[u8], RouterAddress, RouterAddressParseError> {
193 let (rest, cost) = be_u8(input)?;
194 let (rest, expires) = Date::parse_frame(rest)
195 .map_err(|_| Err::Error(RouterAddressParseError::InvalidExpiration))?;
196 let (rest, transport) = Str::parse_frame(rest)
197 .map_err(|_| Err::Error(RouterAddressParseError::InvalidTransport))?;
198 let (rest, options) = Mapping::parse_frame(rest).map_err(Err::convert)?;
199 let socket_address: Option<SocketAddr> = {
200 let maybe_host = options.get(&Str::from("host"));
201 let maybe_port = options.get(&Str::from("port"));
202
203 match (maybe_host, maybe_port) {
204 (Some(host), Some(port)) => {
205 let port = port.parse::<u16>().ok();
206 let host = host.parse::<IpAddr>().ok();
207
208 match (host, port) {
209 (Some(host), Some(port)) => Some(SocketAddr::new(host, port)),
210 (_, _) => None,
211 }
212 }
213 _ => None,
214 }
215 };
216
217 Ok((
218 rest,
219 RouterAddress {
220 cost,
221 expires,
222 transport: TransportKind::try_from(transport)
223 .map_err(|_| Err::Error(RouterAddressParseError::InvalidTransport))?,
224 options,
225 socket_address,
226 },
227 ))
228 }
229
230 pub fn parse(bytes: impl AsRef<[u8]>) -> Result<RouterAddress, RouterAddressParseError> {
232 Ok(Self::parse_frame(bytes.as_ref())?.1)
233 }
234
235 pub fn serialize(&self) -> BytesMut {
237 let options = self.options.serialize();
238 let transport = self.transport.serialize();
239 let mut out = BytesMut::with_capacity(1 + 8 + transport.len() + options.len());
240
241 out.put_u8(self.cost);
242 out.put_slice(&self.expires.serialize());
243 out.put_slice(&transport);
244 out.put_slice(&options);
245
246 out
247 }
248}
249
250#[cfg(test)]
251mod tests {
252 use super::*;
253
254 #[test]
255 fn serialize_deserialize_unpublished_ntcp2() {
256 let serialized = RouterAddress::new_unpublished_ntcp2([1u8; 32], 8888).serialize();
257 let static_key = StaticPrivateKey::from([1u8; 32]).public();
258
259 let address = RouterAddress::parse(&serialized).unwrap();
260 assert_eq!(address.cost, 14);
261 assert_eq!(
262 address.options.get(&Str::from("s")),
263 Some(&Str::from(base64_encode(&static_key)))
264 );
265 assert_eq!(address.options.get(&Str::from("v")), Some(&Str::from("2")));
266 assert!(address.options.get(&Str::from("i")).is_none());
267 assert!(address.options.get(&Str::from("host")).is_none());
268 assert!(address.options.get(&Str::from("port")).is_none());
269 }
270
271 #[test]
272 fn serialize_deserialize_published_ntcp2() {
273 let serialized = RouterAddress::new_published_ntcp2(
274 [1u8; 32],
275 [0xaa; 16],
276 8888,
277 "127.0.0.1".parse().unwrap(),
278 )
279 .serialize();
280 let static_key = StaticPrivateKey::from([1u8; 32]).public();
281
282 let address = RouterAddress::parse(&serialized).unwrap();
283 assert_eq!(address.cost, 3);
284 assert_eq!(
285 address.options.get(&Str::from("i")),
286 Some(&Str::from(base64_encode(&[0xaa; 16])))
287 );
288 assert_eq!(
289 address.options.get(&Str::from("s")),
290 Some(&Str::from(base64_encode(&static_key)))
291 );
292 assert_eq!(address.options.get(&Str::from("v")), Some(&Str::from("2")));
293 assert_eq!(
294 address.options.get(&Str::from("host")),
295 Some(&Str::from("127.0.0.1"))
296 );
297 assert_eq!(
298 address.options.get(&Str::from("port")),
299 Some(&Str::from("8888"))
300 );
301 }
302
303 #[test]
304 fn serialize_deserialize_unpublished_ssu2() {
305 let serialized =
306 RouterAddress::new_unpublished_ssu2([1u8; 32], [2u8; 32], 8888).serialize();
307 let static_key = StaticPrivateKey::from([1u8; 32]).public();
308 let intro_key = [2u8; 32];
309
310 let address = RouterAddress::parse(&serialized).unwrap();
311 assert_eq!(address.cost, 14);
312 assert_eq!(
313 address.options.get(&Str::from("s")),
314 Some(&Str::from(base64_encode(&static_key)))
315 );
316 assert_eq!(
317 address.options.get(&Str::from("i")),
318 Some(&Str::from(base64_encode(&intro_key)))
319 );
320 assert_eq!(address.options.get(&Str::from("v")), Some(&Str::from("2")));
321 assert!(address.options.get(&Str::from("host")).is_none());
322 assert!(address.options.get(&Str::from("port")).is_none());
323 }
324
325 #[test]
326 fn serialize_deserialize_published_ssu2() {
327 let serialized = RouterAddress::new_published_ssu2(
328 [1u8; 32],
329 [2u8; 32],
330 8888,
331 "127.0.0.1".parse().unwrap(),
332 )
333 .serialize();
334 let static_key = StaticPrivateKey::from([1u8; 32]).public();
335 let intro_key = [2u8; 32];
336
337 let address = RouterAddress::parse(&serialized).unwrap();
338 assert_eq!(address.cost, 8);
339 assert_eq!(
340 address.options.get(&Str::from("s")),
341 Some(&Str::from(base64_encode(&static_key)))
342 );
343 assert_eq!(
344 address.options.get(&Str::from("i")),
345 Some(&Str::from(base64_encode(&intro_key)))
346 );
347 assert_eq!(address.options.get(&Str::from("v")), Some(&Str::from("2")));
348 assert_eq!(
349 address.options.get(&Str::from("host")),
350 Some(&Str::from("127.0.0.1"))
351 );
352 assert_eq!(
353 address.options.get(&Str::from("port")),
354 Some(&Str::from("8888"))
355 );
356 }
357}