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 },
664 Response {
665 link_id: LinkId,
666 inbound_actions: Vec<LinkAction>,
667 plaintext: Vec<u8>,
668 },
669 Generic {
670 link_id: LinkId,
671 inbound_actions: Vec<LinkAction>,
672 plaintext: Vec<u8>,
673 context: u8,
674 packet_hash: [u8; 32],
675 },
676 ResourceAdv {
678 link_id: LinkId,
679 inbound_actions: Vec<LinkAction>,
680 plaintext: Vec<u8>,
681 },
682 ResourceReq {
684 link_id: LinkId,
685 inbound_actions: Vec<LinkAction>,
686 plaintext: Vec<u8>,
687 },
688 ResourceHmu {
690 link_id: LinkId,
691 inbound_actions: Vec<LinkAction>,
692 plaintext: Vec<u8>,
693 },
694 ResourcePart {
696 link_id: LinkId,
697 inbound_actions: Vec<LinkAction>,
698 raw_data: Vec<u8>,
699 },
700 ResourcePrf {
702 link_id: LinkId,
703 inbound_actions: Vec<LinkAction>,
704 plaintext: Vec<u8>,
705 },
706 ResourceIcl {
708 link_id: LinkId,
709 inbound_actions: Vec<LinkAction>,
710 },
711 ResourceRcl {
713 link_id: LinkId,
714 inbound_actions: Vec<LinkAction>,
715 },
716 Error,
717 }
718
719 let result = {
720 let link = match self.links.get_mut(link_id_bytes) {
721 Some(l) => l,
722 None => return Vec::new(),
723 };
724
725 match packet.context {
726 constants::CONTEXT_LRRTT => {
727 match link.engine.handle_lrrtt(&packet.data, time::now()) {
728 Ok(link_actions) => {
729 let link_id = *link.engine.link_id();
730 LinkDataResult::Lrrtt {
731 link_id,
732 link_actions,
733 }
734 }
735 Err(e) => {
736 log::debug!("LRRTT handling failed: {}", e);
737 LinkDataResult::Error
738 }
739 }
740 }
741 constants::CONTEXT_LINKIDENTIFY => {
742 match link.engine.handle_identify(&packet.data) {
743 Ok(link_actions) => {
744 let link_id = *link.engine.link_id();
745 link.remote_identity = link.engine.remote_identity().cloned();
746 LinkDataResult::Identify {
747 link_id,
748 link_actions,
749 }
750 }
751 Err(e) => {
752 log::debug!("LINKIDENTIFY failed: {}", e);
753 LinkDataResult::Error
754 }
755 }
756 }
757 constants::CONTEXT_KEEPALIVE => {
758 let inbound_actions = link.engine.record_inbound(time::now());
759 let link_id = *link.engine.link_id();
760 LinkDataResult::Keepalive {
761 link_id,
762 inbound_actions,
763 }
764 }
765 constants::CONTEXT_LINKCLOSE => {
766 let teardown_actions = link.engine.handle_teardown();
767 let link_id = *link.engine.link_id();
768 LinkDataResult::LinkClose {
769 link_id,
770 teardown_actions,
771 }
772 }
773 constants::CONTEXT_CHANNEL => match link.engine.decrypt(&packet.data) {
774 Ok(plaintext) => {
775 let inbound_actions = link.engine.record_inbound(time::now());
776 let link_id = *link.engine.link_id();
777 LinkDataResult::Channel {
778 link_id,
779 inbound_actions,
780 plaintext,
781 packet_hash,
782 }
783 }
784 Err(_) => LinkDataResult::Error,
785 },
786 constants::CONTEXT_REQUEST => match link.engine.decrypt(&packet.data) {
787 Ok(plaintext) => {
788 let inbound_actions = link.engine.record_inbound(time::now());
789 let link_id = *link.engine.link_id();
790 LinkDataResult::Request {
791 link_id,
792 inbound_actions,
793 plaintext,
794 }
795 }
796 Err(_) => LinkDataResult::Error,
797 },
798 constants::CONTEXT_RESPONSE => match link.engine.decrypt(&packet.data) {
799 Ok(plaintext) => {
800 let inbound_actions = link.engine.record_inbound(time::now());
801 let link_id = *link.engine.link_id();
802 LinkDataResult::Response {
803 link_id,
804 inbound_actions,
805 plaintext,
806 }
807 }
808 Err(_) => LinkDataResult::Error,
809 },
810 constants::CONTEXT_RESOURCE_ADV => match link.engine.decrypt(&packet.data) {
812 Ok(plaintext) => {
813 let inbound_actions = link.engine.record_inbound(time::now());
814 let link_id = *link.engine.link_id();
815 LinkDataResult::ResourceAdv {
816 link_id,
817 inbound_actions,
818 plaintext,
819 }
820 }
821 Err(_) => LinkDataResult::Error,
822 },
823 constants::CONTEXT_RESOURCE_REQ => match link.engine.decrypt(&packet.data) {
824 Ok(plaintext) => {
825 let inbound_actions = link.engine.record_inbound(time::now());
826 let link_id = *link.engine.link_id();
827 LinkDataResult::ResourceReq {
828 link_id,
829 inbound_actions,
830 plaintext,
831 }
832 }
833 Err(_) => LinkDataResult::Error,
834 },
835 constants::CONTEXT_RESOURCE_HMU => match link.engine.decrypt(&packet.data) {
836 Ok(plaintext) => {
837 let inbound_actions = link.engine.record_inbound(time::now());
838 let link_id = *link.engine.link_id();
839 LinkDataResult::ResourceHmu {
840 link_id,
841 inbound_actions,
842 plaintext,
843 }
844 }
845 Err(_) => LinkDataResult::Error,
846 },
847 constants::CONTEXT_RESOURCE => {
848 let inbound_actions = link.engine.record_inbound(time::now());
850 let link_id = *link.engine.link_id();
851 LinkDataResult::ResourcePart {
852 link_id,
853 inbound_actions,
854 raw_data: packet.data.clone(),
855 }
856 }
857 constants::CONTEXT_RESOURCE_PRF => match link.engine.decrypt(&packet.data) {
858 Ok(plaintext) => {
859 let inbound_actions = link.engine.record_inbound(time::now());
860 let link_id = *link.engine.link_id();
861 LinkDataResult::ResourcePrf {
862 link_id,
863 inbound_actions,
864 plaintext,
865 }
866 }
867 Err(_) => LinkDataResult::Error,
868 },
869 constants::CONTEXT_RESOURCE_ICL => {
870 let _ = link.engine.decrypt(&packet.data); let inbound_actions = link.engine.record_inbound(time::now());
872 let link_id = *link.engine.link_id();
873 LinkDataResult::ResourceIcl {
874 link_id,
875 inbound_actions,
876 }
877 }
878 constants::CONTEXT_RESOURCE_RCL => {
879 let _ = link.engine.decrypt(&packet.data); let inbound_actions = link.engine.record_inbound(time::now());
881 let link_id = *link.engine.link_id();
882 LinkDataResult::ResourceRcl {
883 link_id,
884 inbound_actions,
885 }
886 }
887 _ => match link.engine.decrypt(&packet.data) {
888 Ok(plaintext) => {
889 let inbound_actions = link.engine.record_inbound(time::now());
890 let link_id = *link.engine.link_id();
891 LinkDataResult::Generic {
892 link_id,
893 inbound_actions,
894 plaintext,
895 context: packet.context,
896 packet_hash,
897 }
898 }
899 Err(_) => LinkDataResult::Error,
900 },
901 }
902 }; let mut actions = Vec::new();
906 match result {
907 LinkDataResult::Lrrtt {
908 link_id,
909 link_actions,
910 } => {
911 actions.extend(self.process_link_actions(&link_id, &link_actions));
912 if let Some(link) = self.links.get_mut(&link_id) {
914 if link.engine.state() == LinkState::Active {
915 let rtt = link.engine.rtt().unwrap_or(1.0);
916 link.channel = Some(Channel::new(rtt));
917 }
918 }
919 }
920 LinkDataResult::Identify {
921 link_id,
922 link_actions,
923 } => {
924 actions.extend(self.process_link_actions(&link_id, &link_actions));
925 }
926 LinkDataResult::Keepalive {
927 link_id,
928 inbound_actions,
929 } => {
930 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
931 }
937 LinkDataResult::LinkClose {
938 link_id,
939 teardown_actions,
940 } => {
941 actions.extend(self.process_link_actions(&link_id, &teardown_actions));
942 }
943 LinkDataResult::Channel {
944 link_id,
945 inbound_actions,
946 plaintext,
947 packet_hash,
948 } => {
949 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
950 if let Some(link) = self.links.get_mut(&link_id) {
952 if let Some(ref mut channel) = link.channel {
953 let chan_actions = channel.receive(&plaintext, time::now());
954 link.channel_messages_received += chan_actions
955 .iter()
956 .filter(|action| {
957 matches!(
958 action,
959 rns_core::channel::ChannelAction::MessageReceived { .. }
960 )
961 })
962 .count()
963 as u64;
964 let _ = link;
966 actions.extend(self.process_channel_actions(&link_id, chan_actions, rng));
967 }
968 }
969 actions.extend(self.build_link_packet_proof(&link_id, &packet_hash));
970 }
971 LinkDataResult::Request {
972 link_id,
973 inbound_actions,
974 plaintext,
975 } => {
976 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
977 actions.extend(self.handle_request(&link_id, &plaintext, rng));
978 }
979 LinkDataResult::Response {
980 link_id,
981 inbound_actions,
982 plaintext,
983 } => {
984 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
985 actions.extend(self.handle_response(&link_id, &plaintext));
987 }
988 LinkDataResult::Generic {
989 link_id,
990 inbound_actions,
991 plaintext,
992 context,
993 packet_hash,
994 } => {
995 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
996 actions.push(LinkManagerAction::LinkDataReceived {
997 link_id,
998 context,
999 data: plaintext,
1000 });
1001
1002 actions.extend(self.build_link_packet_proof(&link_id, &packet_hash));
1003 }
1004 LinkDataResult::ResourceAdv {
1005 link_id,
1006 inbound_actions,
1007 plaintext,
1008 } => {
1009 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
1010 actions.extend(self.handle_resource_adv(&link_id, &plaintext, rng));
1011 }
1012 LinkDataResult::ResourceReq {
1013 link_id,
1014 inbound_actions,
1015 plaintext,
1016 } => {
1017 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
1018 actions.extend(self.handle_resource_req(&link_id, &plaintext, rng));
1019 }
1020 LinkDataResult::ResourceHmu {
1021 link_id,
1022 inbound_actions,
1023 plaintext,
1024 } => {
1025 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
1026 actions.extend(self.handle_resource_hmu(&link_id, &plaintext, rng));
1027 }
1028 LinkDataResult::ResourcePart {
1029 link_id,
1030 inbound_actions,
1031 raw_data,
1032 } => {
1033 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
1034 actions.extend(self.handle_resource_part(&link_id, &raw_data, rng));
1035 }
1036 LinkDataResult::ResourcePrf {
1037 link_id,
1038 inbound_actions,
1039 plaintext,
1040 } => {
1041 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
1042 actions.extend(self.handle_resource_prf(&link_id, &plaintext));
1043 }
1044 LinkDataResult::ResourceIcl {
1045 link_id,
1046 inbound_actions,
1047 } => {
1048 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
1049 actions.extend(self.handle_resource_icl(&link_id));
1050 }
1051 LinkDataResult::ResourceRcl {
1052 link_id,
1053 inbound_actions,
1054 } => {
1055 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
1056 actions.extend(self.handle_resource_rcl(&link_id));
1057 }
1058 LinkDataResult::Error => {}
1059 }
1060
1061 actions
1062 }
1063
1064 fn handle_request(
1066 &mut self,
1067 link_id: &LinkId,
1068 plaintext: &[u8],
1069 rng: &mut dyn Rng,
1070 ) -> Vec<LinkManagerAction> {
1071 use rns_core::msgpack::{self, Value};
1072
1073 let arr = match msgpack::unpack_exact(plaintext) {
1075 Ok(Value::Array(arr)) if arr.len() >= 3 => arr,
1076 _ => return Vec::new(),
1077 };
1078
1079 let path_hash_bytes = match &arr[1] {
1080 Value::Bin(b) if b.len() == 16 => b,
1081 _ => return Vec::new(),
1082 };
1083 let mut path_hash = [0u8; 16];
1084 path_hash.copy_from_slice(path_hash_bytes);
1085
1086 let request_id = rns_core::hash::truncated_hash(plaintext);
1088
1089 let request_data = msgpack::pack(&arr[2]);
1091
1092 if self.management_paths.contains(&path_hash) {
1094 let remote_identity = self
1095 .links
1096 .get(link_id)
1097 .and_then(|l| l.remote_identity)
1098 .map(|(h, k)| (h, k));
1099 return vec![LinkManagerAction::ManagementRequest {
1100 link_id: *link_id,
1101 path_hash,
1102 data: request_data,
1103 request_id,
1104 remote_identity,
1105 }];
1106 }
1107
1108 let handler_idx = self
1110 .request_handlers
1111 .iter()
1112 .position(|h| h.path_hash == path_hash);
1113 let handler_idx = match handler_idx {
1114 Some(i) => i,
1115 None => return Vec::new(),
1116 };
1117
1118 let remote_identity = self
1120 .links
1121 .get(link_id)
1122 .and_then(|l| l.remote_identity.as_ref());
1123 let handler = &self.request_handlers[handler_idx];
1124 if let Some(ref allowed) = handler.allowed_list {
1125 match remote_identity {
1126 Some((identity_hash, _)) => {
1127 if !allowed.contains(identity_hash) {
1128 log::debug!("Request denied: identity not in allowed list");
1129 return Vec::new();
1130 }
1131 }
1132 None => {
1133 log::debug!("Request denied: peer not identified");
1134 return Vec::new();
1135 }
1136 }
1137 }
1138
1139 let path = handler.path.clone();
1141 let response = (handler.handler)(*link_id, &path, &request_data, remote_identity);
1142
1143 let mut actions = Vec::new();
1144 if let Some(response_data) = response {
1145 actions.extend(self.build_response_packet(link_id, &request_id, &response_data, rng));
1146 }
1147
1148 actions
1149 }
1150
1151 fn build_response_packet(
1154 &self,
1155 link_id: &LinkId,
1156 request_id: &[u8; 16],
1157 response_data: &[u8],
1158 rng: &mut dyn Rng,
1159 ) -> Vec<LinkManagerAction> {
1160 use rns_core::msgpack::{self, Value};
1161
1162 let response_value = msgpack::unpack_exact(response_data)
1164 .unwrap_or_else(|_| Value::Bin(response_data.to_vec()));
1165
1166 let response_array = Value::Array(vec![Value::Bin(request_id.to_vec()), response_value]);
1167 let response_plaintext = msgpack::pack(&response_array);
1168
1169 let mut actions = Vec::new();
1170 if let Some(link) = self.links.get(link_id) {
1171 if let Ok(encrypted) = link.engine.encrypt(&response_plaintext, rng) {
1172 let flags = PacketFlags {
1173 header_type: constants::HEADER_1,
1174 context_flag: constants::FLAG_UNSET,
1175 transport_type: constants::TRANSPORT_BROADCAST,
1176 destination_type: constants::DESTINATION_LINK,
1177 packet_type: constants::PACKET_TYPE_DATA,
1178 };
1179 if let Ok(pkt) = RawPacket::pack(
1180 flags,
1181 0,
1182 link_id,
1183 None,
1184 constants::CONTEXT_RESPONSE,
1185 &encrypted,
1186 ) {
1187 actions.push(LinkManagerAction::SendPacket {
1188 raw: pkt.raw,
1189 dest_type: constants::DESTINATION_LINK,
1190 attached_interface: None,
1191 });
1192 }
1193 }
1194 }
1195 actions
1196 }
1197
1198 pub fn send_management_response(
1201 &self,
1202 link_id: &LinkId,
1203 request_id: &[u8; 16],
1204 response_data: &[u8],
1205 rng: &mut dyn Rng,
1206 ) -> Vec<LinkManagerAction> {
1207 self.build_response_packet(link_id, request_id, response_data, rng)
1208 }
1209
1210 pub fn send_request(
1218 &self,
1219 link_id: &LinkId,
1220 path: &str,
1221 data: &[u8],
1222 rng: &mut dyn Rng,
1223 ) -> Vec<LinkManagerAction> {
1224 use rns_core::msgpack::{self, Value};
1225
1226 let link = match self.links.get(link_id) {
1227 Some(l) => l,
1228 None => return Vec::new(),
1229 };
1230
1231 if link.engine.state() != LinkState::Active {
1232 return Vec::new();
1233 }
1234
1235 let path_hash = compute_path_hash(path);
1236
1237 let data_value = msgpack::unpack_exact(data).unwrap_or_else(|_| Value::Bin(data.to_vec()));
1239
1240 let request_array = Value::Array(vec![
1242 Value::Float(time::now()),
1243 Value::Bin(path_hash.to_vec()),
1244 data_value,
1245 ]);
1246 let plaintext = msgpack::pack(&request_array);
1247
1248 let encrypted = match link.engine.encrypt(&plaintext, rng) {
1249 Ok(e) => e,
1250 Err(_) => return Vec::new(),
1251 };
1252
1253 let flags = PacketFlags {
1254 header_type: constants::HEADER_1,
1255 context_flag: constants::FLAG_UNSET,
1256 transport_type: constants::TRANSPORT_BROADCAST,
1257 destination_type: constants::DESTINATION_LINK,
1258 packet_type: constants::PACKET_TYPE_DATA,
1259 };
1260
1261 let mut actions = Vec::new();
1262 if let Ok(pkt) = RawPacket::pack(
1263 flags,
1264 0,
1265 link_id,
1266 None,
1267 constants::CONTEXT_REQUEST,
1268 &encrypted,
1269 ) {
1270 actions.push(LinkManagerAction::SendPacket {
1271 raw: pkt.raw,
1272 dest_type: constants::DESTINATION_LINK,
1273 attached_interface: None,
1274 });
1275 }
1276 actions
1277 }
1278
1279 pub fn send_on_link(
1281 &self,
1282 link_id: &LinkId,
1283 plaintext: &[u8],
1284 context: u8,
1285 rng: &mut dyn Rng,
1286 ) -> Vec<LinkManagerAction> {
1287 let link = match self.links.get(link_id) {
1288 Some(l) => l,
1289 None => return Vec::new(),
1290 };
1291
1292 if link.engine.state() != LinkState::Active {
1293 return Vec::new();
1294 }
1295
1296 let encrypted = match link.engine.encrypt(plaintext, rng) {
1297 Ok(e) => e,
1298 Err(_) => return Vec::new(),
1299 };
1300
1301 let flags = PacketFlags {
1302 header_type: constants::HEADER_1,
1303 context_flag: constants::FLAG_UNSET,
1304 transport_type: constants::TRANSPORT_BROADCAST,
1305 destination_type: constants::DESTINATION_LINK,
1306 packet_type: constants::PACKET_TYPE_DATA,
1307 };
1308
1309 let mut actions = Vec::new();
1310 if let Ok(pkt) = RawPacket::pack(flags, 0, link_id, None, context, &encrypted) {
1311 actions.push(LinkManagerAction::SendPacket {
1312 raw: pkt.raw,
1313 dest_type: constants::DESTINATION_LINK,
1314 attached_interface: None,
1315 });
1316 }
1317 actions
1318 }
1319
1320 pub fn identify(
1322 &self,
1323 link_id: &LinkId,
1324 identity: &rns_crypto::identity::Identity,
1325 rng: &mut dyn Rng,
1326 ) -> Vec<LinkManagerAction> {
1327 let link = match self.links.get(link_id) {
1328 Some(l) => l,
1329 None => return Vec::new(),
1330 };
1331
1332 let encrypted = match link.engine.build_identify(identity, rng) {
1333 Ok(e) => e,
1334 Err(_) => return Vec::new(),
1335 };
1336
1337 let flags = PacketFlags {
1338 header_type: constants::HEADER_1,
1339 context_flag: constants::FLAG_UNSET,
1340 transport_type: constants::TRANSPORT_BROADCAST,
1341 destination_type: constants::DESTINATION_LINK,
1342 packet_type: constants::PACKET_TYPE_DATA,
1343 };
1344
1345 let mut actions = Vec::new();
1346 if let Ok(pkt) = RawPacket::pack(
1347 flags,
1348 0,
1349 link_id,
1350 None,
1351 constants::CONTEXT_LINKIDENTIFY,
1352 &encrypted,
1353 ) {
1354 actions.push(LinkManagerAction::SendPacket {
1355 raw: pkt.raw,
1356 dest_type: constants::DESTINATION_LINK,
1357 attached_interface: None,
1358 });
1359 }
1360 actions
1361 }
1362
1363 pub fn teardown_link(&mut self, link_id: &LinkId) -> Vec<LinkManagerAction> {
1365 let link = match self.links.get_mut(link_id) {
1366 Some(l) => l,
1367 None => return Vec::new(),
1368 };
1369
1370 let teardown_actions = link.engine.teardown();
1371 if let Some(ref mut channel) = link.channel {
1372 channel.shutdown();
1373 }
1374
1375 let mut actions = self.process_link_actions(link_id, &teardown_actions);
1376
1377 let flags = PacketFlags {
1379 header_type: constants::HEADER_1,
1380 context_flag: constants::FLAG_UNSET,
1381 transport_type: constants::TRANSPORT_BROADCAST,
1382 destination_type: constants::DESTINATION_LINK,
1383 packet_type: constants::PACKET_TYPE_DATA,
1384 };
1385 if let Ok(pkt) = RawPacket::pack(flags, 0, link_id, None, constants::CONTEXT_LINKCLOSE, &[])
1386 {
1387 actions.push(LinkManagerAction::SendPacket {
1388 raw: pkt.raw,
1389 dest_type: constants::DESTINATION_LINK,
1390 attached_interface: None,
1391 });
1392 }
1393
1394 actions
1395 }
1396
1397 pub fn teardown_all_links(&mut self) -> Vec<LinkManagerAction> {
1399 let link_ids: Vec<LinkId> = self.links.keys().copied().collect();
1400 let mut actions = Vec::new();
1401 for link_id in link_ids {
1402 actions.extend(self.teardown_link(&link_id));
1403 }
1404 actions
1405 }
1406
1407 fn handle_response(&self, link_id: &LinkId, plaintext: &[u8]) -> Vec<LinkManagerAction> {
1409 use rns_core::msgpack;
1410
1411 let arr = match msgpack::unpack_exact(plaintext) {
1413 Ok(msgpack::Value::Array(arr)) if arr.len() >= 2 => arr,
1414 _ => return Vec::new(),
1415 };
1416
1417 let request_id_bytes = match &arr[0] {
1418 msgpack::Value::Bin(b) if b.len() == 16 => b,
1419 _ => return Vec::new(),
1420 };
1421 let mut request_id = [0u8; 16];
1422 request_id.copy_from_slice(request_id_bytes);
1423
1424 let response_data = msgpack::pack(&arr[1]);
1425
1426 vec![LinkManagerAction::ResponseReceived {
1427 link_id: *link_id,
1428 request_id,
1429 data: response_data,
1430 }]
1431 }
1432
1433 fn handle_resource_adv(
1435 &mut self,
1436 link_id: &LinkId,
1437 adv_plaintext: &[u8],
1438 rng: &mut dyn Rng,
1439 ) -> Vec<LinkManagerAction> {
1440 let link = match self.links.get_mut(link_id) {
1441 Some(l) => l,
1442 None => return Vec::new(),
1443 };
1444
1445 let link_rtt = link.engine.rtt().unwrap_or(1.0);
1446 let now = time::now();
1447
1448 let receiver = match ResourceReceiver::from_advertisement(
1449 adv_plaintext,
1450 constants::RESOURCE_SDU,
1451 link_rtt,
1452 now,
1453 None,
1454 None,
1455 ) {
1456 Ok(r) => r,
1457 Err(e) => {
1458 log::debug!("Resource ADV rejected: {}", e);
1459 return Vec::new();
1460 }
1461 };
1462
1463 let strategy = link.resource_strategy;
1464 let resource_hash = receiver.resource_hash.clone();
1465 let transfer_size = receiver.transfer_size;
1466 let has_metadata = receiver.has_metadata;
1467
1468 match strategy {
1469 ResourceStrategy::AcceptNone => {
1470 let reject_actions = {
1472 let mut r = receiver;
1473 r.reject()
1474 };
1475 self.process_resource_actions(link_id, reject_actions, rng)
1476 }
1477 ResourceStrategy::AcceptAll => {
1478 link.incoming_resources.push(receiver);
1479 let idx = link.incoming_resources.len() - 1;
1480 let resource_actions = link.incoming_resources[idx].accept(now);
1481 let _ = link;
1482 self.process_resource_actions(link_id, resource_actions, rng)
1483 }
1484 ResourceStrategy::AcceptApp => {
1485 link.incoming_resources.push(receiver);
1486 vec![LinkManagerAction::ResourceAcceptQuery {
1488 link_id: *link_id,
1489 resource_hash,
1490 transfer_size,
1491 has_metadata,
1492 }]
1493 }
1494 }
1495 }
1496
1497 pub fn accept_resource(
1499 &mut self,
1500 link_id: &LinkId,
1501 resource_hash: &[u8],
1502 accept: bool,
1503 rng: &mut dyn Rng,
1504 ) -> Vec<LinkManagerAction> {
1505 let link = match self.links.get_mut(link_id) {
1506 Some(l) => l,
1507 None => return Vec::new(),
1508 };
1509
1510 let now = time::now();
1511 let idx = link
1512 .incoming_resources
1513 .iter()
1514 .position(|r| r.resource_hash == resource_hash);
1515 let idx = match idx {
1516 Some(i) => i,
1517 None => return Vec::new(),
1518 };
1519
1520 let resource_actions = if accept {
1521 link.incoming_resources[idx].accept(now)
1522 } else {
1523 link.incoming_resources[idx].reject()
1524 };
1525
1526 let _ = link;
1527 self.process_resource_actions(link_id, resource_actions, rng)
1528 }
1529
1530 fn handle_resource_req(
1532 &mut self,
1533 link_id: &LinkId,
1534 plaintext: &[u8],
1535 rng: &mut dyn Rng,
1536 ) -> Vec<LinkManagerAction> {
1537 let link = match self.links.get_mut(link_id) {
1538 Some(l) => l,
1539 None => return Vec::new(),
1540 };
1541
1542 let now = time::now();
1543 let mut all_actions = Vec::new();
1544 for sender in &mut link.outgoing_resources {
1545 let resource_actions = sender.handle_request(plaintext, now);
1546 if !resource_actions.is_empty() {
1547 all_actions.extend(resource_actions);
1548 break;
1549 }
1550 }
1551
1552 let _ = link;
1553 self.process_resource_actions(link_id, all_actions, rng)
1554 }
1555
1556 fn handle_resource_hmu(
1558 &mut self,
1559 link_id: &LinkId,
1560 plaintext: &[u8],
1561 rng: &mut dyn Rng,
1562 ) -> Vec<LinkManagerAction> {
1563 let link = match self.links.get_mut(link_id) {
1564 Some(l) => l,
1565 None => return Vec::new(),
1566 };
1567
1568 let now = time::now();
1569 let mut all_actions = Vec::new();
1570 for receiver in &mut link.incoming_resources {
1571 let resource_actions = receiver.handle_hashmap_update(plaintext, now);
1572 if !resource_actions.is_empty() {
1573 all_actions.extend(resource_actions);
1574 break;
1575 }
1576 }
1577
1578 let _ = link;
1579 self.process_resource_actions(link_id, all_actions, rng)
1580 }
1581
1582 fn handle_resource_part(
1584 &mut self,
1585 link_id: &LinkId,
1586 raw_data: &[u8],
1587 rng: &mut dyn Rng,
1588 ) -> Vec<LinkManagerAction> {
1589 let link = match self.links.get_mut(link_id) {
1590 Some(l) => l,
1591 None => return Vec::new(),
1592 };
1593
1594 let now = time::now();
1595 let mut all_actions = Vec::new();
1596 let mut assemble_idx = None;
1597
1598 for (idx, receiver) in link.incoming_resources.iter_mut().enumerate() {
1599 let resource_actions = receiver.receive_part(raw_data, now);
1600 if !resource_actions.is_empty() {
1601 if receiver.received_count == receiver.total_parts {
1603 assemble_idx = Some(idx);
1604 }
1605 all_actions.extend(resource_actions);
1606 break;
1607 }
1608 }
1609
1610 if let Some(idx) = assemble_idx {
1612 let decrypt_fn = |ciphertext: &[u8]| -> Result<Vec<u8>, ()> {
1613 link.engine.decrypt(ciphertext).map_err(|_| ())
1614 };
1615 let assemble_actions =
1616 link.incoming_resources[idx].assemble(&decrypt_fn, &Bzip2Compressor);
1617 all_actions.extend(assemble_actions);
1618 }
1619
1620 let _ = link;
1621 self.process_resource_actions(link_id, all_actions, rng)
1622 }
1623
1624 fn handle_resource_prf(
1626 &mut self,
1627 link_id: &LinkId,
1628 plaintext: &[u8],
1629 ) -> Vec<LinkManagerAction> {
1630 let link = match self.links.get_mut(link_id) {
1631 Some(l) => l,
1632 None => return Vec::new(),
1633 };
1634
1635 let now = time::now();
1636 let mut result_actions = Vec::new();
1637 for sender in &mut link.outgoing_resources {
1638 let resource_actions = sender.handle_proof(plaintext, now);
1639 if !resource_actions.is_empty() {
1640 result_actions.extend(resource_actions);
1641 break;
1642 }
1643 }
1644
1645 let mut actions = Vec::new();
1647 for ra in result_actions {
1648 match ra {
1649 ResourceAction::Completed => {
1650 actions.push(LinkManagerAction::ResourceCompleted { link_id: *link_id });
1651 }
1652 ResourceAction::Failed(e) => {
1653 actions.push(LinkManagerAction::ResourceFailed {
1654 link_id: *link_id,
1655 error: format!("{}", e),
1656 });
1657 }
1658 _ => {}
1659 }
1660 }
1661
1662 link.outgoing_resources
1664 .retain(|s| s.status < rns_core::resource::ResourceStatus::Complete);
1665
1666 actions
1667 }
1668
1669 fn handle_resource_icl(&mut self, link_id: &LinkId) -> Vec<LinkManagerAction> {
1671 let link = match self.links.get_mut(link_id) {
1672 Some(l) => l,
1673 None => return Vec::new(),
1674 };
1675
1676 let mut actions = Vec::new();
1677 for receiver in &mut link.incoming_resources {
1678 let ra = receiver.handle_cancel();
1679 for a in ra {
1680 if let ResourceAction::Failed(ref e) = a {
1681 actions.push(LinkManagerAction::ResourceFailed {
1682 link_id: *link_id,
1683 error: format!("{}", e),
1684 });
1685 }
1686 }
1687 }
1688 link.incoming_resources
1689 .retain(|r| r.status < rns_core::resource::ResourceStatus::Complete);
1690 actions
1691 }
1692
1693 fn handle_resource_rcl(&mut self, link_id: &LinkId) -> Vec<LinkManagerAction> {
1695 let link = match self.links.get_mut(link_id) {
1696 Some(l) => l,
1697 None => return Vec::new(),
1698 };
1699
1700 let mut actions = Vec::new();
1701 for sender in &mut link.outgoing_resources {
1702 let ra = sender.handle_reject();
1703 for a in ra {
1704 if let ResourceAction::Failed(ref e) = a {
1705 actions.push(LinkManagerAction::ResourceFailed {
1706 link_id: *link_id,
1707 error: format!("{}", e),
1708 });
1709 }
1710 }
1711 }
1712 link.outgoing_resources
1713 .retain(|s| s.status < rns_core::resource::ResourceStatus::Complete);
1714 actions
1715 }
1716
1717 fn process_resource_actions(
1719 &self,
1720 link_id: &LinkId,
1721 actions: Vec<ResourceAction>,
1722 rng: &mut dyn Rng,
1723 ) -> Vec<LinkManagerAction> {
1724 let link = match self.links.get(link_id) {
1725 Some(l) => l,
1726 None => return Vec::new(),
1727 };
1728
1729 let mut result = Vec::new();
1730 for action in actions {
1731 match action {
1732 ResourceAction::SendAdvertisement(data) => {
1733 if let Ok(encrypted) = link.engine.encrypt(&data, rng) {
1735 result.extend(self.build_link_packet(
1736 link_id,
1737 constants::CONTEXT_RESOURCE_ADV,
1738 &encrypted,
1739 ));
1740 }
1741 }
1742 ResourceAction::SendPart(data) => {
1743 result.extend(self.build_link_packet(
1745 link_id,
1746 constants::CONTEXT_RESOURCE,
1747 &data,
1748 ));
1749 }
1750 ResourceAction::SendRequest(data) => {
1751 if let Ok(encrypted) = link.engine.encrypt(&data, rng) {
1752 result.extend(self.build_link_packet(
1753 link_id,
1754 constants::CONTEXT_RESOURCE_REQ,
1755 &encrypted,
1756 ));
1757 }
1758 }
1759 ResourceAction::SendHmu(data) => {
1760 if let Ok(encrypted) = link.engine.encrypt(&data, rng) {
1761 result.extend(self.build_link_packet(
1762 link_id,
1763 constants::CONTEXT_RESOURCE_HMU,
1764 &encrypted,
1765 ));
1766 }
1767 }
1768 ResourceAction::SendProof(data) => {
1769 if let Ok(encrypted) = link.engine.encrypt(&data, rng) {
1770 result.extend(self.build_link_packet(
1771 link_id,
1772 constants::CONTEXT_RESOURCE_PRF,
1773 &encrypted,
1774 ));
1775 }
1776 }
1777 ResourceAction::SendCancelInitiator(data) => {
1778 if let Ok(encrypted) = link.engine.encrypt(&data, rng) {
1779 result.extend(self.build_link_packet(
1780 link_id,
1781 constants::CONTEXT_RESOURCE_ICL,
1782 &encrypted,
1783 ));
1784 }
1785 }
1786 ResourceAction::SendCancelReceiver(data) => {
1787 if let Ok(encrypted) = link.engine.encrypt(&data, rng) {
1788 result.extend(self.build_link_packet(
1789 link_id,
1790 constants::CONTEXT_RESOURCE_RCL,
1791 &encrypted,
1792 ));
1793 }
1794 }
1795 ResourceAction::DataReceived { data, metadata } => {
1796 result.push(LinkManagerAction::ResourceReceived {
1797 link_id: *link_id,
1798 data,
1799 metadata,
1800 });
1801 }
1802 ResourceAction::Completed => {
1803 result.push(LinkManagerAction::ResourceCompleted { link_id: *link_id });
1804 }
1805 ResourceAction::Failed(e) => {
1806 result.push(LinkManagerAction::ResourceFailed {
1807 link_id: *link_id,
1808 error: format!("{}", e),
1809 });
1810 }
1811 ResourceAction::ProgressUpdate { received, total } => {
1812 result.push(LinkManagerAction::ResourceProgress {
1813 link_id: *link_id,
1814 received,
1815 total,
1816 });
1817 }
1818 }
1819 }
1820 result
1821 }
1822
1823 fn build_link_packet(
1825 &self,
1826 link_id: &LinkId,
1827 context: u8,
1828 data: &[u8],
1829 ) -> Vec<LinkManagerAction> {
1830 let flags = PacketFlags {
1831 header_type: constants::HEADER_1,
1832 context_flag: constants::FLAG_UNSET,
1833 transport_type: constants::TRANSPORT_BROADCAST,
1834 destination_type: constants::DESTINATION_LINK,
1835 packet_type: constants::PACKET_TYPE_DATA,
1836 };
1837 let mut actions = Vec::new();
1838 if let Ok(pkt) = RawPacket::pack(flags, 0, link_id, None, context, data) {
1839 actions.push(LinkManagerAction::SendPacket {
1840 raw: pkt.raw,
1841 dest_type: constants::DESTINATION_LINK,
1842 attached_interface: None,
1843 });
1844 }
1845 actions
1846 }
1847
1848 pub fn send_resource(
1850 &mut self,
1851 link_id: &LinkId,
1852 data: &[u8],
1853 metadata: Option<&[u8]>,
1854 rng: &mut dyn Rng,
1855 ) -> Vec<LinkManagerAction> {
1856 let link = match self.links.get_mut(link_id) {
1857 Some(l) => l,
1858 None => return Vec::new(),
1859 };
1860
1861 if link.engine.state() != LinkState::Active {
1862 return Vec::new();
1863 }
1864
1865 let link_rtt = link.engine.rtt().unwrap_or(1.0);
1866 let now = time::now();
1867
1868 let enc_rng = std::cell::RefCell::new(rns_crypto::OsRng);
1871 let encrypt_fn = |plaintext: &[u8]| -> Vec<u8> {
1872 link.engine
1873 .encrypt(plaintext, &mut *enc_rng.borrow_mut())
1874 .unwrap_or_else(|_| plaintext.to_vec())
1875 };
1876
1877 let sender = match ResourceSender::new(
1878 data,
1879 metadata,
1880 constants::RESOURCE_SDU,
1881 &encrypt_fn,
1882 &Bzip2Compressor,
1883 rng,
1884 now,
1885 true, false, None, 1, 1, None, link_rtt,
1892 6.0, ) {
1894 Ok(s) => s,
1895 Err(e) => {
1896 log::debug!("Failed to create ResourceSender: {}", e);
1897 return Vec::new();
1898 }
1899 };
1900
1901 let mut sender = sender;
1902 let adv_actions = sender.advertise(now);
1903 link.outgoing_resources.push(sender);
1904
1905 let _ = link;
1906 self.process_resource_actions(link_id, adv_actions, rng)
1907 }
1908
1909 pub fn set_resource_strategy(&mut self, link_id: &LinkId, strategy: ResourceStrategy) {
1911 if let Some(link) = self.links.get_mut(link_id) {
1912 link.resource_strategy = strategy;
1913 }
1914 }
1915
1916 pub fn flush_channel_tx(&mut self, link_id: &LinkId) {
1919 if let Some(link) = self.links.get_mut(link_id) {
1920 if let Some(ref mut channel) = link.channel {
1921 channel.flush_tx();
1922 }
1923 }
1924 }
1925
1926 pub fn send_channel_message(
1928 &mut self,
1929 link_id: &LinkId,
1930 msgtype: u16,
1931 payload: &[u8],
1932 rng: &mut dyn Rng,
1933 ) -> Result<Vec<LinkManagerAction>, String> {
1934 let link = match self.links.get_mut(link_id) {
1935 Some(l) => l,
1936 None => return Err("unknown link".to_string()),
1937 };
1938
1939 let channel = match link.channel {
1940 Some(ref mut ch) => ch,
1941 None => return Err("link has no active channel".to_string()),
1942 };
1943
1944 let link_mdu = link.engine.mdu();
1945 let now = time::now();
1946 let chan_actions = match channel.send(msgtype, payload, now, link_mdu) {
1947 Ok(a) => {
1948 link.channel_send_ok += 1;
1949 a
1950 }
1951 Err(e) => {
1952 log::debug!("Channel send failed: {:?}", e);
1953 match e {
1954 rns_core::channel::ChannelError::NotReady => link.channel_send_not_ready += 1,
1955 rns_core::channel::ChannelError::MessageTooBig => {
1956 link.channel_send_too_big += 1;
1957 }
1958 rns_core::channel::ChannelError::InvalidEnvelope => {
1959 link.channel_send_other_error += 1;
1960 }
1961 }
1962 return Err(e.to_string());
1963 }
1964 };
1965
1966 let _ = link;
1967 Ok(self.process_channel_actions(link_id, chan_actions, rng))
1968 }
1969
1970 pub fn tick(&mut self, rng: &mut dyn Rng) -> Vec<LinkManagerAction> {
1972 let now = time::now();
1973 let mut all_actions = Vec::new();
1974
1975 let link_ids: Vec<LinkId> = self.links.keys().copied().collect();
1977
1978 for link_id in &link_ids {
1979 let link = match self.links.get_mut(link_id) {
1980 Some(l) => l,
1981 None => continue,
1982 };
1983
1984 let tick_actions = link.engine.tick(now);
1986 all_actions.extend(self.process_link_actions(link_id, &tick_actions));
1987
1988 let link = match self.links.get_mut(link_id) {
1990 Some(l) => l,
1991 None => continue,
1992 };
1993 if link.engine.needs_keepalive(now) {
1994 let flags = PacketFlags {
1996 header_type: constants::HEADER_1,
1997 context_flag: constants::FLAG_UNSET,
1998 transport_type: constants::TRANSPORT_BROADCAST,
1999 destination_type: constants::DESTINATION_LINK,
2000 packet_type: constants::PACKET_TYPE_DATA,
2001 };
2002 if let Ok(pkt) =
2003 RawPacket::pack(flags, 0, link_id, None, constants::CONTEXT_KEEPALIVE, &[])
2004 {
2005 all_actions.push(LinkManagerAction::SendPacket {
2006 raw: pkt.raw,
2007 dest_type: constants::DESTINATION_LINK,
2008 attached_interface: None,
2009 });
2010 link.engine.record_outbound(now, true);
2011 }
2012 }
2013
2014 if let Some(channel) = link.channel.as_mut() {
2015 let chan_actions = channel.tick(now);
2016 let _ = channel;
2017 let _ = link;
2018 all_actions.extend(self.process_channel_actions(link_id, chan_actions, rng));
2019 }
2020 }
2021
2022 for link_id in &link_ids {
2024 let link = match self.links.get_mut(link_id) {
2025 Some(l) => l,
2026 None => continue,
2027 };
2028
2029 let mut sender_actions = Vec::new();
2031 for sender in &mut link.outgoing_resources {
2032 sender_actions.extend(sender.tick(now));
2033 }
2034
2035 let mut receiver_actions = Vec::new();
2037 for receiver in &mut link.incoming_resources {
2038 let decrypt_fn = |ciphertext: &[u8]| -> Result<Vec<u8>, ()> {
2039 link.engine.decrypt(ciphertext).map_err(|_| ())
2040 };
2041 receiver_actions.extend(receiver.tick(now, &decrypt_fn, &Bzip2Compressor));
2042 }
2043
2044 link.outgoing_resources
2046 .retain(|s| s.status < rns_core::resource::ResourceStatus::Complete);
2047 link.incoming_resources
2048 .retain(|r| r.status < rns_core::resource::ResourceStatus::Assembling);
2049
2050 let _ = link;
2051 all_actions.extend(self.process_resource_actions(link_id, sender_actions, rng));
2052 all_actions.extend(self.process_resource_actions(link_id, receiver_actions, rng));
2053 }
2054
2055 let closed: Vec<LinkId> = self
2057 .links
2058 .iter()
2059 .filter(|(_, l)| l.engine.state() == LinkState::Closed)
2060 .map(|(id, _)| *id)
2061 .collect();
2062 for id in closed {
2063 self.links.remove(&id);
2064 all_actions.push(LinkManagerAction::DeregisterLinkDest { link_id: id });
2065 }
2066
2067 all_actions
2068 }
2069
2070 pub fn is_link_destination(&self, dest_hash: &[u8; 16]) -> bool {
2072 self.links.contains_key(dest_hash) || self.link_destinations.contains_key(dest_hash)
2073 }
2074
2075 pub fn link_state(&self, link_id: &LinkId) -> Option<LinkState> {
2077 self.links.get(link_id).map(|l| l.engine.state())
2078 }
2079
2080 pub fn link_rtt(&self, link_id: &LinkId) -> Option<f64> {
2082 self.links.get(link_id).and_then(|l| l.engine.rtt())
2083 }
2084
2085 pub fn set_link_rtt(&mut self, link_id: &LinkId, rtt: f64) {
2087 if let Some(link) = self.links.get_mut(link_id) {
2088 link.engine.set_rtt(rtt);
2089 }
2090 }
2091
2092 pub fn record_link_inbound(&mut self, link_id: &LinkId) {
2094 if let Some(link) = self.links.get_mut(link_id) {
2095 link.engine.record_inbound(time::now());
2096 }
2097 }
2098
2099 pub fn set_link_mtu(&mut self, link_id: &LinkId, mtu: u32) {
2101 if let Some(link) = self.links.get_mut(link_id) {
2102 link.engine.set_mtu(mtu);
2103 }
2104 }
2105
2106 pub fn link_count(&self) -> usize {
2108 self.links.len()
2109 }
2110
2111 pub fn resource_transfer_count(&self) -> usize {
2113 self.links
2114 .values()
2115 .map(|managed| managed.incoming_resources.len() + managed.outgoing_resources.len())
2116 .sum()
2117 }
2118
2119 pub fn cancel_all_resources(&mut self, rng: &mut dyn Rng) -> Vec<LinkManagerAction> {
2121 let link_ids: Vec<LinkId> = self.links.keys().copied().collect();
2122 let mut all_actions = Vec::new();
2123
2124 for link_id in &link_ids {
2125 let link = match self.links.get_mut(link_id) {
2126 Some(l) => l,
2127 None => continue,
2128 };
2129
2130 let mut sender_actions = Vec::new();
2131 for sender in &mut link.outgoing_resources {
2132 sender_actions.extend(sender.cancel());
2133 }
2134
2135 let mut receiver_actions = Vec::new();
2136 for receiver in &mut link.incoming_resources {
2137 receiver_actions.extend(receiver.reject());
2138 }
2139
2140 link.outgoing_resources
2141 .retain(|s| s.status < rns_core::resource::ResourceStatus::Complete);
2142 link.incoming_resources
2143 .retain(|r| r.status < rns_core::resource::ResourceStatus::Assembling);
2144
2145 let _ = link;
2146 all_actions.extend(self.process_resource_actions(link_id, sender_actions, rng));
2147 all_actions.extend(self.process_resource_actions(link_id, receiver_actions, rng));
2148 }
2149
2150 all_actions
2151 }
2152
2153 pub fn link_entries(&self) -> Vec<crate::event::LinkInfoEntry> {
2155 self.links
2156 .iter()
2157 .map(|(link_id, managed)| {
2158 let state = match managed.engine.state() {
2159 LinkState::Pending => "pending",
2160 LinkState::Handshake => "handshake",
2161 LinkState::Active => "active",
2162 LinkState::Stale => "stale",
2163 LinkState::Closed => "closed",
2164 };
2165 crate::event::LinkInfoEntry {
2166 link_id: *link_id,
2167 state: state.to_string(),
2168 is_initiator: managed.engine.is_initiator(),
2169 dest_hash: managed.dest_hash,
2170 remote_identity: managed.remote_identity.as_ref().map(|(h, _)| *h),
2171 rtt: managed.engine.rtt(),
2172 channel_window: managed.channel.as_ref().map(|c| c.window()),
2173 channel_outstanding: managed.channel.as_ref().map(|c| c.outstanding()),
2174 pending_channel_packets: managed.pending_channel_packets.len(),
2175 channel_send_ok: managed.channel_send_ok,
2176 channel_send_not_ready: managed.channel_send_not_ready,
2177 channel_send_too_big: managed.channel_send_too_big,
2178 channel_send_other_error: managed.channel_send_other_error,
2179 channel_messages_received: managed.channel_messages_received,
2180 channel_proofs_sent: managed.channel_proofs_sent,
2181 channel_proofs_received: managed.channel_proofs_received,
2182 }
2183 })
2184 .collect()
2185 }
2186
2187 pub fn resource_entries(&self) -> Vec<crate::event::ResourceInfoEntry> {
2189 let mut entries = Vec::new();
2190 for (link_id, managed) in &self.links {
2191 for recv in &managed.incoming_resources {
2192 let (received, total) = recv.progress();
2193 entries.push(crate::event::ResourceInfoEntry {
2194 link_id: *link_id,
2195 direction: "incoming".to_string(),
2196 total_parts: total,
2197 transferred_parts: received,
2198 complete: received >= total && total > 0,
2199 });
2200 }
2201 for send in &managed.outgoing_resources {
2202 let total = send.total_parts();
2203 let sent = send.sent_parts;
2204 entries.push(crate::event::ResourceInfoEntry {
2205 link_id: *link_id,
2206 direction: "outgoing".to_string(),
2207 total_parts: total,
2208 transferred_parts: sent,
2209 complete: sent >= total && total > 0,
2210 });
2211 }
2212 }
2213 entries
2214 }
2215
2216 fn process_link_actions(
2218 &self,
2219 link_id: &LinkId,
2220 actions: &[LinkAction],
2221 ) -> Vec<LinkManagerAction> {
2222 let mut result = Vec::new();
2223 for action in actions {
2224 match action {
2225 LinkAction::StateChanged {
2226 new_state, reason, ..
2227 } => match new_state {
2228 LinkState::Closed => {
2229 result.push(LinkManagerAction::LinkClosed {
2230 link_id: *link_id,
2231 reason: *reason,
2232 });
2233 }
2234 _ => {}
2235 },
2236 LinkAction::LinkEstablished {
2237 rtt, is_initiator, ..
2238 } => {
2239 let dest_hash = self
2240 .links
2241 .get(link_id)
2242 .map(|l| l.dest_hash)
2243 .unwrap_or([0u8; 16]);
2244 result.push(LinkManagerAction::LinkEstablished {
2245 link_id: *link_id,
2246 dest_hash,
2247 rtt: *rtt,
2248 is_initiator: *is_initiator,
2249 });
2250 }
2251 LinkAction::RemoteIdentified {
2252 identity_hash,
2253 public_key,
2254 ..
2255 } => {
2256 result.push(LinkManagerAction::RemoteIdentified {
2257 link_id: *link_id,
2258 identity_hash: *identity_hash,
2259 public_key: *public_key,
2260 });
2261 }
2262 LinkAction::DataReceived { .. } => {
2263 }
2265 }
2266 }
2267 result
2268 }
2269
2270 fn process_channel_actions(
2272 &mut self,
2273 link_id: &LinkId,
2274 actions: Vec<rns_core::channel::ChannelAction>,
2275 rng: &mut dyn Rng,
2276 ) -> Vec<LinkManagerAction> {
2277 let mut result = Vec::new();
2278 for action in actions {
2279 match action {
2280 rns_core::channel::ChannelAction::SendOnLink { raw, sequence } => {
2281 let encrypted = match self.links.get(link_id) {
2283 Some(link) => match link.engine.encrypt(&raw, rng) {
2284 Ok(encrypted) => encrypted,
2285 Err(_) => continue,
2286 },
2287 None => continue,
2288 };
2289 let flags = PacketFlags {
2290 header_type: constants::HEADER_1,
2291 context_flag: constants::FLAG_UNSET,
2292 transport_type: constants::TRANSPORT_BROADCAST,
2293 destination_type: constants::DESTINATION_LINK,
2294 packet_type: constants::PACKET_TYPE_DATA,
2295 };
2296 if let Ok(pkt) = RawPacket::pack(
2297 flags,
2298 0,
2299 link_id,
2300 None,
2301 constants::CONTEXT_CHANNEL,
2302 &encrypted,
2303 ) {
2304 if let Some(link_mut) = self.links.get_mut(link_id) {
2305 link_mut
2306 .pending_channel_packets
2307 .insert(pkt.packet_hash, sequence);
2308 }
2309 result.push(LinkManagerAction::SendPacket {
2310 raw: pkt.raw,
2311 dest_type: constants::DESTINATION_LINK,
2312 attached_interface: None,
2313 });
2314 }
2315 }
2316 rns_core::channel::ChannelAction::MessageReceived {
2317 msgtype, payload, ..
2318 } => {
2319 result.push(LinkManagerAction::ChannelMessageReceived {
2320 link_id: *link_id,
2321 msgtype,
2322 payload,
2323 });
2324 }
2325 rns_core::channel::ChannelAction::TeardownLink => {
2326 result.push(LinkManagerAction::LinkClosed {
2327 link_id: *link_id,
2328 reason: Some(TeardownReason::Timeout),
2329 });
2330 }
2331 }
2332 }
2333 result
2334 }
2335}
2336
2337fn compute_path_hash(path: &str) -> [u8; 16] {
2340 let full = rns_core::hash::full_hash(path.as_bytes());
2341 let mut result = [0u8; 16];
2342 result.copy_from_slice(&full[..16]);
2343 result
2344}
2345
2346#[cfg(test)]
2347mod tests {
2348 use super::*;
2349 use rns_crypto::identity::Identity;
2350 use rns_crypto::{FixedRng, OsRng};
2351
2352 fn make_rng(seed: u8) -> FixedRng {
2353 FixedRng::new(&[seed; 128])
2354 }
2355
2356 fn make_dest_keys(rng: &mut dyn Rng) -> (Ed25519PrivateKey, [u8; 32]) {
2357 let sig_prv = Ed25519PrivateKey::generate(rng);
2358 let sig_pub_bytes = sig_prv.public_key().public_bytes();
2359 (sig_prv, sig_pub_bytes)
2360 }
2361
2362 #[test]
2363 fn test_register_link_destination() {
2364 let mut mgr = LinkManager::new();
2365 let mut rng = make_rng(0x01);
2366 let (sig_prv, sig_pub_bytes) = make_dest_keys(&mut rng);
2367 let dest_hash = [0xDD; 16];
2368
2369 mgr.register_link_destination(
2370 dest_hash,
2371 sig_prv,
2372 sig_pub_bytes,
2373 ResourceStrategy::AcceptNone,
2374 );
2375 assert!(mgr.is_link_destination(&dest_hash));
2376
2377 mgr.deregister_link_destination(&dest_hash);
2378 assert!(!mgr.is_link_destination(&dest_hash));
2379 }
2380
2381 #[test]
2382 fn test_create_link() {
2383 let mut mgr = LinkManager::new();
2384 let mut rng = OsRng;
2385 let dest_hash = [0xDD; 16];
2386
2387 let sig_pub_bytes = [0xAA; 32]; let (link_id, actions) = mgr.create_link(
2389 &dest_hash,
2390 &sig_pub_bytes,
2391 1,
2392 constants::MTU as u32,
2393 &mut rng,
2394 );
2395 assert_ne!(link_id, [0u8; 16]);
2396 assert_eq!(actions.len(), 2);
2398 assert!(matches!(
2399 actions[0],
2400 LinkManagerAction::RegisterLinkDest { .. }
2401 ));
2402 assert!(matches!(actions[1], LinkManagerAction::SendPacket { .. }));
2403
2404 assert_eq!(mgr.link_state(&link_id), Some(LinkState::Pending));
2406 }
2407
2408 #[test]
2409 fn test_full_handshake_via_manager() {
2410 let mut rng = OsRng;
2411 let dest_hash = [0xDD; 16];
2412
2413 let mut responder_mgr = LinkManager::new();
2415 let (sig_prv, sig_pub_bytes) = make_dest_keys(&mut rng);
2416 responder_mgr.register_link_destination(
2417 dest_hash,
2418 sig_prv,
2419 sig_pub_bytes,
2420 ResourceStrategy::AcceptNone,
2421 );
2422
2423 let mut initiator_mgr = LinkManager::new();
2425
2426 let (link_id, init_actions) = initiator_mgr.create_link(
2428 &dest_hash,
2429 &sig_pub_bytes,
2430 1,
2431 constants::MTU as u32,
2432 &mut rng,
2433 );
2434 assert_eq!(init_actions.len(), 2);
2435
2436 let linkrequest_raw = match &init_actions[1] {
2438 LinkManagerAction::SendPacket { raw, .. } => raw.clone(),
2439 _ => panic!("Expected SendPacket"),
2440 };
2441
2442 let lr_packet = RawPacket::unpack(&linkrequest_raw).unwrap();
2444
2445 let resp_actions = responder_mgr.handle_local_delivery(
2447 lr_packet.destination_hash,
2448 &linkrequest_raw,
2449 lr_packet.packet_hash,
2450 rns_core::transport::types::InterfaceId(0),
2451 &mut rng,
2452 );
2453 assert!(resp_actions.len() >= 2);
2455 assert!(matches!(
2456 resp_actions[0],
2457 LinkManagerAction::RegisterLinkDest { .. }
2458 ));
2459
2460 let lrproof_raw = match &resp_actions[1] {
2462 LinkManagerAction::SendPacket { raw, .. } => raw.clone(),
2463 _ => panic!("Expected SendPacket for LRPROOF"),
2464 };
2465
2466 let lrproof_packet = RawPacket::unpack(&lrproof_raw).unwrap();
2468 let init_actions2 = initiator_mgr.handle_local_delivery(
2469 lrproof_packet.destination_hash,
2470 &lrproof_raw,
2471 lrproof_packet.packet_hash,
2472 rns_core::transport::types::InterfaceId(0),
2473 &mut rng,
2474 );
2475
2476 let has_established = init_actions2
2478 .iter()
2479 .any(|a| matches!(a, LinkManagerAction::LinkEstablished { .. }));
2480 assert!(has_established, "Initiator should emit LinkEstablished");
2481
2482 let lrrtt_raw = init_actions2
2484 .iter()
2485 .find_map(|a| match a {
2486 LinkManagerAction::SendPacket { raw, .. } => Some(raw.clone()),
2487 _ => None,
2488 })
2489 .expect("Should have LRRTT SendPacket");
2490
2491 let lrrtt_packet = RawPacket::unpack(&lrrtt_raw).unwrap();
2493 let resp_link_id = lrrtt_packet.destination_hash;
2494 let resp_actions2 = responder_mgr.handle_local_delivery(
2495 resp_link_id,
2496 &lrrtt_raw,
2497 lrrtt_packet.packet_hash,
2498 rns_core::transport::types::InterfaceId(0),
2499 &mut rng,
2500 );
2501
2502 let has_established = resp_actions2
2503 .iter()
2504 .any(|a| matches!(a, LinkManagerAction::LinkEstablished { .. }));
2505 assert!(has_established, "Responder should emit LinkEstablished");
2506
2507 assert_eq!(initiator_mgr.link_state(&link_id), Some(LinkState::Active));
2509 assert_eq!(responder_mgr.link_state(&link_id), Some(LinkState::Active));
2510
2511 assert!(initiator_mgr.link_rtt(&link_id).is_some());
2513 assert!(responder_mgr.link_rtt(&link_id).is_some());
2514 }
2515
2516 #[test]
2517 fn test_encrypted_data_exchange() {
2518 let mut rng = OsRng;
2519 let dest_hash = [0xDD; 16];
2520 let mut resp_mgr = LinkManager::new();
2521 let (sig_prv, sig_pub_bytes) = make_dest_keys(&mut rng);
2522 resp_mgr.register_link_destination(
2523 dest_hash,
2524 sig_prv,
2525 sig_pub_bytes,
2526 ResourceStrategy::AcceptNone,
2527 );
2528 let mut init_mgr = LinkManager::new();
2529
2530 let (link_id, init_actions) = init_mgr.create_link(
2532 &dest_hash,
2533 &sig_pub_bytes,
2534 1,
2535 constants::MTU as u32,
2536 &mut rng,
2537 );
2538 let lr_raw = extract_send_packet(&init_actions);
2539 let lr_pkt = RawPacket::unpack(&lr_raw).unwrap();
2540 let resp_actions = resp_mgr.handle_local_delivery(
2541 lr_pkt.destination_hash,
2542 &lr_raw,
2543 lr_pkt.packet_hash,
2544 rns_core::transport::types::InterfaceId(0),
2545 &mut rng,
2546 );
2547 let lrproof_raw = extract_send_packet_at(&resp_actions, 1);
2548 let lrproof_pkt = RawPacket::unpack(&lrproof_raw).unwrap();
2549 let init_actions2 = init_mgr.handle_local_delivery(
2550 lrproof_pkt.destination_hash,
2551 &lrproof_raw,
2552 lrproof_pkt.packet_hash,
2553 rns_core::transport::types::InterfaceId(0),
2554 &mut rng,
2555 );
2556 let lrrtt_raw = extract_any_send_packet(&init_actions2);
2557 let lrrtt_pkt = RawPacket::unpack(&lrrtt_raw).unwrap();
2558 resp_mgr.handle_local_delivery(
2559 lrrtt_pkt.destination_hash,
2560 &lrrtt_raw,
2561 lrrtt_pkt.packet_hash,
2562 rns_core::transport::types::InterfaceId(0),
2563 &mut rng,
2564 );
2565
2566 let actions =
2568 init_mgr.send_on_link(&link_id, b"hello link!", constants::CONTEXT_NONE, &mut rng);
2569 assert_eq!(actions.len(), 1);
2570 assert!(matches!(actions[0], LinkManagerAction::SendPacket { .. }));
2571 }
2572
2573 #[test]
2574 fn test_request_response() {
2575 let mut rng = OsRng;
2576 let dest_hash = [0xDD; 16];
2577 let mut resp_mgr = LinkManager::new();
2578 let (sig_prv, sig_pub_bytes) = make_dest_keys(&mut rng);
2579 resp_mgr.register_link_destination(
2580 dest_hash,
2581 sig_prv,
2582 sig_pub_bytes,
2583 ResourceStrategy::AcceptNone,
2584 );
2585
2586 resp_mgr.register_request_handler("/status", None, |_link_id, _path, _data, _remote| {
2588 Some(b"OK".to_vec())
2589 });
2590
2591 let mut init_mgr = LinkManager::new();
2592
2593 let (link_id, init_actions) = init_mgr.create_link(
2595 &dest_hash,
2596 &sig_pub_bytes,
2597 1,
2598 constants::MTU as u32,
2599 &mut rng,
2600 );
2601 let lr_raw = extract_send_packet(&init_actions);
2602 let lr_pkt = RawPacket::unpack(&lr_raw).unwrap();
2603 let resp_actions = resp_mgr.handle_local_delivery(
2604 lr_pkt.destination_hash,
2605 &lr_raw,
2606 lr_pkt.packet_hash,
2607 rns_core::transport::types::InterfaceId(0),
2608 &mut rng,
2609 );
2610 let lrproof_raw = extract_send_packet_at(&resp_actions, 1);
2611 let lrproof_pkt = RawPacket::unpack(&lrproof_raw).unwrap();
2612 let init_actions2 = init_mgr.handle_local_delivery(
2613 lrproof_pkt.destination_hash,
2614 &lrproof_raw,
2615 lrproof_pkt.packet_hash,
2616 rns_core::transport::types::InterfaceId(0),
2617 &mut rng,
2618 );
2619 let lrrtt_raw = extract_any_send_packet(&init_actions2);
2620 let lrrtt_pkt = RawPacket::unpack(&lrrtt_raw).unwrap();
2621 resp_mgr.handle_local_delivery(
2622 lrrtt_pkt.destination_hash,
2623 &lrrtt_raw,
2624 lrrtt_pkt.packet_hash,
2625 rns_core::transport::types::InterfaceId(0),
2626 &mut rng,
2627 );
2628
2629 let req_actions = init_mgr.send_request(&link_id, "/status", b"query", &mut rng);
2631 assert_eq!(req_actions.len(), 1);
2632
2633 let req_raw = extract_send_packet_from(&req_actions);
2635 let req_pkt = RawPacket::unpack(&req_raw).unwrap();
2636 let resp_actions = resp_mgr.handle_local_delivery(
2637 req_pkt.destination_hash,
2638 &req_raw,
2639 req_pkt.packet_hash,
2640 rns_core::transport::types::InterfaceId(0),
2641 &mut rng,
2642 );
2643
2644 let has_response = resp_actions
2646 .iter()
2647 .any(|a| matches!(a, LinkManagerAction::SendPacket { .. }));
2648 assert!(has_response, "Handler should produce a response packet");
2649 }
2650
2651 #[test]
2652 fn test_request_acl_deny_unidentified() {
2653 let mut rng = OsRng;
2654 let dest_hash = [0xDD; 16];
2655 let mut resp_mgr = LinkManager::new();
2656 let (sig_prv, sig_pub_bytes) = make_dest_keys(&mut rng);
2657 resp_mgr.register_link_destination(
2658 dest_hash,
2659 sig_prv,
2660 sig_pub_bytes,
2661 ResourceStrategy::AcceptNone,
2662 );
2663
2664 resp_mgr.register_request_handler(
2666 "/restricted",
2667 Some(vec![[0xAA; 16]]),
2668 |_link_id, _path, _data, _remote| Some(b"secret".to_vec()),
2669 );
2670
2671 let mut init_mgr = LinkManager::new();
2672
2673 let (link_id, init_actions) = init_mgr.create_link(
2675 &dest_hash,
2676 &sig_pub_bytes,
2677 1,
2678 constants::MTU as u32,
2679 &mut rng,
2680 );
2681 let lr_raw = extract_send_packet(&init_actions);
2682 let lr_pkt = RawPacket::unpack(&lr_raw).unwrap();
2683 let resp_actions = resp_mgr.handle_local_delivery(
2684 lr_pkt.destination_hash,
2685 &lr_raw,
2686 lr_pkt.packet_hash,
2687 rns_core::transport::types::InterfaceId(0),
2688 &mut rng,
2689 );
2690 let lrproof_raw = extract_send_packet_at(&resp_actions, 1);
2691 let lrproof_pkt = RawPacket::unpack(&lrproof_raw).unwrap();
2692 let init_actions2 = init_mgr.handle_local_delivery(
2693 lrproof_pkt.destination_hash,
2694 &lrproof_raw,
2695 lrproof_pkt.packet_hash,
2696 rns_core::transport::types::InterfaceId(0),
2697 &mut rng,
2698 );
2699 let lrrtt_raw = extract_any_send_packet(&init_actions2);
2700 let lrrtt_pkt = RawPacket::unpack(&lrrtt_raw).unwrap();
2701 resp_mgr.handle_local_delivery(
2702 lrrtt_pkt.destination_hash,
2703 &lrrtt_raw,
2704 lrrtt_pkt.packet_hash,
2705 rns_core::transport::types::InterfaceId(0),
2706 &mut rng,
2707 );
2708
2709 let req_actions = init_mgr.send_request(&link_id, "/restricted", b"query", &mut rng);
2711 let req_raw = extract_send_packet_from(&req_actions);
2712 let req_pkt = RawPacket::unpack(&req_raw).unwrap();
2713 let resp_actions = resp_mgr.handle_local_delivery(
2714 req_pkt.destination_hash,
2715 &req_raw,
2716 req_pkt.packet_hash,
2717 rns_core::transport::types::InterfaceId(0),
2718 &mut rng,
2719 );
2720
2721 let has_response = resp_actions
2723 .iter()
2724 .any(|a| matches!(a, LinkManagerAction::SendPacket { .. }));
2725 assert!(!has_response, "Unidentified peer should be denied");
2726 }
2727
2728 #[test]
2729 fn test_teardown_link() {
2730 let mut rng = OsRng;
2731 let dest_hash = [0xDD; 16];
2732 let mut mgr = LinkManager::new();
2733
2734 let dummy_sig = [0xAA; 32];
2735 let (link_id, _) =
2736 mgr.create_link(&dest_hash, &dummy_sig, 1, constants::MTU as u32, &mut rng);
2737 assert_eq!(mgr.link_count(), 1);
2738
2739 let actions = mgr.teardown_link(&link_id);
2740 let has_close = actions
2741 .iter()
2742 .any(|a| matches!(a, LinkManagerAction::LinkClosed { .. }));
2743 assert!(has_close);
2744
2745 let tick_actions = mgr.tick(&mut rng);
2747 let has_deregister = tick_actions
2748 .iter()
2749 .any(|a| matches!(a, LinkManagerAction::DeregisterLinkDest { .. }));
2750 assert!(has_deregister);
2751 assert_eq!(mgr.link_count(), 0);
2752 }
2753
2754 #[test]
2755 fn test_identify_on_link() {
2756 let mut rng = OsRng;
2757 let dest_hash = [0xDD; 16];
2758 let mut resp_mgr = LinkManager::new();
2759 let (sig_prv, sig_pub_bytes) = make_dest_keys(&mut rng);
2760 resp_mgr.register_link_destination(
2761 dest_hash,
2762 sig_prv,
2763 sig_pub_bytes,
2764 ResourceStrategy::AcceptNone,
2765 );
2766 let mut init_mgr = LinkManager::new();
2767
2768 let (link_id, init_actions) = init_mgr.create_link(
2770 &dest_hash,
2771 &sig_pub_bytes,
2772 1,
2773 constants::MTU as u32,
2774 &mut rng,
2775 );
2776 let lr_raw = extract_send_packet(&init_actions);
2777 let lr_pkt = RawPacket::unpack(&lr_raw).unwrap();
2778 let resp_actions = resp_mgr.handle_local_delivery(
2779 lr_pkt.destination_hash,
2780 &lr_raw,
2781 lr_pkt.packet_hash,
2782 rns_core::transport::types::InterfaceId(0),
2783 &mut rng,
2784 );
2785 let lrproof_raw = extract_send_packet_at(&resp_actions, 1);
2786 let lrproof_pkt = RawPacket::unpack(&lrproof_raw).unwrap();
2787 let init_actions2 = init_mgr.handle_local_delivery(
2788 lrproof_pkt.destination_hash,
2789 &lrproof_raw,
2790 lrproof_pkt.packet_hash,
2791 rns_core::transport::types::InterfaceId(0),
2792 &mut rng,
2793 );
2794 let lrrtt_raw = extract_any_send_packet(&init_actions2);
2795 let lrrtt_pkt = RawPacket::unpack(&lrrtt_raw).unwrap();
2796 resp_mgr.handle_local_delivery(
2797 lrrtt_pkt.destination_hash,
2798 &lrrtt_raw,
2799 lrrtt_pkt.packet_hash,
2800 rns_core::transport::types::InterfaceId(0),
2801 &mut rng,
2802 );
2803
2804 let identity = Identity::new(&mut rng);
2806 let id_actions = init_mgr.identify(&link_id, &identity, &mut rng);
2807 assert_eq!(id_actions.len(), 1);
2808
2809 let id_raw = extract_send_packet_from(&id_actions);
2811 let id_pkt = RawPacket::unpack(&id_raw).unwrap();
2812 let resp_actions = resp_mgr.handle_local_delivery(
2813 id_pkt.destination_hash,
2814 &id_raw,
2815 id_pkt.packet_hash,
2816 rns_core::transport::types::InterfaceId(0),
2817 &mut rng,
2818 );
2819
2820 let has_identified = resp_actions
2821 .iter()
2822 .any(|a| matches!(a, LinkManagerAction::RemoteIdentified { .. }));
2823 assert!(has_identified, "Responder should emit RemoteIdentified");
2824 }
2825
2826 #[test]
2827 fn test_path_hash_computation() {
2828 let h1 = compute_path_hash("/status");
2829 let h2 = compute_path_hash("/path");
2830 assert_ne!(h1, h2);
2831
2832 assert_eq!(h1, compute_path_hash("/status"));
2834 }
2835
2836 #[test]
2837 fn test_link_count() {
2838 let mut mgr = LinkManager::new();
2839 let mut rng = OsRng;
2840
2841 assert_eq!(mgr.link_count(), 0);
2842
2843 let dummy_sig = [0xAA; 32];
2844 mgr.create_link(&[0x11; 16], &dummy_sig, 1, constants::MTU as u32, &mut rng);
2845 assert_eq!(mgr.link_count(), 1);
2846
2847 mgr.create_link(&[0x22; 16], &dummy_sig, 1, constants::MTU as u32, &mut rng);
2848 assert_eq!(mgr.link_count(), 2);
2849 }
2850
2851 fn extract_send_packet(actions: &[LinkManagerAction]) -> Vec<u8> {
2854 extract_send_packet_at(actions, actions.len() - 1)
2855 }
2856
2857 fn extract_send_packet_at(actions: &[LinkManagerAction], idx: usize) -> Vec<u8> {
2858 match &actions[idx] {
2859 LinkManagerAction::SendPacket { raw, .. } => raw.clone(),
2860 other => panic!("Expected SendPacket at index {}, got {:?}", idx, other),
2861 }
2862 }
2863
2864 fn extract_any_send_packet(actions: &[LinkManagerAction]) -> Vec<u8> {
2865 actions
2866 .iter()
2867 .find_map(|a| match a {
2868 LinkManagerAction::SendPacket { raw, .. } => Some(raw.clone()),
2869 _ => None,
2870 })
2871 .expect("Expected at least one SendPacket action")
2872 }
2873
2874 fn extract_send_packet_from(actions: &[LinkManagerAction]) -> Vec<u8> {
2875 extract_any_send_packet(actions)
2876 }
2877
2878 fn setup_active_link() -> (LinkManager, LinkManager, LinkId) {
2881 let mut rng = OsRng;
2882 let dest_hash = [0xDD; 16];
2883 let mut resp_mgr = LinkManager::new();
2884 let (sig_prv, sig_pub_bytes) = make_dest_keys(&mut rng);
2885 resp_mgr.register_link_destination(
2886 dest_hash,
2887 sig_prv,
2888 sig_pub_bytes,
2889 ResourceStrategy::AcceptNone,
2890 );
2891 let mut init_mgr = LinkManager::new();
2892
2893 let (link_id, init_actions) = init_mgr.create_link(
2894 &dest_hash,
2895 &sig_pub_bytes,
2896 1,
2897 constants::MTU as u32,
2898 &mut rng,
2899 );
2900 let lr_raw = extract_send_packet(&init_actions);
2901 let lr_pkt = RawPacket::unpack(&lr_raw).unwrap();
2902 let resp_actions = resp_mgr.handle_local_delivery(
2903 lr_pkt.destination_hash,
2904 &lr_raw,
2905 lr_pkt.packet_hash,
2906 rns_core::transport::types::InterfaceId(0),
2907 &mut rng,
2908 );
2909 let lrproof_raw = extract_send_packet_at(&resp_actions, 1);
2910 let lrproof_pkt = RawPacket::unpack(&lrproof_raw).unwrap();
2911 let init_actions2 = init_mgr.handle_local_delivery(
2912 lrproof_pkt.destination_hash,
2913 &lrproof_raw,
2914 lrproof_pkt.packet_hash,
2915 rns_core::transport::types::InterfaceId(0),
2916 &mut rng,
2917 );
2918 let lrrtt_raw = extract_any_send_packet(&init_actions2);
2919 let lrrtt_pkt = RawPacket::unpack(&lrrtt_raw).unwrap();
2920 resp_mgr.handle_local_delivery(
2921 lrrtt_pkt.destination_hash,
2922 &lrrtt_raw,
2923 lrrtt_pkt.packet_hash,
2924 rns_core::transport::types::InterfaceId(0),
2925 &mut rng,
2926 );
2927
2928 assert_eq!(init_mgr.link_state(&link_id), Some(LinkState::Active));
2929 assert_eq!(resp_mgr.link_state(&link_id), Some(LinkState::Active));
2930
2931 (init_mgr, resp_mgr, link_id)
2932 }
2933
2934 #[test]
2939 fn test_resource_strategy_default() {
2940 let mut mgr = LinkManager::new();
2941 let mut rng = OsRng;
2942 let dummy_sig = [0xAA; 32];
2943 let (link_id, _) =
2944 mgr.create_link(&[0x11; 16], &dummy_sig, 1, constants::MTU as u32, &mut rng);
2945
2946 let link = mgr.links.get(&link_id).unwrap();
2948 assert_eq!(link.resource_strategy, ResourceStrategy::AcceptNone);
2949 }
2950
2951 #[test]
2952 fn test_set_resource_strategy() {
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 mgr.set_resource_strategy(&link_id, ResourceStrategy::AcceptAll);
2960 assert_eq!(
2961 mgr.links.get(&link_id).unwrap().resource_strategy,
2962 ResourceStrategy::AcceptAll
2963 );
2964
2965 mgr.set_resource_strategy(&link_id, ResourceStrategy::AcceptApp);
2966 assert_eq!(
2967 mgr.links.get(&link_id).unwrap().resource_strategy,
2968 ResourceStrategy::AcceptApp
2969 );
2970 }
2971
2972 #[test]
2973 fn test_send_resource_on_active_link() {
2974 let (mut init_mgr, _resp_mgr, link_id) = setup_active_link();
2975 let mut rng = OsRng;
2976
2977 let data = vec![0xAB; 100]; let actions = init_mgr.send_resource(&link_id, &data, None, &mut rng);
2980
2981 let has_send = actions
2983 .iter()
2984 .any(|a| matches!(a, LinkManagerAction::SendPacket { .. }));
2985 assert!(
2986 has_send,
2987 "send_resource should emit advertisement SendPacket"
2988 );
2989 }
2990
2991 #[test]
2992 fn test_send_resource_on_inactive_link() {
2993 let mut mgr = LinkManager::new();
2994 let mut rng = OsRng;
2995 let dummy_sig = [0xAA; 32];
2996 let (link_id, _) =
2997 mgr.create_link(&[0x11; 16], &dummy_sig, 1, constants::MTU as u32, &mut rng);
2998
2999 let actions = mgr.send_resource(&link_id, b"data", None, &mut rng);
3001 assert!(actions.is_empty(), "Cannot send resource on inactive link");
3002 }
3003
3004 #[test]
3005 fn test_resource_adv_rejected_by_accept_none() {
3006 let (mut init_mgr, mut resp_mgr, link_id) = setup_active_link();
3007 let mut rng = OsRng;
3008
3009 let data = vec![0xCD; 100];
3012 let adv_actions = init_mgr.send_resource(&link_id, &data, None, &mut rng);
3013
3014 for action in &adv_actions {
3016 if let LinkManagerAction::SendPacket { raw, .. } = action {
3017 let pkt = RawPacket::unpack(raw).unwrap();
3018 let resp_actions = resp_mgr.handle_local_delivery(
3019 pkt.destination_hash,
3020 raw,
3021 pkt.packet_hash,
3022 rns_core::transport::types::InterfaceId(0),
3023 &mut rng,
3024 );
3025 let has_resource_received = resp_actions
3027 .iter()
3028 .any(|a| matches!(a, LinkManagerAction::ResourceReceived { .. }));
3029 assert!(
3030 !has_resource_received,
3031 "AcceptNone should not accept resource"
3032 );
3033 }
3034 }
3035 }
3036
3037 #[test]
3038 fn test_resource_adv_accepted_by_accept_all() {
3039 let (mut init_mgr, mut resp_mgr, link_id) = setup_active_link();
3040 let mut rng = OsRng;
3041
3042 resp_mgr.set_resource_strategy(&link_id, ResourceStrategy::AcceptAll);
3044
3045 let data = vec![0xCD; 100];
3047 let adv_actions = init_mgr.send_resource(&link_id, &data, None, &mut rng);
3048
3049 for action in &adv_actions {
3051 if let LinkManagerAction::SendPacket { raw, .. } = action {
3052 let pkt = RawPacket::unpack(raw).unwrap();
3053 let resp_actions = resp_mgr.handle_local_delivery(
3054 pkt.destination_hash,
3055 raw,
3056 pkt.packet_hash,
3057 rns_core::transport::types::InterfaceId(0),
3058 &mut rng,
3059 );
3060 let has_send = resp_actions
3062 .iter()
3063 .any(|a| matches!(a, LinkManagerAction::SendPacket { .. }));
3064 assert!(has_send, "AcceptAll should accept and request parts");
3065 }
3066 }
3067 }
3068
3069 #[test]
3070 fn test_resource_accept_app_query() {
3071 let (mut init_mgr, mut resp_mgr, link_id) = setup_active_link();
3072 let mut rng = OsRng;
3073
3074 resp_mgr.set_resource_strategy(&link_id, ResourceStrategy::AcceptApp);
3076
3077 let data = vec![0xCD; 100];
3079 let adv_actions = init_mgr.send_resource(&link_id, &data, None, &mut rng);
3080
3081 let mut got_query = false;
3083 for action in &adv_actions {
3084 if let LinkManagerAction::SendPacket { raw, .. } = action {
3085 let pkt = RawPacket::unpack(raw).unwrap();
3086 let resp_actions = resp_mgr.handle_local_delivery(
3087 pkt.destination_hash,
3088 raw,
3089 pkt.packet_hash,
3090 rns_core::transport::types::InterfaceId(0),
3091 &mut rng,
3092 );
3093 for a in &resp_actions {
3094 if matches!(a, LinkManagerAction::ResourceAcceptQuery { .. }) {
3095 got_query = true;
3096 }
3097 }
3098 }
3099 }
3100 assert!(got_query, "AcceptApp should emit ResourceAcceptQuery");
3101 }
3102
3103 #[test]
3104 fn test_resource_accept_app_accept() {
3105 let (mut init_mgr, mut resp_mgr, link_id) = setup_active_link();
3106 let mut rng = OsRng;
3107
3108 resp_mgr.set_resource_strategy(&link_id, ResourceStrategy::AcceptApp);
3109
3110 let data = vec![0xCD; 100];
3111 let adv_actions = init_mgr.send_resource(&link_id, &data, None, &mut rng);
3112
3113 for action in &adv_actions {
3114 if let LinkManagerAction::SendPacket { raw, .. } = action {
3115 let pkt = RawPacket::unpack(raw).unwrap();
3116 let resp_actions = resp_mgr.handle_local_delivery(
3117 pkt.destination_hash,
3118 raw,
3119 pkt.packet_hash,
3120 rns_core::transport::types::InterfaceId(0),
3121 &mut rng,
3122 );
3123 for a in &resp_actions {
3124 if let LinkManagerAction::ResourceAcceptQuery {
3125 link_id: lid,
3126 resource_hash,
3127 ..
3128 } = a
3129 {
3130 let accept_actions =
3132 resp_mgr.accept_resource(lid, resource_hash, true, &mut rng);
3133 let has_send = accept_actions
3135 .iter()
3136 .any(|a| matches!(a, LinkManagerAction::SendPacket { .. }));
3137 assert!(
3138 has_send,
3139 "Accepting resource should produce request for parts"
3140 );
3141 }
3142 }
3143 }
3144 }
3145 }
3146
3147 #[test]
3148 fn test_resource_accept_app_reject() {
3149 let (mut init_mgr, mut resp_mgr, link_id) = setup_active_link();
3150 let mut rng = OsRng;
3151
3152 resp_mgr.set_resource_strategy(&link_id, ResourceStrategy::AcceptApp);
3153
3154 let data = vec![0xCD; 100];
3155 let adv_actions = init_mgr.send_resource(&link_id, &data, None, &mut rng);
3156
3157 for action in &adv_actions {
3158 if let LinkManagerAction::SendPacket { raw, .. } = action {
3159 let pkt = RawPacket::unpack(raw).unwrap();
3160 let resp_actions = resp_mgr.handle_local_delivery(
3161 pkt.destination_hash,
3162 raw,
3163 pkt.packet_hash,
3164 rns_core::transport::types::InterfaceId(0),
3165 &mut rng,
3166 );
3167 for a in &resp_actions {
3168 if let LinkManagerAction::ResourceAcceptQuery {
3169 link_id: lid,
3170 resource_hash,
3171 ..
3172 } = a
3173 {
3174 let reject_actions =
3176 resp_mgr.accept_resource(lid, resource_hash, false, &mut rng);
3177 let has_resource_received = reject_actions
3180 .iter()
3181 .any(|a| matches!(a, LinkManagerAction::ResourceReceived { .. }));
3182 assert!(!has_resource_received);
3183 }
3184 }
3185 }
3186 }
3187 }
3188
3189 #[test]
3190 fn test_resource_full_transfer() {
3191 let (mut init_mgr, mut resp_mgr, link_id) = setup_active_link();
3192 let mut rng = OsRng;
3193
3194 resp_mgr.set_resource_strategy(&link_id, ResourceStrategy::AcceptAll);
3196
3197 let original_data = b"Hello, Resource Transfer!".to_vec();
3199 let adv_actions = init_mgr.send_resource(&link_id, &original_data, None, &mut rng);
3200
3201 let mut pending: Vec<(char, LinkManagerAction)> =
3204 adv_actions.into_iter().map(|a| ('i', a)).collect();
3205 let mut rounds = 0;
3206 let max_rounds = 50;
3207 let mut resource_received = false;
3208 let mut sender_completed = false;
3209
3210 while !pending.is_empty() && rounds < max_rounds {
3211 rounds += 1;
3212 let mut next: Vec<(char, LinkManagerAction)> = Vec::new();
3213
3214 for (source, action) in pending.drain(..) {
3215 if let LinkManagerAction::SendPacket { raw, .. } = action {
3216 let pkt = RawPacket::unpack(&raw).unwrap();
3217
3218 let target_actions = if source == 'i' {
3220 resp_mgr.handle_local_delivery(
3221 pkt.destination_hash,
3222 &raw,
3223 pkt.packet_hash,
3224 rns_core::transport::types::InterfaceId(0),
3225 &mut rng,
3226 )
3227 } else {
3228 init_mgr.handle_local_delivery(
3229 pkt.destination_hash,
3230 &raw,
3231 pkt.packet_hash,
3232 rns_core::transport::types::InterfaceId(0),
3233 &mut rng,
3234 )
3235 };
3236
3237 let target_source = if source == 'i' { 'r' } else { 'i' };
3238 for a in &target_actions {
3239 match a {
3240 LinkManagerAction::ResourceReceived { data, .. } => {
3241 assert_eq!(*data, original_data);
3242 resource_received = true;
3243 }
3244 LinkManagerAction::ResourceCompleted { .. } => {
3245 sender_completed = true;
3246 }
3247 _ => {}
3248 }
3249 }
3250 next.extend(target_actions.into_iter().map(|a| (target_source, a)));
3251 }
3252 }
3253 pending = next;
3254 }
3255
3256 assert!(
3257 resource_received,
3258 "Responder should receive resource data (rounds={})",
3259 rounds
3260 );
3261 assert!(
3262 sender_completed,
3263 "Sender should get completion proof (rounds={})",
3264 rounds
3265 );
3266 }
3267
3268 #[test]
3269 fn test_resource_cancel_icl() {
3270 let (mut init_mgr, mut resp_mgr, link_id) = setup_active_link();
3271 let mut rng = OsRng;
3272
3273 resp_mgr.set_resource_strategy(&link_id, ResourceStrategy::AcceptAll);
3274
3275 let data = vec![0xAB; 2000];
3277 let adv_actions = init_mgr.send_resource(&link_id, &data, None, &mut rng);
3278
3279 for action in &adv_actions {
3281 if let LinkManagerAction::SendPacket { raw, .. } = action {
3282 let pkt = RawPacket::unpack(raw).unwrap();
3283 resp_mgr.handle_local_delivery(
3284 pkt.destination_hash,
3285 raw,
3286 pkt.packet_hash,
3287 rns_core::transport::types::InterfaceId(0),
3288 &mut rng,
3289 );
3290 }
3291 }
3292
3293 assert!(!resp_mgr
3295 .links
3296 .get(&link_id)
3297 .unwrap()
3298 .incoming_resources
3299 .is_empty());
3300
3301 let icl_actions = resp_mgr.handle_resource_icl(&link_id);
3303
3304 let has_failed = icl_actions
3306 .iter()
3307 .any(|a| matches!(a, LinkManagerAction::ResourceFailed { .. }));
3308 assert!(has_failed, "ICL should produce ResourceFailed");
3309 }
3310
3311 #[test]
3312 fn test_resource_cancel_rcl() {
3313 let (mut init_mgr, _resp_mgr, link_id) = setup_active_link();
3314 let mut rng = OsRng;
3315
3316 let data = vec![0xAB; 2000];
3318 init_mgr.send_resource(&link_id, &data, None, &mut rng);
3319
3320 assert!(!init_mgr
3322 .links
3323 .get(&link_id)
3324 .unwrap()
3325 .outgoing_resources
3326 .is_empty());
3327
3328 let rcl_actions = init_mgr.handle_resource_rcl(&link_id);
3330
3331 let has_failed = rcl_actions
3332 .iter()
3333 .any(|a| matches!(a, LinkManagerAction::ResourceFailed { .. }));
3334 assert!(has_failed, "RCL should produce ResourceFailed");
3335 }
3336
3337 #[test]
3338 fn test_cancel_all_resources_clears_active_transfers() {
3339 let (mut init_mgr, _resp_mgr, link_id) = setup_active_link();
3340 let mut rng = OsRng;
3341
3342 let actions = init_mgr.send_resource(&link_id, b"resource body", None, &mut rng);
3343 assert!(!actions.is_empty());
3344 assert_eq!(init_mgr.resource_transfer_count(), 1);
3345
3346 let cancel_actions = init_mgr.cancel_all_resources(&mut rng);
3347
3348 assert_eq!(init_mgr.resource_transfer_count(), 0);
3349 assert!(cancel_actions
3350 .iter()
3351 .any(|action| matches!(action, LinkManagerAction::SendPacket { .. })));
3352 }
3353
3354 #[test]
3355 fn test_resource_tick_cleans_up() {
3356 let (mut init_mgr, _resp_mgr, link_id) = setup_active_link();
3357 let mut rng = OsRng;
3358
3359 let data = vec![0xAB; 100];
3360 init_mgr.send_resource(&link_id, &data, None, &mut rng);
3361
3362 assert!(!init_mgr
3363 .links
3364 .get(&link_id)
3365 .unwrap()
3366 .outgoing_resources
3367 .is_empty());
3368
3369 init_mgr.handle_resource_rcl(&link_id);
3371
3372 init_mgr.tick(&mut rng);
3374
3375 assert!(
3376 init_mgr
3377 .links
3378 .get(&link_id)
3379 .unwrap()
3380 .outgoing_resources
3381 .is_empty(),
3382 "Tick should clean up completed/failed outgoing resources"
3383 );
3384 }
3385
3386 #[test]
3387 fn test_build_link_packet() {
3388 let (init_mgr, _resp_mgr, link_id) = setup_active_link();
3389
3390 let actions =
3391 init_mgr.build_link_packet(&link_id, constants::CONTEXT_RESOURCE, b"test data");
3392 assert_eq!(actions.len(), 1);
3393 if let LinkManagerAction::SendPacket { raw, dest_type, .. } = &actions[0] {
3394 let pkt = RawPacket::unpack(raw).unwrap();
3395 assert_eq!(pkt.context, constants::CONTEXT_RESOURCE);
3396 assert_eq!(*dest_type, constants::DESTINATION_LINK);
3397 } else {
3398 panic!("Expected SendPacket");
3399 }
3400 }
3401
3402 #[test]
3407 fn test_channel_message_delivery() {
3408 let (mut init_mgr, mut resp_mgr, link_id) = setup_active_link();
3409 let mut rng = OsRng;
3410
3411 let chan_actions = init_mgr
3413 .send_channel_message(&link_id, 42, b"channel data", &mut rng)
3414 .expect("active link channel send should succeed");
3415 assert!(!chan_actions.is_empty());
3416
3417 let mut got_channel_msg = false;
3419 for action in &chan_actions {
3420 if let LinkManagerAction::SendPacket { raw, .. } = action {
3421 let pkt = RawPacket::unpack(raw).unwrap();
3422 let resp_actions = resp_mgr.handle_local_delivery(
3423 pkt.destination_hash,
3424 raw,
3425 pkt.packet_hash,
3426 rns_core::transport::types::InterfaceId(0),
3427 &mut rng,
3428 );
3429 for a in &resp_actions {
3430 if let LinkManagerAction::ChannelMessageReceived {
3431 msgtype, payload, ..
3432 } = a
3433 {
3434 assert_eq!(*msgtype, 42);
3435 assert_eq!(*payload, b"channel data");
3436 got_channel_msg = true;
3437 }
3438 }
3439 }
3440 }
3441 assert!(got_channel_msg, "Responder should receive channel message");
3442 }
3443
3444 #[test]
3445 fn test_channel_proof_reopens_send_window() {
3446 let (mut init_mgr, _resp_mgr, link_id) = setup_active_link();
3447 let mut rng = OsRng;
3448
3449 init_mgr
3450 .send_channel_message(&link_id, 42, b"first", &mut rng)
3451 .expect("first send should succeed");
3452 init_mgr
3453 .send_channel_message(&link_id, 42, b"second", &mut rng)
3454 .expect("second send should succeed");
3455
3456 let err = init_mgr
3457 .send_channel_message(&link_id, 42, b"third", &mut rng)
3458 .expect_err("third send should hit the initial channel window");
3459 assert_eq!(err, "Channel is not ready to send");
3460
3461 let queued_packets = init_mgr
3462 .links
3463 .get(&link_id)
3464 .unwrap()
3465 .pending_channel_packets
3466 .clone();
3467 assert_eq!(queued_packets.len(), 2);
3468 for tracked_hash in queued_packets.keys().take(1) {
3469 let mut proof_data = Vec::with_capacity(96);
3470 proof_data.extend_from_slice(tracked_hash);
3471 proof_data.extend_from_slice(&[0x11; 64]);
3472 let flags = PacketFlags {
3473 header_type: constants::HEADER_1,
3474 context_flag: constants::FLAG_UNSET,
3475 transport_type: constants::TRANSPORT_BROADCAST,
3476 destination_type: constants::DESTINATION_LINK,
3477 packet_type: constants::PACKET_TYPE_PROOF,
3478 };
3479 let proof = RawPacket::pack(
3480 flags,
3481 0,
3482 &link_id,
3483 None,
3484 constants::CONTEXT_NONE,
3485 &proof_data,
3486 )
3487 .expect("proof packet should pack");
3488 let ack_actions = init_mgr.handle_local_delivery(
3489 link_id,
3490 &proof.raw,
3491 proof.packet_hash,
3492 rns_core::transport::types::InterfaceId(0),
3493 &mut rng,
3494 );
3495 assert!(
3496 ack_actions.is_empty(),
3497 "proof delivery should only update channel state"
3498 );
3499 }
3500
3501 init_mgr
3502 .send_channel_message(&link_id, 42, b"third", &mut rng)
3503 .expect("proof should free one channel slot");
3504 }
3505
3506 #[test]
3507 fn test_generic_link_data_delivery() {
3508 let (init_mgr, mut resp_mgr, link_id) = setup_active_link();
3509 let mut rng = OsRng;
3510
3511 let actions = init_mgr.send_on_link(&link_id, b"raw stuff", 0x42, &mut rng);
3513 assert_eq!(actions.len(), 1);
3514
3515 let raw = extract_any_send_packet(&actions);
3517 let pkt = RawPacket::unpack(&raw).unwrap();
3518 let resp_actions = resp_mgr.handle_local_delivery(
3519 pkt.destination_hash,
3520 &raw,
3521 pkt.packet_hash,
3522 rns_core::transport::types::InterfaceId(0),
3523 &mut rng,
3524 );
3525
3526 let has_data = resp_actions
3527 .iter()
3528 .any(|a| matches!(a, LinkManagerAction::LinkDataReceived { context: 0x42, .. }));
3529 assert!(
3530 has_data,
3531 "Responder should receive LinkDataReceived for unknown context"
3532 );
3533 }
3534
3535 #[test]
3536 fn test_response_delivery() {
3537 let (mut init_mgr, mut resp_mgr, link_id) = setup_active_link();
3538 let mut rng = OsRng;
3539
3540 resp_mgr.register_request_handler("/echo", None, |_link_id, _path, data, _remote| {
3542 Some(data.to_vec())
3543 });
3544
3545 let req_actions = init_mgr.send_request(&link_id, "/echo", b"\xc0", &mut rng); assert!(!req_actions.is_empty());
3548
3549 let req_raw = extract_any_send_packet(&req_actions);
3551 let req_pkt = RawPacket::unpack(&req_raw).unwrap();
3552 let resp_actions = resp_mgr.handle_local_delivery(
3553 req_pkt.destination_hash,
3554 &req_raw,
3555 req_pkt.packet_hash,
3556 rns_core::transport::types::InterfaceId(0),
3557 &mut rng,
3558 );
3559 let has_resp_send = resp_actions
3560 .iter()
3561 .any(|a| matches!(a, LinkManagerAction::SendPacket { .. }));
3562 assert!(has_resp_send, "Handler should produce response");
3563
3564 let resp_raw = extract_any_send_packet(&resp_actions);
3566 let resp_pkt = RawPacket::unpack(&resp_raw).unwrap();
3567 let init_actions = init_mgr.handle_local_delivery(
3568 resp_pkt.destination_hash,
3569 &resp_raw,
3570 resp_pkt.packet_hash,
3571 rns_core::transport::types::InterfaceId(0),
3572 &mut rng,
3573 );
3574
3575 let has_response_received = init_actions
3576 .iter()
3577 .any(|a| matches!(a, LinkManagerAction::ResponseReceived { .. }));
3578 assert!(
3579 has_response_received,
3580 "Initiator should receive ResponseReceived"
3581 );
3582 }
3583
3584 #[test]
3585 fn test_send_channel_message_on_no_channel() {
3586 let mut mgr = LinkManager::new();
3587 let mut rng = OsRng;
3588 let dummy_sig = [0xAA; 32];
3589 let (link_id, _) =
3590 mgr.create_link(&[0x11; 16], &dummy_sig, 1, constants::MTU as u32, &mut rng);
3591
3592 let err = mgr
3594 .send_channel_message(&link_id, 1, b"test", &mut rng)
3595 .expect_err("pending link should reject channel send");
3596 assert_eq!(err, "link has no active channel");
3597 }
3598
3599 #[test]
3600 fn test_send_on_link_requires_active() {
3601 let mut mgr = LinkManager::new();
3602 let mut rng = OsRng;
3603 let dummy_sig = [0xAA; 32];
3604 let (link_id, _) =
3605 mgr.create_link(&[0x11; 16], &dummy_sig, 1, constants::MTU as u32, &mut rng);
3606
3607 let actions = mgr.send_on_link(&link_id, b"test", constants::CONTEXT_NONE, &mut rng);
3608 assert!(actions.is_empty(), "Cannot send on pending link");
3609 }
3610
3611 #[test]
3612 fn test_send_on_link_unknown_link() {
3613 let mgr = LinkManager::new();
3614 let mut rng = OsRng;
3615
3616 let actions = mgr.send_on_link(&[0xFF; 16], b"test", constants::CONTEXT_NONE, &mut rng);
3617 assert!(actions.is_empty());
3618 }
3619
3620 #[test]
3621 fn test_resource_full_transfer_large() {
3622 let (mut init_mgr, mut resp_mgr, link_id) = setup_active_link();
3623 let mut rng = OsRng;
3624
3625 resp_mgr.set_resource_strategy(&link_id, ResourceStrategy::AcceptAll);
3626
3627 let original_data: Vec<u8> = (0..2000u32)
3629 .map(|i| {
3630 let pos = i as usize;
3631 (pos ^ (pos >> 8) ^ (pos >> 16)) as u8
3632 })
3633 .collect();
3634
3635 let adv_actions = init_mgr.send_resource(&link_id, &original_data, None, &mut rng);
3636
3637 let mut pending: Vec<(char, LinkManagerAction)> =
3638 adv_actions.into_iter().map(|a| ('i', a)).collect();
3639 let mut rounds = 0;
3640 let max_rounds = 200;
3641 let mut resource_received = false;
3642 let mut sender_completed = false;
3643
3644 while !pending.is_empty() && rounds < max_rounds {
3645 rounds += 1;
3646 let mut next: Vec<(char, LinkManagerAction)> = Vec::new();
3647
3648 for (source, action) in pending.drain(..) {
3649 if let LinkManagerAction::SendPacket { raw, .. } = action {
3650 let pkt = match RawPacket::unpack(&raw) {
3651 Ok(p) => p,
3652 Err(_) => continue,
3653 };
3654
3655 let target_actions = if source == 'i' {
3656 resp_mgr.handle_local_delivery(
3657 pkt.destination_hash,
3658 &raw,
3659 pkt.packet_hash,
3660 rns_core::transport::types::InterfaceId(0),
3661 &mut rng,
3662 )
3663 } else {
3664 init_mgr.handle_local_delivery(
3665 pkt.destination_hash,
3666 &raw,
3667 pkt.packet_hash,
3668 rns_core::transport::types::InterfaceId(0),
3669 &mut rng,
3670 )
3671 };
3672
3673 let target_source = if source == 'i' { 'r' } else { 'i' };
3674 for a in &target_actions {
3675 match a {
3676 LinkManagerAction::ResourceReceived { data, .. } => {
3677 assert_eq!(*data, original_data);
3678 resource_received = true;
3679 }
3680 LinkManagerAction::ResourceCompleted { .. } => {
3681 sender_completed = true;
3682 }
3683 _ => {}
3684 }
3685 }
3686 next.extend(target_actions.into_iter().map(|a| (target_source, a)));
3687 }
3688 }
3689 pending = next;
3690 }
3691
3692 assert!(
3693 resource_received,
3694 "Should receive large resource (rounds={})",
3695 rounds
3696 );
3697 assert!(
3698 sender_completed,
3699 "Sender should complete (rounds={})",
3700 rounds
3701 );
3702 }
3703
3704 #[test]
3705 fn test_process_resource_actions_mapping() {
3706 let (init_mgr, _resp_mgr, link_id) = setup_active_link();
3707 let mut rng = OsRng;
3708
3709 let actions = vec![
3711 ResourceAction::DataReceived {
3712 data: vec![1, 2, 3],
3713 metadata: Some(vec![4, 5]),
3714 },
3715 ResourceAction::Completed,
3716 ResourceAction::Failed(rns_core::resource::ResourceError::Timeout),
3717 ResourceAction::ProgressUpdate {
3718 received: 10,
3719 total: 20,
3720 },
3721 ];
3722
3723 let result = init_mgr.process_resource_actions(&link_id, actions, &mut rng);
3724
3725 assert!(matches!(
3726 result[0],
3727 LinkManagerAction::ResourceReceived { .. }
3728 ));
3729 assert!(matches!(
3730 result[1],
3731 LinkManagerAction::ResourceCompleted { .. }
3732 ));
3733 assert!(matches!(
3734 result[2],
3735 LinkManagerAction::ResourceFailed { .. }
3736 ));
3737 assert!(matches!(
3738 result[3],
3739 LinkManagerAction::ResourceProgress {
3740 received: 10,
3741 total: 20,
3742 ..
3743 }
3744 ));
3745 }
3746
3747 #[test]
3748 fn test_link_state_empty() {
3749 let mgr = LinkManager::new();
3750 let fake_id = [0xAA; 16];
3751 assert!(mgr.link_state(&fake_id).is_none());
3752 }
3753}