1use std::collections::HashMap;
10
11use super::compressor::Bzip2Compressor;
12use rns_core::channel::{Channel, Sequence};
13use rns_core::constants;
14use rns_core::link::types::{LinkId, LinkState, TeardownReason};
15use rns_core::link::{LinkAction, LinkEngine, LinkMode};
16use rns_core::packet::{PacketFlags, RawPacket};
17use rns_core::resource::{ResourceAction, ResourceReceiver, ResourceSender};
18use rns_crypto::ed25519::Ed25519PrivateKey;
19use rns_crypto::Rng;
20
21use super::time;
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
25pub enum ResourceStrategy {
26 AcceptNone,
28 AcceptAll,
30 AcceptApp,
32}
33
34impl Default for ResourceStrategy {
35 fn default() -> Self {
36 ResourceStrategy::AcceptNone
37 }
38}
39
40struct ManagedLink {
42 engine: LinkEngine,
43 channel: Option<Channel>,
44 pending_channel_packets: HashMap<[u8; 32], Sequence>,
45 channel_send_ok: u64,
46 channel_send_not_ready: u64,
47 channel_send_too_big: u64,
48 channel_send_other_error: u64,
49 channel_messages_received: u64,
50 channel_proofs_sent: u64,
51 channel_proofs_received: u64,
52 dest_hash: [u8; 16],
54 remote_identity: Option<([u8; 16], [u8; 64])>,
56 dest_sig_pub_bytes: Option<[u8; 32]>,
58 incoming_resources: Vec<ResourceReceiver>,
60 outgoing_resources: Vec<ResourceSender>,
62 resource_strategy: ResourceStrategy,
64}
65
66struct LinkDestination {
68 sig_prv: Ed25519PrivateKey,
69 sig_pub_bytes: [u8; 32],
70 resource_strategy: ResourceStrategy,
71}
72
73struct RequestHandlerEntry {
75 path: String,
77 path_hash: [u8; 16],
79 allowed_list: Option<Vec<[u8; 16]>>,
81 handler:
83 Box<dyn Fn(LinkId, &str, &[u8], Option<&([u8; 16], [u8; 64])>) -> Option<Vec<u8>> + Send>,
84}
85
86#[derive(Debug)]
88pub enum LinkManagerAction {
89 SendPacket {
91 raw: Vec<u8>,
92 dest_type: u8,
93 attached_interface: Option<rns_core::transport::types::InterfaceId>,
94 },
95 LinkEstablished {
97 link_id: LinkId,
98 dest_hash: [u8; 16],
99 rtt: f64,
100 is_initiator: bool,
101 },
102 LinkClosed {
104 link_id: LinkId,
105 reason: Option<TeardownReason>,
106 },
107 RemoteIdentified {
109 link_id: LinkId,
110 identity_hash: [u8; 16],
111 public_key: [u8; 64],
112 },
113 RegisterLinkDest { link_id: LinkId },
115 DeregisterLinkDest { link_id: LinkId },
117 ManagementRequest {
120 link_id: LinkId,
121 path_hash: [u8; 16],
122 data: Vec<u8>,
124 request_id: [u8; 16],
126 remote_identity: Option<([u8; 16], [u8; 64])>,
127 },
128 ResourceReceived {
130 link_id: LinkId,
131 data: Vec<u8>,
132 metadata: Option<Vec<u8>>,
133 },
134 ResourceCompleted { link_id: LinkId },
136 ResourceFailed { link_id: LinkId, error: String },
138 ResourceProgress {
140 link_id: LinkId,
141 received: usize,
142 total: usize,
143 },
144 ResourceAcceptQuery {
146 link_id: LinkId,
147 resource_hash: Vec<u8>,
148 transfer_size: u64,
149 has_metadata: bool,
150 },
151 ChannelMessageReceived {
153 link_id: LinkId,
154 msgtype: u16,
155 payload: Vec<u8>,
156 },
157 LinkDataReceived {
159 link_id: LinkId,
160 context: u8,
161 data: Vec<u8>,
162 },
163 ResponseReceived {
165 link_id: LinkId,
166 request_id: [u8; 16],
167 data: Vec<u8>,
168 },
169 LinkRequestReceived {
171 link_id: LinkId,
172 receiving_interface: rns_core::transport::types::InterfaceId,
173 },
174}
175
176pub struct LinkManager {
178 links: HashMap<LinkId, ManagedLink>,
179 link_destinations: HashMap<[u8; 16], LinkDestination>,
180 request_handlers: Vec<RequestHandlerEntry>,
181 management_paths: Vec<[u8; 16]>,
184}
185
186impl LinkManager {
187 pub fn new() -> Self {
189 LinkManager {
190 links: HashMap::new(),
191 link_destinations: HashMap::new(),
192 request_handlers: Vec::new(),
193 management_paths: Vec::new(),
194 }
195 }
196
197 pub fn register_management_path(&mut self, path_hash: [u8; 16]) {
201 if !self.management_paths.contains(&path_hash) {
202 self.management_paths.push(path_hash);
203 }
204 }
205
206 pub fn get_derived_key(&self, link_id: &LinkId) -> Option<Vec<u8>> {
208 self.links
209 .get(link_id)
210 .and_then(|link| link.engine.derived_key().map(|dk| dk.to_vec()))
211 }
212
213 pub fn register_link_destination(
215 &mut self,
216 dest_hash: [u8; 16],
217 sig_prv: Ed25519PrivateKey,
218 sig_pub_bytes: [u8; 32],
219 resource_strategy: ResourceStrategy,
220 ) {
221 self.link_destinations.insert(
222 dest_hash,
223 LinkDestination {
224 sig_prv,
225 sig_pub_bytes,
226 resource_strategy,
227 },
228 );
229 }
230
231 pub fn deregister_link_destination(&mut self, dest_hash: &[u8; 16]) {
233 self.link_destinations.remove(dest_hash);
234 }
235
236 pub fn register_request_handler<F>(
242 &mut self,
243 path: &str,
244 allowed_list: Option<Vec<[u8; 16]>>,
245 handler: F,
246 ) where
247 F: Fn(LinkId, &str, &[u8], Option<&([u8; 16], [u8; 64])>) -> Option<Vec<u8>>
248 + Send
249 + 'static,
250 {
251 let path_hash = compute_path_hash(path);
252 self.request_handlers.push(RequestHandlerEntry {
253 path: path.to_string(),
254 path_hash,
255 allowed_list,
256 handler: Box::new(handler),
257 });
258 }
259
260 pub fn create_link(
268 &mut self,
269 dest_hash: &[u8; 16],
270 dest_sig_pub_bytes: &[u8; 32],
271 hops: u8,
272 mtu: u32,
273 rng: &mut dyn Rng,
274 ) -> (LinkId, Vec<LinkManagerAction>) {
275 let mode = LinkMode::Aes256Cbc;
276 let (mut engine, request_data) =
277 LinkEngine::new_initiator(dest_hash, hops, mode, Some(mtu), time::now(), rng);
278
279 let flags = PacketFlags {
281 header_type: constants::HEADER_1,
282 context_flag: constants::FLAG_UNSET,
283 transport_type: constants::TRANSPORT_BROADCAST,
284 destination_type: constants::DESTINATION_SINGLE,
285 packet_type: constants::PACKET_TYPE_LINKREQUEST,
286 };
287
288 let packet = match RawPacket::pack(
289 flags,
290 0,
291 dest_hash,
292 None,
293 constants::CONTEXT_NONE,
294 &request_data,
295 ) {
296 Ok(p) => p,
297 Err(_) => {
298 return ([0u8; 16], Vec::new());
300 }
301 };
302
303 engine.set_link_id_from_hashable(&packet.get_hashable_part(), request_data.len());
304 let link_id = *engine.link_id();
305
306 let managed = ManagedLink {
307 engine,
308 channel: None,
309 pending_channel_packets: HashMap::new(),
310 channel_send_ok: 0,
311 channel_send_not_ready: 0,
312 channel_send_too_big: 0,
313 channel_send_other_error: 0,
314 channel_messages_received: 0,
315 channel_proofs_sent: 0,
316 channel_proofs_received: 0,
317 dest_hash: *dest_hash,
318 remote_identity: None,
319 dest_sig_pub_bytes: Some(*dest_sig_pub_bytes),
320 incoming_resources: Vec::new(),
321 outgoing_resources: Vec::new(),
322 resource_strategy: ResourceStrategy::default(),
323 };
324 self.links.insert(link_id, managed);
325
326 let mut actions = Vec::new();
327 actions.push(LinkManagerAction::RegisterLinkDest { link_id });
329 actions.push(LinkManagerAction::SendPacket {
331 raw: packet.raw,
332 dest_type: constants::DESTINATION_LINK,
333 attached_interface: None,
334 });
335
336 (link_id, actions)
337 }
338
339 pub fn handle_local_delivery(
345 &mut self,
346 dest_hash: [u8; 16],
347 raw: &[u8],
348 packet_hash: [u8; 32],
349 receiving_interface: rns_core::transport::types::InterfaceId,
350 rng: &mut dyn Rng,
351 ) -> Vec<LinkManagerAction> {
352 let packet = match RawPacket::unpack(raw) {
353 Ok(p) => p,
354 Err(_) => return Vec::new(),
355 };
356
357 match packet.flags.packet_type {
358 constants::PACKET_TYPE_LINKREQUEST => {
359 self.handle_linkrequest(&dest_hash, &packet, receiving_interface, rng)
360 }
361 constants::PACKET_TYPE_PROOF if packet.context == constants::CONTEXT_LRPROOF => {
362 self.handle_lrproof(&dest_hash, &packet, rng)
364 }
365 constants::PACKET_TYPE_PROOF => self.handle_link_proof(&dest_hash, &packet, rng),
366 constants::PACKET_TYPE_DATA => {
367 self.handle_link_data(&dest_hash, &packet, packet_hash, rng)
368 }
369 _ => Vec::new(),
370 }
371 }
372
373 fn handle_linkrequest(
375 &mut self,
376 dest_hash: &[u8; 16],
377 packet: &RawPacket,
378 receiving_interface: rns_core::transport::types::InterfaceId,
379 rng: &mut dyn Rng,
380 ) -> Vec<LinkManagerAction> {
381 let ld = match self.link_destinations.get(dest_hash) {
383 Some(ld) => ld,
384 None => return Vec::new(),
385 };
386
387 let hashable = packet.get_hashable_part();
388 let now = time::now();
389
390 let (engine, lrproof_data) = match LinkEngine::new_responder(
392 &ld.sig_prv,
393 &ld.sig_pub_bytes,
394 &packet.data,
395 &hashable,
396 dest_hash,
397 packet.hops,
398 now,
399 rng,
400 ) {
401 Ok(r) => r,
402 Err(e) => {
403 log::debug!("LINKREQUEST rejected: {}", e);
404 return Vec::new();
405 }
406 };
407
408 let link_id = *engine.link_id();
409
410 let managed = ManagedLink {
411 engine,
412 channel: None,
413 pending_channel_packets: HashMap::new(),
414 channel_send_ok: 0,
415 channel_send_not_ready: 0,
416 channel_send_too_big: 0,
417 channel_send_other_error: 0,
418 channel_messages_received: 0,
419 channel_proofs_sent: 0,
420 channel_proofs_received: 0,
421 dest_hash: *dest_hash,
422 remote_identity: None,
423 dest_sig_pub_bytes: None,
424 incoming_resources: Vec::new(),
425 outgoing_resources: Vec::new(),
426 resource_strategy: ld.resource_strategy,
427 };
428 self.links.insert(link_id, managed);
429
430 let flags = PacketFlags {
432 header_type: constants::HEADER_1,
433 context_flag: constants::FLAG_UNSET,
434 transport_type: constants::TRANSPORT_BROADCAST,
435 destination_type: constants::DESTINATION_LINK,
436 packet_type: constants::PACKET_TYPE_PROOF,
437 };
438
439 let mut actions = Vec::new();
440
441 actions.push(LinkManagerAction::RegisterLinkDest { link_id });
443
444 if let Ok(pkt) = RawPacket::pack(
445 flags,
446 0,
447 &link_id,
448 None,
449 constants::CONTEXT_LRPROOF,
450 &lrproof_data,
451 ) {
452 actions.push(LinkManagerAction::SendPacket {
453 raw: pkt.raw,
454 dest_type: constants::DESTINATION_LINK,
455 attached_interface: None,
456 });
457 }
458
459 actions.push(LinkManagerAction::LinkRequestReceived {
461 link_id,
462 receiving_interface,
463 });
464
465 actions
466 }
467
468 fn handle_link_proof(
469 &mut self,
470 link_id: &LinkId,
471 packet: &RawPacket,
472 rng: &mut dyn Rng,
473 ) -> Vec<LinkManagerAction> {
474 if packet.data.len() < 32 {
475 return Vec::new();
476 }
477
478 let mut tracked_hash = [0u8; 32];
479 tracked_hash.copy_from_slice(&packet.data[..32]);
480
481 let Some(link) = self.links.get_mut(link_id) else {
482 return Vec::new();
483 };
484 let Some(sequence) = link.pending_channel_packets.remove(&tracked_hash) else {
485 return Vec::new();
486 };
487 link.channel_proofs_received += 1;
488 let Some(channel) = link.channel.as_mut() else {
489 return Vec::new();
490 };
491
492 let chan_actions = channel.packet_delivered(sequence);
493 let _ = channel;
494 let _ = link;
495 self.process_channel_actions(link_id, chan_actions, rng)
496 }
497
498 fn build_link_packet_proof(
499 &mut self,
500 link_id: &LinkId,
501 packet_hash: &[u8; 32],
502 ) -> Vec<LinkManagerAction> {
503 let dest_hash = match self.links.get(link_id) {
504 Some(link) => link.dest_hash,
505 None => return Vec::new(),
506 };
507 let Some(ld) = self.link_destinations.get(&dest_hash) else {
508 return Vec::new();
509 };
510 if let Some(link) = self.links.get_mut(link_id) {
511 link.channel_proofs_sent += 1;
512 }
513
514 let signature = ld.sig_prv.sign(packet_hash);
515 let mut proof_data = Vec::with_capacity(96);
516 proof_data.extend_from_slice(packet_hash);
517 proof_data.extend_from_slice(&signature);
518
519 let flags = PacketFlags {
520 header_type: constants::HEADER_1,
521 context_flag: constants::FLAG_UNSET,
522 transport_type: constants::TRANSPORT_BROADCAST,
523 destination_type: constants::DESTINATION_LINK,
524 packet_type: constants::PACKET_TYPE_PROOF,
525 };
526 if let Ok(pkt) = RawPacket::pack(
527 flags,
528 0,
529 link_id,
530 None,
531 constants::CONTEXT_NONE,
532 &proof_data,
533 ) {
534 vec![LinkManagerAction::SendPacket {
535 raw: pkt.raw,
536 dest_type: constants::DESTINATION_LINK,
537 attached_interface: None,
538 }]
539 } else {
540 Vec::new()
541 }
542 }
543
544 fn handle_lrproof(
546 &mut self,
547 link_id_bytes: &[u8; 16],
548 packet: &RawPacket,
549 rng: &mut dyn Rng,
550 ) -> Vec<LinkManagerAction> {
551 let link = match self.links.get_mut(link_id_bytes) {
552 Some(l) => l,
553 None => return Vec::new(),
554 };
555
556 if link.engine.state() != LinkState::Pending || !link.engine.is_initiator() {
557 return Vec::new();
558 }
559
560 let dest_sig_pub_bytes = match link.dest_sig_pub_bytes {
562 Some(b) => b,
563 None => {
564 log::debug!("LRPROOF: no destination signing key available");
565 return Vec::new();
566 }
567 };
568
569 let now = time::now();
570 let (lrrtt_encrypted, link_actions) =
571 match link
572 .engine
573 .handle_lrproof(&packet.data, &dest_sig_pub_bytes, now, rng)
574 {
575 Ok(r) => r,
576 Err(e) => {
577 log::debug!("LRPROOF validation failed: {}", e);
578 return Vec::new();
579 }
580 };
581
582 let link_id = *link.engine.link_id();
583 let mut actions = Vec::new();
584
585 actions.extend(self.process_link_actions(&link_id, &link_actions));
587
588 let flags = PacketFlags {
590 header_type: constants::HEADER_1,
591 context_flag: constants::FLAG_UNSET,
592 transport_type: constants::TRANSPORT_BROADCAST,
593 destination_type: constants::DESTINATION_LINK,
594 packet_type: constants::PACKET_TYPE_DATA,
595 };
596
597 if let Ok(pkt) = RawPacket::pack(
598 flags,
599 0,
600 &link_id,
601 None,
602 constants::CONTEXT_LRRTT,
603 &lrrtt_encrypted,
604 ) {
605 actions.push(LinkManagerAction::SendPacket {
606 raw: pkt.raw,
607 dest_type: constants::DESTINATION_LINK,
608 attached_interface: None,
609 });
610 }
611
612 if let Some(link) = self.links.get_mut(&link_id) {
614 if link.engine.state() == LinkState::Active {
615 let rtt = link.engine.rtt().unwrap_or(1.0);
616 link.channel = Some(Channel::new(rtt));
617 }
618 }
619
620 actions
621 }
622
623 fn handle_link_data(
629 &mut self,
630 link_id_bytes: &[u8; 16],
631 packet: &RawPacket,
632 packet_hash: [u8; 32],
633 rng: &mut dyn Rng,
634 ) -> Vec<LinkManagerAction> {
635 enum LinkDataResult {
637 Lrrtt {
638 link_id: LinkId,
639 link_actions: Vec<LinkAction>,
640 },
641 Identify {
642 link_id: LinkId,
643 link_actions: Vec<LinkAction>,
644 },
645 Keepalive {
646 link_id: LinkId,
647 inbound_actions: Vec<LinkAction>,
648 },
649 LinkClose {
650 link_id: LinkId,
651 teardown_actions: Vec<LinkAction>,
652 },
653 Channel {
654 link_id: LinkId,
655 inbound_actions: Vec<LinkAction>,
656 plaintext: Vec<u8>,
657 packet_hash: [u8; 32],
658 },
659 Request {
660 link_id: LinkId,
661 inbound_actions: Vec<LinkAction>,
662 plaintext: Vec<u8>,
663 packet_hash: [u8; 32],
664 },
665 Response {
666 link_id: LinkId,
667 inbound_actions: Vec<LinkAction>,
668 plaintext: Vec<u8>,
669 },
670 Generic {
671 link_id: LinkId,
672 inbound_actions: Vec<LinkAction>,
673 plaintext: Vec<u8>,
674 context: u8,
675 packet_hash: [u8; 32],
676 },
677 ResourceAdv {
679 link_id: LinkId,
680 inbound_actions: Vec<LinkAction>,
681 plaintext: Vec<u8>,
682 },
683 ResourceReq {
685 link_id: LinkId,
686 inbound_actions: Vec<LinkAction>,
687 plaintext: Vec<u8>,
688 },
689 ResourceHmu {
691 link_id: LinkId,
692 inbound_actions: Vec<LinkAction>,
693 plaintext: Vec<u8>,
694 },
695 ResourcePart {
697 link_id: LinkId,
698 inbound_actions: Vec<LinkAction>,
699 raw_data: Vec<u8>,
700 },
701 ResourcePrf {
703 link_id: LinkId,
704 inbound_actions: Vec<LinkAction>,
705 plaintext: Vec<u8>,
706 },
707 ResourceIcl {
709 link_id: LinkId,
710 inbound_actions: Vec<LinkAction>,
711 },
712 ResourceRcl {
714 link_id: LinkId,
715 inbound_actions: Vec<LinkAction>,
716 },
717 Error,
718 }
719
720 let result = {
721 let link = match self.links.get_mut(link_id_bytes) {
722 Some(l) => l,
723 None => return Vec::new(),
724 };
725
726 match packet.context {
727 constants::CONTEXT_LRRTT => {
728 match link.engine.handle_lrrtt(&packet.data, time::now()) {
729 Ok(link_actions) => {
730 let link_id = *link.engine.link_id();
731 LinkDataResult::Lrrtt {
732 link_id,
733 link_actions,
734 }
735 }
736 Err(e) => {
737 log::debug!("LRRTT handling failed: {}", e);
738 LinkDataResult::Error
739 }
740 }
741 }
742 constants::CONTEXT_LINKIDENTIFY => {
743 match link.engine.handle_identify(&packet.data) {
744 Ok(link_actions) => {
745 let link_id = *link.engine.link_id();
746 link.remote_identity = link.engine.remote_identity().cloned();
747 LinkDataResult::Identify {
748 link_id,
749 link_actions,
750 }
751 }
752 Err(e) => {
753 log::debug!("LINKIDENTIFY failed: {}", e);
754 LinkDataResult::Error
755 }
756 }
757 }
758 constants::CONTEXT_KEEPALIVE => {
759 let inbound_actions = link.engine.record_inbound(time::now());
760 let link_id = *link.engine.link_id();
761 LinkDataResult::Keepalive {
762 link_id,
763 inbound_actions,
764 }
765 }
766 constants::CONTEXT_LINKCLOSE => {
767 let teardown_actions = link.engine.handle_teardown();
768 let link_id = *link.engine.link_id();
769 LinkDataResult::LinkClose {
770 link_id,
771 teardown_actions,
772 }
773 }
774 constants::CONTEXT_CHANNEL => match link.engine.decrypt(&packet.data) {
775 Ok(plaintext) => {
776 let inbound_actions = link.engine.record_inbound(time::now());
777 let link_id = *link.engine.link_id();
778 LinkDataResult::Channel {
779 link_id,
780 inbound_actions,
781 plaintext,
782 packet_hash,
783 }
784 }
785 Err(_) => LinkDataResult::Error,
786 },
787 constants::CONTEXT_REQUEST => match link.engine.decrypt(&packet.data) {
788 Ok(plaintext) => {
789 let inbound_actions = link.engine.record_inbound(time::now());
790 let link_id = *link.engine.link_id();
791 LinkDataResult::Request {
792 link_id,
793 inbound_actions,
794 plaintext,
795 packet_hash,
796 }
797 }
798 Err(_) => LinkDataResult::Error,
799 },
800 constants::CONTEXT_RESPONSE => match link.engine.decrypt(&packet.data) {
801 Ok(plaintext) => {
802 let inbound_actions = link.engine.record_inbound(time::now());
803 let link_id = *link.engine.link_id();
804 LinkDataResult::Response {
805 link_id,
806 inbound_actions,
807 plaintext,
808 }
809 }
810 Err(_) => LinkDataResult::Error,
811 },
812 constants::CONTEXT_RESOURCE_ADV => match link.engine.decrypt(&packet.data) {
814 Ok(plaintext) => {
815 let inbound_actions = link.engine.record_inbound(time::now());
816 let link_id = *link.engine.link_id();
817 LinkDataResult::ResourceAdv {
818 link_id,
819 inbound_actions,
820 plaintext,
821 }
822 }
823 Err(_) => LinkDataResult::Error,
824 },
825 constants::CONTEXT_RESOURCE_REQ => match link.engine.decrypt(&packet.data) {
826 Ok(plaintext) => {
827 let inbound_actions = link.engine.record_inbound(time::now());
828 let link_id = *link.engine.link_id();
829 LinkDataResult::ResourceReq {
830 link_id,
831 inbound_actions,
832 plaintext,
833 }
834 }
835 Err(_) => LinkDataResult::Error,
836 },
837 constants::CONTEXT_RESOURCE_HMU => match link.engine.decrypt(&packet.data) {
838 Ok(plaintext) => {
839 let inbound_actions = link.engine.record_inbound(time::now());
840 let link_id = *link.engine.link_id();
841 LinkDataResult::ResourceHmu {
842 link_id,
843 inbound_actions,
844 plaintext,
845 }
846 }
847 Err(_) => LinkDataResult::Error,
848 },
849 constants::CONTEXT_RESOURCE => {
850 let inbound_actions = link.engine.record_inbound(time::now());
852 let link_id = *link.engine.link_id();
853 LinkDataResult::ResourcePart {
854 link_id,
855 inbound_actions,
856 raw_data: packet.data.clone(),
857 }
858 }
859 constants::CONTEXT_RESOURCE_PRF => match link.engine.decrypt(&packet.data) {
860 Ok(plaintext) => {
861 let inbound_actions = link.engine.record_inbound(time::now());
862 let link_id = *link.engine.link_id();
863 LinkDataResult::ResourcePrf {
864 link_id,
865 inbound_actions,
866 plaintext,
867 }
868 }
869 Err(_) => LinkDataResult::Error,
870 },
871 constants::CONTEXT_RESOURCE_ICL => {
872 let _ = link.engine.decrypt(&packet.data); let inbound_actions = link.engine.record_inbound(time::now());
874 let link_id = *link.engine.link_id();
875 LinkDataResult::ResourceIcl {
876 link_id,
877 inbound_actions,
878 }
879 }
880 constants::CONTEXT_RESOURCE_RCL => {
881 let _ = link.engine.decrypt(&packet.data); let inbound_actions = link.engine.record_inbound(time::now());
883 let link_id = *link.engine.link_id();
884 LinkDataResult::ResourceRcl {
885 link_id,
886 inbound_actions,
887 }
888 }
889 _ => match link.engine.decrypt(&packet.data) {
890 Ok(plaintext) => {
891 let inbound_actions = link.engine.record_inbound(time::now());
892 let link_id = *link.engine.link_id();
893 LinkDataResult::Generic {
894 link_id,
895 inbound_actions,
896 plaintext,
897 context: packet.context,
898 packet_hash,
899 }
900 }
901 Err(_) => LinkDataResult::Error,
902 },
903 }
904 }; let mut actions = Vec::new();
908 match result {
909 LinkDataResult::Lrrtt {
910 link_id,
911 link_actions,
912 } => {
913 actions.extend(self.process_link_actions(&link_id, &link_actions));
914 if let Some(link) = self.links.get_mut(&link_id) {
916 if link.engine.state() == LinkState::Active {
917 let rtt = link.engine.rtt().unwrap_or(1.0);
918 link.channel = Some(Channel::new(rtt));
919 }
920 }
921 }
922 LinkDataResult::Identify {
923 link_id,
924 link_actions,
925 } => {
926 actions.extend(self.process_link_actions(&link_id, &link_actions));
927 }
928 LinkDataResult::Keepalive {
929 link_id,
930 inbound_actions,
931 } => {
932 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
933 }
939 LinkDataResult::LinkClose {
940 link_id,
941 teardown_actions,
942 } => {
943 actions.extend(self.process_link_actions(&link_id, &teardown_actions));
944 }
945 LinkDataResult::Channel {
946 link_id,
947 inbound_actions,
948 plaintext,
949 packet_hash,
950 } => {
951 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
952 if let Some(link) = self.links.get_mut(&link_id) {
954 if let Some(ref mut channel) = link.channel {
955 let chan_actions = channel.receive(&plaintext, time::now());
956 link.channel_messages_received += chan_actions
957 .iter()
958 .filter(|action| {
959 matches!(
960 action,
961 rns_core::channel::ChannelAction::MessageReceived { .. }
962 )
963 })
964 .count()
965 as u64;
966 let _ = link;
968 actions.extend(self.process_channel_actions(&link_id, chan_actions, rng));
969 }
970 }
971 actions.extend(self.build_link_packet_proof(&link_id, &packet_hash));
972 }
973 LinkDataResult::Request {
974 link_id,
975 inbound_actions,
976 plaintext,
977 packet_hash,
978 } => {
979 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
980 actions.extend(self.handle_request(&link_id, &plaintext, packet_hash, rng));
981 }
982 LinkDataResult::Response {
983 link_id,
984 inbound_actions,
985 plaintext,
986 } => {
987 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
988 actions.extend(self.handle_response(&link_id, &plaintext));
990 }
991 LinkDataResult::Generic {
992 link_id,
993 inbound_actions,
994 plaintext,
995 context,
996 packet_hash,
997 } => {
998 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
999 actions.push(LinkManagerAction::LinkDataReceived {
1000 link_id,
1001 context,
1002 data: plaintext,
1003 });
1004
1005 actions.extend(self.build_link_packet_proof(&link_id, &packet_hash));
1006 }
1007 LinkDataResult::ResourceAdv {
1008 link_id,
1009 inbound_actions,
1010 plaintext,
1011 } => {
1012 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
1013 actions.extend(self.handle_resource_adv(&link_id, &plaintext, rng));
1014 }
1015 LinkDataResult::ResourceReq {
1016 link_id,
1017 inbound_actions,
1018 plaintext,
1019 } => {
1020 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
1021 actions.extend(self.handle_resource_req(&link_id, &plaintext, rng));
1022 }
1023 LinkDataResult::ResourceHmu {
1024 link_id,
1025 inbound_actions,
1026 plaintext,
1027 } => {
1028 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
1029 actions.extend(self.handle_resource_hmu(&link_id, &plaintext, rng));
1030 }
1031 LinkDataResult::ResourcePart {
1032 link_id,
1033 inbound_actions,
1034 raw_data,
1035 } => {
1036 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
1037 actions.extend(self.handle_resource_part(&link_id, &raw_data, rng));
1038 }
1039 LinkDataResult::ResourcePrf {
1040 link_id,
1041 inbound_actions,
1042 plaintext,
1043 } => {
1044 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
1045 actions.extend(self.handle_resource_prf(&link_id, &plaintext));
1046 }
1047 LinkDataResult::ResourceIcl {
1048 link_id,
1049 inbound_actions,
1050 } => {
1051 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
1052 actions.extend(self.handle_resource_icl(&link_id));
1053 }
1054 LinkDataResult::ResourceRcl {
1055 link_id,
1056 inbound_actions,
1057 } => {
1058 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
1059 actions.extend(self.handle_resource_rcl(&link_id));
1060 }
1061 LinkDataResult::Error => {}
1062 }
1063
1064 actions
1065 }
1066
1067 fn handle_request(
1069 &mut self,
1070 link_id: &LinkId,
1071 plaintext: &[u8],
1072 packet_hash: [u8; 32],
1073 rng: &mut dyn Rng,
1074 ) -> Vec<LinkManagerAction> {
1075 use rns_core::msgpack::{self, Value};
1076
1077 let arr = match msgpack::unpack_exact(plaintext) {
1079 Ok(Value::Array(arr)) if arr.len() >= 3 => arr,
1080 _ => return Vec::new(),
1081 };
1082
1083 let path_hash_bytes = match &arr[1] {
1084 Value::Bin(b) if b.len() == 16 => b,
1085 _ => return Vec::new(),
1086 };
1087 let mut path_hash = [0u8; 16];
1088 path_hash.copy_from_slice(path_hash_bytes);
1089
1090 let request_id = {
1097 let mut id = [0u8; 16];
1098 id.copy_from_slice(&packet_hash[..16]);
1099 id
1100 };
1101
1102 let request_data = msgpack::pack(&arr[2]);
1104
1105 if self.management_paths.contains(&path_hash) {
1107 let remote_identity = self
1108 .links
1109 .get(link_id)
1110 .and_then(|l| l.remote_identity)
1111 .map(|(h, k)| (h, k));
1112 return vec![LinkManagerAction::ManagementRequest {
1113 link_id: *link_id,
1114 path_hash,
1115 data: request_data,
1116 request_id,
1117 remote_identity,
1118 }];
1119 }
1120
1121 let handler_idx = self
1123 .request_handlers
1124 .iter()
1125 .position(|h| h.path_hash == path_hash);
1126 let handler_idx = match handler_idx {
1127 Some(i) => i,
1128 None => return Vec::new(),
1129 };
1130
1131 let remote_identity = self
1133 .links
1134 .get(link_id)
1135 .and_then(|l| l.remote_identity.as_ref());
1136 let handler = &self.request_handlers[handler_idx];
1137 if let Some(ref allowed) = handler.allowed_list {
1138 match remote_identity {
1139 Some((identity_hash, _)) => {
1140 if !allowed.contains(identity_hash) {
1141 log::debug!("Request denied: identity not in allowed list");
1142 return Vec::new();
1143 }
1144 }
1145 None => {
1146 log::debug!("Request denied: peer not identified");
1147 return Vec::new();
1148 }
1149 }
1150 }
1151
1152 let path = handler.path.clone();
1154 let response = (handler.handler)(*link_id, &path, &request_data, remote_identity);
1155
1156 let mut actions = Vec::new();
1157 if let Some(response_data) = response {
1158 actions.extend(self.build_response_packet(link_id, &request_id, &response_data, rng));
1159 }
1160
1161 actions
1162 }
1163
1164 fn build_response_packet(
1167 &self,
1168 link_id: &LinkId,
1169 request_id: &[u8; 16],
1170 response_data: &[u8],
1171 rng: &mut dyn Rng,
1172 ) -> Vec<LinkManagerAction> {
1173 use rns_core::msgpack::{self, Value};
1174
1175 let response_value = msgpack::unpack_exact(response_data)
1177 .unwrap_or_else(|_| Value::Bin(response_data.to_vec()));
1178
1179 let response_array = Value::Array(vec![Value::Bin(request_id.to_vec()), response_value]);
1180 let response_plaintext = msgpack::pack(&response_array);
1181
1182 let mut actions = Vec::new();
1183 if let Some(link) = self.links.get(link_id) {
1184 if let Ok(encrypted) = link.engine.encrypt(&response_plaintext, rng) {
1185 let flags = PacketFlags {
1186 header_type: constants::HEADER_1,
1187 context_flag: constants::FLAG_UNSET,
1188 transport_type: constants::TRANSPORT_BROADCAST,
1189 destination_type: constants::DESTINATION_LINK,
1190 packet_type: constants::PACKET_TYPE_DATA,
1191 };
1192 if let Ok(pkt) = RawPacket::pack(
1193 flags,
1194 0,
1195 link_id,
1196 None,
1197 constants::CONTEXT_RESPONSE,
1198 &encrypted,
1199 ) {
1200 actions.push(LinkManagerAction::SendPacket {
1201 raw: pkt.raw,
1202 dest_type: constants::DESTINATION_LINK,
1203 attached_interface: None,
1204 });
1205 }
1206 }
1207 }
1208 actions
1209 }
1210
1211 pub fn send_management_response(
1214 &self,
1215 link_id: &LinkId,
1216 request_id: &[u8; 16],
1217 response_data: &[u8],
1218 rng: &mut dyn Rng,
1219 ) -> Vec<LinkManagerAction> {
1220 self.build_response_packet(link_id, request_id, response_data, rng)
1221 }
1222
1223 pub fn send_request(
1231 &self,
1232 link_id: &LinkId,
1233 path: &str,
1234 data: &[u8],
1235 rng: &mut dyn Rng,
1236 ) -> Vec<LinkManagerAction> {
1237 use rns_core::msgpack::{self, Value};
1238
1239 let link = match self.links.get(link_id) {
1240 Some(l) => l,
1241 None => return Vec::new(),
1242 };
1243
1244 if link.engine.state() != LinkState::Active {
1245 return Vec::new();
1246 }
1247
1248 let path_hash = compute_path_hash(path);
1249
1250 let data_value = msgpack::unpack_exact(data).unwrap_or_else(|_| Value::Bin(data.to_vec()));
1252
1253 let request_array = Value::Array(vec![
1255 Value::Float(time::now()),
1256 Value::Bin(path_hash.to_vec()),
1257 data_value,
1258 ]);
1259 let plaintext = msgpack::pack(&request_array);
1260
1261 let encrypted = match link.engine.encrypt(&plaintext, rng) {
1262 Ok(e) => e,
1263 Err(_) => return Vec::new(),
1264 };
1265
1266 let flags = PacketFlags {
1267 header_type: constants::HEADER_1,
1268 context_flag: constants::FLAG_UNSET,
1269 transport_type: constants::TRANSPORT_BROADCAST,
1270 destination_type: constants::DESTINATION_LINK,
1271 packet_type: constants::PACKET_TYPE_DATA,
1272 };
1273
1274 let mut actions = Vec::new();
1275 if let Ok(pkt) = RawPacket::pack(
1276 flags,
1277 0,
1278 link_id,
1279 None,
1280 constants::CONTEXT_REQUEST,
1281 &encrypted,
1282 ) {
1283 actions.push(LinkManagerAction::SendPacket {
1284 raw: pkt.raw,
1285 dest_type: constants::DESTINATION_LINK,
1286 attached_interface: None,
1287 });
1288 }
1289 actions
1290 }
1291
1292 pub fn send_on_link(
1294 &self,
1295 link_id: &LinkId,
1296 plaintext: &[u8],
1297 context: u8,
1298 rng: &mut dyn Rng,
1299 ) -> Vec<LinkManagerAction> {
1300 let link = match self.links.get(link_id) {
1301 Some(l) => l,
1302 None => return Vec::new(),
1303 };
1304
1305 if link.engine.state() != LinkState::Active {
1306 return Vec::new();
1307 }
1308
1309 let encrypted = match link.engine.encrypt(plaintext, rng) {
1310 Ok(e) => e,
1311 Err(_) => return Vec::new(),
1312 };
1313
1314 let flags = PacketFlags {
1315 header_type: constants::HEADER_1,
1316 context_flag: constants::FLAG_UNSET,
1317 transport_type: constants::TRANSPORT_BROADCAST,
1318 destination_type: constants::DESTINATION_LINK,
1319 packet_type: constants::PACKET_TYPE_DATA,
1320 };
1321
1322 let mut actions = Vec::new();
1323 if let Ok(pkt) = RawPacket::pack(flags, 0, link_id, None, context, &encrypted) {
1324 actions.push(LinkManagerAction::SendPacket {
1325 raw: pkt.raw,
1326 dest_type: constants::DESTINATION_LINK,
1327 attached_interface: None,
1328 });
1329 }
1330 actions
1331 }
1332
1333 pub fn identify(
1335 &self,
1336 link_id: &LinkId,
1337 identity: &rns_crypto::identity::Identity,
1338 rng: &mut dyn Rng,
1339 ) -> Vec<LinkManagerAction> {
1340 let link = match self.links.get(link_id) {
1341 Some(l) => l,
1342 None => return Vec::new(),
1343 };
1344
1345 let encrypted = match link.engine.build_identify(identity, rng) {
1346 Ok(e) => e,
1347 Err(_) => return Vec::new(),
1348 };
1349
1350 let flags = PacketFlags {
1351 header_type: constants::HEADER_1,
1352 context_flag: constants::FLAG_UNSET,
1353 transport_type: constants::TRANSPORT_BROADCAST,
1354 destination_type: constants::DESTINATION_LINK,
1355 packet_type: constants::PACKET_TYPE_DATA,
1356 };
1357
1358 let mut actions = Vec::new();
1359 if let Ok(pkt) = RawPacket::pack(
1360 flags,
1361 0,
1362 link_id,
1363 None,
1364 constants::CONTEXT_LINKIDENTIFY,
1365 &encrypted,
1366 ) {
1367 actions.push(LinkManagerAction::SendPacket {
1368 raw: pkt.raw,
1369 dest_type: constants::DESTINATION_LINK,
1370 attached_interface: None,
1371 });
1372 }
1373 actions
1374 }
1375
1376 pub fn teardown_link(&mut self, link_id: &LinkId) -> Vec<LinkManagerAction> {
1378 let link = match self.links.get_mut(link_id) {
1379 Some(l) => l,
1380 None => return Vec::new(),
1381 };
1382
1383 let teardown_actions = link.engine.teardown();
1384 if let Some(ref mut channel) = link.channel {
1385 channel.shutdown();
1386 }
1387
1388 let mut actions = self.process_link_actions(link_id, &teardown_actions);
1389
1390 let flags = PacketFlags {
1392 header_type: constants::HEADER_1,
1393 context_flag: constants::FLAG_UNSET,
1394 transport_type: constants::TRANSPORT_BROADCAST,
1395 destination_type: constants::DESTINATION_LINK,
1396 packet_type: constants::PACKET_TYPE_DATA,
1397 };
1398 if let Ok(pkt) = RawPacket::pack(flags, 0, link_id, None, constants::CONTEXT_LINKCLOSE, &[])
1399 {
1400 actions.push(LinkManagerAction::SendPacket {
1401 raw: pkt.raw,
1402 dest_type: constants::DESTINATION_LINK,
1403 attached_interface: None,
1404 });
1405 }
1406
1407 actions
1408 }
1409
1410 pub fn teardown_all_links(&mut self) -> Vec<LinkManagerAction> {
1412 let link_ids: Vec<LinkId> = self.links.keys().copied().collect();
1413 let mut actions = Vec::new();
1414 for link_id in link_ids {
1415 actions.extend(self.teardown_link(&link_id));
1416 }
1417 actions
1418 }
1419
1420 fn handle_response(&self, link_id: &LinkId, plaintext: &[u8]) -> Vec<LinkManagerAction> {
1422 use rns_core::msgpack;
1423
1424 let arr = match msgpack::unpack_exact(plaintext) {
1426 Ok(msgpack::Value::Array(arr)) if arr.len() >= 2 => arr,
1427 _ => return Vec::new(),
1428 };
1429
1430 let request_id_bytes = match &arr[0] {
1431 msgpack::Value::Bin(b) if b.len() == 16 => b,
1432 _ => return Vec::new(),
1433 };
1434 let mut request_id = [0u8; 16];
1435 request_id.copy_from_slice(request_id_bytes);
1436
1437 let response_data = msgpack::pack(&arr[1]);
1438
1439 vec![LinkManagerAction::ResponseReceived {
1440 link_id: *link_id,
1441 request_id,
1442 data: response_data,
1443 }]
1444 }
1445
1446 fn handle_resource_adv(
1448 &mut self,
1449 link_id: &LinkId,
1450 adv_plaintext: &[u8],
1451 rng: &mut dyn Rng,
1452 ) -> Vec<LinkManagerAction> {
1453 let link = match self.links.get_mut(link_id) {
1454 Some(l) => l,
1455 None => return Vec::new(),
1456 };
1457
1458 let link_rtt = link.engine.rtt().unwrap_or(1.0);
1459 let now = time::now();
1460
1461 let receiver = match ResourceReceiver::from_advertisement(
1462 adv_plaintext,
1463 constants::RESOURCE_SDU,
1464 link_rtt,
1465 now,
1466 None,
1467 None,
1468 ) {
1469 Ok(r) => r,
1470 Err(e) => {
1471 log::debug!("Resource ADV rejected: {}", e);
1472 return Vec::new();
1473 }
1474 };
1475
1476 let strategy = link.resource_strategy;
1477 let resource_hash = receiver.resource_hash.clone();
1478 let transfer_size = receiver.transfer_size;
1479 let has_metadata = receiver.has_metadata;
1480
1481 match strategy {
1482 ResourceStrategy::AcceptNone => {
1483 let reject_actions = {
1485 let mut r = receiver;
1486 r.reject()
1487 };
1488 self.process_resource_actions(link_id, reject_actions, rng)
1489 }
1490 ResourceStrategy::AcceptAll => {
1491 link.incoming_resources.push(receiver);
1492 let idx = link.incoming_resources.len() - 1;
1493 let resource_actions = link.incoming_resources[idx].accept(now);
1494 let _ = link;
1495 self.process_resource_actions(link_id, resource_actions, rng)
1496 }
1497 ResourceStrategy::AcceptApp => {
1498 link.incoming_resources.push(receiver);
1499 vec![LinkManagerAction::ResourceAcceptQuery {
1501 link_id: *link_id,
1502 resource_hash,
1503 transfer_size,
1504 has_metadata,
1505 }]
1506 }
1507 }
1508 }
1509
1510 pub fn accept_resource(
1512 &mut self,
1513 link_id: &LinkId,
1514 resource_hash: &[u8],
1515 accept: bool,
1516 rng: &mut dyn Rng,
1517 ) -> Vec<LinkManagerAction> {
1518 let link = match self.links.get_mut(link_id) {
1519 Some(l) => l,
1520 None => return Vec::new(),
1521 };
1522
1523 let now = time::now();
1524 let idx = link
1525 .incoming_resources
1526 .iter()
1527 .position(|r| r.resource_hash == resource_hash);
1528 let idx = match idx {
1529 Some(i) => i,
1530 None => return Vec::new(),
1531 };
1532
1533 let resource_actions = if accept {
1534 link.incoming_resources[idx].accept(now)
1535 } else {
1536 link.incoming_resources[idx].reject()
1537 };
1538
1539 let _ = link;
1540 self.process_resource_actions(link_id, resource_actions, rng)
1541 }
1542
1543 fn handle_resource_req(
1545 &mut self,
1546 link_id: &LinkId,
1547 plaintext: &[u8],
1548 rng: &mut dyn Rng,
1549 ) -> Vec<LinkManagerAction> {
1550 let link = match self.links.get_mut(link_id) {
1551 Some(l) => l,
1552 None => return Vec::new(),
1553 };
1554
1555 let now = time::now();
1556 let mut all_actions = Vec::new();
1557 for sender in &mut link.outgoing_resources {
1558 let resource_actions = sender.handle_request(plaintext, now);
1559 if !resource_actions.is_empty() {
1560 all_actions.extend(resource_actions);
1561 break;
1562 }
1563 }
1564
1565 let _ = link;
1566 self.process_resource_actions(link_id, all_actions, rng)
1567 }
1568
1569 fn handle_resource_hmu(
1571 &mut self,
1572 link_id: &LinkId,
1573 plaintext: &[u8],
1574 rng: &mut dyn Rng,
1575 ) -> Vec<LinkManagerAction> {
1576 let link = match self.links.get_mut(link_id) {
1577 Some(l) => l,
1578 None => return Vec::new(),
1579 };
1580
1581 let now = time::now();
1582 let mut all_actions = Vec::new();
1583 for receiver in &mut link.incoming_resources {
1584 let resource_actions = receiver.handle_hashmap_update(plaintext, now);
1585 if !resource_actions.is_empty() {
1586 all_actions.extend(resource_actions);
1587 break;
1588 }
1589 }
1590
1591 let _ = link;
1592 self.process_resource_actions(link_id, all_actions, rng)
1593 }
1594
1595 fn handle_resource_part(
1597 &mut self,
1598 link_id: &LinkId,
1599 raw_data: &[u8],
1600 rng: &mut dyn Rng,
1601 ) -> Vec<LinkManagerAction> {
1602 let link = match self.links.get_mut(link_id) {
1603 Some(l) => l,
1604 None => return Vec::new(),
1605 };
1606
1607 let now = time::now();
1608 let mut all_actions = Vec::new();
1609 let mut assemble_idx = None;
1610
1611 for (idx, receiver) in link.incoming_resources.iter_mut().enumerate() {
1612 let resource_actions = receiver.receive_part(raw_data, now);
1613 if !resource_actions.is_empty() {
1614 if receiver.received_count == receiver.total_parts {
1616 assemble_idx = Some(idx);
1617 }
1618 all_actions.extend(resource_actions);
1619 break;
1620 }
1621 }
1622
1623 if let Some(idx) = assemble_idx {
1625 let decrypt_fn = |ciphertext: &[u8]| -> Result<Vec<u8>, ()> {
1626 link.engine.decrypt(ciphertext).map_err(|_| ())
1627 };
1628 let assemble_actions =
1629 link.incoming_resources[idx].assemble(&decrypt_fn, &Bzip2Compressor);
1630 all_actions.extend(assemble_actions);
1631 }
1632
1633 let _ = link;
1634 self.process_resource_actions(link_id, all_actions, rng)
1635 }
1636
1637 fn handle_resource_prf(
1639 &mut self,
1640 link_id: &LinkId,
1641 plaintext: &[u8],
1642 ) -> Vec<LinkManagerAction> {
1643 let link = match self.links.get_mut(link_id) {
1644 Some(l) => l,
1645 None => return Vec::new(),
1646 };
1647
1648 let now = time::now();
1649 let mut result_actions = Vec::new();
1650 for sender in &mut link.outgoing_resources {
1651 let resource_actions = sender.handle_proof(plaintext, now);
1652 if !resource_actions.is_empty() {
1653 result_actions.extend(resource_actions);
1654 break;
1655 }
1656 }
1657
1658 let mut actions = Vec::new();
1660 for ra in result_actions {
1661 match ra {
1662 ResourceAction::Completed => {
1663 actions.push(LinkManagerAction::ResourceCompleted { link_id: *link_id });
1664 }
1665 ResourceAction::Failed(e) => {
1666 actions.push(LinkManagerAction::ResourceFailed {
1667 link_id: *link_id,
1668 error: format!("{}", e),
1669 });
1670 }
1671 _ => {}
1672 }
1673 }
1674
1675 link.outgoing_resources
1677 .retain(|s| s.status < rns_core::resource::ResourceStatus::Complete);
1678
1679 actions
1680 }
1681
1682 fn handle_resource_icl(&mut self, link_id: &LinkId) -> Vec<LinkManagerAction> {
1684 let link = match self.links.get_mut(link_id) {
1685 Some(l) => l,
1686 None => return Vec::new(),
1687 };
1688
1689 let mut actions = Vec::new();
1690 for receiver in &mut link.incoming_resources {
1691 let ra = receiver.handle_cancel();
1692 for a in ra {
1693 if let ResourceAction::Failed(ref e) = a {
1694 actions.push(LinkManagerAction::ResourceFailed {
1695 link_id: *link_id,
1696 error: format!("{}", e),
1697 });
1698 }
1699 }
1700 }
1701 link.incoming_resources
1702 .retain(|r| r.status < rns_core::resource::ResourceStatus::Complete);
1703 actions
1704 }
1705
1706 fn handle_resource_rcl(&mut self, link_id: &LinkId) -> Vec<LinkManagerAction> {
1708 let link = match self.links.get_mut(link_id) {
1709 Some(l) => l,
1710 None => return Vec::new(),
1711 };
1712
1713 let mut actions = Vec::new();
1714 for sender in &mut link.outgoing_resources {
1715 let ra = sender.handle_reject();
1716 for a in ra {
1717 if let ResourceAction::Failed(ref e) = a {
1718 actions.push(LinkManagerAction::ResourceFailed {
1719 link_id: *link_id,
1720 error: format!("{}", e),
1721 });
1722 }
1723 }
1724 }
1725 link.outgoing_resources
1726 .retain(|s| s.status < rns_core::resource::ResourceStatus::Complete);
1727 actions
1728 }
1729
1730 fn process_resource_actions(
1732 &self,
1733 link_id: &LinkId,
1734 actions: Vec<ResourceAction>,
1735 rng: &mut dyn Rng,
1736 ) -> Vec<LinkManagerAction> {
1737 let link = match self.links.get(link_id) {
1738 Some(l) => l,
1739 None => return Vec::new(),
1740 };
1741
1742 let mut result = Vec::new();
1743 for action in actions {
1744 match action {
1745 ResourceAction::SendAdvertisement(data) => {
1746 if let Ok(encrypted) = link.engine.encrypt(&data, rng) {
1748 result.extend(self.build_link_packet(
1749 link_id,
1750 constants::CONTEXT_RESOURCE_ADV,
1751 &encrypted,
1752 ));
1753 }
1754 }
1755 ResourceAction::SendPart(data) => {
1756 result.extend(self.build_link_packet(
1758 link_id,
1759 constants::CONTEXT_RESOURCE,
1760 &data,
1761 ));
1762 }
1763 ResourceAction::SendRequest(data) => {
1764 if let Ok(encrypted) = link.engine.encrypt(&data, rng) {
1765 result.extend(self.build_link_packet(
1766 link_id,
1767 constants::CONTEXT_RESOURCE_REQ,
1768 &encrypted,
1769 ));
1770 }
1771 }
1772 ResourceAction::SendHmu(data) => {
1773 if let Ok(encrypted) = link.engine.encrypt(&data, rng) {
1774 result.extend(self.build_link_packet(
1775 link_id,
1776 constants::CONTEXT_RESOURCE_HMU,
1777 &encrypted,
1778 ));
1779 }
1780 }
1781 ResourceAction::SendProof(data) => {
1782 if let Ok(encrypted) = link.engine.encrypt(&data, rng) {
1783 result.extend(self.build_link_packet(
1784 link_id,
1785 constants::CONTEXT_RESOURCE_PRF,
1786 &encrypted,
1787 ));
1788 }
1789 }
1790 ResourceAction::SendCancelInitiator(data) => {
1791 if let Ok(encrypted) = link.engine.encrypt(&data, rng) {
1792 result.extend(self.build_link_packet(
1793 link_id,
1794 constants::CONTEXT_RESOURCE_ICL,
1795 &encrypted,
1796 ));
1797 }
1798 }
1799 ResourceAction::SendCancelReceiver(data) => {
1800 if let Ok(encrypted) = link.engine.encrypt(&data, rng) {
1801 result.extend(self.build_link_packet(
1802 link_id,
1803 constants::CONTEXT_RESOURCE_RCL,
1804 &encrypted,
1805 ));
1806 }
1807 }
1808 ResourceAction::DataReceived { data, metadata } => {
1809 result.push(LinkManagerAction::ResourceReceived {
1810 link_id: *link_id,
1811 data,
1812 metadata,
1813 });
1814 }
1815 ResourceAction::Completed => {
1816 result.push(LinkManagerAction::ResourceCompleted { link_id: *link_id });
1817 }
1818 ResourceAction::Failed(e) => {
1819 result.push(LinkManagerAction::ResourceFailed {
1820 link_id: *link_id,
1821 error: format!("{}", e),
1822 });
1823 }
1824 ResourceAction::ProgressUpdate { received, total } => {
1825 result.push(LinkManagerAction::ResourceProgress {
1826 link_id: *link_id,
1827 received,
1828 total,
1829 });
1830 }
1831 }
1832 }
1833 result
1834 }
1835
1836 fn build_link_packet(
1838 &self,
1839 link_id: &LinkId,
1840 context: u8,
1841 data: &[u8],
1842 ) -> Vec<LinkManagerAction> {
1843 let flags = PacketFlags {
1844 header_type: constants::HEADER_1,
1845 context_flag: constants::FLAG_UNSET,
1846 transport_type: constants::TRANSPORT_BROADCAST,
1847 destination_type: constants::DESTINATION_LINK,
1848 packet_type: constants::PACKET_TYPE_DATA,
1849 };
1850 let mut actions = Vec::new();
1851 if let Ok(pkt) = RawPacket::pack(flags, 0, link_id, None, context, data) {
1852 actions.push(LinkManagerAction::SendPacket {
1853 raw: pkt.raw,
1854 dest_type: constants::DESTINATION_LINK,
1855 attached_interface: None,
1856 });
1857 }
1858 actions
1859 }
1860
1861 pub fn send_resource(
1863 &mut self,
1864 link_id: &LinkId,
1865 data: &[u8],
1866 metadata: Option<&[u8]>,
1867 rng: &mut dyn Rng,
1868 ) -> Vec<LinkManagerAction> {
1869 let link = match self.links.get_mut(link_id) {
1870 Some(l) => l,
1871 None => return Vec::new(),
1872 };
1873
1874 if link.engine.state() != LinkState::Active {
1875 return Vec::new();
1876 }
1877
1878 let link_rtt = link.engine.rtt().unwrap_or(1.0);
1879 let now = time::now();
1880
1881 let enc_rng = std::cell::RefCell::new(rns_crypto::OsRng);
1884 let encrypt_fn = |plaintext: &[u8]| -> Vec<u8> {
1885 link.engine
1886 .encrypt(plaintext, &mut *enc_rng.borrow_mut())
1887 .unwrap_or_else(|_| plaintext.to_vec())
1888 };
1889
1890 let sender = match ResourceSender::new(
1891 data,
1892 metadata,
1893 constants::RESOURCE_SDU,
1894 &encrypt_fn,
1895 &Bzip2Compressor,
1896 rng,
1897 now,
1898 true, false, None, 1, 1, None, link_rtt,
1905 6.0, ) {
1907 Ok(s) => s,
1908 Err(e) => {
1909 log::debug!("Failed to create ResourceSender: {}", e);
1910 return Vec::new();
1911 }
1912 };
1913
1914 let mut sender = sender;
1915 let adv_actions = sender.advertise(now);
1916 link.outgoing_resources.push(sender);
1917
1918 let _ = link;
1919 self.process_resource_actions(link_id, adv_actions, rng)
1920 }
1921
1922 pub fn set_resource_strategy(&mut self, link_id: &LinkId, strategy: ResourceStrategy) {
1924 if let Some(link) = self.links.get_mut(link_id) {
1925 link.resource_strategy = strategy;
1926 }
1927 }
1928
1929 pub fn flush_channel_tx(&mut self, link_id: &LinkId) {
1932 if let Some(link) = self.links.get_mut(link_id) {
1933 if let Some(ref mut channel) = link.channel {
1934 channel.flush_tx();
1935 }
1936 }
1937 }
1938
1939 pub fn send_channel_message(
1941 &mut self,
1942 link_id: &LinkId,
1943 msgtype: u16,
1944 payload: &[u8],
1945 rng: &mut dyn Rng,
1946 ) -> Result<Vec<LinkManagerAction>, String> {
1947 let link = match self.links.get_mut(link_id) {
1948 Some(l) => l,
1949 None => return Err("unknown link".to_string()),
1950 };
1951
1952 let channel = match link.channel {
1953 Some(ref mut ch) => ch,
1954 None => return Err("link has no active channel".to_string()),
1955 };
1956
1957 let link_mdu = link.engine.mdu();
1958 let now = time::now();
1959 let chan_actions = match channel.send(msgtype, payload, now, link_mdu) {
1960 Ok(a) => {
1961 link.channel_send_ok += 1;
1962 a
1963 }
1964 Err(e) => {
1965 log::debug!("Channel send failed: {:?}", e);
1966 match e {
1967 rns_core::channel::ChannelError::NotReady => link.channel_send_not_ready += 1,
1968 rns_core::channel::ChannelError::MessageTooBig => {
1969 link.channel_send_too_big += 1;
1970 }
1971 rns_core::channel::ChannelError::InvalidEnvelope => {
1972 link.channel_send_other_error += 1;
1973 }
1974 }
1975 return Err(e.to_string());
1976 }
1977 };
1978
1979 let _ = link;
1980 Ok(self.process_channel_actions(link_id, chan_actions, rng))
1981 }
1982
1983 pub fn tick(&mut self, rng: &mut dyn Rng) -> Vec<LinkManagerAction> {
1985 let now = time::now();
1986 let mut all_actions = Vec::new();
1987
1988 let link_ids: Vec<LinkId> = self.links.keys().copied().collect();
1990
1991 for link_id in &link_ids {
1992 let link = match self.links.get_mut(link_id) {
1993 Some(l) => l,
1994 None => continue,
1995 };
1996
1997 let tick_actions = link.engine.tick(now);
1999 all_actions.extend(self.process_link_actions(link_id, &tick_actions));
2000
2001 let link = match self.links.get_mut(link_id) {
2003 Some(l) => l,
2004 None => continue,
2005 };
2006 if link.engine.needs_keepalive(now) {
2007 let flags = PacketFlags {
2009 header_type: constants::HEADER_1,
2010 context_flag: constants::FLAG_UNSET,
2011 transport_type: constants::TRANSPORT_BROADCAST,
2012 destination_type: constants::DESTINATION_LINK,
2013 packet_type: constants::PACKET_TYPE_DATA,
2014 };
2015 if let Ok(pkt) =
2016 RawPacket::pack(flags, 0, link_id, None, constants::CONTEXT_KEEPALIVE, &[])
2017 {
2018 all_actions.push(LinkManagerAction::SendPacket {
2019 raw: pkt.raw,
2020 dest_type: constants::DESTINATION_LINK,
2021 attached_interface: None,
2022 });
2023 link.engine.record_outbound(now, true);
2024 }
2025 }
2026
2027 if let Some(channel) = link.channel.as_mut() {
2028 let chan_actions = channel.tick(now);
2029 let _ = channel;
2030 let _ = link;
2031 all_actions.extend(self.process_channel_actions(link_id, chan_actions, rng));
2032 }
2033 }
2034
2035 for link_id in &link_ids {
2037 let link = match self.links.get_mut(link_id) {
2038 Some(l) => l,
2039 None => continue,
2040 };
2041
2042 let mut sender_actions = Vec::new();
2044 for sender in &mut link.outgoing_resources {
2045 sender_actions.extend(sender.tick(now));
2046 }
2047
2048 let mut receiver_actions = Vec::new();
2050 for receiver in &mut link.incoming_resources {
2051 let decrypt_fn = |ciphertext: &[u8]| -> Result<Vec<u8>, ()> {
2052 link.engine.decrypt(ciphertext).map_err(|_| ())
2053 };
2054 receiver_actions.extend(receiver.tick(now, &decrypt_fn, &Bzip2Compressor));
2055 }
2056
2057 link.outgoing_resources
2059 .retain(|s| s.status < rns_core::resource::ResourceStatus::Complete);
2060 link.incoming_resources
2061 .retain(|r| r.status < rns_core::resource::ResourceStatus::Assembling);
2062
2063 let _ = link;
2064 all_actions.extend(self.process_resource_actions(link_id, sender_actions, rng));
2065 all_actions.extend(self.process_resource_actions(link_id, receiver_actions, rng));
2066 }
2067
2068 let closed: Vec<LinkId> = self
2070 .links
2071 .iter()
2072 .filter(|(_, l)| l.engine.state() == LinkState::Closed)
2073 .map(|(id, _)| *id)
2074 .collect();
2075 for id in closed {
2076 self.links.remove(&id);
2077 all_actions.push(LinkManagerAction::DeregisterLinkDest { link_id: id });
2078 }
2079
2080 all_actions
2081 }
2082
2083 pub fn is_link_destination(&self, dest_hash: &[u8; 16]) -> bool {
2085 self.links.contains_key(dest_hash) || self.link_destinations.contains_key(dest_hash)
2086 }
2087
2088 pub fn link_state(&self, link_id: &LinkId) -> Option<LinkState> {
2090 self.links.get(link_id).map(|l| l.engine.state())
2091 }
2092
2093 pub fn link_rtt(&self, link_id: &LinkId) -> Option<f64> {
2095 self.links.get(link_id).and_then(|l| l.engine.rtt())
2096 }
2097
2098 pub fn set_link_rtt(&mut self, link_id: &LinkId, rtt: f64) {
2100 if let Some(link) = self.links.get_mut(link_id) {
2101 link.engine.set_rtt(rtt);
2102 }
2103 }
2104
2105 pub fn record_link_inbound(&mut self, link_id: &LinkId) {
2107 if let Some(link) = self.links.get_mut(link_id) {
2108 link.engine.record_inbound(time::now());
2109 }
2110 }
2111
2112 pub fn set_link_mtu(&mut self, link_id: &LinkId, mtu: u32) {
2114 if let Some(link) = self.links.get_mut(link_id) {
2115 link.engine.set_mtu(mtu);
2116 }
2117 }
2118
2119 pub fn link_count(&self) -> usize {
2121 self.links.len()
2122 }
2123
2124 pub fn resource_transfer_count(&self) -> usize {
2126 self.links
2127 .values()
2128 .map(|managed| managed.incoming_resources.len() + managed.outgoing_resources.len())
2129 .sum()
2130 }
2131
2132 pub fn cancel_all_resources(&mut self, rng: &mut dyn Rng) -> Vec<LinkManagerAction> {
2134 let link_ids: Vec<LinkId> = self.links.keys().copied().collect();
2135 let mut all_actions = Vec::new();
2136
2137 for link_id in &link_ids {
2138 let link = match self.links.get_mut(link_id) {
2139 Some(l) => l,
2140 None => continue,
2141 };
2142
2143 let mut sender_actions = Vec::new();
2144 for sender in &mut link.outgoing_resources {
2145 sender_actions.extend(sender.cancel());
2146 }
2147
2148 let mut receiver_actions = Vec::new();
2149 for receiver in &mut link.incoming_resources {
2150 receiver_actions.extend(receiver.reject());
2151 }
2152
2153 link.outgoing_resources
2154 .retain(|s| s.status < rns_core::resource::ResourceStatus::Complete);
2155 link.incoming_resources
2156 .retain(|r| r.status < rns_core::resource::ResourceStatus::Assembling);
2157
2158 let _ = link;
2159 all_actions.extend(self.process_resource_actions(link_id, sender_actions, rng));
2160 all_actions.extend(self.process_resource_actions(link_id, receiver_actions, rng));
2161 }
2162
2163 all_actions
2164 }
2165
2166 pub fn link_entries(&self) -> Vec<crate::event::LinkInfoEntry> {
2168 self.links
2169 .iter()
2170 .map(|(link_id, managed)| {
2171 let state = match managed.engine.state() {
2172 LinkState::Pending => "pending",
2173 LinkState::Handshake => "handshake",
2174 LinkState::Active => "active",
2175 LinkState::Stale => "stale",
2176 LinkState::Closed => "closed",
2177 };
2178 crate::event::LinkInfoEntry {
2179 link_id: *link_id,
2180 state: state.to_string(),
2181 is_initiator: managed.engine.is_initiator(),
2182 dest_hash: managed.dest_hash,
2183 remote_identity: managed.remote_identity.as_ref().map(|(h, _)| *h),
2184 rtt: managed.engine.rtt(),
2185 channel_window: managed.channel.as_ref().map(|c| c.window()),
2186 channel_outstanding: managed.channel.as_ref().map(|c| c.outstanding()),
2187 pending_channel_packets: managed.pending_channel_packets.len(),
2188 channel_send_ok: managed.channel_send_ok,
2189 channel_send_not_ready: managed.channel_send_not_ready,
2190 channel_send_too_big: managed.channel_send_too_big,
2191 channel_send_other_error: managed.channel_send_other_error,
2192 channel_messages_received: managed.channel_messages_received,
2193 channel_proofs_sent: managed.channel_proofs_sent,
2194 channel_proofs_received: managed.channel_proofs_received,
2195 }
2196 })
2197 .collect()
2198 }
2199
2200 pub fn resource_entries(&self) -> Vec<crate::event::ResourceInfoEntry> {
2202 let mut entries = Vec::new();
2203 for (link_id, managed) in &self.links {
2204 for recv in &managed.incoming_resources {
2205 let (received, total) = recv.progress();
2206 entries.push(crate::event::ResourceInfoEntry {
2207 link_id: *link_id,
2208 direction: "incoming".to_string(),
2209 total_parts: total,
2210 transferred_parts: received,
2211 complete: received >= total && total > 0,
2212 });
2213 }
2214 for send in &managed.outgoing_resources {
2215 let total = send.total_parts();
2216 let sent = send.sent_parts;
2217 entries.push(crate::event::ResourceInfoEntry {
2218 link_id: *link_id,
2219 direction: "outgoing".to_string(),
2220 total_parts: total,
2221 transferred_parts: sent,
2222 complete: sent >= total && total > 0,
2223 });
2224 }
2225 }
2226 entries
2227 }
2228
2229 fn process_link_actions(
2231 &self,
2232 link_id: &LinkId,
2233 actions: &[LinkAction],
2234 ) -> Vec<LinkManagerAction> {
2235 let mut result = Vec::new();
2236 for action in actions {
2237 match action {
2238 LinkAction::StateChanged {
2239 new_state, reason, ..
2240 } => match new_state {
2241 LinkState::Closed => {
2242 result.push(LinkManagerAction::LinkClosed {
2243 link_id: *link_id,
2244 reason: *reason,
2245 });
2246 }
2247 _ => {}
2248 },
2249 LinkAction::LinkEstablished {
2250 rtt, is_initiator, ..
2251 } => {
2252 let dest_hash = self
2253 .links
2254 .get(link_id)
2255 .map(|l| l.dest_hash)
2256 .unwrap_or([0u8; 16]);
2257 result.push(LinkManagerAction::LinkEstablished {
2258 link_id: *link_id,
2259 dest_hash,
2260 rtt: *rtt,
2261 is_initiator: *is_initiator,
2262 });
2263 }
2264 LinkAction::RemoteIdentified {
2265 identity_hash,
2266 public_key,
2267 ..
2268 } => {
2269 result.push(LinkManagerAction::RemoteIdentified {
2270 link_id: *link_id,
2271 identity_hash: *identity_hash,
2272 public_key: *public_key,
2273 });
2274 }
2275 LinkAction::DataReceived { .. } => {
2276 }
2278 }
2279 }
2280 result
2281 }
2282
2283 fn process_channel_actions(
2285 &mut self,
2286 link_id: &LinkId,
2287 actions: Vec<rns_core::channel::ChannelAction>,
2288 rng: &mut dyn Rng,
2289 ) -> Vec<LinkManagerAction> {
2290 let mut result = Vec::new();
2291 for action in actions {
2292 match action {
2293 rns_core::channel::ChannelAction::SendOnLink { raw, sequence } => {
2294 let encrypted = match self.links.get(link_id) {
2296 Some(link) => match link.engine.encrypt(&raw, rng) {
2297 Ok(encrypted) => encrypted,
2298 Err(_) => continue,
2299 },
2300 None => continue,
2301 };
2302 let flags = PacketFlags {
2303 header_type: constants::HEADER_1,
2304 context_flag: constants::FLAG_UNSET,
2305 transport_type: constants::TRANSPORT_BROADCAST,
2306 destination_type: constants::DESTINATION_LINK,
2307 packet_type: constants::PACKET_TYPE_DATA,
2308 };
2309 if let Ok(pkt) = RawPacket::pack(
2310 flags,
2311 0,
2312 link_id,
2313 None,
2314 constants::CONTEXT_CHANNEL,
2315 &encrypted,
2316 ) {
2317 if let Some(link_mut) = self.links.get_mut(link_id) {
2318 link_mut
2319 .pending_channel_packets
2320 .insert(pkt.packet_hash, sequence);
2321 }
2322 result.push(LinkManagerAction::SendPacket {
2323 raw: pkt.raw,
2324 dest_type: constants::DESTINATION_LINK,
2325 attached_interface: None,
2326 });
2327 }
2328 }
2329 rns_core::channel::ChannelAction::MessageReceived {
2330 msgtype, payload, ..
2331 } => {
2332 result.push(LinkManagerAction::ChannelMessageReceived {
2333 link_id: *link_id,
2334 msgtype,
2335 payload,
2336 });
2337 }
2338 rns_core::channel::ChannelAction::TeardownLink => {
2339 result.push(LinkManagerAction::LinkClosed {
2340 link_id: *link_id,
2341 reason: Some(TeardownReason::Timeout),
2342 });
2343 }
2344 }
2345 }
2346 result
2347 }
2348}
2349
2350fn compute_path_hash(path: &str) -> [u8; 16] {
2353 let full = rns_core::hash::full_hash(path.as_bytes());
2354 let mut result = [0u8; 16];
2355 result.copy_from_slice(&full[..16]);
2356 result
2357}
2358
2359#[cfg(test)]
2360mod tests {
2361 use super::*;
2362 use rns_crypto::identity::Identity;
2363 use rns_crypto::{FixedRng, OsRng};
2364
2365 fn make_rng(seed: u8) -> FixedRng {
2366 FixedRng::new(&[seed; 128])
2367 }
2368
2369 fn make_dest_keys(rng: &mut dyn Rng) -> (Ed25519PrivateKey, [u8; 32]) {
2370 let sig_prv = Ed25519PrivateKey::generate(rng);
2371 let sig_pub_bytes = sig_prv.public_key().public_bytes();
2372 (sig_prv, sig_pub_bytes)
2373 }
2374
2375 #[test]
2376 fn test_register_link_destination() {
2377 let mut mgr = LinkManager::new();
2378 let mut rng = make_rng(0x01);
2379 let (sig_prv, sig_pub_bytes) = make_dest_keys(&mut rng);
2380 let dest_hash = [0xDD; 16];
2381
2382 mgr.register_link_destination(
2383 dest_hash,
2384 sig_prv,
2385 sig_pub_bytes,
2386 ResourceStrategy::AcceptNone,
2387 );
2388 assert!(mgr.is_link_destination(&dest_hash));
2389
2390 mgr.deregister_link_destination(&dest_hash);
2391 assert!(!mgr.is_link_destination(&dest_hash));
2392 }
2393
2394 #[test]
2395 fn test_create_link() {
2396 let mut mgr = LinkManager::new();
2397 let mut rng = OsRng;
2398 let dest_hash = [0xDD; 16];
2399
2400 let sig_pub_bytes = [0xAA; 32]; let (link_id, actions) = mgr.create_link(
2402 &dest_hash,
2403 &sig_pub_bytes,
2404 1,
2405 constants::MTU as u32,
2406 &mut rng,
2407 );
2408 assert_ne!(link_id, [0u8; 16]);
2409 assert_eq!(actions.len(), 2);
2411 assert!(matches!(
2412 actions[0],
2413 LinkManagerAction::RegisterLinkDest { .. }
2414 ));
2415 assert!(matches!(actions[1], LinkManagerAction::SendPacket { .. }));
2416
2417 assert_eq!(mgr.link_state(&link_id), Some(LinkState::Pending));
2419 }
2420
2421 #[test]
2422 fn test_full_handshake_via_manager() {
2423 let mut rng = OsRng;
2424 let dest_hash = [0xDD; 16];
2425
2426 let mut responder_mgr = LinkManager::new();
2428 let (sig_prv, sig_pub_bytes) = make_dest_keys(&mut rng);
2429 responder_mgr.register_link_destination(
2430 dest_hash,
2431 sig_prv,
2432 sig_pub_bytes,
2433 ResourceStrategy::AcceptNone,
2434 );
2435
2436 let mut initiator_mgr = LinkManager::new();
2438
2439 let (link_id, init_actions) = initiator_mgr.create_link(
2441 &dest_hash,
2442 &sig_pub_bytes,
2443 1,
2444 constants::MTU as u32,
2445 &mut rng,
2446 );
2447 assert_eq!(init_actions.len(), 2);
2448
2449 let linkrequest_raw = match &init_actions[1] {
2451 LinkManagerAction::SendPacket { raw, .. } => raw.clone(),
2452 _ => panic!("Expected SendPacket"),
2453 };
2454
2455 let lr_packet = RawPacket::unpack(&linkrequest_raw).unwrap();
2457
2458 let resp_actions = responder_mgr.handle_local_delivery(
2460 lr_packet.destination_hash,
2461 &linkrequest_raw,
2462 lr_packet.packet_hash,
2463 rns_core::transport::types::InterfaceId(0),
2464 &mut rng,
2465 );
2466 assert!(resp_actions.len() >= 2);
2468 assert!(matches!(
2469 resp_actions[0],
2470 LinkManagerAction::RegisterLinkDest { .. }
2471 ));
2472
2473 let lrproof_raw = match &resp_actions[1] {
2475 LinkManagerAction::SendPacket { raw, .. } => raw.clone(),
2476 _ => panic!("Expected SendPacket for LRPROOF"),
2477 };
2478
2479 let lrproof_packet = RawPacket::unpack(&lrproof_raw).unwrap();
2481 let init_actions2 = initiator_mgr.handle_local_delivery(
2482 lrproof_packet.destination_hash,
2483 &lrproof_raw,
2484 lrproof_packet.packet_hash,
2485 rns_core::transport::types::InterfaceId(0),
2486 &mut rng,
2487 );
2488
2489 let has_established = init_actions2
2491 .iter()
2492 .any(|a| matches!(a, LinkManagerAction::LinkEstablished { .. }));
2493 assert!(has_established, "Initiator should emit LinkEstablished");
2494
2495 let lrrtt_raw = init_actions2
2497 .iter()
2498 .find_map(|a| match a {
2499 LinkManagerAction::SendPacket { raw, .. } => Some(raw.clone()),
2500 _ => None,
2501 })
2502 .expect("Should have LRRTT SendPacket");
2503
2504 let lrrtt_packet = RawPacket::unpack(&lrrtt_raw).unwrap();
2506 let resp_link_id = lrrtt_packet.destination_hash;
2507 let resp_actions2 = responder_mgr.handle_local_delivery(
2508 resp_link_id,
2509 &lrrtt_raw,
2510 lrrtt_packet.packet_hash,
2511 rns_core::transport::types::InterfaceId(0),
2512 &mut rng,
2513 );
2514
2515 let has_established = resp_actions2
2516 .iter()
2517 .any(|a| matches!(a, LinkManagerAction::LinkEstablished { .. }));
2518 assert!(has_established, "Responder should emit LinkEstablished");
2519
2520 assert_eq!(initiator_mgr.link_state(&link_id), Some(LinkState::Active));
2522 assert_eq!(responder_mgr.link_state(&link_id), Some(LinkState::Active));
2523
2524 assert!(initiator_mgr.link_rtt(&link_id).is_some());
2526 assert!(responder_mgr.link_rtt(&link_id).is_some());
2527 }
2528
2529 #[test]
2530 fn test_encrypted_data_exchange() {
2531 let mut rng = OsRng;
2532 let dest_hash = [0xDD; 16];
2533 let mut resp_mgr = LinkManager::new();
2534 let (sig_prv, sig_pub_bytes) = make_dest_keys(&mut rng);
2535 resp_mgr.register_link_destination(
2536 dest_hash,
2537 sig_prv,
2538 sig_pub_bytes,
2539 ResourceStrategy::AcceptNone,
2540 );
2541 let mut init_mgr = LinkManager::new();
2542
2543 let (link_id, init_actions) = init_mgr.create_link(
2545 &dest_hash,
2546 &sig_pub_bytes,
2547 1,
2548 constants::MTU as u32,
2549 &mut rng,
2550 );
2551 let lr_raw = extract_send_packet(&init_actions);
2552 let lr_pkt = RawPacket::unpack(&lr_raw).unwrap();
2553 let resp_actions = resp_mgr.handle_local_delivery(
2554 lr_pkt.destination_hash,
2555 &lr_raw,
2556 lr_pkt.packet_hash,
2557 rns_core::transport::types::InterfaceId(0),
2558 &mut rng,
2559 );
2560 let lrproof_raw = extract_send_packet_at(&resp_actions, 1);
2561 let lrproof_pkt = RawPacket::unpack(&lrproof_raw).unwrap();
2562 let init_actions2 = init_mgr.handle_local_delivery(
2563 lrproof_pkt.destination_hash,
2564 &lrproof_raw,
2565 lrproof_pkt.packet_hash,
2566 rns_core::transport::types::InterfaceId(0),
2567 &mut rng,
2568 );
2569 let lrrtt_raw = extract_any_send_packet(&init_actions2);
2570 let lrrtt_pkt = RawPacket::unpack(&lrrtt_raw).unwrap();
2571 resp_mgr.handle_local_delivery(
2572 lrrtt_pkt.destination_hash,
2573 &lrrtt_raw,
2574 lrrtt_pkt.packet_hash,
2575 rns_core::transport::types::InterfaceId(0),
2576 &mut rng,
2577 );
2578
2579 let actions =
2581 init_mgr.send_on_link(&link_id, b"hello link!", constants::CONTEXT_NONE, &mut rng);
2582 assert_eq!(actions.len(), 1);
2583 assert!(matches!(actions[0], LinkManagerAction::SendPacket { .. }));
2584 }
2585
2586 #[test]
2587 fn test_request_response() {
2588 let mut rng = OsRng;
2589 let dest_hash = [0xDD; 16];
2590 let mut resp_mgr = LinkManager::new();
2591 let (sig_prv, sig_pub_bytes) = make_dest_keys(&mut rng);
2592 resp_mgr.register_link_destination(
2593 dest_hash,
2594 sig_prv,
2595 sig_pub_bytes,
2596 ResourceStrategy::AcceptNone,
2597 );
2598
2599 resp_mgr.register_request_handler("/status", None, |_link_id, _path, _data, _remote| {
2601 Some(b"OK".to_vec())
2602 });
2603
2604 let mut init_mgr = LinkManager::new();
2605
2606 let (link_id, init_actions) = init_mgr.create_link(
2608 &dest_hash,
2609 &sig_pub_bytes,
2610 1,
2611 constants::MTU as u32,
2612 &mut rng,
2613 );
2614 let lr_raw = extract_send_packet(&init_actions);
2615 let lr_pkt = RawPacket::unpack(&lr_raw).unwrap();
2616 let resp_actions = resp_mgr.handle_local_delivery(
2617 lr_pkt.destination_hash,
2618 &lr_raw,
2619 lr_pkt.packet_hash,
2620 rns_core::transport::types::InterfaceId(0),
2621 &mut rng,
2622 );
2623 let lrproof_raw = extract_send_packet_at(&resp_actions, 1);
2624 let lrproof_pkt = RawPacket::unpack(&lrproof_raw).unwrap();
2625 let init_actions2 = init_mgr.handle_local_delivery(
2626 lrproof_pkt.destination_hash,
2627 &lrproof_raw,
2628 lrproof_pkt.packet_hash,
2629 rns_core::transport::types::InterfaceId(0),
2630 &mut rng,
2631 );
2632 let lrrtt_raw = extract_any_send_packet(&init_actions2);
2633 let lrrtt_pkt = RawPacket::unpack(&lrrtt_raw).unwrap();
2634 resp_mgr.handle_local_delivery(
2635 lrrtt_pkt.destination_hash,
2636 &lrrtt_raw,
2637 lrrtt_pkt.packet_hash,
2638 rns_core::transport::types::InterfaceId(0),
2639 &mut rng,
2640 );
2641
2642 let req_actions = init_mgr.send_request(&link_id, "/status", b"query", &mut rng);
2644 assert_eq!(req_actions.len(), 1);
2645
2646 let req_raw = extract_send_packet_from(&req_actions);
2648 let req_pkt = RawPacket::unpack(&req_raw).unwrap();
2649 let resp_actions = resp_mgr.handle_local_delivery(
2650 req_pkt.destination_hash,
2651 &req_raw,
2652 req_pkt.packet_hash,
2653 rns_core::transport::types::InterfaceId(0),
2654 &mut rng,
2655 );
2656
2657 let has_response = resp_actions
2659 .iter()
2660 .any(|a| matches!(a, LinkManagerAction::SendPacket { .. }));
2661 assert!(has_response, "Handler should produce a response packet");
2662 }
2663
2664 #[test]
2665 fn test_request_acl_deny_unidentified() {
2666 let mut rng = OsRng;
2667 let dest_hash = [0xDD; 16];
2668 let mut resp_mgr = LinkManager::new();
2669 let (sig_prv, sig_pub_bytes) = make_dest_keys(&mut rng);
2670 resp_mgr.register_link_destination(
2671 dest_hash,
2672 sig_prv,
2673 sig_pub_bytes,
2674 ResourceStrategy::AcceptNone,
2675 );
2676
2677 resp_mgr.register_request_handler(
2679 "/restricted",
2680 Some(vec![[0xAA; 16]]),
2681 |_link_id, _path, _data, _remote| Some(b"secret".to_vec()),
2682 );
2683
2684 let mut init_mgr = LinkManager::new();
2685
2686 let (link_id, init_actions) = init_mgr.create_link(
2688 &dest_hash,
2689 &sig_pub_bytes,
2690 1,
2691 constants::MTU as u32,
2692 &mut rng,
2693 );
2694 let lr_raw = extract_send_packet(&init_actions);
2695 let lr_pkt = RawPacket::unpack(&lr_raw).unwrap();
2696 let resp_actions = resp_mgr.handle_local_delivery(
2697 lr_pkt.destination_hash,
2698 &lr_raw,
2699 lr_pkt.packet_hash,
2700 rns_core::transport::types::InterfaceId(0),
2701 &mut rng,
2702 );
2703 let lrproof_raw = extract_send_packet_at(&resp_actions, 1);
2704 let lrproof_pkt = RawPacket::unpack(&lrproof_raw).unwrap();
2705 let init_actions2 = init_mgr.handle_local_delivery(
2706 lrproof_pkt.destination_hash,
2707 &lrproof_raw,
2708 lrproof_pkt.packet_hash,
2709 rns_core::transport::types::InterfaceId(0),
2710 &mut rng,
2711 );
2712 let lrrtt_raw = extract_any_send_packet(&init_actions2);
2713 let lrrtt_pkt = RawPacket::unpack(&lrrtt_raw).unwrap();
2714 resp_mgr.handle_local_delivery(
2715 lrrtt_pkt.destination_hash,
2716 &lrrtt_raw,
2717 lrrtt_pkt.packet_hash,
2718 rns_core::transport::types::InterfaceId(0),
2719 &mut rng,
2720 );
2721
2722 let req_actions = init_mgr.send_request(&link_id, "/restricted", b"query", &mut rng);
2724 let req_raw = extract_send_packet_from(&req_actions);
2725 let req_pkt = RawPacket::unpack(&req_raw).unwrap();
2726 let resp_actions = resp_mgr.handle_local_delivery(
2727 req_pkt.destination_hash,
2728 &req_raw,
2729 req_pkt.packet_hash,
2730 rns_core::transport::types::InterfaceId(0),
2731 &mut rng,
2732 );
2733
2734 let has_response = resp_actions
2736 .iter()
2737 .any(|a| matches!(a, LinkManagerAction::SendPacket { .. }));
2738 assert!(!has_response, "Unidentified peer should be denied");
2739 }
2740
2741 #[test]
2742 fn test_teardown_link() {
2743 let mut rng = OsRng;
2744 let dest_hash = [0xDD; 16];
2745 let mut mgr = LinkManager::new();
2746
2747 let dummy_sig = [0xAA; 32];
2748 let (link_id, _) =
2749 mgr.create_link(&dest_hash, &dummy_sig, 1, constants::MTU as u32, &mut rng);
2750 assert_eq!(mgr.link_count(), 1);
2751
2752 let actions = mgr.teardown_link(&link_id);
2753 let has_close = actions
2754 .iter()
2755 .any(|a| matches!(a, LinkManagerAction::LinkClosed { .. }));
2756 assert!(has_close);
2757
2758 let tick_actions = mgr.tick(&mut rng);
2760 let has_deregister = tick_actions
2761 .iter()
2762 .any(|a| matches!(a, LinkManagerAction::DeregisterLinkDest { .. }));
2763 assert!(has_deregister);
2764 assert_eq!(mgr.link_count(), 0);
2765 }
2766
2767 #[test]
2768 fn test_identify_on_link() {
2769 let mut rng = OsRng;
2770 let dest_hash = [0xDD; 16];
2771 let mut resp_mgr = LinkManager::new();
2772 let (sig_prv, sig_pub_bytes) = make_dest_keys(&mut rng);
2773 resp_mgr.register_link_destination(
2774 dest_hash,
2775 sig_prv,
2776 sig_pub_bytes,
2777 ResourceStrategy::AcceptNone,
2778 );
2779 let mut init_mgr = LinkManager::new();
2780
2781 let (link_id, init_actions) = init_mgr.create_link(
2783 &dest_hash,
2784 &sig_pub_bytes,
2785 1,
2786 constants::MTU as u32,
2787 &mut rng,
2788 );
2789 let lr_raw = extract_send_packet(&init_actions);
2790 let lr_pkt = RawPacket::unpack(&lr_raw).unwrap();
2791 let resp_actions = resp_mgr.handle_local_delivery(
2792 lr_pkt.destination_hash,
2793 &lr_raw,
2794 lr_pkt.packet_hash,
2795 rns_core::transport::types::InterfaceId(0),
2796 &mut rng,
2797 );
2798 let lrproof_raw = extract_send_packet_at(&resp_actions, 1);
2799 let lrproof_pkt = RawPacket::unpack(&lrproof_raw).unwrap();
2800 let init_actions2 = init_mgr.handle_local_delivery(
2801 lrproof_pkt.destination_hash,
2802 &lrproof_raw,
2803 lrproof_pkt.packet_hash,
2804 rns_core::transport::types::InterfaceId(0),
2805 &mut rng,
2806 );
2807 let lrrtt_raw = extract_any_send_packet(&init_actions2);
2808 let lrrtt_pkt = RawPacket::unpack(&lrrtt_raw).unwrap();
2809 resp_mgr.handle_local_delivery(
2810 lrrtt_pkt.destination_hash,
2811 &lrrtt_raw,
2812 lrrtt_pkt.packet_hash,
2813 rns_core::transport::types::InterfaceId(0),
2814 &mut rng,
2815 );
2816
2817 let identity = Identity::new(&mut rng);
2819 let id_actions = init_mgr.identify(&link_id, &identity, &mut rng);
2820 assert_eq!(id_actions.len(), 1);
2821
2822 let id_raw = extract_send_packet_from(&id_actions);
2824 let id_pkt = RawPacket::unpack(&id_raw).unwrap();
2825 let resp_actions = resp_mgr.handle_local_delivery(
2826 id_pkt.destination_hash,
2827 &id_raw,
2828 id_pkt.packet_hash,
2829 rns_core::transport::types::InterfaceId(0),
2830 &mut rng,
2831 );
2832
2833 let has_identified = resp_actions
2834 .iter()
2835 .any(|a| matches!(a, LinkManagerAction::RemoteIdentified { .. }));
2836 assert!(has_identified, "Responder should emit RemoteIdentified");
2837 }
2838
2839 #[test]
2840 fn test_path_hash_computation() {
2841 let h1 = compute_path_hash("/status");
2842 let h2 = compute_path_hash("/path");
2843 assert_ne!(h1, h2);
2844
2845 assert_eq!(h1, compute_path_hash("/status"));
2847 }
2848
2849 #[test]
2850 fn test_link_count() {
2851 let mut mgr = LinkManager::new();
2852 let mut rng = OsRng;
2853
2854 assert_eq!(mgr.link_count(), 0);
2855
2856 let dummy_sig = [0xAA; 32];
2857 mgr.create_link(&[0x11; 16], &dummy_sig, 1, constants::MTU as u32, &mut rng);
2858 assert_eq!(mgr.link_count(), 1);
2859
2860 mgr.create_link(&[0x22; 16], &dummy_sig, 1, constants::MTU as u32, &mut rng);
2861 assert_eq!(mgr.link_count(), 2);
2862 }
2863
2864 fn extract_send_packet(actions: &[LinkManagerAction]) -> Vec<u8> {
2867 extract_send_packet_at(actions, actions.len() - 1)
2868 }
2869
2870 fn extract_send_packet_at(actions: &[LinkManagerAction], idx: usize) -> Vec<u8> {
2871 match &actions[idx] {
2872 LinkManagerAction::SendPacket { raw, .. } => raw.clone(),
2873 other => panic!("Expected SendPacket at index {}, got {:?}", idx, other),
2874 }
2875 }
2876
2877 fn extract_any_send_packet(actions: &[LinkManagerAction]) -> Vec<u8> {
2878 actions
2879 .iter()
2880 .find_map(|a| match a {
2881 LinkManagerAction::SendPacket { raw, .. } => Some(raw.clone()),
2882 _ => None,
2883 })
2884 .expect("Expected at least one SendPacket action")
2885 }
2886
2887 fn extract_send_packet_from(actions: &[LinkManagerAction]) -> Vec<u8> {
2888 extract_any_send_packet(actions)
2889 }
2890
2891 fn setup_active_link() -> (LinkManager, LinkManager, LinkId) {
2894 let mut rng = OsRng;
2895 let dest_hash = [0xDD; 16];
2896 let mut resp_mgr = LinkManager::new();
2897 let (sig_prv, sig_pub_bytes) = make_dest_keys(&mut rng);
2898 resp_mgr.register_link_destination(
2899 dest_hash,
2900 sig_prv,
2901 sig_pub_bytes,
2902 ResourceStrategy::AcceptNone,
2903 );
2904 let mut init_mgr = LinkManager::new();
2905
2906 let (link_id, init_actions) = init_mgr.create_link(
2907 &dest_hash,
2908 &sig_pub_bytes,
2909 1,
2910 constants::MTU as u32,
2911 &mut rng,
2912 );
2913 let lr_raw = extract_send_packet(&init_actions);
2914 let lr_pkt = RawPacket::unpack(&lr_raw).unwrap();
2915 let resp_actions = resp_mgr.handle_local_delivery(
2916 lr_pkt.destination_hash,
2917 &lr_raw,
2918 lr_pkt.packet_hash,
2919 rns_core::transport::types::InterfaceId(0),
2920 &mut rng,
2921 );
2922 let lrproof_raw = extract_send_packet_at(&resp_actions, 1);
2923 let lrproof_pkt = RawPacket::unpack(&lrproof_raw).unwrap();
2924 let init_actions2 = init_mgr.handle_local_delivery(
2925 lrproof_pkt.destination_hash,
2926 &lrproof_raw,
2927 lrproof_pkt.packet_hash,
2928 rns_core::transport::types::InterfaceId(0),
2929 &mut rng,
2930 );
2931 let lrrtt_raw = extract_any_send_packet(&init_actions2);
2932 let lrrtt_pkt = RawPacket::unpack(&lrrtt_raw).unwrap();
2933 resp_mgr.handle_local_delivery(
2934 lrrtt_pkt.destination_hash,
2935 &lrrtt_raw,
2936 lrrtt_pkt.packet_hash,
2937 rns_core::transport::types::InterfaceId(0),
2938 &mut rng,
2939 );
2940
2941 assert_eq!(init_mgr.link_state(&link_id), Some(LinkState::Active));
2942 assert_eq!(resp_mgr.link_state(&link_id), Some(LinkState::Active));
2943
2944 (init_mgr, resp_mgr, link_id)
2945 }
2946
2947 #[test]
2952 fn test_resource_strategy_default() {
2953 let mut mgr = LinkManager::new();
2954 let mut rng = OsRng;
2955 let dummy_sig = [0xAA; 32];
2956 let (link_id, _) =
2957 mgr.create_link(&[0x11; 16], &dummy_sig, 1, constants::MTU as u32, &mut rng);
2958
2959 let link = mgr.links.get(&link_id).unwrap();
2961 assert_eq!(link.resource_strategy, ResourceStrategy::AcceptNone);
2962 }
2963
2964 #[test]
2965 fn test_set_resource_strategy() {
2966 let mut mgr = LinkManager::new();
2967 let mut rng = OsRng;
2968 let dummy_sig = [0xAA; 32];
2969 let (link_id, _) =
2970 mgr.create_link(&[0x11; 16], &dummy_sig, 1, constants::MTU as u32, &mut rng);
2971
2972 mgr.set_resource_strategy(&link_id, ResourceStrategy::AcceptAll);
2973 assert_eq!(
2974 mgr.links.get(&link_id).unwrap().resource_strategy,
2975 ResourceStrategy::AcceptAll
2976 );
2977
2978 mgr.set_resource_strategy(&link_id, ResourceStrategy::AcceptApp);
2979 assert_eq!(
2980 mgr.links.get(&link_id).unwrap().resource_strategy,
2981 ResourceStrategy::AcceptApp
2982 );
2983 }
2984
2985 #[test]
2986 fn test_send_resource_on_active_link() {
2987 let (mut init_mgr, _resp_mgr, link_id) = setup_active_link();
2988 let mut rng = OsRng;
2989
2990 let data = vec![0xAB; 100]; let actions = init_mgr.send_resource(&link_id, &data, None, &mut rng);
2993
2994 let has_send = actions
2996 .iter()
2997 .any(|a| matches!(a, LinkManagerAction::SendPacket { .. }));
2998 assert!(
2999 has_send,
3000 "send_resource should emit advertisement SendPacket"
3001 );
3002 }
3003
3004 #[test]
3005 fn test_send_resource_on_inactive_link() {
3006 let mut mgr = LinkManager::new();
3007 let mut rng = OsRng;
3008 let dummy_sig = [0xAA; 32];
3009 let (link_id, _) =
3010 mgr.create_link(&[0x11; 16], &dummy_sig, 1, constants::MTU as u32, &mut rng);
3011
3012 let actions = mgr.send_resource(&link_id, b"data", None, &mut rng);
3014 assert!(actions.is_empty(), "Cannot send resource on inactive link");
3015 }
3016
3017 #[test]
3018 fn test_resource_adv_rejected_by_accept_none() {
3019 let (mut init_mgr, mut resp_mgr, link_id) = setup_active_link();
3020 let mut rng = OsRng;
3021
3022 let data = vec![0xCD; 100];
3025 let adv_actions = init_mgr.send_resource(&link_id, &data, None, &mut rng);
3026
3027 for action in &adv_actions {
3029 if let LinkManagerAction::SendPacket { raw, .. } = action {
3030 let pkt = RawPacket::unpack(raw).unwrap();
3031 let resp_actions = resp_mgr.handle_local_delivery(
3032 pkt.destination_hash,
3033 raw,
3034 pkt.packet_hash,
3035 rns_core::transport::types::InterfaceId(0),
3036 &mut rng,
3037 );
3038 let has_resource_received = resp_actions
3040 .iter()
3041 .any(|a| matches!(a, LinkManagerAction::ResourceReceived { .. }));
3042 assert!(
3043 !has_resource_received,
3044 "AcceptNone should not accept resource"
3045 );
3046 }
3047 }
3048 }
3049
3050 #[test]
3051 fn test_resource_adv_accepted_by_accept_all() {
3052 let (mut init_mgr, mut resp_mgr, link_id) = setup_active_link();
3053 let mut rng = OsRng;
3054
3055 resp_mgr.set_resource_strategy(&link_id, ResourceStrategy::AcceptAll);
3057
3058 let data = vec![0xCD; 100];
3060 let adv_actions = init_mgr.send_resource(&link_id, &data, None, &mut rng);
3061
3062 for action in &adv_actions {
3064 if let LinkManagerAction::SendPacket { raw, .. } = action {
3065 let pkt = RawPacket::unpack(raw).unwrap();
3066 let resp_actions = resp_mgr.handle_local_delivery(
3067 pkt.destination_hash,
3068 raw,
3069 pkt.packet_hash,
3070 rns_core::transport::types::InterfaceId(0),
3071 &mut rng,
3072 );
3073 let has_send = resp_actions
3075 .iter()
3076 .any(|a| matches!(a, LinkManagerAction::SendPacket { .. }));
3077 assert!(has_send, "AcceptAll should accept and request parts");
3078 }
3079 }
3080 }
3081
3082 #[test]
3083 fn test_resource_accept_app_query() {
3084 let (mut init_mgr, mut resp_mgr, link_id) = setup_active_link();
3085 let mut rng = OsRng;
3086
3087 resp_mgr.set_resource_strategy(&link_id, ResourceStrategy::AcceptApp);
3089
3090 let data = vec![0xCD; 100];
3092 let adv_actions = init_mgr.send_resource(&link_id, &data, None, &mut rng);
3093
3094 let mut got_query = false;
3096 for action in &adv_actions {
3097 if let LinkManagerAction::SendPacket { raw, .. } = action {
3098 let pkt = RawPacket::unpack(raw).unwrap();
3099 let resp_actions = resp_mgr.handle_local_delivery(
3100 pkt.destination_hash,
3101 raw,
3102 pkt.packet_hash,
3103 rns_core::transport::types::InterfaceId(0),
3104 &mut rng,
3105 );
3106 for a in &resp_actions {
3107 if matches!(a, LinkManagerAction::ResourceAcceptQuery { .. }) {
3108 got_query = true;
3109 }
3110 }
3111 }
3112 }
3113 assert!(got_query, "AcceptApp should emit ResourceAcceptQuery");
3114 }
3115
3116 #[test]
3117 fn test_resource_accept_app_accept() {
3118 let (mut init_mgr, mut resp_mgr, link_id) = setup_active_link();
3119 let mut rng = OsRng;
3120
3121 resp_mgr.set_resource_strategy(&link_id, ResourceStrategy::AcceptApp);
3122
3123 let data = vec![0xCD; 100];
3124 let adv_actions = init_mgr.send_resource(&link_id, &data, None, &mut rng);
3125
3126 for action in &adv_actions {
3127 if let LinkManagerAction::SendPacket { raw, .. } = action {
3128 let pkt = RawPacket::unpack(raw).unwrap();
3129 let resp_actions = resp_mgr.handle_local_delivery(
3130 pkt.destination_hash,
3131 raw,
3132 pkt.packet_hash,
3133 rns_core::transport::types::InterfaceId(0),
3134 &mut rng,
3135 );
3136 for a in &resp_actions {
3137 if let LinkManagerAction::ResourceAcceptQuery {
3138 link_id: lid,
3139 resource_hash,
3140 ..
3141 } = a
3142 {
3143 let accept_actions =
3145 resp_mgr.accept_resource(lid, resource_hash, true, &mut rng);
3146 let has_send = accept_actions
3148 .iter()
3149 .any(|a| matches!(a, LinkManagerAction::SendPacket { .. }));
3150 assert!(
3151 has_send,
3152 "Accepting resource should produce request for parts"
3153 );
3154 }
3155 }
3156 }
3157 }
3158 }
3159
3160 #[test]
3161 fn test_resource_accept_app_reject() {
3162 let (mut init_mgr, mut resp_mgr, link_id) = setup_active_link();
3163 let mut rng = OsRng;
3164
3165 resp_mgr.set_resource_strategy(&link_id, ResourceStrategy::AcceptApp);
3166
3167 let data = vec![0xCD; 100];
3168 let adv_actions = init_mgr.send_resource(&link_id, &data, None, &mut rng);
3169
3170 for action in &adv_actions {
3171 if let LinkManagerAction::SendPacket { raw, .. } = action {
3172 let pkt = RawPacket::unpack(raw).unwrap();
3173 let resp_actions = resp_mgr.handle_local_delivery(
3174 pkt.destination_hash,
3175 raw,
3176 pkt.packet_hash,
3177 rns_core::transport::types::InterfaceId(0),
3178 &mut rng,
3179 );
3180 for a in &resp_actions {
3181 if let LinkManagerAction::ResourceAcceptQuery {
3182 link_id: lid,
3183 resource_hash,
3184 ..
3185 } = a
3186 {
3187 let reject_actions =
3189 resp_mgr.accept_resource(lid, resource_hash, false, &mut rng);
3190 let has_resource_received = reject_actions
3193 .iter()
3194 .any(|a| matches!(a, LinkManagerAction::ResourceReceived { .. }));
3195 assert!(!has_resource_received);
3196 }
3197 }
3198 }
3199 }
3200 }
3201
3202 #[test]
3203 fn test_resource_full_transfer() {
3204 let (mut init_mgr, mut resp_mgr, link_id) = setup_active_link();
3205 let mut rng = OsRng;
3206
3207 resp_mgr.set_resource_strategy(&link_id, ResourceStrategy::AcceptAll);
3209
3210 let original_data = b"Hello, Resource Transfer!".to_vec();
3212 let adv_actions = init_mgr.send_resource(&link_id, &original_data, None, &mut rng);
3213
3214 let mut pending: Vec<(char, LinkManagerAction)> =
3217 adv_actions.into_iter().map(|a| ('i', a)).collect();
3218 let mut rounds = 0;
3219 let max_rounds = 50;
3220 let mut resource_received = false;
3221 let mut sender_completed = false;
3222
3223 while !pending.is_empty() && rounds < max_rounds {
3224 rounds += 1;
3225 let mut next: Vec<(char, LinkManagerAction)> = Vec::new();
3226
3227 for (source, action) in pending.drain(..) {
3228 if let LinkManagerAction::SendPacket { raw, .. } = action {
3229 let pkt = RawPacket::unpack(&raw).unwrap();
3230
3231 let target_actions = if source == 'i' {
3233 resp_mgr.handle_local_delivery(
3234 pkt.destination_hash,
3235 &raw,
3236 pkt.packet_hash,
3237 rns_core::transport::types::InterfaceId(0),
3238 &mut rng,
3239 )
3240 } else {
3241 init_mgr.handle_local_delivery(
3242 pkt.destination_hash,
3243 &raw,
3244 pkt.packet_hash,
3245 rns_core::transport::types::InterfaceId(0),
3246 &mut rng,
3247 )
3248 };
3249
3250 let target_source = if source == 'i' { 'r' } else { 'i' };
3251 for a in &target_actions {
3252 match a {
3253 LinkManagerAction::ResourceReceived { data, .. } => {
3254 assert_eq!(*data, original_data);
3255 resource_received = true;
3256 }
3257 LinkManagerAction::ResourceCompleted { .. } => {
3258 sender_completed = true;
3259 }
3260 _ => {}
3261 }
3262 }
3263 next.extend(target_actions.into_iter().map(|a| (target_source, a)));
3264 }
3265 }
3266 pending = next;
3267 }
3268
3269 assert!(
3270 resource_received,
3271 "Responder should receive resource data (rounds={})",
3272 rounds
3273 );
3274 assert!(
3275 sender_completed,
3276 "Sender should get completion proof (rounds={})",
3277 rounds
3278 );
3279 }
3280
3281 #[test]
3282 fn test_resource_cancel_icl() {
3283 let (mut init_mgr, mut resp_mgr, link_id) = setup_active_link();
3284 let mut rng = OsRng;
3285
3286 resp_mgr.set_resource_strategy(&link_id, ResourceStrategy::AcceptAll);
3287
3288 let data = vec![0xAB; 2000];
3290 let adv_actions = init_mgr.send_resource(&link_id, &data, None, &mut rng);
3291
3292 for action in &adv_actions {
3294 if let LinkManagerAction::SendPacket { raw, .. } = action {
3295 let pkt = RawPacket::unpack(raw).unwrap();
3296 resp_mgr.handle_local_delivery(
3297 pkt.destination_hash,
3298 raw,
3299 pkt.packet_hash,
3300 rns_core::transport::types::InterfaceId(0),
3301 &mut rng,
3302 );
3303 }
3304 }
3305
3306 assert!(!resp_mgr
3308 .links
3309 .get(&link_id)
3310 .unwrap()
3311 .incoming_resources
3312 .is_empty());
3313
3314 let icl_actions = resp_mgr.handle_resource_icl(&link_id);
3316
3317 let has_failed = icl_actions
3319 .iter()
3320 .any(|a| matches!(a, LinkManagerAction::ResourceFailed { .. }));
3321 assert!(has_failed, "ICL should produce ResourceFailed");
3322 }
3323
3324 #[test]
3325 fn test_resource_cancel_rcl() {
3326 let (mut init_mgr, _resp_mgr, link_id) = setup_active_link();
3327 let mut rng = OsRng;
3328
3329 let data = vec![0xAB; 2000];
3331 init_mgr.send_resource(&link_id, &data, None, &mut rng);
3332
3333 assert!(!init_mgr
3335 .links
3336 .get(&link_id)
3337 .unwrap()
3338 .outgoing_resources
3339 .is_empty());
3340
3341 let rcl_actions = init_mgr.handle_resource_rcl(&link_id);
3343
3344 let has_failed = rcl_actions
3345 .iter()
3346 .any(|a| matches!(a, LinkManagerAction::ResourceFailed { .. }));
3347 assert!(has_failed, "RCL should produce ResourceFailed");
3348 }
3349
3350 #[test]
3351 fn test_cancel_all_resources_clears_active_transfers() {
3352 let (mut init_mgr, _resp_mgr, link_id) = setup_active_link();
3353 let mut rng = OsRng;
3354
3355 let actions = init_mgr.send_resource(&link_id, b"resource body", None, &mut rng);
3356 assert!(!actions.is_empty());
3357 assert_eq!(init_mgr.resource_transfer_count(), 1);
3358
3359 let cancel_actions = init_mgr.cancel_all_resources(&mut rng);
3360
3361 assert_eq!(init_mgr.resource_transfer_count(), 0);
3362 assert!(cancel_actions
3363 .iter()
3364 .any(|action| matches!(action, LinkManagerAction::SendPacket { .. })));
3365 }
3366
3367 #[test]
3368 fn test_resource_tick_cleans_up() {
3369 let (mut init_mgr, _resp_mgr, link_id) = setup_active_link();
3370 let mut rng = OsRng;
3371
3372 let data = vec![0xAB; 100];
3373 init_mgr.send_resource(&link_id, &data, None, &mut rng);
3374
3375 assert!(!init_mgr
3376 .links
3377 .get(&link_id)
3378 .unwrap()
3379 .outgoing_resources
3380 .is_empty());
3381
3382 init_mgr.handle_resource_rcl(&link_id);
3384
3385 init_mgr.tick(&mut rng);
3387
3388 assert!(
3389 init_mgr
3390 .links
3391 .get(&link_id)
3392 .unwrap()
3393 .outgoing_resources
3394 .is_empty(),
3395 "Tick should clean up completed/failed outgoing resources"
3396 );
3397 }
3398
3399 #[test]
3400 fn test_build_link_packet() {
3401 let (init_mgr, _resp_mgr, link_id) = setup_active_link();
3402
3403 let actions =
3404 init_mgr.build_link_packet(&link_id, constants::CONTEXT_RESOURCE, b"test data");
3405 assert_eq!(actions.len(), 1);
3406 if let LinkManagerAction::SendPacket { raw, dest_type, .. } = &actions[0] {
3407 let pkt = RawPacket::unpack(raw).unwrap();
3408 assert_eq!(pkt.context, constants::CONTEXT_RESOURCE);
3409 assert_eq!(*dest_type, constants::DESTINATION_LINK);
3410 } else {
3411 panic!("Expected SendPacket");
3412 }
3413 }
3414
3415 #[test]
3420 fn test_channel_message_delivery() {
3421 let (mut init_mgr, mut resp_mgr, link_id) = setup_active_link();
3422 let mut rng = OsRng;
3423
3424 let chan_actions = init_mgr
3426 .send_channel_message(&link_id, 42, b"channel data", &mut rng)
3427 .expect("active link channel send should succeed");
3428 assert!(!chan_actions.is_empty());
3429
3430 let mut got_channel_msg = false;
3432 for action in &chan_actions {
3433 if let LinkManagerAction::SendPacket { raw, .. } = action {
3434 let pkt = RawPacket::unpack(raw).unwrap();
3435 let resp_actions = resp_mgr.handle_local_delivery(
3436 pkt.destination_hash,
3437 raw,
3438 pkt.packet_hash,
3439 rns_core::transport::types::InterfaceId(0),
3440 &mut rng,
3441 );
3442 for a in &resp_actions {
3443 if let LinkManagerAction::ChannelMessageReceived {
3444 msgtype, payload, ..
3445 } = a
3446 {
3447 assert_eq!(*msgtype, 42);
3448 assert_eq!(*payload, b"channel data");
3449 got_channel_msg = true;
3450 }
3451 }
3452 }
3453 }
3454 assert!(got_channel_msg, "Responder should receive channel message");
3455 }
3456
3457 #[test]
3458 fn test_channel_proof_reopens_send_window() {
3459 let (mut init_mgr, _resp_mgr, link_id) = setup_active_link();
3460 let mut rng = OsRng;
3461
3462 init_mgr
3463 .send_channel_message(&link_id, 42, b"first", &mut rng)
3464 .expect("first send should succeed");
3465 init_mgr
3466 .send_channel_message(&link_id, 42, b"second", &mut rng)
3467 .expect("second send should succeed");
3468
3469 let err = init_mgr
3470 .send_channel_message(&link_id, 42, b"third", &mut rng)
3471 .expect_err("third send should hit the initial channel window");
3472 assert_eq!(err, "Channel is not ready to send");
3473
3474 let queued_packets = init_mgr
3475 .links
3476 .get(&link_id)
3477 .unwrap()
3478 .pending_channel_packets
3479 .clone();
3480 assert_eq!(queued_packets.len(), 2);
3481 for tracked_hash in queued_packets.keys().take(1) {
3482 let mut proof_data = Vec::with_capacity(96);
3483 proof_data.extend_from_slice(tracked_hash);
3484 proof_data.extend_from_slice(&[0x11; 64]);
3485 let flags = PacketFlags {
3486 header_type: constants::HEADER_1,
3487 context_flag: constants::FLAG_UNSET,
3488 transport_type: constants::TRANSPORT_BROADCAST,
3489 destination_type: constants::DESTINATION_LINK,
3490 packet_type: constants::PACKET_TYPE_PROOF,
3491 };
3492 let proof = RawPacket::pack(
3493 flags,
3494 0,
3495 &link_id,
3496 None,
3497 constants::CONTEXT_NONE,
3498 &proof_data,
3499 )
3500 .expect("proof packet should pack");
3501 let ack_actions = init_mgr.handle_local_delivery(
3502 link_id,
3503 &proof.raw,
3504 proof.packet_hash,
3505 rns_core::transport::types::InterfaceId(0),
3506 &mut rng,
3507 );
3508 assert!(
3509 ack_actions.is_empty(),
3510 "proof delivery should only update channel state"
3511 );
3512 }
3513
3514 init_mgr
3515 .send_channel_message(&link_id, 42, b"third", &mut rng)
3516 .expect("proof should free one channel slot");
3517 }
3518
3519 #[test]
3520 fn test_generic_link_data_delivery() {
3521 let (init_mgr, mut resp_mgr, link_id) = setup_active_link();
3522 let mut rng = OsRng;
3523
3524 let actions = init_mgr.send_on_link(&link_id, b"raw stuff", 0x42, &mut rng);
3526 assert_eq!(actions.len(), 1);
3527
3528 let raw = extract_any_send_packet(&actions);
3530 let pkt = RawPacket::unpack(&raw).unwrap();
3531 let resp_actions = resp_mgr.handle_local_delivery(
3532 pkt.destination_hash,
3533 &raw,
3534 pkt.packet_hash,
3535 rns_core::transport::types::InterfaceId(0),
3536 &mut rng,
3537 );
3538
3539 let has_data = resp_actions
3540 .iter()
3541 .any(|a| matches!(a, LinkManagerAction::LinkDataReceived { context: 0x42, .. }));
3542 assert!(
3543 has_data,
3544 "Responder should receive LinkDataReceived for unknown context"
3545 );
3546 }
3547
3548 #[test]
3549 fn test_response_delivery() {
3550 let (mut init_mgr, mut resp_mgr, link_id) = setup_active_link();
3551 let mut rng = OsRng;
3552
3553 resp_mgr.register_request_handler("/echo", None, |_link_id, _path, data, _remote| {
3555 Some(data.to_vec())
3556 });
3557
3558 let req_actions = init_mgr.send_request(&link_id, "/echo", b"\xc0", &mut rng); assert!(!req_actions.is_empty());
3561
3562 let req_raw = extract_any_send_packet(&req_actions);
3564 let req_pkt = RawPacket::unpack(&req_raw).unwrap();
3565 let resp_actions = resp_mgr.handle_local_delivery(
3566 req_pkt.destination_hash,
3567 &req_raw,
3568 req_pkt.packet_hash,
3569 rns_core::transport::types::InterfaceId(0),
3570 &mut rng,
3571 );
3572 let has_resp_send = resp_actions
3573 .iter()
3574 .any(|a| matches!(a, LinkManagerAction::SendPacket { .. }));
3575 assert!(has_resp_send, "Handler should produce response");
3576
3577 let resp_raw = extract_any_send_packet(&resp_actions);
3579 let resp_pkt = RawPacket::unpack(&resp_raw).unwrap();
3580 let init_actions = init_mgr.handle_local_delivery(
3581 resp_pkt.destination_hash,
3582 &resp_raw,
3583 resp_pkt.packet_hash,
3584 rns_core::transport::types::InterfaceId(0),
3585 &mut rng,
3586 );
3587
3588 let has_response_received = init_actions
3589 .iter()
3590 .any(|a| matches!(a, LinkManagerAction::ResponseReceived { .. }));
3591 assert!(
3592 has_response_received,
3593 "Initiator should receive ResponseReceived"
3594 );
3595 }
3596
3597 #[test]
3598 fn test_send_channel_message_on_no_channel() {
3599 let mut mgr = LinkManager::new();
3600 let mut rng = OsRng;
3601 let dummy_sig = [0xAA; 32];
3602 let (link_id, _) =
3603 mgr.create_link(&[0x11; 16], &dummy_sig, 1, constants::MTU as u32, &mut rng);
3604
3605 let err = mgr
3607 .send_channel_message(&link_id, 1, b"test", &mut rng)
3608 .expect_err("pending link should reject channel send");
3609 assert_eq!(err, "link has no active channel");
3610 }
3611
3612 #[test]
3613 fn test_send_on_link_requires_active() {
3614 let mut mgr = LinkManager::new();
3615 let mut rng = OsRng;
3616 let dummy_sig = [0xAA; 32];
3617 let (link_id, _) =
3618 mgr.create_link(&[0x11; 16], &dummy_sig, 1, constants::MTU as u32, &mut rng);
3619
3620 let actions = mgr.send_on_link(&link_id, b"test", constants::CONTEXT_NONE, &mut rng);
3621 assert!(actions.is_empty(), "Cannot send on pending link");
3622 }
3623
3624 #[test]
3625 fn test_send_on_link_unknown_link() {
3626 let mgr = LinkManager::new();
3627 let mut rng = OsRng;
3628
3629 let actions = mgr.send_on_link(&[0xFF; 16], b"test", constants::CONTEXT_NONE, &mut rng);
3630 assert!(actions.is_empty());
3631 }
3632
3633 #[test]
3634 fn test_resource_full_transfer_large() {
3635 let (mut init_mgr, mut resp_mgr, link_id) = setup_active_link();
3636 let mut rng = OsRng;
3637
3638 resp_mgr.set_resource_strategy(&link_id, ResourceStrategy::AcceptAll);
3639
3640 let original_data: Vec<u8> = (0..2000u32)
3642 .map(|i| {
3643 let pos = i as usize;
3644 (pos ^ (pos >> 8) ^ (pos >> 16)) as u8
3645 })
3646 .collect();
3647
3648 let adv_actions = init_mgr.send_resource(&link_id, &original_data, None, &mut rng);
3649
3650 let mut pending: Vec<(char, LinkManagerAction)> =
3651 adv_actions.into_iter().map(|a| ('i', a)).collect();
3652 let mut rounds = 0;
3653 let max_rounds = 200;
3654 let mut resource_received = false;
3655 let mut sender_completed = false;
3656
3657 while !pending.is_empty() && rounds < max_rounds {
3658 rounds += 1;
3659 let mut next: Vec<(char, LinkManagerAction)> = Vec::new();
3660
3661 for (source, action) in pending.drain(..) {
3662 if let LinkManagerAction::SendPacket { raw, .. } = action {
3663 let pkt = match RawPacket::unpack(&raw) {
3664 Ok(p) => p,
3665 Err(_) => continue,
3666 };
3667
3668 let target_actions = if source == 'i' {
3669 resp_mgr.handle_local_delivery(
3670 pkt.destination_hash,
3671 &raw,
3672 pkt.packet_hash,
3673 rns_core::transport::types::InterfaceId(0),
3674 &mut rng,
3675 )
3676 } else {
3677 init_mgr.handle_local_delivery(
3678 pkt.destination_hash,
3679 &raw,
3680 pkt.packet_hash,
3681 rns_core::transport::types::InterfaceId(0),
3682 &mut rng,
3683 )
3684 };
3685
3686 let target_source = if source == 'i' { 'r' } else { 'i' };
3687 for a in &target_actions {
3688 match a {
3689 LinkManagerAction::ResourceReceived { data, .. } => {
3690 assert_eq!(*data, original_data);
3691 resource_received = true;
3692 }
3693 LinkManagerAction::ResourceCompleted { .. } => {
3694 sender_completed = true;
3695 }
3696 _ => {}
3697 }
3698 }
3699 next.extend(target_actions.into_iter().map(|a| (target_source, a)));
3700 }
3701 }
3702 pending = next;
3703 }
3704
3705 assert!(
3706 resource_received,
3707 "Should receive large resource (rounds={})",
3708 rounds
3709 );
3710 assert!(
3711 sender_completed,
3712 "Sender should complete (rounds={})",
3713 rounds
3714 );
3715 }
3716
3717 #[test]
3718 fn test_process_resource_actions_mapping() {
3719 let (init_mgr, _resp_mgr, link_id) = setup_active_link();
3720 let mut rng = OsRng;
3721
3722 let actions = vec![
3724 ResourceAction::DataReceived {
3725 data: vec![1, 2, 3],
3726 metadata: Some(vec![4, 5]),
3727 },
3728 ResourceAction::Completed,
3729 ResourceAction::Failed(rns_core::resource::ResourceError::Timeout),
3730 ResourceAction::ProgressUpdate {
3731 received: 10,
3732 total: 20,
3733 },
3734 ];
3735
3736 let result = init_mgr.process_resource_actions(&link_id, actions, &mut rng);
3737
3738 assert!(matches!(
3739 result[0],
3740 LinkManagerAction::ResourceReceived { .. }
3741 ));
3742 assert!(matches!(
3743 result[1],
3744 LinkManagerAction::ResourceCompleted { .. }
3745 ));
3746 assert!(matches!(
3747 result[2],
3748 LinkManagerAction::ResourceFailed { .. }
3749 ));
3750 assert!(matches!(
3751 result[3],
3752 LinkManagerAction::ResourceProgress {
3753 received: 10,
3754 total: 20,
3755 ..
3756 }
3757 ));
3758 }
3759
3760 #[test]
3761 fn test_link_state_empty() {
3762 let mgr = LinkManager::new();
3763 let fake_id = [0xAA; 16];
3764 assert!(mgr.link_state(&fake_id).is_none());
3765 }
3766}