1use super::ProtocolError;
4use crate::NodeAddr;
5use crate::tree::TreeCoordinate;
6use std::fmt;
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq)]
25#[repr(u8)]
26pub enum SessionMessageType {
27 DataPacket = 0x10,
31 SenderReport = 0x11,
33 ReceiverReport = 0x12,
35 PathMtuNotification = 0x13,
37 CoordsWarmup = 0x14,
39 EndpointData = 0x15,
41 TraversalOffer = 0x16,
43 TraversalAnswer = 0x17,
45
46 CoordsRequired = 0x20,
49 PathBroken = 0x21,
51 MtuExceeded = 0x22,
53}
54
55impl SessionMessageType {
56 pub fn from_byte(b: u8) -> Option<Self> {
58 match b {
59 0x10 => Some(SessionMessageType::DataPacket),
60 0x11 => Some(SessionMessageType::SenderReport),
61 0x12 => Some(SessionMessageType::ReceiverReport),
62 0x13 => Some(SessionMessageType::PathMtuNotification),
63 0x14 => Some(SessionMessageType::CoordsWarmup),
64 0x15 => Some(SessionMessageType::EndpointData),
65 0x16 => Some(SessionMessageType::TraversalOffer),
66 0x17 => Some(SessionMessageType::TraversalAnswer),
67 0x20 => Some(SessionMessageType::CoordsRequired),
68 0x21 => Some(SessionMessageType::PathBroken),
69 0x22 => Some(SessionMessageType::MtuExceeded),
70 _ => None,
71 }
72 }
73
74 pub fn to_byte(self) -> u8 {
76 self as u8
77 }
78}
79
80impl fmt::Display for SessionMessageType {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 let name = match self {
83 SessionMessageType::DataPacket => "DataPacket",
84 SessionMessageType::SenderReport => "SenderReport",
85 SessionMessageType::ReceiverReport => "ReceiverReport",
86 SessionMessageType::PathMtuNotification => "PathMtuNotification",
87 SessionMessageType::CoordsWarmup => "CoordsWarmup",
88 SessionMessageType::EndpointData => "EndpointData",
89 SessionMessageType::TraversalOffer => "TraversalOffer",
90 SessionMessageType::TraversalAnswer => "TraversalAnswer",
91 SessionMessageType::CoordsRequired => "CoordsRequired",
92 SessionMessageType::PathBroken => "PathBroken",
93 SessionMessageType::MtuExceeded => "MtuExceeded",
94 };
95 write!(f, "{}", name)
96 }
97}
98
99pub(crate) fn coords_wire_size(coords: &TreeCoordinate) -> usize {
105 2 + coords.entries().len() * 16
106}
107
108pub(crate) fn encode_coords(coords: &TreeCoordinate, buf: &mut Vec<u8>) {
113 let addrs: Vec<&NodeAddr> = coords.node_addrs().collect();
114 let count = addrs.len() as u16;
115 buf.extend_from_slice(&count.to_le_bytes());
116 for addr in addrs {
117 buf.extend_from_slice(addr.as_bytes());
118 }
119}
120
121pub(crate) fn decode_coords(data: &[u8]) -> Result<(TreeCoordinate, usize), ProtocolError> {
125 if data.len() < 2 {
126 return Err(ProtocolError::MessageTooShort {
127 expected: 2,
128 got: data.len(),
129 });
130 }
131 let count = u16::from_le_bytes([data[0], data[1]]) as usize;
132 let needed = 2 + count * 16;
133 if data.len() < needed {
134 return Err(ProtocolError::MessageTooShort {
135 expected: needed,
136 got: data.len(),
137 });
138 }
139 if count == 0 {
140 return Err(ProtocolError::Malformed(
141 "coordinate with zero entries".into(),
142 ));
143 }
144 let mut addrs = Vec::with_capacity(count);
145 for i in 0..count {
146 let offset = 2 + i * 16;
147 let mut bytes = [0u8; 16];
148 bytes.copy_from_slice(&data[offset..offset + 16]);
149 addrs.push(NodeAddr::from_bytes(bytes));
150 }
151 let coord =
152 TreeCoordinate::from_addrs(addrs).map_err(|e| ProtocolError::Malformed(e.to_string()))?;
153 Ok((coord, needed))
154}
155
156pub(crate) fn decode_optional_coords(
160 data: &[u8],
161) -> Result<(Option<TreeCoordinate>, usize), ProtocolError> {
162 if data.len() < 2 {
163 return Err(ProtocolError::MessageTooShort {
164 expected: 2,
165 got: data.len(),
166 });
167 }
168 let count = u16::from_le_bytes([data[0], data[1]]) as usize;
169 let needed = 2 + count * 16;
170 if data.len() < needed {
171 return Err(ProtocolError::MessageTooShort {
172 expected: needed,
173 got: data.len(),
174 });
175 }
176 if count == 0 {
177 return Ok((None, 2));
178 }
179 let mut addrs = Vec::with_capacity(count);
180 for i in 0..count {
181 let offset = 2 + i * 16;
182 let mut bytes = [0u8; 16];
183 bytes.copy_from_slice(&data[offset..offset + 16]);
184 addrs.push(NodeAddr::from_bytes(bytes));
185 }
186 let coord =
187 TreeCoordinate::from_addrs(addrs).map_err(|e| ProtocolError::Malformed(e.to_string()))?;
188 Ok((Some(coord), needed))
189}
190
191fn encode_empty_coords(buf: &mut Vec<u8>) {
193 buf.extend_from_slice(&0u16.to_le_bytes());
194}
195
196#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
202pub struct SessionFlags {
203 pub request_ack: bool,
205 pub bidirectional: bool,
207}
208
209impl SessionFlags {
210 pub fn new() -> Self {
212 Self::default()
213 }
214
215 pub fn with_ack(mut self) -> Self {
217 self.request_ack = true;
218 self
219 }
220
221 pub fn bidirectional(mut self) -> Self {
223 self.bidirectional = true;
224 self
225 }
226
227 pub fn to_byte(&self) -> u8 {
229 let mut flags = 0u8;
230 if self.request_ack {
231 flags |= 0x01;
232 }
233 if self.bidirectional {
234 flags |= 0x02;
235 }
236 flags
237 }
238
239 pub fn from_byte(byte: u8) -> Self {
241 Self {
242 request_ack: byte & 0x01 != 0,
243 bidirectional: byte & 0x02 != 0,
244 }
245 }
246}
247
248#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
261pub struct FspFlags {
262 pub coords_present: bool,
264 pub key_epoch: bool,
266 pub unencrypted: bool,
268}
269
270impl FspFlags {
271 pub fn new() -> Self {
273 Self::default()
274 }
275
276 pub fn to_byte(&self) -> u8 {
278 let mut flags = 0u8;
279 if self.coords_present {
280 flags |= 0x01;
281 }
282 if self.key_epoch {
283 flags |= 0x02;
284 }
285 if self.unencrypted {
286 flags |= 0x04;
287 }
288 flags
289 }
290
291 pub fn from_byte(byte: u8) -> Self {
293 Self {
294 coords_present: byte & 0x01 != 0,
295 key_epoch: byte & 0x02 != 0,
296 unencrypted: byte & 0x04 != 0,
297 }
298 }
299}
300
301#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
308pub struct FspInnerFlags {
309 pub spin_bit: bool,
311}
312
313impl FspInnerFlags {
314 pub fn new() -> Self {
316 Self::default()
317 }
318
319 pub fn to_byte(&self) -> u8 {
321 if self.spin_bit { 0x01 } else { 0x00 }
322 }
323
324 pub fn from_byte(byte: u8) -> Self {
326 Self {
327 spin_bit: byte & 0x01 != 0,
328 }
329 }
330}
331
332#[derive(Clone, Debug)]
364pub struct SessionSetup {
365 pub src_coords: TreeCoordinate,
367 pub dest_coords: TreeCoordinate,
369 pub flags: SessionFlags,
371 pub handshake_payload: Vec<u8>,
373}
374
375impl SessionSetup {
376 pub fn new(src_coords: TreeCoordinate, dest_coords: TreeCoordinate) -> Self {
378 Self {
379 src_coords,
380 dest_coords,
381 flags: SessionFlags::new(),
382 handshake_payload: Vec::new(),
383 }
384 }
385
386 pub fn with_flags(mut self, flags: SessionFlags) -> Self {
388 self.flags = flags;
389 self
390 }
391
392 pub fn with_handshake(mut self, payload: Vec<u8>) -> Self {
394 self.handshake_payload = payload;
395 self
396 }
397
398 pub fn encode(&self) -> Vec<u8> {
403 let mut body = Vec::new();
405 body.push(self.flags.to_byte());
406 encode_coords(&self.src_coords, &mut body);
407 encode_coords(&self.dest_coords, &mut body);
408 let hs_len = self.handshake_payload.len() as u16;
409 body.extend_from_slice(&hs_len.to_le_bytes());
410 body.extend_from_slice(&self.handshake_payload);
411
412 let payload_len = body.len() as u16;
414 let mut buf = Vec::with_capacity(4 + body.len());
415 buf.push(0x01); buf.push(0x00); buf.extend_from_slice(&payload_len.to_le_bytes());
418 buf.extend_from_slice(&body);
419 buf
420 }
421
422 pub fn decode(payload: &[u8]) -> Result<Self, ProtocolError> {
424 if payload.is_empty() {
425 return Err(ProtocolError::MessageTooShort {
426 expected: 1,
427 got: 0,
428 });
429 }
430 let flags = SessionFlags::from_byte(payload[0]);
431 let mut offset = 1;
432
433 let (src_coords, consumed) = decode_coords(&payload[offset..])?;
434 offset += consumed;
435
436 let (dest_coords, consumed) = decode_coords(&payload[offset..])?;
437 offset += consumed;
438
439 if payload.len() < offset + 2 {
440 return Err(ProtocolError::MessageTooShort {
441 expected: offset + 2,
442 got: payload.len(),
443 });
444 }
445 let hs_len = u16::from_le_bytes([payload[offset], payload[offset + 1]]) as usize;
446 offset += 2;
447
448 if payload.len() < offset + hs_len {
449 return Err(ProtocolError::MessageTooShort {
450 expected: offset + hs_len,
451 got: payload.len(),
452 });
453 }
454 let handshake_payload = payload[offset..offset + hs_len].to_vec();
455
456 Ok(Self {
457 src_coords,
458 dest_coords,
459 flags,
460 handshake_payload,
461 })
462 }
463}
464
465#[derive(Clone, Debug)]
497pub struct SessionAck {
498 pub src_coords: TreeCoordinate,
500 pub dest_coords: TreeCoordinate,
502 pub flags: u8,
504 pub handshake_payload: Vec<u8>,
506}
507
508impl SessionAck {
509 pub fn new(src_coords: TreeCoordinate, dest_coords: TreeCoordinate) -> Self {
511 Self {
512 src_coords,
513 dest_coords,
514 flags: 0,
515 handshake_payload: Vec::new(),
516 }
517 }
518
519 pub fn with_handshake(mut self, payload: Vec<u8>) -> Self {
521 self.handshake_payload = payload;
522 self
523 }
524
525 pub fn encode(&self) -> Vec<u8> {
530 let mut body = Vec::new();
532 body.push(self.flags);
533 encode_coords(&self.src_coords, &mut body);
534 encode_coords(&self.dest_coords, &mut body);
535 let hs_len = self.handshake_payload.len() as u16;
536 body.extend_from_slice(&hs_len.to_le_bytes());
537 body.extend_from_slice(&self.handshake_payload);
538
539 let payload_len = body.len() as u16;
541 let mut buf = Vec::with_capacity(4 + body.len());
542 buf.push(0x02); buf.push(0x00); buf.extend_from_slice(&payload_len.to_le_bytes());
545 buf.extend_from_slice(&body);
546 buf
547 }
548
549 pub fn decode(payload: &[u8]) -> Result<Self, ProtocolError> {
551 if payload.is_empty() {
552 return Err(ProtocolError::MessageTooShort {
553 expected: 1,
554 got: 0,
555 });
556 }
557 let flags = payload[0];
558 let mut offset = 1;
559
560 let (src_coords, consumed) = decode_coords(&payload[offset..])?;
561 offset += consumed;
562
563 let (dest_coords, consumed) = decode_coords(&payload[offset..])?;
564 offset += consumed;
565
566 if payload.len() < offset + 2 {
567 return Err(ProtocolError::MessageTooShort {
568 expected: offset + 2,
569 got: payload.len(),
570 });
571 }
572 let hs_len = u16::from_le_bytes([payload[offset], payload[offset + 1]]) as usize;
573 offset += 2;
574
575 if payload.len() < offset + hs_len {
576 return Err(ProtocolError::MessageTooShort {
577 expected: offset + hs_len,
578 got: payload.len(),
579 });
580 }
581 let handshake_payload = payload[offset..offset + hs_len].to_vec();
582
583 Ok(Self {
584 src_coords,
585 dest_coords,
586 flags,
587 handshake_payload,
588 })
589 }
590}
591
592#[derive(Clone, Debug)]
610pub struct SessionMsg3 {
611 pub flags: u8,
613 pub handshake_payload: Vec<u8>,
615}
616
617impl SessionMsg3 {
618 pub fn new(handshake_payload: Vec<u8>) -> Self {
620 Self {
621 flags: 0,
622 handshake_payload,
623 }
624 }
625
626 pub fn encode(&self) -> Vec<u8> {
631 let mut body = Vec::new();
633 body.push(self.flags);
634 let hs_len = self.handshake_payload.len() as u16;
635 body.extend_from_slice(&hs_len.to_le_bytes());
636 body.extend_from_slice(&self.handshake_payload);
637
638 let payload_len = body.len() as u16;
640 let mut buf = Vec::with_capacity(4 + body.len());
641 buf.push(0x03); buf.push(0x00); buf.extend_from_slice(&payload_len.to_le_bytes());
644 buf.extend_from_slice(&body);
645 buf
646 }
647
648 pub fn decode(payload: &[u8]) -> Result<Self, ProtocolError> {
650 if payload.is_empty() {
651 return Err(ProtocolError::MessageTooShort {
652 expected: 1,
653 got: 0,
654 });
655 }
656 let flags = payload[0];
657 let mut offset = 1;
658
659 if payload.len() < offset + 2 {
660 return Err(ProtocolError::MessageTooShort {
661 expected: offset + 2,
662 got: payload.len(),
663 });
664 }
665 let hs_len = u16::from_le_bytes([payload[offset], payload[offset + 1]]) as usize;
666 offset += 2;
667
668 if payload.len() < offset + hs_len {
669 return Err(ProtocolError::MessageTooShort {
670 expected: offset + hs_len,
671 got: payload.len(),
672 });
673 }
674 let handshake_payload = payload[offset..offset + hs_len].to_vec();
675
676 Ok(Self {
677 flags,
678 handshake_payload,
679 })
680 }
681}
682
683#[derive(Debug, Clone, PartialEq, Eq)]
706pub struct SessionSenderReport {
707 pub interval_start_counter: u64,
708 pub interval_end_counter: u64,
709 pub interval_start_timestamp: u32,
710 pub interval_end_timestamp: u32,
711 pub interval_bytes_sent: u32,
712 pub cumulative_packets_sent: u64,
713 pub cumulative_bytes_sent: u64,
714}
715
716pub const SESSION_SENDER_REPORT_SIZE: usize = 46;
718
719impl SessionSenderReport {
720 pub fn encode(&self) -> Vec<u8> {
722 let mut buf = Vec::with_capacity(SESSION_SENDER_REPORT_SIZE);
723 buf.extend_from_slice(&[0u8; 2]); buf.extend_from_slice(&self.interval_start_counter.to_le_bytes());
725 buf.extend_from_slice(&self.interval_end_counter.to_le_bytes());
726 buf.extend_from_slice(&self.interval_start_timestamp.to_le_bytes());
727 buf.extend_from_slice(&self.interval_end_timestamp.to_le_bytes());
728 buf.extend_from_slice(&self.interval_bytes_sent.to_le_bytes());
729 buf.extend_from_slice(&self.cumulative_packets_sent.to_le_bytes());
730 buf.extend_from_slice(&self.cumulative_bytes_sent.to_le_bytes());
731 buf
732 }
733
734 pub fn decode(body: &[u8]) -> Result<Self, ProtocolError> {
736 if body.len() < SESSION_SENDER_REPORT_SIZE {
737 return Err(ProtocolError::MessageTooShort {
738 expected: SESSION_SENDER_REPORT_SIZE,
739 got: body.len(),
740 });
741 }
742 let p = &body[2..];
744 Ok(Self {
745 interval_start_counter: u64::from_le_bytes(p[0..8].try_into().unwrap()),
746 interval_end_counter: u64::from_le_bytes(p[8..16].try_into().unwrap()),
747 interval_start_timestamp: u32::from_le_bytes(p[16..20].try_into().unwrap()),
748 interval_end_timestamp: u32::from_le_bytes(p[20..24].try_into().unwrap()),
749 interval_bytes_sent: u32::from_le_bytes(p[24..28].try_into().unwrap()),
750 cumulative_packets_sent: u64::from_le_bytes(p[28..36].try_into().unwrap()),
751 cumulative_bytes_sent: u64::from_le_bytes(p[36..44].try_into().unwrap()),
752 })
753 }
754}
755
756#[derive(Debug, Clone, PartialEq, Eq)]
782pub struct SessionReceiverReport {
783 pub highest_counter: u64,
784 pub cumulative_packets_recv: u64,
785 pub cumulative_bytes_recv: u64,
786 pub timestamp_echo: u32,
787 pub dwell_time: u16,
788 pub max_burst_loss: u16,
789 pub mean_burst_loss: u16,
790 pub jitter: u32,
791 pub ecn_ce_count: u32,
792 pub owd_trend: i32,
793 pub burst_loss_count: u32,
794 pub cumulative_reorder_count: u32,
795 pub interval_packets_recv: u32,
796 pub interval_bytes_recv: u32,
797}
798
799pub const SESSION_RECEIVER_REPORT_SIZE: usize = 66;
801
802impl SessionReceiverReport {
803 pub fn encode(&self) -> Vec<u8> {
805 let mut buf = Vec::with_capacity(SESSION_RECEIVER_REPORT_SIZE);
806 buf.extend_from_slice(&[0u8; 2]); buf.extend_from_slice(&self.highest_counter.to_le_bytes());
808 buf.extend_from_slice(&self.cumulative_packets_recv.to_le_bytes());
809 buf.extend_from_slice(&self.cumulative_bytes_recv.to_le_bytes());
810 buf.extend_from_slice(&self.timestamp_echo.to_le_bytes());
811 buf.extend_from_slice(&self.dwell_time.to_le_bytes());
812 buf.extend_from_slice(&self.max_burst_loss.to_le_bytes());
813 buf.extend_from_slice(&self.mean_burst_loss.to_le_bytes());
814 buf.extend_from_slice(&[0u8; 2]); buf.extend_from_slice(&self.jitter.to_le_bytes());
816 buf.extend_from_slice(&self.ecn_ce_count.to_le_bytes());
817 buf.extend_from_slice(&self.owd_trend.to_le_bytes());
818 buf.extend_from_slice(&self.burst_loss_count.to_le_bytes());
819 buf.extend_from_slice(&self.cumulative_reorder_count.to_le_bytes());
820 buf.extend_from_slice(&self.interval_packets_recv.to_le_bytes());
821 buf.extend_from_slice(&self.interval_bytes_recv.to_le_bytes());
822 buf
823 }
824
825 pub fn decode(body: &[u8]) -> Result<Self, ProtocolError> {
827 if body.len() < SESSION_RECEIVER_REPORT_SIZE {
828 return Err(ProtocolError::MessageTooShort {
829 expected: SESSION_RECEIVER_REPORT_SIZE,
830 got: body.len(),
831 });
832 }
833 let p = &body[2..];
835 Ok(Self {
836 highest_counter: u64::from_le_bytes(p[0..8].try_into().unwrap()),
837 cumulative_packets_recv: u64::from_le_bytes(p[8..16].try_into().unwrap()),
838 cumulative_bytes_recv: u64::from_le_bytes(p[16..24].try_into().unwrap()),
839 timestamp_echo: u32::from_le_bytes(p[24..28].try_into().unwrap()),
840 dwell_time: u16::from_le_bytes(p[28..30].try_into().unwrap()),
841 max_burst_loss: u16::from_le_bytes(p[30..32].try_into().unwrap()),
842 mean_burst_loss: u16::from_le_bytes(p[32..34].try_into().unwrap()),
843 jitter: u32::from_le_bytes(p[36..40].try_into().unwrap()),
845 ecn_ce_count: u32::from_le_bytes(p[40..44].try_into().unwrap()),
846 owd_trend: i32::from_le_bytes(p[44..48].try_into().unwrap()),
847 burst_loss_count: u32::from_le_bytes(p[48..52].try_into().unwrap()),
848 cumulative_reorder_count: u32::from_le_bytes(p[52..56].try_into().unwrap()),
849 interval_packets_recv: u32::from_le_bytes(p[56..60].try_into().unwrap()),
850 interval_bytes_recv: u32::from_le_bytes(p[60..64].try_into().unwrap()),
851 })
852 }
853}
854
855#[derive(Debug, Clone, PartialEq, Eq)]
867pub struct PathMtuNotification {
868 pub path_mtu: u16,
870}
871
872pub const PATH_MTU_NOTIFICATION_SIZE: usize = 2;
874
875impl PathMtuNotification {
876 pub fn new(path_mtu: u16) -> Self {
878 Self { path_mtu }
879 }
880
881 pub fn encode(&self) -> Vec<u8> {
883 self.path_mtu.to_le_bytes().to_vec()
884 }
885
886 pub fn decode(body: &[u8]) -> Result<Self, ProtocolError> {
888 if body.len() < PATH_MTU_NOTIFICATION_SIZE {
889 return Err(ProtocolError::MessageTooShort {
890 expected: PATH_MTU_NOTIFICATION_SIZE,
891 got: body.len(),
892 });
893 }
894 Ok(Self {
895 path_mtu: u16::from_le_bytes([body[0], body[1]]),
896 })
897 }
898}
899
900#[derive(Clone, Debug)]
924pub struct CoordsRequired {
925 pub dest_addr: NodeAddr,
927 pub reporter: NodeAddr,
929}
930
931pub const COORDS_REQUIRED_SIZE: usize = 34;
933
934impl CoordsRequired {
935 pub fn new(dest_addr: NodeAddr, reporter: NodeAddr) -> Self {
937 Self {
938 dest_addr,
939 reporter,
940 }
941 }
942
943 pub fn encode(&self) -> Vec<u8> {
947 let body_len = 1 + 1 + 16 + 16; let mut buf = Vec::with_capacity(4 + body_len);
950 buf.push(0x00); buf.push(0x04); let payload_len = body_len as u16;
954 buf.extend_from_slice(&payload_len.to_le_bytes());
955 buf.push(SessionMessageType::CoordsRequired.to_byte());
957 buf.push(0x00); buf.extend_from_slice(self.dest_addr.as_bytes());
959 buf.extend_from_slice(self.reporter.as_bytes());
960 buf
961 }
962
963 pub fn decode(payload: &[u8]) -> Result<Self, ProtocolError> {
965 if payload.len() < 33 {
967 return Err(ProtocolError::MessageTooShort {
968 expected: 33,
969 got: payload.len(),
970 });
971 }
972 let mut dest_bytes = [0u8; 16];
974 dest_bytes.copy_from_slice(&payload[1..17]);
975 let mut reporter_bytes = [0u8; 16];
976 reporter_bytes.copy_from_slice(&payload[17..33]);
977
978 Ok(Self {
979 dest_addr: NodeAddr::from_bytes(dest_bytes),
980 reporter: NodeAddr::from_bytes(reporter_bytes),
981 })
982 }
983}
984
985#[derive(Clone, Debug)]
1003pub struct PathBroken {
1004 pub dest_addr: NodeAddr,
1006 pub reporter: NodeAddr,
1008 pub last_known_coords: Option<TreeCoordinate>,
1010}
1011
1012impl PathBroken {
1013 pub fn new(dest_addr: NodeAddr, reporter: NodeAddr) -> Self {
1015 Self {
1016 dest_addr,
1017 reporter,
1018 last_known_coords: None,
1019 }
1020 }
1021
1022 pub fn with_last_coords(mut self, coords: TreeCoordinate) -> Self {
1024 self.last_known_coords = Some(coords);
1025 self
1026 }
1027
1028 pub fn encode(&self) -> Vec<u8> {
1032 let mut body = Vec::new();
1034 body.push(SessionMessageType::PathBroken.to_byte());
1035 body.push(0x00); body.extend_from_slice(self.dest_addr.as_bytes());
1037 body.extend_from_slice(self.reporter.as_bytes());
1038 if let Some(ref coords) = self.last_known_coords {
1039 encode_coords(coords, &mut body);
1040 } else {
1041 encode_empty_coords(&mut body);
1042 }
1043
1044 let payload_len = body.len() as u16;
1046 let mut buf = Vec::with_capacity(4 + body.len());
1047 buf.push(0x00); buf.push(0x04); buf.extend_from_slice(&payload_len.to_le_bytes());
1050 buf.extend_from_slice(&body);
1051 buf
1052 }
1053
1054 pub fn decode(payload: &[u8]) -> Result<Self, ProtocolError> {
1056 if payload.len() < 35 {
1058 return Err(ProtocolError::MessageTooShort {
1059 expected: 35,
1060 got: payload.len(),
1061 });
1062 }
1063 let mut dest_bytes = [0u8; 16];
1065 dest_bytes.copy_from_slice(&payload[1..17]);
1066 let mut reporter_bytes = [0u8; 16];
1067 reporter_bytes.copy_from_slice(&payload[17..33]);
1068
1069 let (last_known_coords, _consumed) = decode_optional_coords(&payload[33..])?;
1070
1071 Ok(Self {
1072 dest_addr: NodeAddr::from_bytes(dest_bytes),
1073 reporter: NodeAddr::from_bytes(reporter_bytes),
1074 last_known_coords,
1075 })
1076 }
1077}
1078
1079#[derive(Clone, Debug)]
1097pub struct MtuExceeded {
1098 pub dest_addr: NodeAddr,
1100 pub reporter: NodeAddr,
1102 pub mtu: u16,
1104}
1105
1106pub const MTU_EXCEEDED_SIZE: usize = 36;
1108
1109impl MtuExceeded {
1110 pub fn new(dest_addr: NodeAddr, reporter: NodeAddr, mtu: u16) -> Self {
1112 Self {
1113 dest_addr,
1114 reporter,
1115 mtu,
1116 }
1117 }
1118
1119 pub fn encode(&self) -> Vec<u8> {
1123 let body_len = MTU_EXCEEDED_SIZE; let mut buf = Vec::with_capacity(4 + body_len);
1125 buf.push(0x00); buf.push(0x04); let payload_len = body_len as u16;
1129 buf.extend_from_slice(&payload_len.to_le_bytes());
1130 buf.push(SessionMessageType::MtuExceeded.to_byte());
1132 buf.push(0x00); buf.extend_from_slice(self.dest_addr.as_bytes());
1134 buf.extend_from_slice(self.reporter.as_bytes());
1135 buf.extend_from_slice(&self.mtu.to_le_bytes());
1136 buf
1137 }
1138
1139 pub fn decode(payload: &[u8]) -> Result<Self, ProtocolError> {
1141 if payload.len() < 35 {
1143 return Err(ProtocolError::MessageTooShort {
1144 expected: 35,
1145 got: payload.len(),
1146 });
1147 }
1148 let mut dest_bytes = [0u8; 16];
1150 dest_bytes.copy_from_slice(&payload[1..17]);
1151 let mut reporter_bytes = [0u8; 16];
1152 reporter_bytes.copy_from_slice(&payload[17..33]);
1153 let mtu = u16::from_le_bytes([payload[33], payload[34]]);
1154
1155 Ok(Self {
1156 dest_addr: NodeAddr::from_bytes(dest_bytes),
1157 reporter: NodeAddr::from_bytes(reporter_bytes),
1158 mtu,
1159 })
1160 }
1161}
1162
1163#[cfg(test)]
1164mod tests {
1165 use super::*;
1166
1167 fn make_node_addr(val: u8) -> NodeAddr {
1168 let mut bytes = [0u8; 16];
1169 bytes[0] = val;
1170 NodeAddr::from_bytes(bytes)
1171 }
1172
1173 fn make_coords(ids: &[u8]) -> TreeCoordinate {
1174 TreeCoordinate::from_addrs(ids.iter().map(|&v| make_node_addr(v)).collect()).unwrap()
1175 }
1176
1177 #[test]
1180 fn test_session_message_type_roundtrip() {
1181 let types = [
1182 SessionMessageType::DataPacket,
1183 SessionMessageType::SenderReport,
1184 SessionMessageType::ReceiverReport,
1185 SessionMessageType::PathMtuNotification,
1186 SessionMessageType::CoordsWarmup,
1187 SessionMessageType::EndpointData,
1188 SessionMessageType::CoordsRequired,
1189 SessionMessageType::PathBroken,
1190 SessionMessageType::MtuExceeded,
1191 ];
1192
1193 for ty in types {
1194 let byte = ty.to_byte();
1195 let restored = SessionMessageType::from_byte(byte);
1196 assert_eq!(restored, Some(ty));
1197 }
1198 }
1199
1200 #[test]
1201 fn test_session_message_type_invalid() {
1202 assert!(SessionMessageType::from_byte(0xFF).is_none());
1203 assert!(SessionMessageType::from_byte(0x99).is_none());
1204 }
1205
1206 #[test]
1209 fn test_session_flags() {
1210 let flags = SessionFlags::new().with_ack().bidirectional();
1211
1212 assert!(flags.request_ack);
1213 assert!(flags.bidirectional);
1214
1215 let byte = flags.to_byte();
1216 let restored = SessionFlags::from_byte(byte);
1217
1218 assert_eq!(flags, restored);
1219 }
1220
1221 #[test]
1222 fn test_session_flags_default() {
1223 let flags = SessionFlags::new();
1224 assert!(!flags.request_ack);
1225 assert!(!flags.bidirectional);
1226 assert_eq!(flags.to_byte(), 0);
1227 }
1228
1229 #[test]
1232 fn test_session_setup() {
1233 let setup = SessionSetup::new(make_coords(&[1, 0]), make_coords(&[2, 0]))
1234 .with_flags(SessionFlags::new().with_ack());
1235
1236 assert!(setup.flags.request_ack);
1237 assert!(!setup.flags.bidirectional);
1238 }
1239
1240 #[test]
1243 fn test_coords_required() {
1244 let err = CoordsRequired::new(make_node_addr(1), make_node_addr(2));
1245
1246 assert_eq!(err.dest_addr, make_node_addr(1));
1247 assert_eq!(err.reporter, make_node_addr(2));
1248 }
1249
1250 #[test]
1253 fn test_path_broken() {
1254 let err = PathBroken::new(make_node_addr(2), make_node_addr(3))
1255 .with_last_coords(make_coords(&[2, 0]));
1256
1257 assert_eq!(err.dest_addr, make_node_addr(2));
1258 assert_eq!(err.reporter, make_node_addr(3));
1259 assert!(err.last_known_coords.is_some());
1260 }
1261
1262 #[test]
1265 fn test_session_setup_encode_decode() {
1266 let handshake = vec![0xAA; 82]; let setup = SessionSetup::new(make_coords(&[1, 2, 0]), make_coords(&[3, 4, 0]))
1268 .with_flags(SessionFlags::new().with_ack().bidirectional())
1269 .with_handshake(handshake.clone());
1270
1271 let encoded = setup.encode();
1272
1273 assert_eq!(encoded[0], 0x01);
1275 assert_eq!(encoded[1], 0x00); let payload_len = u16::from_le_bytes([encoded[2], encoded[3]]);
1277 assert_eq!(payload_len as usize, encoded.len() - 4);
1278
1279 let decoded = SessionSetup::decode(&encoded[4..]).unwrap();
1281
1282 assert_eq!(decoded.flags, setup.flags);
1283 assert_eq!(decoded.src_coords, setup.src_coords);
1284 assert_eq!(decoded.dest_coords, setup.dest_coords);
1285 assert_eq!(decoded.handshake_payload, handshake);
1286 }
1287
1288 #[test]
1289 fn test_session_setup_no_handshake() {
1290 let setup = SessionSetup::new(make_coords(&[5, 0]), make_coords(&[6, 0]));
1291
1292 let encoded = setup.encode();
1293 let decoded = SessionSetup::decode(&encoded[4..]).unwrap();
1294
1295 assert!(decoded.handshake_payload.is_empty());
1296 assert_eq!(decoded.src_coords, setup.src_coords);
1297 assert_eq!(decoded.dest_coords, setup.dest_coords);
1298 }
1299
1300 #[test]
1301 fn test_session_ack_encode_decode() {
1302 let handshake = vec![0xBB; 33]; let ack = SessionAck::new(make_coords(&[7, 8, 0]), make_coords(&[3, 4, 0]))
1304 .with_handshake(handshake.clone());
1305
1306 let encoded = ack.encode();
1307 assert_eq!(encoded[0], 0x02);
1309 assert_eq!(encoded[1], 0x00); let decoded = SessionAck::decode(&encoded[4..]).unwrap();
1312 assert_eq!(decoded.src_coords, ack.src_coords);
1313 assert_eq!(decoded.dest_coords, ack.dest_coords);
1314 assert_eq!(decoded.handshake_payload, handshake);
1315 }
1316
1317 #[test]
1318 fn test_coords_required_encode_decode() {
1319 let err = CoordsRequired::new(make_node_addr(0xAA), make_node_addr(0xBB));
1320
1321 let encoded = err.encode();
1322 assert_eq!(encoded.len(), 4 + COORDS_REQUIRED_SIZE);
1324 assert_eq!(encoded[0], 0x00);
1326 assert_eq!(encoded[1], 0x04); assert_eq!(encoded[4], 0x20);
1329
1330 let decoded = CoordsRequired::decode(&encoded[5..]).unwrap();
1332 assert_eq!(decoded.dest_addr, err.dest_addr);
1333 assert_eq!(decoded.reporter, err.reporter);
1334 }
1335
1336 #[test]
1337 fn test_path_broken_encode_decode_no_coords() {
1338 let err = PathBroken::new(make_node_addr(0xCC), make_node_addr(0xDD));
1339
1340 let encoded = err.encode();
1341 assert_eq!(encoded[0], 0x00);
1343 assert_eq!(encoded[1], 0x04); assert_eq!(encoded[4], 0x21); let decoded = PathBroken::decode(&encoded[5..]).unwrap();
1347 assert_eq!(decoded.dest_addr, err.dest_addr);
1348 assert_eq!(decoded.reporter, err.reporter);
1349 assert!(decoded.last_known_coords.is_none());
1350 }
1351
1352 #[test]
1353 fn test_path_broken_encode_decode_with_coords() {
1354 let coords = make_coords(&[0xCC, 0xDD, 0xEE]);
1355 let err = PathBroken::new(make_node_addr(0x11), make_node_addr(0x22))
1356 .with_last_coords(coords.clone());
1357
1358 let encoded = err.encode();
1359 let decoded = PathBroken::decode(&encoded[5..]).unwrap();
1360
1361 assert_eq!(decoded.dest_addr, err.dest_addr);
1362 assert_eq!(decoded.reporter, err.reporter);
1363 assert_eq!(decoded.last_known_coords.unwrap(), coords);
1364 }
1365
1366 #[test]
1367 fn test_session_setup_decode_too_short() {
1368 assert!(SessionSetup::decode(&[]).is_err());
1369 }
1370
1371 #[test]
1372 fn test_session_ack_decode_too_short() {
1373 assert!(SessionAck::decode(&[]).is_err());
1374 }
1375
1376 #[test]
1377 fn test_coords_required_decode_too_short() {
1378 assert!(CoordsRequired::decode(&[]).is_err());
1379 assert!(CoordsRequired::decode(&[0x00; 10]).is_err());
1380 }
1381
1382 #[test]
1383 fn test_path_broken_decode_too_short() {
1384 assert!(PathBroken::decode(&[]).is_err());
1385 assert!(PathBroken::decode(&[0x00; 20]).is_err());
1386 }
1387
1388 #[test]
1389 fn test_session_setup_deep_coords() {
1390 let addrs: Vec<u8> = (0..11).collect();
1392 let src = make_coords(&addrs);
1393 let dest = make_coords(&[20, 21, 22, 23, 24]);
1394 let setup = SessionSetup::new(src.clone(), dest.clone()).with_handshake(vec![0x55; 82]);
1395
1396 let encoded = setup.encode();
1397 let decoded = SessionSetup::decode(&encoded[4..]).unwrap();
1398
1399 assert_eq!(decoded.src_coords, src);
1400 assert_eq!(decoded.dest_coords, dest);
1401 }
1402
1403 #[test]
1406 fn test_fsp_flags_default() {
1407 let flags = FspFlags::new();
1408 assert!(!flags.coords_present);
1409 assert!(!flags.key_epoch);
1410 assert!(!flags.unencrypted);
1411 assert_eq!(flags.to_byte(), 0x00);
1412 }
1413
1414 #[test]
1415 fn test_fsp_flags_roundtrip() {
1416 for byte in 0u8..=0x07 {
1418 let flags = FspFlags::from_byte(byte);
1419 assert_eq!(flags.to_byte(), byte);
1420 }
1421 }
1422
1423 #[test]
1424 fn test_fsp_flags_individual_bits() {
1425 let cp = FspFlags::from_byte(0x01);
1426 assert!(cp.coords_present);
1427 assert!(!cp.key_epoch);
1428 assert!(!cp.unencrypted);
1429
1430 let k = FspFlags::from_byte(0x02);
1431 assert!(!k.coords_present);
1432 assert!(k.key_epoch);
1433 assert!(!k.unencrypted);
1434
1435 let u = FspFlags::from_byte(0x04);
1436 assert!(!u.coords_present);
1437 assert!(!u.key_epoch);
1438 assert!(u.unencrypted);
1439 }
1440
1441 #[test]
1442 fn test_fsp_flags_ignores_reserved_bits() {
1443 let flags = FspFlags::from_byte(0xFF);
1445 assert!(flags.coords_present);
1446 assert!(flags.key_epoch);
1447 assert!(flags.unencrypted);
1448 assert_eq!(flags.to_byte(), 0x07); }
1450
1451 #[test]
1454 fn test_fsp_inner_flags_default() {
1455 let flags = FspInnerFlags::new();
1456 assert!(!flags.spin_bit);
1457 assert_eq!(flags.to_byte(), 0x00);
1458 }
1459
1460 #[test]
1461 fn test_fsp_inner_flags_roundtrip() {
1462 let flags = FspInnerFlags::from_byte(0x01);
1463 assert!(flags.spin_bit);
1464 assert_eq!(flags.to_byte(), 0x01);
1465
1466 let flags = FspInnerFlags::from_byte(0x00);
1467 assert!(!flags.spin_bit);
1468 assert_eq!(flags.to_byte(), 0x00);
1469 }
1470
1471 #[test]
1472 fn test_fsp_inner_flags_ignores_reserved() {
1473 let flags = FspInnerFlags::from_byte(0xFE);
1474 assert!(!flags.spin_bit);
1475 assert_eq!(flags.to_byte(), 0x00);
1476
1477 let flags = FspInnerFlags::from_byte(0xFF);
1478 assert!(flags.spin_bit);
1479 assert_eq!(flags.to_byte(), 0x01);
1480 }
1481
1482 #[test]
1485 fn test_session_message_type_new_values() {
1486 assert_eq!(SessionMessageType::SenderReport.to_byte(), 0x11);
1487 assert_eq!(SessionMessageType::ReceiverReport.to_byte(), 0x12);
1488 assert_eq!(SessionMessageType::PathMtuNotification.to_byte(), 0x13);
1489 assert_eq!(SessionMessageType::CoordsWarmup.to_byte(), 0x14);
1490 assert_eq!(SessionMessageType::EndpointData.to_byte(), 0x15);
1491 }
1492
1493 #[test]
1494 fn test_session_message_type_display() {
1495 assert_eq!(
1496 format!("{}", SessionMessageType::SenderReport),
1497 "SenderReport"
1498 );
1499 assert_eq!(
1500 format!("{}", SessionMessageType::ReceiverReport),
1501 "ReceiverReport"
1502 );
1503 assert_eq!(
1504 format!("{}", SessionMessageType::PathMtuNotification),
1505 "PathMtuNotification"
1506 );
1507 assert_eq!(
1508 format!("{}", SessionMessageType::CoordsWarmup),
1509 "CoordsWarmup"
1510 );
1511 assert_eq!(
1512 format!("{}", SessionMessageType::EndpointData),
1513 "EndpointData"
1514 );
1515 }
1516
1517 fn sample_session_sender_report() -> SessionSenderReport {
1520 SessionSenderReport {
1521 interval_start_counter: 100,
1522 interval_end_counter: 200,
1523 interval_start_timestamp: 5000,
1524 interval_end_timestamp: 6000,
1525 interval_bytes_sent: 50_000,
1526 cumulative_packets_sent: 10_000,
1527 cumulative_bytes_sent: 5_000_000,
1528 }
1529 }
1530
1531 #[test]
1532 fn test_session_sender_report_encode_size() {
1533 let sr = sample_session_sender_report();
1534 let encoded = sr.encode();
1535 assert_eq!(encoded.len(), SESSION_SENDER_REPORT_SIZE);
1536 }
1537
1538 #[test]
1539 fn test_session_sender_report_roundtrip() {
1540 let sr = sample_session_sender_report();
1541 let encoded = sr.encode();
1542 let decoded = SessionSenderReport::decode(&encoded).unwrap();
1543 assert_eq!(sr, decoded);
1544 }
1545
1546 #[test]
1547 fn test_session_sender_report_too_short() {
1548 assert!(SessionSenderReport::decode(&[0u8; 10]).is_err());
1549 }
1550
1551 fn sample_session_receiver_report() -> SessionReceiverReport {
1554 SessionReceiverReport {
1555 highest_counter: 195,
1556 cumulative_packets_recv: 9_500,
1557 cumulative_bytes_recv: 4_750_000,
1558 timestamp_echo: 5900,
1559 dwell_time: 5,
1560 max_burst_loss: 3,
1561 mean_burst_loss: 384,
1562 jitter: 1200,
1563 ecn_ce_count: 0,
1564 owd_trend: -50,
1565 burst_loss_count: 2,
1566 cumulative_reorder_count: 10,
1567 interval_packets_recv: 95,
1568 interval_bytes_recv: 47_500,
1569 }
1570 }
1571
1572 #[test]
1573 fn test_session_receiver_report_encode_size() {
1574 let rr = sample_session_receiver_report();
1575 let encoded = rr.encode();
1576 assert_eq!(encoded.len(), SESSION_RECEIVER_REPORT_SIZE);
1577 }
1578
1579 #[test]
1580 fn test_session_receiver_report_roundtrip() {
1581 let rr = sample_session_receiver_report();
1582 let encoded = rr.encode();
1583 let decoded = SessionReceiverReport::decode(&encoded).unwrap();
1584 assert_eq!(rr, decoded);
1585 }
1586
1587 #[test]
1588 fn test_session_receiver_report_too_short() {
1589 assert!(SessionReceiverReport::decode(&[0u8; 10]).is_err());
1590 }
1591
1592 #[test]
1593 fn test_session_receiver_report_negative_owd_trend() {
1594 let rr = SessionReceiverReport {
1595 owd_trend: -12345,
1596 ..sample_session_receiver_report()
1597 };
1598 let encoded = rr.encode();
1599 let decoded = SessionReceiverReport::decode(&encoded).unwrap();
1600 assert_eq!(decoded.owd_trend, -12345);
1601 }
1602
1603 #[test]
1606 fn test_path_mtu_notification_encode_size() {
1607 let n = PathMtuNotification::new(1400);
1608 let encoded = n.encode();
1609 assert_eq!(encoded.len(), PATH_MTU_NOTIFICATION_SIZE);
1610 }
1611
1612 #[test]
1613 fn test_path_mtu_notification_roundtrip() {
1614 let n = PathMtuNotification::new(1400);
1615 let encoded = n.encode();
1616 let decoded = PathMtuNotification::decode(&encoded).unwrap();
1617 assert_eq!(decoded.path_mtu, 1400);
1618 }
1619
1620 #[test]
1621 fn test_path_mtu_notification_too_short() {
1622 assert!(PathMtuNotification::decode(&[]).is_err());
1623 assert!(PathMtuNotification::decode(&[0x00]).is_err());
1624 }
1625
1626 #[test]
1627 fn test_path_mtu_notification_boundary_values() {
1628 for mtu in [0u16, 1280, 1500, u16::MAX] {
1629 let n = PathMtuNotification::new(mtu);
1630 let encoded = n.encode();
1631 let decoded = PathMtuNotification::decode(&encoded).unwrap();
1632 assert_eq!(decoded.path_mtu, mtu);
1633 }
1634 }
1635
1636 #[test]
1639 fn test_mtu_exceeded_encode_size() {
1640 let err = MtuExceeded::new(make_node_addr(0xAA), make_node_addr(0xBB), 1400);
1641 let encoded = err.encode();
1642 assert_eq!(encoded.len(), 4 + MTU_EXCEEDED_SIZE);
1644 }
1645
1646 #[test]
1647 fn test_mtu_exceeded_encode_decode() {
1648 let err = MtuExceeded::new(make_node_addr(0xAA), make_node_addr(0xBB), 1400);
1649
1650 let encoded = err.encode();
1651 assert_eq!(encoded[0], 0x00);
1653 assert_eq!(encoded[1], 0x04); assert_eq!(encoded[4], 0x22);
1656
1657 let decoded = MtuExceeded::decode(&encoded[5..]).unwrap();
1659 assert_eq!(decoded.dest_addr, err.dest_addr);
1660 assert_eq!(decoded.reporter, err.reporter);
1661 assert_eq!(decoded.mtu, 1400);
1662 }
1663
1664 #[test]
1665 fn test_mtu_exceeded_decode_too_short() {
1666 assert!(MtuExceeded::decode(&[]).is_err());
1667 assert!(MtuExceeded::decode(&[0x00; 20]).is_err());
1668 assert!(MtuExceeded::decode(&[0x00; 34]).is_err()); }
1670
1671 #[test]
1672 fn test_mtu_exceeded_boundary_mtu_values() {
1673 for mtu in [0u16, 1280, 1500, u16::MAX] {
1674 let err = MtuExceeded::new(make_node_addr(1), make_node_addr(2), mtu);
1675 let encoded = err.encode();
1676 let decoded = MtuExceeded::decode(&encoded[5..]).unwrap();
1677 assert_eq!(decoded.mtu, mtu);
1678 }
1679 }
1680
1681 #[test]
1682 fn test_mtu_exceeded_message_type_value() {
1683 assert_eq!(SessionMessageType::MtuExceeded.to_byte(), 0x22);
1684 assert_eq!(
1685 SessionMessageType::from_byte(0x22),
1686 Some(SessionMessageType::MtuExceeded)
1687 );
1688 }
1689
1690 #[test]
1691 fn test_mtu_exceeded_display() {
1692 assert_eq!(
1693 format!("{}", SessionMessageType::MtuExceeded),
1694 "MtuExceeded"
1695 );
1696 }
1697
1698 #[test]
1701 fn test_session_msg3_encode_decode() {
1702 let handshake = vec![0xCC; 73]; let msg3 = SessionMsg3::new(handshake.clone());
1704
1705 let encoded = msg3.encode();
1706 assert_eq!(encoded[0], 0x03);
1708 assert_eq!(encoded[1], 0x00); let payload_len = u16::from_le_bytes([encoded[2], encoded[3]]);
1710 assert_eq!(payload_len as usize, encoded.len() - 4);
1711
1712 let decoded = SessionMsg3::decode(&encoded[4..]).unwrap();
1714 assert_eq!(decoded.flags, 0);
1715 assert_eq!(decoded.handshake_payload, handshake);
1716 }
1717
1718 #[test]
1719 fn test_session_msg3_decode_too_short() {
1720 assert!(SessionMsg3::decode(&[]).is_err());
1721 assert!(SessionMsg3::decode(&[0x00]).is_err()); }
1723
1724 #[test]
1725 fn test_session_msg3_empty_handshake() {
1726 let msg3 = SessionMsg3::new(vec![]);
1727 let encoded = msg3.encode();
1728 let decoded = SessionMsg3::decode(&encoded[4..]).unwrap();
1729 assert!(decoded.handshake_payload.is_empty());
1730 }
1731}