1use borsh::{BorshDeserialize, BorshSerialize};
3use ipnet::IpNet;
4use serde::{Deserialize, Serialize};
5use std::{
6 fmt::Display,
7 net::{AddrParseError, IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
8 ops::Deref,
9 str::FromStr,
10};
11use uuid::Uuid;
12use wasm_bindgen::prelude::*;
13
14#[wasm_bindgen(typescript_custom_section)]
16const TS_IP_ADDRESS: &'static str = r#"
17 /**
18 * Generic network address representation.
19 *
20 * @category General
21 */
22 export interface INetworkAddress {
23 /**
24 * IPv4 or IPv6 address.
25 */
26 ip: string;
27 /**
28 * Optional port number.
29 */
30 port?: number;
31 }
32"#;
33
34#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
39pub struct PrefixBucket(u64);
40
41impl PrefixBucket {
42 pub fn as_u64(&self) -> u64 {
43 self.0
44 }
45}
46
47impl From<&IpAddress> for PrefixBucket {
48 fn from(ip_address: &IpAddress) -> Self {
49 match ip_address.0 {
50 IpAddr::V4(ipv4) => {
51 let prefix_bytes = ipv4.octets();
52 Self(u64::from_be_bytes([0u8, 0u8, 0u8, 0u8, 0u8, 0u8, prefix_bytes[0], prefix_bytes[1]]))
53 }
54 IpAddr::V6(ipv6) => {
55 if let Some(ipv4) = ipv6.to_ipv4() {
56 let prefix_bytes = ipv4.octets();
57 Self(u64::from_be_bytes([0u8, 0u8, 0u8, 0u8, 0u8, 0u8, prefix_bytes[0], prefix_bytes[1]]))
58 } else {
59 Self(u64::from_be_bytes(ipv6.octets().as_slice()[..8].try_into().expect("Slice with incorrect length")))
61 }
62 }
63 }
64 }
65}
66
67impl From<&NetAddress> for PrefixBucket {
68 fn from(net_address: &NetAddress) -> Self {
69 Self::from(&net_address.ip)
70 }
71}
72
73#[derive(PartialEq, Eq, Hash, Copy, Clone, Serialize, Deserialize, Debug)]
75#[repr(transparent)]
76pub struct IpAddress(pub IpAddr);
77
78impl IpAddress {
79 pub fn new(ip: IpAddr) -> Self {
80 Self(ip)
81 }
82
83 pub fn is_publicly_routable(&self) -> bool {
84 if self.is_loopback() || self.is_unspecified() {
85 return false;
86 }
87
88 match self.0 {
89 IpAddr::V4(ip) => {
90 if ip.is_broadcast() || ip.is_private() || ip.is_documentation() || ip.is_link_local() {
95 return false;
96 }
97 }
98 IpAddr::V6(_ip) => {
99 }
101 }
102
103 let unroutable_nets = [
105 "198.18.0.0/15", "2001:DB8::/32", "2002::/16", "FC00::/7", "2001::/32", "2001:10::/28", "FE80::/64", "64:FF9B::/96", "::FFFF:0:0:0/96", "100.64.0.0/10", "0.0.0.0/8", "2001:470::/32", ];
118
119 for curr_net in unroutable_nets {
120 if IpNet::from_str(curr_net).unwrap().contains(&self.0) {
121 return false;
122 }
123 }
124
125 true
126 }
127
128 pub fn prefix_bucket(&self) -> PrefixBucket {
129 PrefixBucket::from(self)
130 }
131}
132
133impl From<IpAddr> for IpAddress {
134 fn from(ip: IpAddr) -> Self {
135 Self(ip)
136 }
137}
138impl From<Ipv4Addr> for IpAddress {
139 fn from(value: Ipv4Addr) -> Self {
140 Self(value.into())
141 }
142}
143impl From<Ipv6Addr> for IpAddress {
144 fn from(value: Ipv6Addr) -> Self {
145 Self(value.into())
146 }
147}
148impl From<IpAddress> for IpAddr {
149 fn from(value: IpAddress) -> Self {
150 value.0
151 }
152}
153
154impl FromStr for IpAddress {
155 type Err = AddrParseError;
156
157 fn from_str(s: &str) -> Result<Self, Self::Err> {
158 IpAddr::from_str(s).map(IpAddress::from)
159 }
160}
161
162impl Display for IpAddress {
163 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
164 self.0.fmt(f)
165 }
166}
167
168impl Deref for IpAddress {
169 type Target = IpAddr;
170
171 fn deref(&self) -> &Self::Target {
172 &self.0
173 }
174}
175
176impl BorshSerialize for IpAddress {
182 fn serialize<W: std::io::Write>(&self, writer: &mut W) -> ::core::result::Result<(), std::io::Error> {
183 let variant_idx: u8 = match self.0 {
184 IpAddr::V4(..) => 0u8,
185 IpAddr::V6(..) => 1u8,
186 };
187 writer.write_all(&variant_idx.to_le_bytes())?;
188 match self.0 {
189 IpAddr::V4(id0) => {
190 borsh::BorshSerialize::serialize(&id0.octets(), writer)?;
191 }
192 IpAddr::V6(id0) => {
193 borsh::BorshSerialize::serialize(&id0.octets(), writer)?;
194 }
195 }
196 Ok(())
197 }
198}
199
200impl BorshDeserialize for IpAddress {
201 fn deserialize_reader<R: std::io::Read>(reader: &mut R) -> ::core::result::Result<Self, borsh::io::Error> {
202 let variant_idx: u8 = BorshDeserialize::deserialize_reader(reader)?;
203 let ip = match variant_idx {
204 0u8 => {
205 let octets: [u8; 4] = BorshDeserialize::deserialize_reader(reader)?;
206 IpAddr::V4(Ipv4Addr::from(octets))
207 }
208 1u8 => {
209 let octets: [u8; 16] = BorshDeserialize::deserialize_reader(reader)?;
210 IpAddr::V6(Ipv6Addr::from(octets))
211 }
212 _ => {
213 let msg = format!("Unexpected variant index: {:?}", variant_idx);
214 return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, msg));
215 }
216 };
217 Ok(Self(ip))
218 }
219}
220
221#[derive(PartialEq, Eq, Hash, Copy, Clone, Serialize, Deserialize, Debug, BorshSerialize, BorshDeserialize)]
223pub struct NetAddress {
224 pub ip: IpAddress,
225 pub port: u16,
226}
227
228impl NetAddress {
229 pub fn new(ip: IpAddress, port: u16) -> Self {
230 Self { ip, port }
231 }
232
233 pub fn prefix_bucket(&self) -> PrefixBucket {
234 PrefixBucket::from(self)
235 }
236}
237
238impl From<SocketAddr> for NetAddress {
239 fn from(value: SocketAddr) -> Self {
240 Self::new(value.ip().into(), value.port())
241 }
242}
243
244impl From<NetAddress> for SocketAddr {
245 fn from(value: NetAddress) -> Self {
246 Self::new(value.ip.0, value.port)
247 }
248}
249
250impl FromStr for NetAddress {
251 type Err = AddrParseError;
252
253 fn from_str(s: &str) -> Result<Self, Self::Err> {
254 SocketAddr::from_str(s).map(NetAddress::from)
255 }
256}
257
258impl Display for NetAddress {
259 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
260 SocketAddr::from(self.to_owned()).fmt(f)
261 }
262}
263
264#[derive(PartialEq, Eq, Hash, Copy, Clone, Serialize, Deserialize, Debug, BorshSerialize, BorshDeserialize)]
268pub struct ContextualNetAddress {
269 ip: IpAddress,
270 port: Option<u16>,
271}
272
273impl ContextualNetAddress {
274 pub fn new(ip: IpAddress, port: Option<u16>) -> Self {
275 Self { ip, port }
276 }
277
278 pub fn has_port(&self) -> bool {
279 self.port.is_some()
280 }
281
282 pub fn normalize(&self, default_port: u16) -> NetAddress {
283 NetAddress::new(self.ip, self.port.unwrap_or(default_port))
284 }
285
286 pub fn unspecified() -> Self {
287 Self { ip: IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)).into(), port: None }
288 }
289
290 pub fn loopback() -> Self {
291 Self { ip: IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).into(), port: None }
292 }
293
294 pub fn port_not_specified(&self) -> bool {
295 self.port.is_none()
296 }
297
298 pub fn with_port(&self, port: u16) -> Self {
299 Self { ip: self.ip, port: Some(port) }
300 }
301}
302
303impl From<NetAddress> for ContextualNetAddress {
304 fn from(value: NetAddress) -> Self {
305 Self::new(value.ip, Some(value.port))
306 }
307}
308
309impl FromStr for ContextualNetAddress {
310 type Err = AddrParseError;
311
312 fn from_str(s: &str) -> Result<Self, Self::Err> {
313 match SocketAddr::from_str(s) {
314 Ok(socket) => Ok(Self::new(socket.ip().into(), Some(socket.port()))),
315 Err(_) => Ok(Self::new(IpAddress::from_str(s)?, None)),
316 }
317 }
318}
319
320impl TryFrom<&str> for ContextualNetAddress {
321 type Error = AddrParseError;
322
323 fn try_from(s: &str) -> Result<Self, Self::Error> {
324 ContextualNetAddress::from_str(s)
325 }
326}
327
328impl TryFrom<String> for ContextualNetAddress {
329 type Error = AddrParseError;
330
331 fn try_from(s: String) -> Result<Self, Self::Error> {
332 ContextualNetAddress::from_str(&s)
333 }
334}
335
336impl Display for ContextualNetAddress {
337 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
338 match self.port {
339 Some(port) => SocketAddr::new(self.ip.into(), port).fmt(f),
340 None => self.ip.fmt(f),
341 }
342 }
343}
344#[derive(PartialEq, Eq, Hash, Copy, Clone, Serialize, Deserialize, Debug, Default)]
345#[repr(transparent)]
346pub struct PeerId(pub Uuid);
347
348impl PeerId {
349 pub fn new(id: Uuid) -> Self {
350 Self(id)
351 }
352
353 pub fn from_slice(bytes: &[u8]) -> Result<Self, uuid::Error> {
354 Ok(Uuid::from_slice(bytes)?.into())
355 }
356}
357impl From<Uuid> for PeerId {
358 fn from(id: Uuid) -> Self {
359 Self(id)
360 }
361}
362impl From<PeerId> for Uuid {
363 fn from(value: PeerId) -> Self {
364 value.0
365 }
366}
367
368impl FromStr for PeerId {
369 type Err = uuid::Error;
370
371 fn from_str(s: &str) -> Result<Self, Self::Err> {
372 Uuid::from_str(s).map(PeerId::from)
373 }
374}
375
376impl Display for PeerId {
377 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
378 self.0.fmt(f)
379 }
380}
381
382impl Deref for PeerId {
383 type Target = Uuid;
384
385 fn deref(&self) -> &Self::Target {
386 &self.0
387 }
388}
389
390impl BorshSerialize for PeerId {
396 fn serialize<W: std::io::Write>(&self, writer: &mut W) -> ::core::result::Result<(), std::io::Error> {
397 borsh::BorshSerialize::serialize(&self.0.as_bytes(), writer)?;
398 Ok(())
399 }
400}
401
402impl BorshDeserialize for PeerId {
403 fn deserialize_reader<R: std::io::Read>(reader: &mut R) -> ::core::result::Result<Self, std::io::Error> {
404 let bytes: uuid::Bytes = BorshDeserialize::deserialize_reader(reader)?;
405 Ok(Self::new(Uuid::from_bytes(bytes)))
406 }
407}
408
409#[cfg(test)]
410mod tests {
411 use super::*;
412 use std::str::FromStr;
413
414 #[test]
415 fn test_ip_address_borsh() {
416 let ip: IpAddress = Ipv4Addr::from([44u8; 4]).into();
418 let bin = borsh::to_vec(&ip).unwrap();
419 let ip2: IpAddress = BorshDeserialize::try_from_slice(&bin).unwrap();
420 assert_eq!(ip, ip2);
421
422 let ip: IpAddress = Ipv6Addr::from([66u8; 16]).into();
423 let bin = borsh::to_vec(&ip).unwrap();
424 let ip2: IpAddress = BorshDeserialize::try_from_slice(&bin).unwrap();
425 assert_eq!(ip, ip2);
426 }
427
428 #[test]
429 fn test_peer_id_borsh() {
430 let id: PeerId = Uuid::new_v4().into();
432 let bin = borsh::to_vec(&id).unwrap();
433 let id2: PeerId = BorshDeserialize::try_from_slice(&bin).unwrap();
434 assert_eq!(id, id2);
435
436 let id: PeerId = Uuid::from_bytes([123u8; 16]).into();
437 let bin = borsh::to_vec(&id).unwrap();
438 let id2: PeerId = BorshDeserialize::try_from_slice(&bin).unwrap();
439 assert_eq!(id, id2);
440 }
441
442 #[test]
443 fn test_net_address_from_str() {
444 let addr_v4 = NetAddress::from_str("1.2.3.4:5678");
445 assert!(addr_v4.is_ok());
446 let addr_v6 = NetAddress::from_str("[2a01:4f8:191:1143::2]:5678");
447 assert!(addr_v6.is_ok());
448 }
449
450 #[test]
451 fn test_prefix_bucket() {
452 let prefix_bytes: [u8; 2] = [42u8, 43u8];
453 let addr = NetAddress::from_str(format!("{0}.{1}.3.4:5678", prefix_bytes[0], prefix_bytes[1]).as_str()).unwrap();
454 assert!(addr.prefix_bucket() == PrefixBucket(u16::from_be_bytes(prefix_bytes) as u64));
455 }
456
457 #[test]
458 fn test_contextual_address_ser() {
459 let addr = IpAddress::from_str("127.0.0.1").unwrap();
460 let port = Some(1234);
461 let net_addr = ContextualNetAddress::new(addr, port);
462 let s = serde_json::to_string(&net_addr).unwrap();
463 assert_eq!(s, r#"{"ip":"127.0.0.1","port":1234}"#);
464 }
465
466 #[test]
467 fn test_is_publicly_routable() {
468 assert!(!IpAddress::from_str("198.18.0.0").unwrap().is_publicly_routable());
470 assert!(!IpAddress::from_str("198.19.255.255").unwrap().is_publicly_routable());
471 assert!(IpAddress::from_str("198.17.255.255").unwrap().is_publicly_routable());
472 assert!(IpAddress::from_str("198.20.0.0").unwrap().is_publicly_routable());
473
474 assert!(!IpAddress::from_str("0.0.0.0").unwrap().is_publicly_routable());
476 assert!(!IpAddress::from_str("0.0.0.1").unwrap().is_publicly_routable());
477 assert!(!IpAddress::from_str("0.0.1.0").unwrap().is_publicly_routable());
478 assert!(!IpAddress::from_str("0.1.0.0").unwrap().is_publicly_routable());
479
480 assert!(!IpAddress::from_str("2001:db8::").unwrap().is_publicly_routable());
482 assert!(!IpAddress::from_str("2001:db8:ffff:ffff:ffff:ffff:ffff:ffff").unwrap().is_publicly_routable());
483 assert!(IpAddress::from_str("2001:db7:ffff:ffff:ffff:ffff:ffff:ffff").unwrap().is_publicly_routable());
484 assert!(IpAddress::from_str("2001:db9::").unwrap().is_publicly_routable());
485
486 assert!(!IpAddress::from_str("127.0.0.1").unwrap().is_publicly_routable());
488
489 assert!(IpAddress::from_str("123.45.67.89").unwrap().is_publicly_routable());
491
492 assert!(!IpAddress::from_str("10.0.0.0").unwrap().is_publicly_routable());
494 assert!(!IpAddress::from_str("10.255.255.255").unwrap().is_publicly_routable());
495 assert!(IpAddress::from_str("9.255.255.255").unwrap().is_publicly_routable());
496 assert!(IpAddress::from_str("11.0.0.0").unwrap().is_publicly_routable());
497
498 assert!(!IpAddress::from_str("172.16.0.0").unwrap().is_publicly_routable());
499 assert!(!IpAddress::from_str("172.31.255.255").unwrap().is_publicly_routable());
500 assert!(IpAddress::from_str("172.15.255.255").unwrap().is_publicly_routable());
501 assert!(IpAddress::from_str("172.32.0.0").unwrap().is_publicly_routable());
502
503 assert!(!IpAddress::from_str("192.168.0.0").unwrap().is_publicly_routable());
504 assert!(!IpAddress::from_str("192.168.255.255").unwrap().is_publicly_routable());
505 assert!(IpAddress::from_str("192.167.255.255").unwrap().is_publicly_routable());
506 assert!(IpAddress::from_str("192.169.0.0").unwrap().is_publicly_routable());
507
508 assert!(!IpAddress::from_str("169.254.0.0").unwrap().is_publicly_routable());
510 assert!(!IpAddress::from_str("169.254.255.255").unwrap().is_publicly_routable());
511 assert!(IpAddress::from_str("169.253.255.255").unwrap().is_publicly_routable());
512 assert!(IpAddress::from_str("169.255.0.0").unwrap().is_publicly_routable());
513
514 assert!(!IpAddress::from_str("2002::").unwrap().is_publicly_routable());
516 assert!(!IpAddress::from_str("2002:ffff:ffff:ffff:ffff:ffff:ffff:ffff").unwrap().is_publicly_routable());
517 assert!(IpAddress::from_str("2001:ffff:ffff:ffff:ffff:ffff:ffff:ffff").unwrap().is_publicly_routable());
518 assert!(IpAddress::from_str("2003::").unwrap().is_publicly_routable());
519
520 assert!(!IpAddress::from_str("fc00::").unwrap().is_publicly_routable());
522 assert!(!IpAddress::from_str("fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff").unwrap().is_publicly_routable());
523 assert!(IpAddress::from_str("fb00:ffff:ffff:ffff:ffff:ffff:ffff:ffff").unwrap().is_publicly_routable());
524 assert!(IpAddress::from_str("fe00::").unwrap().is_publicly_routable());
525
526 assert!(!IpAddress::from_str("2001::").unwrap().is_publicly_routable());
528 assert!(!IpAddress::from_str("2001:0:ffff:ffff:ffff:ffff:ffff:ffff").unwrap().is_publicly_routable());
529 assert!(IpAddress::from_str("2000:0:ffff:ffff:ffff:ffff:ffff:ffff").unwrap().is_publicly_routable());
530 assert!(IpAddress::from_str("2001:1::").unwrap().is_publicly_routable());
531
532 assert!(!IpAddress::from_str("2001:10::").unwrap().is_publicly_routable());
534 assert!(!IpAddress::from_str("2001:1f:ffff:ffff:ffff:ffff:ffff:ffff").unwrap().is_publicly_routable());
535 assert!(IpAddress::from_str("2001:f:ffff:ffff:ffff:ffff:ffff:ffff").unwrap().is_publicly_routable());
536 assert!(IpAddress::from_str("2001:20::").unwrap().is_publicly_routable());
537
538 assert!(!IpAddress::from_str("fe80::").unwrap().is_publicly_routable());
540 assert!(!IpAddress::from_str("fe80::ffff:ffff:ffff:ffff").unwrap().is_publicly_routable());
541 assert!(IpAddress::from_str("fe7f::ffff:ffff:ffff:ffff").unwrap().is_publicly_routable());
542 assert!(IpAddress::from_str("fe81::").unwrap().is_publicly_routable());
543
544 assert!(!IpAddress::from_str("192.0.2.0").unwrap().is_publicly_routable());
546 assert!(!IpAddress::from_str("192.0.2.255").unwrap().is_publicly_routable());
547 assert!(IpAddress::from_str("192.0.1.255").unwrap().is_publicly_routable());
548 assert!(IpAddress::from_str("192.0.3.0").unwrap().is_publicly_routable());
549
550 assert!(!IpAddress::from_str("198.51.100.0").unwrap().is_publicly_routable());
551 assert!(!IpAddress::from_str("198.51.100.255").unwrap().is_publicly_routable());
552 assert!(IpAddress::from_str("198.51.99.255").unwrap().is_publicly_routable());
553 assert!(IpAddress::from_str("198.51.101.0").unwrap().is_publicly_routable());
554
555 assert!(!IpAddress::from_str("203.0.113.0").unwrap().is_publicly_routable());
556 assert!(!IpAddress::from_str("203.0.113.255").unwrap().is_publicly_routable());
557 assert!(IpAddress::from_str("203.0.112.255").unwrap().is_publicly_routable());
558 assert!(IpAddress::from_str("203.0.114.0").unwrap().is_publicly_routable());
559
560 assert!(!IpAddress::from_str("64:ff9b::").unwrap().is_publicly_routable());
562 assert!(!IpAddress::from_str("64:ff9b::ffff:ffff").unwrap().is_publicly_routable());
563 assert!(IpAddress::from_str("64:ff9a::ffff:ffff").unwrap().is_publicly_routable());
564 assert!(IpAddress::from_str("64:ff9b:1::").unwrap().is_publicly_routable());
565
566 assert!(!IpAddress::from_str("::ffff:0:0:0").unwrap().is_publicly_routable());
568 assert!(!IpAddress::from_str("::ffff:0:ffff:ffff").unwrap().is_publicly_routable());
569 assert!(IpAddress::from_str("::fffe:0:ffff:ffff").unwrap().is_publicly_routable());
570 assert!(IpAddress::from_str("::ffff:1:0:0").unwrap().is_publicly_routable());
571
572 assert!(!IpAddress::from_str("100.64.0.0").unwrap().is_publicly_routable());
574 assert!(!IpAddress::from_str("100.127.255.255").unwrap().is_publicly_routable());
575 assert!(IpAddress::from_str("100.63.255.255").unwrap().is_publicly_routable());
576 assert!(IpAddress::from_str("100.128.0.0").unwrap().is_publicly_routable());
577
578 assert!(!IpAddress::from_str("2001:470::").unwrap().is_publicly_routable());
580 assert!(!IpAddress::from_str("2001:470:ffff:ffff:ffff:ffff:ffff:ffff").unwrap().is_publicly_routable());
581 assert!(IpAddress::from_str("2001:46f:ffff:ffff:ffff:ffff:ffff:ffff").unwrap().is_publicly_routable());
582 assert!(IpAddress::from_str("2001:471::").unwrap().is_publicly_routable());
583
584 assert!(!IpAddress::from_str("255.255.255.255").unwrap().is_publicly_routable());
586 }
587}