wacore_noise/
edge_routing.rs1use thiserror::Error;
2use wacore_binary::consts::WA_CONN_HEADER;
3
4pub const MAX_EDGE_ROUTING_LEN: usize = 0xFF_FFFF;
6
7#[derive(Debug, Error)]
8pub enum EdgeRoutingError {
9 #[error("edge routing info too large (max {MAX_EDGE_ROUTING_LEN} bytes)")]
10 RoutingInfoTooLarge,
11}
12
13pub fn build_edge_routing_preintro(routing_info: &[u8]) -> Result<Vec<u8>, EdgeRoutingError> {
16 let len = routing_info.len();
17 if len > MAX_EDGE_ROUTING_LEN {
18 return Err(EdgeRoutingError::RoutingInfoTooLarge);
19 }
20
21 let mut preintro = Vec::with_capacity(7 + len);
22 preintro.extend_from_slice(b"ED\x00\x01");
23 preintro.push((len >> 16) as u8);
24 preintro.push((len >> 8) as u8);
25 preintro.push(len as u8);
26 preintro.extend_from_slice(routing_info);
27 Ok(preintro)
28}
29
30pub fn build_handshake_header(edge_routing_info: Option<&[u8]>) -> (Vec<u8>, bool) {
38 let Some(routing_info) = edge_routing_info else {
39 return (WA_CONN_HEADER.to_vec(), false);
40 };
41
42 match build_edge_routing_preintro(routing_info) {
43 Ok(mut header) => {
44 header.extend_from_slice(&WA_CONN_HEADER);
45 (header, true)
46 }
47 Err(_) => (WA_CONN_HEADER.to_vec(), false),
51 }
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57
58 #[test]
59 fn test_build_edge_routing_preintro_basic() {
60 let routing_data = vec![0x01, 0x02, 0x03];
61 let preintro = build_edge_routing_preintro(&routing_data)
62 .expect("valid routing data should build preintro");
63
64 assert_eq!(&preintro[0..4], b"ED\x00\x01");
65 assert_eq!(preintro[4], 0x00);
66 assert_eq!(preintro[5], 0x00);
67 assert_eq!(preintro[6], 0x03);
68 assert_eq!(&preintro[7..], &routing_data[..]);
69 }
70
71 #[test]
72 fn test_build_edge_routing_preintro_empty() {
73 let preintro =
74 build_edge_routing_preintro(&[]).expect("valid routing data should build preintro");
75
76 assert_eq!(&preintro[0..4], b"ED\x00\x01");
77 assert_eq!(preintro[4], 0x00);
78 assert_eq!(preintro[5], 0x00);
79 assert_eq!(preintro[6], 0x00);
80 assert_eq!(preintro.len(), 7);
81 }
82
83 #[test]
84 fn test_build_edge_routing_preintro_large_length() {
85 let routing_data = vec![0xAA; 0x010203];
86 let preintro = build_edge_routing_preintro(&routing_data)
87 .expect("valid routing data should build preintro");
88
89 assert_eq!(preintro[4], 0x01);
90 assert_eq!(preintro[5], 0x02);
91 assert_eq!(preintro[6], 0x03);
92 }
93
94 #[test]
95 fn test_build_edge_routing_preintro_too_large() {
96 let routing_data = vec![0x00; MAX_EDGE_ROUTING_LEN + 1];
97 let result = build_edge_routing_preintro(&routing_data);
98
99 assert!(matches!(result, Err(EdgeRoutingError::RoutingInfoTooLarge)));
100 }
101
102 #[test]
103 fn test_build_edge_routing_preintro_max_size() {
104 let len = MAX_EDGE_ROUTING_LEN;
105
106 assert_eq!((len >> 16) as u8, 0xFF);
107 assert_eq!((len >> 8) as u8, 0xFF);
108 assert_eq!(len as u8, 0xFF);
109 }
110
111 #[test]
112 fn test_build_handshake_header_without_edge_routing() {
113 let (header, used) = build_handshake_header(None);
114 assert_eq!(header, WA_CONN_HEADER.to_vec());
115 assert!(!used);
116 }
117
118 #[test]
119 fn test_build_handshake_header_with_edge_routing() {
120 let routing = vec![0x01, 0x02, 0x03];
121 let (header, used) = build_handshake_header(Some(&routing));
122
123 assert!(used);
124 assert!(header.starts_with(b"ED\x00\x01"));
125 assert!(header.ends_with(&WA_CONN_HEADER));
126 }
127
128 #[test]
129 fn test_build_handshake_header_with_oversized_routing() {
130 let routing = vec![0x00; MAX_EDGE_ROUTING_LEN + 1];
131 let (header, used) = build_handshake_header(Some(&routing));
132
133 assert!(!used);
134 assert_eq!(header, WA_CONN_HEADER.to_vec());
135 }
136}