1use std::net::IpAddr;
8
9use serde::{Deserialize, Serialize};
10
11#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
12#[serde(rename_all = "lowercase")]
13pub enum TransportProtocol {
14 Quic,
15 Tcp,
16}
17
18#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
25pub struct RelayRoute {
26 pub relay_addr: Box<PeerAddr>,
28 pub slot_id: u64,
30}
31
32#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
33pub struct PeerAddr {
34 pub ip: IpAddr,
35 pub port: u16,
36 pub transport: TransportProtocol,
37 pub pubkey_hint: Option<[u8; 32]>,
38 #[serde(default, skip_serializing_if = "Option::is_none")]
41 pub relay_via: Option<RelayRoute>,
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47
48 #[test]
49 fn peer_addr_cbor_roundtrip() {
50 let addr = PeerAddr {
51 ip: "127.0.0.1".parse().expect("valid ip"),
52 port: 7000,
53 transport: TransportProtocol::Quic,
54 pubkey_hint: Some([7u8; 32]),
55 relay_via: None,
56 };
57
58 let encoded = crate::cbor::to_vec(&addr).expect("encode peer addr");
59 let decoded: PeerAddr = crate::cbor::from_slice(&encoded).expect("decode peer addr");
60 assert_eq!(decoded, addr);
61 }
62
63 #[test]
64 fn peer_addr_with_relay_via_roundtrip() {
65 let relay = PeerAddr {
66 ip: "10.0.0.1".parse().expect("valid ip"),
67 port: 8000,
68 transport: TransportProtocol::Tcp,
69 pubkey_hint: Some([1u8; 32]),
70 relay_via: None,
71 };
72 let addr = PeerAddr {
73 ip: "192.168.1.5".parse().expect("valid ip"),
74 port: 7000,
75 transport: TransportProtocol::Tcp,
76 pubkey_hint: Some([7u8; 32]),
77 relay_via: Some(RelayRoute {
78 relay_addr: Box::new(relay.clone()),
79 slot_id: 42,
80 }),
81 };
82
83 let encoded = crate::cbor::to_vec(&addr).expect("encode peer addr with relay");
84 let decoded: PeerAddr =
85 crate::cbor::from_slice(&encoded).expect("decode peer addr with relay");
86 assert_eq!(decoded, addr);
87 let route = decoded.relay_via.unwrap();
88 assert_eq!(*route.relay_addr, relay);
89 assert_eq!(route.slot_id, 42);
90 }
91
92 #[test]
93 fn peer_addr_without_relay_via_is_backward_compatible() {
94 let original = PeerAddr {
99 ip: "10.0.0.5".parse().unwrap(),
100 port: 9000,
101 transport: TransportProtocol::Tcp,
102 pubkey_hint: None,
103 relay_via: None,
104 };
105 let full_bytes = crate::cbor::to_vec(&original).expect("encode");
106 let mut val: crate::cbor::Value =
107 crate::cbor::from_slice(&full_bytes).expect("decode value");
108 if let crate::cbor::Value::Map(ref mut m) = val {
110 m.retain(|(k, _)| *k != crate::cbor::Value::Text("relay_via".into()));
111 }
112 let legacy = crate::cbor::to_vec(&val).expect("re-encode without relay_via");
113 let decoded: PeerAddr = crate::cbor::from_slice(&legacy).expect("decode legacy peer addr");
114 assert_eq!(decoded.relay_via, None);
115 assert_eq!(decoded.ip, original.ip);
116 assert_eq!(decoded.port, 9000);
117 }
118}