1use bytes::{Buf, BufMut};
46use std::net::{IpAddr, SocketAddr};
47use std::time::Duration;
48
49use crate::coding::{self, Codec};
50use crate::transport::{TransportAddr, TransportCapabilities, TransportType};
51use crate::varint::VarInt;
52
53#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
74pub struct CapabilityFlags(u16);
75
76impl CapabilityFlags {
77 const SUPPORTS_FULL_QUIC: u16 = 1 << 0;
79 const HALF_DUPLEX: u16 = 1 << 1;
80 const BROADCAST: u16 = 1 << 2;
81 const METERED: u16 = 1 << 3;
82 const POWER_CONSTRAINED: u16 = 1 << 4;
83 const LINK_LAYER_ACKS: u16 = 1 << 5;
84 const MTU_TIER_SHIFT: u16 = 6;
85 const MTU_TIER_MASK: u16 = 0b11 << 6;
86 const BANDWIDTH_TIER_SHIFT: u16 = 8;
87 const BANDWIDTH_TIER_MASK: u16 = 0b11 << 8;
88 const LATENCY_TIER_SHIFT: u16 = 10;
89 const LATENCY_TIER_MASK: u16 = 0b11 << 10;
90
91 pub const fn empty() -> Self {
93 Self(0)
94 }
95
96 pub const fn from_raw(raw: u16) -> Self {
98 Self(raw)
99 }
100
101 pub const fn to_raw(self) -> u16 {
103 self.0
104 }
105
106 pub fn from_capabilities(caps: &TransportCapabilities) -> Self {
108 let mut flags = 0u16;
109
110 if caps.supports_full_quic() {
111 flags |= Self::SUPPORTS_FULL_QUIC;
112 }
113 if caps.half_duplex {
114 flags |= Self::HALF_DUPLEX;
115 }
116 if caps.broadcast {
117 flags |= Self::BROADCAST;
118 }
119 if caps.metered {
120 flags |= Self::METERED;
121 }
122 if caps.power_constrained {
123 flags |= Self::POWER_CONSTRAINED;
124 }
125 if caps.link_layer_acks {
126 flags |= Self::LINK_LAYER_ACKS;
127 }
128
129 let mtu_tier = match caps.mtu {
131 0..=499 => 0,
132 500..=1199 => 1,
133 1200..=4095 => 2,
134 _ => 3,
135 };
136 flags |= (mtu_tier as u16) << Self::MTU_TIER_SHIFT;
137
138 let bandwidth_tier = match caps.bandwidth_class() {
140 crate::transport::BandwidthClass::VeryLow => 0,
141 crate::transport::BandwidthClass::Low => 1,
142 crate::transport::BandwidthClass::Medium => 2,
143 crate::transport::BandwidthClass::High => 3,
144 };
145 flags |= (bandwidth_tier as u16) << Self::BANDWIDTH_TIER_SHIFT;
146
147 let latency_tier = if caps.typical_rtt >= Duration::from_secs(2) {
149 0
150 } else if caps.typical_rtt >= Duration::from_millis(500) {
151 1
152 } else if caps.typical_rtt >= Duration::from_millis(100) {
153 2
154 } else {
155 3
156 };
157 flags |= (latency_tier as u16) << Self::LATENCY_TIER_SHIFT;
158
159 Self(flags)
160 }
161
162 pub const fn supports_full_quic(self) -> bool {
164 (self.0 & Self::SUPPORTS_FULL_QUIC) != 0
165 }
166
167 pub const fn half_duplex(self) -> bool {
169 (self.0 & Self::HALF_DUPLEX) != 0
170 }
171
172 pub const fn broadcast(self) -> bool {
174 (self.0 & Self::BROADCAST) != 0
175 }
176
177 pub const fn metered(self) -> bool {
179 (self.0 & Self::METERED) != 0
180 }
181
182 pub const fn power_constrained(self) -> bool {
184 (self.0 & Self::POWER_CONSTRAINED) != 0
185 }
186
187 pub const fn link_layer_acks(self) -> bool {
189 (self.0 & Self::LINK_LAYER_ACKS) != 0
190 }
191
192 pub const fn mtu_tier(self) -> u8 {
194 ((self.0 & Self::MTU_TIER_MASK) >> Self::MTU_TIER_SHIFT) as u8
195 }
196
197 pub const fn bandwidth_tier(self) -> u8 {
199 ((self.0 & Self::BANDWIDTH_TIER_MASK) >> Self::BANDWIDTH_TIER_SHIFT) as u8
200 }
201
202 pub const fn latency_tier(self) -> u8 {
204 ((self.0 & Self::LATENCY_TIER_MASK) >> Self::LATENCY_TIER_SHIFT) as u8
205 }
206
207 pub fn mtu_range(self) -> (usize, usize) {
209 match self.mtu_tier() {
210 0 => (0, 499),
211 1 => (500, 1199),
212 2 => (1200, 4095),
213 _ => (4096, 65535),
214 }
215 }
216
217 pub fn latency_range(self) -> (Duration, Duration) {
219 match self.latency_tier() {
220 0 => (Duration::from_secs(2), Duration::from_secs(60)),
221 1 => (Duration::from_millis(500), Duration::from_secs(2)),
222 2 => (Duration::from_millis(100), Duration::from_millis(500)),
223 _ => (Duration::ZERO, Duration::from_millis(100)),
224 }
225 }
226
227 pub const fn with_supports_full_quic(mut self, value: bool) -> Self {
229 if value {
230 self.0 |= Self::SUPPORTS_FULL_QUIC;
231 } else {
232 self.0 &= !Self::SUPPORTS_FULL_QUIC;
233 }
234 self
235 }
236
237 pub const fn with_half_duplex(mut self, value: bool) -> Self {
239 if value {
240 self.0 |= Self::HALF_DUPLEX;
241 } else {
242 self.0 &= !Self::HALF_DUPLEX;
243 }
244 self
245 }
246
247 pub const fn with_broadcast(mut self, value: bool) -> Self {
249 if value {
250 self.0 |= Self::BROADCAST;
251 } else {
252 self.0 &= !Self::BROADCAST;
253 }
254 self
255 }
256
257 pub const fn with_metered(mut self, value: bool) -> Self {
259 if value {
260 self.0 |= Self::METERED;
261 } else {
262 self.0 &= !Self::METERED;
263 }
264 self
265 }
266
267 pub const fn with_power_constrained(mut self, value: bool) -> Self {
269 if value {
270 self.0 |= Self::POWER_CONSTRAINED;
271 } else {
272 self.0 &= !Self::POWER_CONSTRAINED;
273 }
274 self
275 }
276
277 pub const fn with_link_layer_acks(mut self, value: bool) -> Self {
279 if value {
280 self.0 |= Self::LINK_LAYER_ACKS;
281 } else {
282 self.0 &= !Self::LINK_LAYER_ACKS;
283 }
284 self
285 }
286
287 pub const fn with_mtu_tier(mut self, tier: u8) -> Self {
289 let tier = if tier > 3 { 3 } else { tier };
290 self.0 = (self.0 & !Self::MTU_TIER_MASK) | ((tier as u16) << Self::MTU_TIER_SHIFT);
291 self
292 }
293
294 pub const fn with_bandwidth_tier(mut self, tier: u8) -> Self {
296 let tier = if tier > 3 { 3 } else { tier };
297 self.0 =
298 (self.0 & !Self::BANDWIDTH_TIER_MASK) | ((tier as u16) << Self::BANDWIDTH_TIER_SHIFT);
299 self
300 }
301
302 pub const fn with_latency_tier(mut self, tier: u8) -> Self {
304 let tier = if tier > 3 { 3 } else { tier };
305 self.0 = (self.0 & !Self::LATENCY_TIER_MASK) | ((tier as u16) << Self::LATENCY_TIER_SHIFT);
306 self
307 }
308
309 pub const fn broadband() -> Self {
311 Self::empty()
312 .with_supports_full_quic(true)
313 .with_broadcast(true)
314 .with_mtu_tier(2) .with_bandwidth_tier(3) .with_latency_tier(3) }
318
319 pub const fn ble() -> Self {
321 Self::empty()
322 .with_broadcast(true)
323 .with_power_constrained(true)
324 .with_link_layer_acks(true)
325 .with_mtu_tier(0) .with_bandwidth_tier(2) .with_latency_tier(2) }
329
330 pub const fn lora_long_range() -> Self {
332 Self::empty()
333 .with_half_duplex(true)
334 .with_broadcast(true)
335 .with_power_constrained(true)
336 .with_mtu_tier(0) .with_bandwidth_tier(0) .with_latency_tier(0) }
340}
341
342pub const FRAME_TYPE_ADD_ADDRESS: u64 = 0x3d7e90;
344pub const FRAME_TYPE_PUNCH_ME_NOW: u64 = 0x3d7e91;
346pub const FRAME_TYPE_REMOVE_ADDRESS: u64 = 0x3d7e92;
348
349#[derive(Debug, Clone, PartialEq, Eq)]
377pub struct AddAddress {
378 pub sequence: u64,
380 pub priority: u64,
382 pub transport_type: TransportType,
384 pub address: TransportAddr,
386 pub capabilities: Option<CapabilityFlags>,
388}
389
390impl AddAddress {
391 pub fn udp(sequence: u64, priority: u64, socket_addr: SocketAddr) -> Self {
396 Self {
397 sequence,
398 priority,
399 transport_type: TransportType::Udp,
400 address: TransportAddr::Udp(socket_addr),
401 capabilities: None,
402 }
403 }
404
405 pub fn new(sequence: u64, priority: u64, address: TransportAddr) -> Self {
410 Self {
411 sequence,
412 priority,
413 transport_type: address.transport_type(),
414 address,
415 capabilities: None,
416 }
417 }
418
419 pub fn with_capabilities(
421 sequence: u64,
422 priority: u64,
423 address: TransportAddr,
424 capabilities: CapabilityFlags,
425 ) -> Self {
426 Self {
427 sequence,
428 priority,
429 transport_type: address.transport_type(),
430 address,
431 capabilities: Some(capabilities),
432 }
433 }
434
435 pub fn from_capabilities(
439 sequence: u64,
440 priority: u64,
441 address: TransportAddr,
442 capabilities: &TransportCapabilities,
443 ) -> Self {
444 Self {
445 sequence,
446 priority,
447 transport_type: address.transport_type(),
448 address,
449 capabilities: Some(CapabilityFlags::from_capabilities(capabilities)),
450 }
451 }
452
453 pub fn socket_addr(&self) -> Option<SocketAddr> {
457 self.address.as_socket_addr()
458 }
459
460 pub fn has_capabilities(&self) -> bool {
462 self.capabilities.is_some()
463 }
464
465 pub fn capability_flags(&self) -> Option<CapabilityFlags> {
467 self.capabilities
468 }
469
470 pub fn supports_full_quic(&self) -> Option<bool> {
472 self.capabilities.map(|c| c.supports_full_quic())
473 }
474}
475
476#[derive(Debug, Clone, PartialEq, Eq)]
484pub struct PunchMeNow {
485 pub round: u64,
487 pub paired_with_sequence_number: u64,
489 pub address: SocketAddr,
491 pub target_peer_id: Option<[u8; 32]>,
493}
494
495#[derive(Debug, Clone, PartialEq, Eq)]
497pub struct RemoveAddress {
498 pub sequence: u64,
500}
501
502const TRANSPORT_TYPE_UDP: u64 = 0;
504const TRANSPORT_TYPE_BLE: u64 = 1;
505const TRANSPORT_TYPE_LORA: u64 = 2;
506const TRANSPORT_TYPE_SERIAL: u64 = 3;
507const TRANSPORT_TYPE_AX25: u64 = 4;
508const TRANSPORT_TYPE_I2P: u64 = 5;
509const TRANSPORT_TYPE_YGGDRASIL: u64 = 6;
510
511impl Codec for AddAddress {
512 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> {
513 if buf.remaining() < 1 {
514 return Err(coding::UnexpectedEnd);
515 }
516
517 let sequence = VarInt::decode(buf)?.into_inner();
519
520 let priority = VarInt::decode(buf)?.into_inner();
522
523 let transport_type_raw = if buf.remaining() > 0 {
526 VarInt::decode(buf)?.into_inner()
527 } else {
528 TRANSPORT_TYPE_UDP
529 };
530
531 let transport_type = match transport_type_raw {
532 TRANSPORT_TYPE_UDP => TransportType::Udp,
533 TRANSPORT_TYPE_BLE => TransportType::Ble,
534 TRANSPORT_TYPE_LORA => TransportType::LoRa,
535 TRANSPORT_TYPE_SERIAL => TransportType::Serial,
536 TRANSPORT_TYPE_AX25 => TransportType::Ax25,
537 TRANSPORT_TYPE_I2P => TransportType::I2p,
538 TRANSPORT_TYPE_YGGDRASIL => TransportType::Yggdrasil,
539 _ => TransportType::Udp, };
541
542 let address = match transport_type {
544 TransportType::Udp => {
545 if buf.remaining() < 1 {
547 return Err(coding::UnexpectedEnd);
548 }
549 let addr_type = buf.get_u8();
550 let ip = match addr_type {
551 4 => {
552 if buf.remaining() < 4 {
553 return Err(coding::UnexpectedEnd);
554 }
555 let mut addr = [0u8; 4];
556 buf.copy_to_slice(&mut addr);
557 IpAddr::from(addr)
558 }
559 6 => {
560 if buf.remaining() < 16 {
561 return Err(coding::UnexpectedEnd);
562 }
563 let mut addr = [0u8; 16];
564 buf.copy_to_slice(&mut addr);
565 IpAddr::from(addr)
566 }
567 _ => return Err(coding::UnexpectedEnd),
568 };
569
570 if buf.remaining() < 2 {
571 return Err(coding::UnexpectedEnd);
572 }
573 let port = buf.get_u16();
574 TransportAddr::Udp(SocketAddr::new(ip, port))
575 }
576 TransportType::Ble => {
577 if buf.remaining() < 6 {
579 return Err(coding::UnexpectedEnd);
580 }
581 let mut device_id = [0u8; 6];
582 buf.copy_to_slice(&mut device_id);
583
584 let service_uuid = if buf.remaining() > 0 {
585 let has_uuid = buf.get_u8();
586 if has_uuid == 1 && buf.remaining() >= 16 {
587 let mut uuid = [0u8; 16];
588 buf.copy_to_slice(&mut uuid);
589 Some(uuid)
590 } else {
591 None
592 }
593 } else {
594 None
595 };
596
597 TransportAddr::Ble {
598 device_id,
599 service_uuid,
600 }
601 }
602 TransportType::LoRa => {
603 if buf.remaining() < 8 {
605 return Err(coding::UnexpectedEnd);
606 }
607 let mut device_addr = [0u8; 4];
608 buf.copy_to_slice(&mut device_addr);
609 let spreading_factor = buf.get_u8();
610 let bandwidth_khz = buf.get_u16();
611 let coding_rate = buf.get_u8();
612
613 TransportAddr::LoRa {
614 device_addr,
615 params: crate::transport::LoRaParams {
616 spreading_factor,
617 bandwidth_khz,
618 coding_rate,
619 },
620 }
621 }
622 TransportType::Serial => {
623 let name_len = VarInt::decode(buf)?.into_inner() as usize;
625 if buf.remaining() < name_len {
626 return Err(coding::UnexpectedEnd);
627 }
628 let mut name_bytes = vec![0u8; name_len];
629 buf.copy_to_slice(&mut name_bytes);
630 let port_name =
631 String::from_utf8(name_bytes).unwrap_or_else(|_| String::from("/dev/null"));
632 TransportAddr::Serial { port: port_name }
633 }
634 TransportType::Ax25 | TransportType::I2p | TransportType::Yggdrasil => {
635 TransportAddr::Udp(SocketAddr::new(IpAddr::from([0, 0, 0, 0]), 0))
639 }
640 };
641
642 let capabilities = if buf.remaining() > 0 {
644 let has_caps = buf.get_u8();
645 if has_caps == 1 && buf.remaining() >= 2 {
646 Some(CapabilityFlags::from_raw(buf.get_u16()))
647 } else {
648 None
649 }
650 } else {
651 None
652 };
653
654 Ok(Self {
655 sequence,
656 priority,
657 transport_type,
658 address,
659 capabilities,
660 })
661 }
662
663 fn encode<B: BufMut>(&self, buf: &mut B) {
664 VarInt::from_u64(self.sequence)
666 .unwrap_or(VarInt::from_u32(0))
667 .encode(buf);
668
669 VarInt::from_u64(self.priority)
671 .unwrap_or(VarInt::from_u32(0))
672 .encode(buf);
673
674 let transport_type_raw = match self.transport_type {
676 TransportType::Udp => TRANSPORT_TYPE_UDP,
677 TransportType::Ble => TRANSPORT_TYPE_BLE,
678 TransportType::LoRa => TRANSPORT_TYPE_LORA,
679 TransportType::Serial => TRANSPORT_TYPE_SERIAL,
680 TransportType::Ax25 => TRANSPORT_TYPE_AX25,
681 TransportType::I2p => TRANSPORT_TYPE_I2P,
682 TransportType::Yggdrasil => TRANSPORT_TYPE_YGGDRASIL,
683 };
684 VarInt::from_u64(transport_type_raw)
685 .unwrap_or(VarInt::from_u32(0))
686 .encode(buf);
687
688 match &self.address {
690 TransportAddr::Udp(socket_addr) => {
691 match socket_addr.ip() {
692 IpAddr::V4(ipv4) => {
693 buf.put_u8(4); buf.put_slice(&ipv4.octets());
695 }
696 IpAddr::V6(ipv6) => {
697 buf.put_u8(6); buf.put_slice(&ipv6.octets());
699 }
700 }
701 buf.put_u16(socket_addr.port());
702 }
703 TransportAddr::Ble {
704 device_id,
705 service_uuid,
706 } => {
707 buf.put_slice(device_id);
708 match service_uuid {
709 Some(uuid) => {
710 buf.put_u8(1); buf.put_slice(uuid);
712 }
713 None => {
714 buf.put_u8(0); }
716 }
717 }
718 TransportAddr::LoRa {
719 device_addr,
720 params,
721 } => {
722 buf.put_slice(device_addr);
723 buf.put_u8(params.spreading_factor);
724 buf.put_u16(params.bandwidth_khz);
725 buf.put_u8(params.coding_rate);
726 }
727 TransportAddr::Serial { port } => {
728 let name_bytes = port.as_bytes();
729 VarInt::from_u64(name_bytes.len() as u64)
730 .unwrap_or(VarInt::from_u32(0))
731 .encode(buf);
732 buf.put_slice(name_bytes);
733 }
734 TransportAddr::Ax25 { callsign, ssid } => {
735 let callsign_bytes = callsign.as_bytes();
737 VarInt::from_u64(callsign_bytes.len() as u64)
738 .unwrap_or(VarInt::from_u32(0))
739 .encode(buf);
740 buf.put_slice(callsign_bytes);
741 buf.put_u8(*ssid);
742 }
743 TransportAddr::I2p { destination } => {
744 buf.put_slice(destination.as_ref());
746 }
747 TransportAddr::Yggdrasil { address } => {
748 buf.put_slice(address);
750 }
751 TransportAddr::Broadcast { transport_type: _ } => {
752 buf.put_u8(4);
755 buf.put_slice(&[0, 0, 0, 0]);
756 buf.put_u16(0);
757 }
758 }
759
760 match &self.capabilities {
762 Some(caps) => {
763 buf.put_u8(1); buf.put_u16(caps.to_raw());
765 }
766 None => {
767 buf.put_u8(0); }
769 }
770 }
771}
772
773impl Codec for PunchMeNow {
774 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> {
775 if buf.remaining() < 1 {
776 return Err(coding::UnexpectedEnd);
777 }
778
779 let round = VarInt::decode(buf)?.into_inner();
781
782 let paired_with_sequence_number = VarInt::decode(buf)?.into_inner();
784
785 let addr_type = buf.get_u8();
787 let ip = match addr_type {
788 4 => {
789 if buf.remaining() < 4 {
790 return Err(coding::UnexpectedEnd);
791 }
792 let mut addr = [0u8; 4];
793 buf.copy_to_slice(&mut addr);
794 IpAddr::from(addr)
795 }
796 6 => {
797 if buf.remaining() < 16 {
798 return Err(coding::UnexpectedEnd);
799 }
800 let mut addr = [0u8; 16];
801 buf.copy_to_slice(&mut addr);
802 IpAddr::from(addr)
803 }
804 _ => return Err(coding::UnexpectedEnd),
805 };
806
807 if buf.remaining() < 2 {
809 return Err(coding::UnexpectedEnd);
810 }
811 let port = buf.get_u16();
812
813 let target_peer_id = if buf.remaining() > 0 {
815 let has_peer_id = buf.get_u8();
816 if has_peer_id == 1 {
817 if buf.remaining() < 32 {
818 return Err(coding::UnexpectedEnd);
819 }
820 let mut peer_id = [0u8; 32];
821 buf.copy_to_slice(&mut peer_id);
822 Some(peer_id)
823 } else {
824 None
825 }
826 } else {
827 None
828 };
829
830 Ok(Self {
831 round,
832 paired_with_sequence_number,
833 address: SocketAddr::new(ip, port),
834 target_peer_id,
835 })
836 }
837
838 fn encode<B: BufMut>(&self, buf: &mut B) {
839 VarInt::from_u64(self.round)
841 .unwrap_or(VarInt::from_u32(0))
842 .encode(buf);
843
844 VarInt::from_u64(self.paired_with_sequence_number)
846 .unwrap_or(VarInt::from_u32(0))
847 .encode(buf);
848
849 match self.address.ip() {
851 IpAddr::V4(ipv4) => {
852 buf.put_u8(4); buf.put_slice(&ipv4.octets());
854 }
855 IpAddr::V6(ipv6) => {
856 buf.put_u8(6); buf.put_slice(&ipv6.octets());
858 }
859 }
860
861 buf.put_u16(self.address.port());
863
864 match &self.target_peer_id {
866 Some(peer_id) => {
867 buf.put_u8(1); buf.put_slice(peer_id);
869 }
870 None => {
871 buf.put_u8(0); }
873 }
874 }
875}
876
877impl Codec for RemoveAddress {
878 fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> {
879 if buf.remaining() < 1 {
880 return Err(coding::UnexpectedEnd);
881 }
882
883 let sequence = VarInt::decode(buf)?.into_inner();
884
885 Ok(Self { sequence })
886 }
887
888 fn encode<B: BufMut>(&self, buf: &mut B) {
889 VarInt::from_u64(self.sequence)
890 .unwrap_or(VarInt::from_u32(0))
891 .encode(buf);
892 }
893}
894
895impl AddAddress {
896 pub fn encode_with_type<B: BufMut>(&self, buf: &mut B) {
898 VarInt::from_u64(FRAME_TYPE_ADD_ADDRESS)
899 .unwrap_or(VarInt::from_u32(0))
900 .encode(buf);
901 Codec::encode(self, buf);
902 }
903}
904
905impl PunchMeNow {
906 pub fn encode_with_type<B: BufMut>(&self, buf: &mut B) {
908 VarInt::from_u64(FRAME_TYPE_PUNCH_ME_NOW)
909 .unwrap_or(VarInt::from_u32(0))
910 .encode(buf);
911 Codec::encode(self, buf);
912 }
913}
914
915impl RemoveAddress {
916 pub fn encode_with_type<B: BufMut>(&self, buf: &mut B) {
918 VarInt::from_u64(FRAME_TYPE_REMOVE_ADDRESS)
919 .unwrap_or(VarInt::from_u32(0))
920 .encode(buf);
921 Codec::encode(self, buf);
922 }
923}
924
925#[cfg(test)]
926mod tests {
927 use super::*;
928 use bytes::BytesMut;
929
930 fn test_socket_addr_v4() -> SocketAddr {
931 "192.168.1.100:9000".parse().expect("valid addr")
932 }
933
934 fn test_socket_addr_v6() -> SocketAddr {
935 "[::1]:9000".parse().expect("valid addr")
936 }
937
938 #[test]
939 fn test_add_address_udp_ipv4_roundtrip() {
940 let original = AddAddress::udp(42, 100, test_socket_addr_v4());
941
942 let mut buf = BytesMut::new();
944 Codec::encode(&original, &mut buf);
945
946 let decoded = AddAddress::decode(&mut buf.freeze()).expect("decode failed");
948
949 assert_eq!(decoded.sequence, 42);
950 assert_eq!(decoded.priority, 100);
951 assert_eq!(decoded.transport_type, TransportType::Udp);
952 assert_eq!(decoded.socket_addr(), Some(test_socket_addr_v4()));
953 }
954
955 #[test]
956 fn test_add_address_udp_ipv6_roundtrip() {
957 let original = AddAddress::udp(1, 50, test_socket_addr_v6());
958
959 let mut buf = BytesMut::new();
960 Codec::encode(&original, &mut buf);
961
962 let decoded = AddAddress::decode(&mut buf.freeze()).expect("decode failed");
963
964 assert_eq!(decoded.sequence, 1);
965 assert_eq!(decoded.transport_type, TransportType::Udp);
966 assert_eq!(decoded.socket_addr(), Some(test_socket_addr_v6()));
967 }
968
969 #[test]
970 fn test_add_address_ble_roundtrip() {
971 let device_id = [0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC];
972 let original = AddAddress::new(
973 10,
974 200,
975 TransportAddr::Ble {
976 device_id,
977 service_uuid: None,
978 },
979 );
980
981 let mut buf = BytesMut::new();
982 Codec::encode(&original, &mut buf);
983
984 let decoded = AddAddress::decode(&mut buf.freeze()).expect("decode failed");
985
986 assert_eq!(decoded.sequence, 10);
987 assert_eq!(decoded.priority, 200);
988 assert_eq!(decoded.transport_type, TransportType::Ble);
989
990 if let TransportAddr::Ble {
991 device_id: decoded_id,
992 service_uuid,
993 } = decoded.address
994 {
995 assert_eq!(decoded_id, device_id);
996 assert!(service_uuid.is_none());
997 } else {
998 panic!("Expected BLE address");
999 }
1000 }
1001
1002 #[test]
1003 fn test_add_address_ble_with_uuid_roundtrip() {
1004 let device_id = [0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF];
1005 let service_uuid = [
1006 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
1007 0x0F, 0x10,
1008 ];
1009 let original = AddAddress::new(
1010 5,
1011 300,
1012 TransportAddr::Ble {
1013 device_id,
1014 service_uuid: Some(service_uuid),
1015 },
1016 );
1017
1018 let mut buf = BytesMut::new();
1019 Codec::encode(&original, &mut buf);
1020
1021 let decoded = AddAddress::decode(&mut buf.freeze()).expect("decode failed");
1022
1023 if let TransportAddr::Ble {
1024 device_id: decoded_id,
1025 service_uuid: decoded_uuid,
1026 } = decoded.address
1027 {
1028 assert_eq!(decoded_id, device_id);
1029 assert_eq!(decoded_uuid, Some(service_uuid));
1030 } else {
1031 panic!("Expected BLE address");
1032 }
1033 }
1034
1035 #[test]
1036 fn test_add_address_lora_roundtrip() {
1037 let device_addr = [0xDE, 0xAD, 0xBE, 0xEF];
1038 let params = crate::transport::LoRaParams {
1039 spreading_factor: 10,
1040 bandwidth_khz: 250,
1041 coding_rate: 6,
1042 };
1043 let original = AddAddress::new(
1044 99,
1045 500,
1046 TransportAddr::LoRa {
1047 device_addr,
1048 params: params.clone(),
1049 },
1050 );
1051
1052 let mut buf = BytesMut::new();
1053 Codec::encode(&original, &mut buf);
1054
1055 let decoded = AddAddress::decode(&mut buf.freeze()).expect("decode failed");
1056
1057 assert_eq!(decoded.sequence, 99);
1058 assert_eq!(decoded.transport_type, TransportType::LoRa);
1059
1060 if let TransportAddr::LoRa {
1061 device_addr: decoded_addr,
1062 params: decoded_params,
1063 } = decoded.address
1064 {
1065 assert_eq!(decoded_addr, device_addr);
1066 assert_eq!(decoded_params.spreading_factor, 10);
1067 assert_eq!(decoded_params.bandwidth_khz, 250);
1068 assert_eq!(decoded_params.coding_rate, 6);
1069 } else {
1070 panic!("Expected LoRa address");
1071 }
1072 }
1073
1074 #[test]
1075 fn test_add_address_serial_roundtrip() {
1076 let original = AddAddress::new(
1077 7,
1078 50,
1079 TransportAddr::Serial {
1080 port: "/dev/ttyUSB0".to_string(),
1081 },
1082 );
1083
1084 let mut buf = BytesMut::new();
1085 Codec::encode(&original, &mut buf);
1086
1087 let decoded = AddAddress::decode(&mut buf.freeze()).expect("decode failed");
1088
1089 assert_eq!(decoded.sequence, 7);
1090 assert_eq!(decoded.transport_type, TransportType::Serial);
1091
1092 if let TransportAddr::Serial { port } = decoded.address {
1093 assert_eq!(port, "/dev/ttyUSB0");
1094 } else {
1095 panic!("Expected Serial address");
1096 }
1097 }
1098
1099 #[test]
1100 fn test_add_address_helper_methods() {
1101 let socket_addr = test_socket_addr_v4();
1102 let frame = AddAddress::udp(1, 100, socket_addr);
1103
1104 assert_eq!(frame.socket_addr(), Some(socket_addr));
1105
1106 let ble_frame = AddAddress::new(
1107 2,
1108 100,
1109 TransportAddr::Ble {
1110 device_id: [0; 6],
1111 service_uuid: None,
1112 },
1113 );
1114 assert_eq!(ble_frame.socket_addr(), None);
1115 }
1116
1117 #[test]
1118 fn test_punch_me_now_roundtrip() {
1119 let original = PunchMeNow {
1120 round: 3,
1121 paired_with_sequence_number: 42,
1122 address: test_socket_addr_v4(),
1123 target_peer_id: None,
1124 };
1125
1126 let mut buf = BytesMut::new();
1127 Codec::encode(&original, &mut buf);
1128
1129 let decoded = PunchMeNow::decode(&mut buf.freeze()).expect("decode failed");
1130
1131 assert_eq!(decoded.round, 3);
1132 assert_eq!(decoded.paired_with_sequence_number, 42);
1133 assert_eq!(decoded.address, test_socket_addr_v4());
1134 assert!(decoded.target_peer_id.is_none());
1135 }
1136
1137 #[test]
1138 fn test_punch_me_now_with_peer_id_roundtrip() {
1139 let peer_id = [0x42u8; 32];
1140 let original = PunchMeNow {
1141 round: 5,
1142 paired_with_sequence_number: 10,
1143 address: test_socket_addr_v6(),
1144 target_peer_id: Some(peer_id),
1145 };
1146
1147 let mut buf = BytesMut::new();
1148 Codec::encode(&original, &mut buf);
1149
1150 let decoded = PunchMeNow::decode(&mut buf.freeze()).expect("decode failed");
1151
1152 assert_eq!(decoded.round, 5);
1153 assert_eq!(decoded.target_peer_id, Some(peer_id));
1154 }
1155
1156 #[test]
1157 fn test_remove_address_roundtrip() {
1158 let original = RemoveAddress { sequence: 123 };
1159
1160 let mut buf = BytesMut::new();
1161 Codec::encode(&original, &mut buf);
1162
1163 let decoded = RemoveAddress::decode(&mut buf.freeze()).expect("decode failed");
1164
1165 assert_eq!(decoded.sequence, 123);
1166 }
1167
1168 #[test]
1169 fn test_transport_type_wire_values() {
1170 assert_eq!(TRANSPORT_TYPE_UDP, 0);
1172 assert_eq!(TRANSPORT_TYPE_BLE, 1);
1173 assert_eq!(TRANSPORT_TYPE_LORA, 2);
1174 assert_eq!(TRANSPORT_TYPE_SERIAL, 3);
1175 }
1176
1177 #[test]
1178 fn test_frame_types() {
1179 assert_eq!(FRAME_TYPE_ADD_ADDRESS, 0x3d7e90);
1181 assert_eq!(FRAME_TYPE_PUNCH_ME_NOW, 0x3d7e91);
1182 assert_eq!(FRAME_TYPE_REMOVE_ADDRESS, 0x3d7e92);
1183 }
1184
1185 #[test]
1188 fn test_capability_flags_empty() {
1189 let flags = CapabilityFlags::empty();
1190 assert_eq!(flags.to_raw(), 0);
1191 assert!(!flags.supports_full_quic());
1192 assert!(!flags.half_duplex());
1193 assert!(!flags.broadcast());
1194 assert!(!flags.metered());
1195 assert!(!flags.power_constrained());
1196 assert!(!flags.link_layer_acks());
1197 assert_eq!(flags.mtu_tier(), 0);
1198 assert_eq!(flags.bandwidth_tier(), 0);
1199 assert_eq!(flags.latency_tier(), 0);
1200 }
1201
1202 #[test]
1203 fn test_capability_flags_individual_bits() {
1204 let flags = CapabilityFlags::empty().with_supports_full_quic(true);
1206 assert!(flags.supports_full_quic());
1207 assert_eq!(flags.to_raw(), 1);
1208
1209 let flags = CapabilityFlags::empty().with_half_duplex(true);
1210 assert!(flags.half_duplex());
1211 assert_eq!(flags.to_raw(), 2);
1212
1213 let flags = CapabilityFlags::empty().with_broadcast(true);
1214 assert!(flags.broadcast());
1215 assert_eq!(flags.to_raw(), 4);
1216
1217 let flags = CapabilityFlags::empty().with_metered(true);
1218 assert!(flags.metered());
1219 assert_eq!(flags.to_raw(), 8);
1220
1221 let flags = CapabilityFlags::empty().with_power_constrained(true);
1222 assert!(flags.power_constrained());
1223 assert_eq!(flags.to_raw(), 16);
1224
1225 let flags = CapabilityFlags::empty().with_link_layer_acks(true);
1226 assert!(flags.link_layer_acks());
1227 assert_eq!(flags.to_raw(), 32);
1228 }
1229
1230 #[test]
1231 fn test_capability_flags_tiers() {
1232 let flags = CapabilityFlags::empty().with_mtu_tier(0);
1234 assert_eq!(flags.mtu_tier(), 0);
1235 assert_eq!(flags.mtu_range(), (0, 499));
1236
1237 let flags = CapabilityFlags::empty().with_mtu_tier(1);
1238 assert_eq!(flags.mtu_tier(), 1);
1239 assert_eq!(flags.mtu_range(), (500, 1199));
1240
1241 let flags = CapabilityFlags::empty().with_mtu_tier(2);
1242 assert_eq!(flags.mtu_tier(), 2);
1243 assert_eq!(flags.mtu_range(), (1200, 4095));
1244
1245 let flags = CapabilityFlags::empty().with_mtu_tier(3);
1246 assert_eq!(flags.mtu_tier(), 3);
1247 assert_eq!(flags.mtu_range(), (4096, 65535));
1248
1249 let flags = CapabilityFlags::empty().with_bandwidth_tier(0);
1251 assert_eq!(flags.bandwidth_tier(), 0);
1252
1253 let flags = CapabilityFlags::empty().with_bandwidth_tier(3);
1254 assert_eq!(flags.bandwidth_tier(), 3);
1255
1256 let flags = CapabilityFlags::empty().with_latency_tier(0);
1258 assert_eq!(flags.latency_tier(), 0);
1259 assert_eq!(flags.latency_range().0, Duration::from_secs(2));
1260
1261 let flags = CapabilityFlags::empty().with_latency_tier(3);
1262 assert_eq!(flags.latency_tier(), 3);
1263 assert_eq!(flags.latency_range().1, Duration::from_millis(100));
1264 }
1265
1266 #[test]
1267 fn test_capability_flags_tier_clamping() {
1268 let flags = CapabilityFlags::empty().with_mtu_tier(10);
1270 assert_eq!(flags.mtu_tier(), 3);
1271
1272 let flags = CapabilityFlags::empty().with_bandwidth_tier(255);
1273 assert_eq!(flags.bandwidth_tier(), 3);
1274
1275 let flags = CapabilityFlags::empty().with_latency_tier(100);
1276 assert_eq!(flags.latency_tier(), 3);
1277 }
1278
1279 #[test]
1280 fn test_capability_flags_presets() {
1281 let broadband = CapabilityFlags::broadband();
1283 assert!(broadband.supports_full_quic());
1284 assert!(broadband.broadcast());
1285 assert!(!broadband.half_duplex());
1286 assert!(!broadband.power_constrained());
1287 assert_eq!(broadband.mtu_tier(), 2);
1288 assert_eq!(broadband.bandwidth_tier(), 3);
1289 assert_eq!(broadband.latency_tier(), 3);
1290
1291 let ble = CapabilityFlags::ble();
1293 assert!(!ble.supports_full_quic());
1294 assert!(ble.broadcast());
1295 assert!(ble.power_constrained());
1296 assert!(ble.link_layer_acks());
1297 assert_eq!(ble.mtu_tier(), 0);
1298 assert_eq!(ble.bandwidth_tier(), 2);
1299 assert_eq!(ble.latency_tier(), 2);
1300
1301 let lora = CapabilityFlags::lora_long_range();
1303 assert!(!lora.supports_full_quic());
1304 assert!(lora.half_duplex());
1305 assert!(lora.broadcast());
1306 assert!(lora.power_constrained());
1307 assert_eq!(lora.mtu_tier(), 0);
1308 assert_eq!(lora.bandwidth_tier(), 0);
1309 assert_eq!(lora.latency_tier(), 0);
1310 }
1311
1312 #[test]
1313 fn test_capability_flags_from_transport_capabilities() {
1314 let caps = TransportCapabilities::broadband();
1316 let flags = CapabilityFlags::from_capabilities(&caps);
1317
1318 assert!(flags.supports_full_quic());
1319 assert!(!flags.half_duplex());
1320 assert!(flags.broadcast());
1321 assert!(!flags.metered());
1322 assert!(!flags.power_constrained());
1323 assert_eq!(flags.bandwidth_tier(), 3); let caps = TransportCapabilities::ble();
1327 let flags = CapabilityFlags::from_capabilities(&caps);
1328
1329 assert!(!flags.supports_full_quic()); assert!(flags.power_constrained());
1331 assert!(flags.link_layer_acks());
1332 assert_eq!(flags.bandwidth_tier(), 2); let caps = TransportCapabilities::lora_long_range();
1336 let flags = CapabilityFlags::from_capabilities(&caps);
1337
1338 assert!(!flags.supports_full_quic());
1339 assert!(flags.half_duplex());
1340 assert!(flags.broadcast());
1341 assert!(flags.power_constrained());
1342 assert_eq!(flags.bandwidth_tier(), 0); assert_eq!(flags.latency_tier(), 0); }
1345
1346 #[test]
1347 fn test_capability_flags_roundtrip() {
1348 let original = CapabilityFlags::empty()
1350 .with_supports_full_quic(true)
1351 .with_broadcast(true)
1352 .with_mtu_tier(2)
1353 .with_bandwidth_tier(3)
1354 .with_latency_tier(1);
1355
1356 let raw = original.to_raw();
1357 let decoded = CapabilityFlags::from_raw(raw);
1358
1359 assert_eq!(decoded.supports_full_quic(), original.supports_full_quic());
1360 assert_eq!(decoded.broadcast(), original.broadcast());
1361 assert_eq!(decoded.mtu_tier(), original.mtu_tier());
1362 assert_eq!(decoded.bandwidth_tier(), original.bandwidth_tier());
1363 assert_eq!(decoded.latency_tier(), original.latency_tier());
1364 }
1365
1366 #[test]
1367 fn test_add_address_with_capabilities_roundtrip() {
1368 let caps = CapabilityFlags::broadband();
1369 let original =
1370 AddAddress::with_capabilities(42, 100, TransportAddr::Udp(test_socket_addr_v4()), caps);
1371
1372 assert!(original.has_capabilities());
1373 assert_eq!(original.capability_flags(), Some(caps));
1374 assert_eq!(original.supports_full_quic(), Some(true));
1375
1376 let mut buf = BytesMut::new();
1378 Codec::encode(&original, &mut buf);
1379
1380 let decoded = AddAddress::decode(&mut buf.freeze()).expect("decode failed");
1381
1382 assert_eq!(decoded.sequence, 42);
1383 assert_eq!(decoded.priority, 100);
1384 assert!(decoded.has_capabilities());
1385 assert_eq!(decoded.capability_flags(), Some(caps));
1386 assert_eq!(decoded.supports_full_quic(), Some(true));
1387 }
1388
1389 #[test]
1390 fn test_add_address_without_capabilities_roundtrip() {
1391 let original = AddAddress::udp(1, 50, test_socket_addr_v4());
1392
1393 assert!(!original.has_capabilities());
1394 assert_eq!(original.capability_flags(), None);
1395 assert_eq!(original.supports_full_quic(), None);
1396
1397 let mut buf = BytesMut::new();
1399 Codec::encode(&original, &mut buf);
1400
1401 let decoded = AddAddress::decode(&mut buf.freeze()).expect("decode failed");
1402
1403 assert!(!decoded.has_capabilities());
1404 assert_eq!(decoded.capability_flags(), None);
1405 }
1406
1407 #[test]
1408 fn test_add_address_from_transport_capabilities() {
1409 let caps = TransportCapabilities::ble();
1410 let original = AddAddress::from_capabilities(
1411 10,
1412 200,
1413 TransportAddr::Ble {
1414 device_id: [0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC],
1415 service_uuid: None,
1416 },
1417 &caps,
1418 );
1419
1420 assert!(original.has_capabilities());
1421 assert_eq!(original.supports_full_quic(), Some(false));
1423
1424 let mut buf = BytesMut::new();
1426 Codec::encode(&original, &mut buf);
1427
1428 let decoded = AddAddress::decode(&mut buf.freeze()).expect("decode failed");
1429
1430 assert!(decoded.has_capabilities());
1431 let flags = decoded.capability_flags().expect("expected flags");
1432 assert!(!flags.supports_full_quic());
1433 assert!(flags.power_constrained());
1434 assert!(flags.link_layer_acks());
1435 }
1436
1437 #[test]
1438 fn test_add_address_ble_with_capabilities_roundtrip() {
1439 let caps = CapabilityFlags::ble();
1440 let device_id = [0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF];
1441 let original = AddAddress::with_capabilities(
1442 5,
1443 300,
1444 TransportAddr::Ble {
1445 device_id,
1446 service_uuid: None,
1447 },
1448 caps,
1449 );
1450
1451 let mut buf = BytesMut::new();
1452 Codec::encode(&original, &mut buf);
1453
1454 let decoded = AddAddress::decode(&mut buf.freeze()).expect("decode failed");
1455
1456 assert_eq!(decoded.transport_type, TransportType::Ble);
1457 assert!(decoded.has_capabilities());
1458 let flags = decoded.capability_flags().expect("expected flags");
1459 assert!(flags.power_constrained());
1460 assert_eq!(flags.mtu_tier(), 0);
1461 }
1462
1463 #[test]
1464 fn test_add_address_lora_with_capabilities_roundtrip() {
1465 let caps = CapabilityFlags::lora_long_range();
1466 let device_addr = [0xDE, 0xAD, 0xBE, 0xEF];
1467 let params = crate::transport::LoRaParams {
1468 spreading_factor: 12,
1469 bandwidth_khz: 125,
1470 coding_rate: 5,
1471 };
1472 let original = AddAddress::with_capabilities(
1473 99,
1474 500,
1475 TransportAddr::LoRa {
1476 device_addr,
1477 params,
1478 },
1479 caps,
1480 );
1481
1482 let mut buf = BytesMut::new();
1483 Codec::encode(&original, &mut buf);
1484
1485 let decoded = AddAddress::decode(&mut buf.freeze()).expect("decode failed");
1486
1487 assert_eq!(decoded.transport_type, TransportType::LoRa);
1488 assert!(decoded.has_capabilities());
1489 let flags = decoded.capability_flags().expect("expected flags");
1490 assert!(flags.half_duplex());
1491 assert!(flags.power_constrained());
1492 assert_eq!(flags.bandwidth_tier(), 0); assert_eq!(flags.latency_tier(), 0); }
1495}