1use std::collections::HashMap;
10use std::fs::File;
11use std::io::{Read, Write};
12use std::path::PathBuf;
13
14use super::compressor::Bzip2Compressor;
15use rns_core::channel::{Channel, Sequence};
16use rns_core::constants;
17use rns_core::link::types::{LinkId, LinkState, TeardownReason};
18use rns_core::link::{LinkAction, LinkEngine, LinkMode};
19use rns_core::packet::{PacketFlags, RawPacket};
20use rns_core::resource::{ResourceAction, ResourceReceiver, ResourceSender};
21use rns_crypto::ed25519::Ed25519PrivateKey;
22use rns_crypto::{OsRng, Rng};
23
24use super::time;
25
26mod channel_handling;
27mod receive_worker;
28mod request_handling;
29mod resource_handling;
30mod state;
31
32use crate::resource::{
33 ReceivedResourceFile, ResourceReceiveMode, ResourceTransferError, ResourceTransferId,
34};
35use resource_handling::ResourceSendParams;
36use state::*;
37
38const MAX_PRE_RTT_PACKETS: usize = 8;
40const MAX_PRE_RTT_BYTES: usize = 64 * 1024;
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
44pub enum ResourceStrategy {
45 #[default]
47 AcceptNone,
48 AcceptAll,
50 AcceptApp,
52}
53
54struct IncomingSplitTransfer {
55 total_segments: u64,
56 completed_segments: u64,
57 current_segment_index: u64,
58 current_received_parts: usize,
59 current_total_parts: usize,
60 storage: IncomingSplitStorage,
61 metadata: Option<Vec<u8>>,
62 is_request: bool,
63 is_response: bool,
64}
65
66enum IncomingSplitStorage {
67 Memory(Vec<u8>),
68 File {
69 file: File,
70 path: PathBuf,
71 size: u64,
72 },
73}
74
75struct OutgoingSplitTransfer {
76 total_segments: u64,
77 completed_segments: u64,
78 current_segment_index: u64,
79 current_sent_parts: usize,
80 current_total_parts: usize,
81}
82
83struct OutgoingStreamTransfer {
84 transfer_id: ResourceTransferId,
85 reader: Box<dyn Read + Send>,
86 remaining: u64,
87 declared_length: u64,
88 metadata_overhead: u64,
89 auto_compress: bool,
90}
91
92#[derive(Debug, Clone, PartialEq, Eq)]
94pub enum RequestResponse {
95 Bytes(Vec<u8>),
97 Resource {
99 data: Vec<u8>,
100 metadata: Option<Vec<u8>>,
101 auto_compress: bool,
102 },
103 File {
106 data: Vec<u8>,
107 metadata: Vec<u8>,
108 auto_compress: bool,
109 },
110}
111
112#[derive(Debug, Clone, Copy, PartialEq, Eq)]
114pub enum RequestFailure {
115 ResponseTooLarge { size: u64, maximum: usize },
117}
118
119impl From<Vec<u8>> for RequestResponse {
120 fn from(data: Vec<u8>) -> Self {
121 RequestResponse::Bytes(data)
122 }
123}
124
125#[derive(Debug)]
127pub enum LinkManagerAction {
128 SendPacket {
130 raw: Vec<u8>,
131 dest_type: u8,
132 attached_interface: Option<rns_core::transport::types::InterfaceId>,
133 },
134 LinkEstablished {
136 link_id: LinkId,
137 dest_hash: [u8; 16],
138 hops: u8,
139 rebalanced_at: Option<f64>,
140 rtt: f64,
141 is_initiator: bool,
142 },
143 LinkClosed {
145 link_id: LinkId,
146 reason: Option<TeardownReason>,
147 },
148 RemoteIdentified {
150 link_id: LinkId,
151 identity_hash: [u8; 16],
152 public_key: [u8; 64],
153 },
154 RegisterLinkDest { link_id: LinkId },
156 DeregisterLinkDest { link_id: LinkId },
158 ManagementRequest {
161 link_id: LinkId,
162 path_hash: [u8; 16],
163 data: Vec<u8>,
165 request_id: [u8; 16],
167 remote_identity: Option<([u8; 16], [u8; 64])>,
168 },
169 ResourceReceived {
171 link_id: LinkId,
172 data: Vec<u8>,
173 metadata: Option<Vec<u8>>,
174 },
175 ResourceFileReceived {
177 link_id: LinkId,
178 resource: ReceivedResourceFile,
179 },
180 ResourceCompleted { link_id: LinkId },
182 ResourceFailed { link_id: LinkId, error: String },
184 ResourceProgress {
186 link_id: LinkId,
187 received: usize,
188 total: usize,
189 },
190 ResourceStreamCompleted {
191 link_id: LinkId,
192 transfer_id: ResourceTransferId,
193 },
194 ResourceStreamFailed {
195 link_id: LinkId,
196 transfer_id: ResourceTransferId,
197 error: ResourceTransferError,
198 },
199 ResourceStreamProgress {
200 link_id: LinkId,
201 transfer_id: ResourceTransferId,
202 transferred: u64,
203 total: u64,
204 },
205 ResourceAcceptQuery {
207 link_id: LinkId,
208 resource_hash: Vec<u8>,
209 transfer_size: u64,
210 has_metadata: bool,
211 },
212 ChannelMessageReceived {
214 link_id: LinkId,
215 msgtype: u16,
216 payload: Vec<u8>,
217 },
218 LinkDataReceived {
220 link_id: LinkId,
221 context: u8,
222 data: Vec<u8>,
223 },
224 ResponseReceived {
226 link_id: LinkId,
227 request_id: [u8; 16],
228 data: Vec<u8>,
229 metadata: Option<Vec<u8>>,
230 },
231 RequestFailed {
233 link_id: LinkId,
234 request_id: [u8; 16],
235 reason: RequestFailure,
236 },
237 LinkRequestReceived {
239 link_id: LinkId,
240 receiving_interface: rns_core::transport::types::InterfaceId,
241 },
242 ProtocolViolation {
244 receiving_interface: rns_core::transport::types::InterfaceId,
245 },
246}
247
248pub struct LinkManager {
250 receive_worker: Option<receive_worker::Worker>,
251 receive_worker_wake: Option<crate::event::EventSender>,
252 links: HashMap<LinkId, ManagedLink>,
256 link_destinations: HashMap<[u8; 16], LinkDestination>,
257 request_handlers: Vec<RequestHandlerEntry>,
258 deferred_request_handlers: Vec<DeferredRequestHandlerEntry>,
259 management_paths: Vec<[u8; 16]>,
262 link_mtu_discovery: bool,
263}
264
265#[derive(Debug, Clone, Copy, PartialEq, Eq)]
266pub struct LinkRouteHint {
267 pub interface: rns_core::transport::types::InterfaceId,
268 pub transport_id: Option<[u8; 16]>,
269}
270
271impl LinkManager {
272 fn resource_sdu_for_link(link: &ManagedLink) -> usize {
273 let mtu = link.engine.mtu() as usize;
276 let derived = mtu.saturating_sub(constants::HEADER_MAXSIZE + constants::IFAC_MIN_SIZE);
277 if derived > 0 {
278 derived
279 } else {
280 constants::RESOURCE_SDU
281 }
282 }
283
284 fn split_progress_parts(
285 segment_index: u64,
286 total_segments: u64,
287 current_done: usize,
288 current_total: usize,
289 sdu: usize,
290 ) -> (usize, usize) {
291 let max_parts_per_segment = constants::RESOURCE_MAX_EFFICIENT_SIZE.div_ceil(sdu.max(1));
292 let total = (total_segments as usize).saturating_mul(max_parts_per_segment);
293 let completed_segments = segment_index.saturating_sub(1) as usize;
294 let completed = completed_segments.saturating_mul(max_parts_per_segment);
295 let current = if current_total == 0 {
296 0
297 } else if current_total < max_parts_per_segment {
298 let scaled =
299 (current_done as f64) * (max_parts_per_segment as f64 / current_total as f64);
300 scaled.floor() as usize
301 } else {
302 current_done
303 };
304 (completed.saturating_add(current).min(total), total)
305 }
306
307 fn resource_hash_key(hash: &[u8]) -> Option<[u8; 32]> {
308 let mut key = [0u8; 32];
309 if hash.len() != key.len() {
310 return None;
311 }
312 key.copy_from_slice(hash);
313 Some(key)
314 }
315
316 fn incoming_storage(
317 mode: &ResourceReceiveMode,
318 original_hash: &[u8; 32],
319 ) -> std::io::Result<IncomingSplitStorage> {
320 match mode {
321 ResourceReceiveMode::Memory { .. } => Ok(IncomingSplitStorage::Memory(Vec::new())),
322 ResourceReceiveMode::TemporaryFile { directory, .. } => {
323 let (file, path) = crate::resource::create_receive_file(directory, original_hash)?;
324 Ok(IncomingSplitStorage::File {
325 file,
326 path,
327 size: 0,
328 })
329 }
330 }
331 }
332
333 fn incoming_split_progress(split: &IncomingSplitTransfer, sdu: usize) -> (usize, usize) {
334 Self::split_progress_parts(
335 split.current_segment_index,
336 split.total_segments,
337 split.current_received_parts,
338 split.current_total_parts,
339 sdu,
340 )
341 }
342
343 fn outgoing_split_progress(split: &OutgoingSplitTransfer, sdu: usize) -> (usize, usize) {
344 Self::split_progress_parts(
345 split.current_segment_index,
346 split.total_segments,
347 split.current_sent_parts,
348 split.current_total_parts,
349 sdu,
350 )
351 }
352
353 pub fn new() -> Self {
355 LinkManager {
356 receive_worker: None,
357 receive_worker_wake: None,
358 links: HashMap::new(),
359 link_destinations: HashMap::new(),
360 request_handlers: Vec::new(),
361 deferred_request_handlers: Vec::new(),
362 management_paths: Vec::new(),
363 link_mtu_discovery: true,
364 }
365 }
366
367 pub(crate) fn set_link_mtu_discovery(&mut self, enabled: bool) {
368 self.link_mtu_discovery = enabled;
369 }
370
371 pub fn register_management_path(&mut self, path_hash: [u8; 16]) {
375 if !self.management_paths.contains(&path_hash) {
376 self.management_paths.push(path_hash);
377 }
378 }
379
380 pub(crate) fn resource_generation(&self, id: &LinkId) -> Option<std::sync::Arc<()>> {
381 self.links
382 .get(id)
383 .filter(|link| link.engine.state() == LinkState::Active)
384 .map(|link| link.resource_generation.clone())
385 }
386
387 pub fn get_derived_key(&self, link_id: &LinkId) -> Option<Vec<u8>> {
389 self.links
390 .get(link_id)
391 .and_then(|link| link.engine.derived_key().map(|dk| dk.to_vec()))
392 }
393
394 pub fn remote_identity_hash(&self, link_id: &LinkId) -> Option<[u8; 16]> {
396 self.links
397 .get(link_id)
398 .and_then(|link| link.remote_identity.as_ref().map(|(hash, _)| *hash))
399 }
400
401 pub fn get_link_route_hint(&self, link_id: &LinkId) -> Option<LinkRouteHint> {
403 self.links.get(link_id).and_then(|link| {
404 link.route_interface.map(|interface| LinkRouteHint {
405 interface,
406 transport_id: link.route_transport_id,
407 })
408 })
409 }
410
411 pub fn set_link_route_hint(
413 &mut self,
414 link_id: &LinkId,
415 interface: rns_core::transport::types::InterfaceId,
416 transport_id: Option<[u8; 16]>,
417 ) -> bool {
418 let Some(link) = self.links.get_mut(link_id) else {
419 return false;
420 };
421 link.route_interface = Some(interface);
422 link.route_transport_id = transport_id;
423 true
424 }
425
426 pub fn register_link_destination(
428 &mut self,
429 dest_hash: [u8; 16],
430 sig_prv: Ed25519PrivateKey,
431 sig_pub_bytes: [u8; 32],
432 resource_strategy: ResourceStrategy,
433 ) {
434 self.link_destinations.insert(
435 dest_hash,
436 LinkDestination {
437 sig_prv,
438 sig_pub_bytes,
439 resource_strategy,
440 max_request_size: None,
441 },
442 );
443 }
444
445 pub fn set_link_destination_max_request_size(
450 &mut self,
451 dest_hash: &[u8; 16],
452 max_request_size: Option<usize>,
453 ) -> bool {
454 let Some(destination) = self.link_destinations.get_mut(dest_hash) else {
455 return false;
456 };
457 destination.max_request_size = max_request_size;
458 for link in self.links.values_mut() {
459 if link.dest_hash == *dest_hash && link.dest_sig_pub_bytes.is_none() {
460 link.max_request_size = max_request_size;
461 }
462 }
463 true
464 }
465
466 pub fn deregister_link_destination(&mut self, dest_hash: &[u8; 16]) {
468 self.link_destinations.remove(dest_hash);
469 }
470
471 pub fn register_request_handler<F>(
477 &mut self,
478 path: &str,
479 allowed_list: Option<Vec<[u8; 16]>>,
480 handler: F,
481 ) where
482 F: Fn(LinkId, &str, &[u8], Option<&([u8; 16], [u8; 64])>) -> Option<Vec<u8>>
483 + Send
484 + 'static,
485 {
486 let path_hash = compute_path_hash(path);
487 self.request_handlers.push(RequestHandlerEntry {
488 path: path.to_string(),
489 path_hash,
490 allowed_list,
491 handler: Box::new(move |link_id, p, data, remote| {
492 handler(link_id, p, data, remote).map(RequestResponse::Bytes)
493 }),
494 });
495 }
496
497 pub fn register_request_handler_response<F>(
499 &mut self,
500 path: &str,
501 allowed_list: Option<Vec<[u8; 16]>>,
502 handler: F,
503 ) where
504 F: Fn(LinkId, &str, &[u8], Option<&([u8; 16], [u8; 64])>) -> Option<RequestResponse>
505 + Send
506 + 'static,
507 {
508 let path_hash = compute_path_hash(path);
509 self.request_handlers.push(RequestHandlerEntry {
510 path: path.to_string(),
511 path_hash,
512 allowed_list,
513 handler: Box::new(handler),
514 });
515 }
516
517 pub fn register_deferred_request_handler<F>(
519 &mut self,
520 path: &str,
521 allowed_list: Option<Vec<[u8; 16]>>,
522 handler: F,
523 ) where
524 F: Fn(LinkId, &str, [u8; 16], &[u8], Option<&([u8; 16], [u8; 64])>) + Send + 'static,
525 {
526 self.deferred_request_handlers
527 .push(DeferredRequestHandlerEntry {
528 path: path.to_string(),
529 path_hash: compute_path_hash(path),
530 allowed_list,
531 handler: Box::new(handler),
532 });
533 }
534
535 pub fn create_link(
543 &mut self,
544 dest_hash: &[u8; 16],
545 dest_sig_pub_bytes: &[u8; 32],
546 hops: u8,
547 mtu: u32,
548 rng: &mut dyn Rng,
549 ) -> (LinkId, Vec<LinkManagerAction>) {
550 let mode = LinkMode::Aes256Cbc;
551 let signalled_mtu = self.link_mtu_discovery.then_some(mtu);
552 let (mut engine, request_data) =
553 LinkEngine::new_initiator(dest_hash, hops, mode, signalled_mtu, time::now(), rng);
554
555 let flags = PacketFlags {
557 header_type: constants::HEADER_1,
558 context_flag: constants::FLAG_UNSET,
559 transport_type: constants::TRANSPORT_BROADCAST,
560 destination_type: constants::DESTINATION_SINGLE,
561 packet_type: constants::PACKET_TYPE_LINKREQUEST,
562 };
563
564 let packet = match RawPacket::pack(
565 flags,
566 0,
567 dest_hash,
568 None,
569 constants::CONTEXT_NONE,
570 &request_data,
571 ) {
572 Ok(p) => p,
573 Err(_) => {
574 return ([0u8; 16], Vec::new());
576 }
577 };
578
579 engine.set_link_id_from_hashable(&packet.get_hashable_part(), request_data.len());
580 let link_id = *engine.link_id();
581
582 engine.record_outbound_traffic(packet.data().len());
583 let managed = ManagedLink {
584 resource_generation: std::sync::Arc::new(()),
585 engine,
586 channel: None,
587 pre_rtt_packets: Vec::new(),
588 pending_channel_packets: HashMap::new(),
589 channel_send_ok: 0,
590 channel_send_not_ready: 0,
591 channel_send_too_big: 0,
592 channel_send_other_error: 0,
593 channel_messages_received: 0,
594 channel_proofs_sent: 0,
595 channel_proofs_received: 0,
596 dest_hash: *dest_hash,
597 remote_identity: None,
598 dest_sig_pub_bytes: Some(*dest_sig_pub_bytes),
599 incoming_resources: Vec::new(),
600 outgoing_resources: Vec::new(),
601 pending_requests: HashMap::new(),
602 incoming_splits: HashMap::new(),
603 outgoing_splits: HashMap::new(),
604 outgoing_streams: HashMap::new(),
605 resource_strategy: ResourceStrategy::default(),
606 resource_receive_mode: ResourceReceiveMode::default(),
607 max_request_size: None,
608 route_interface: None,
609 route_transport_id: None,
610 };
611 self.links.insert(link_id, managed);
612
613 let actions = vec![
614 LinkManagerAction::RegisterLinkDest { link_id },
616 LinkManagerAction::SendPacket {
618 raw: packet.raw,
619 dest_type: constants::DESTINATION_LINK,
620 attached_interface: None,
621 },
622 ];
623
624 (link_id, actions)
625 }
626
627 pub fn handle_local_delivery(
633 &mut self,
634 dest_hash: [u8; 16],
635 raw: &[u8],
636 packet_hash: [u8; 32],
637 receiving_interface: rns_core::transport::types::InterfaceId,
638 rng: &mut dyn Rng,
639 ) -> Vec<LinkManagerAction> {
640 let packet = match RawPacket::unpack(raw) {
641 Ok(p) => p,
642 Err(_) => return Vec::new(),
643 };
644
645 if packet.flags.packet_type != constants::PACKET_TYPE_LINKREQUEST {
648 if let Some(link) = self.links.get_mut(&dest_hash) {
649 link.engine.record_inbound_traffic(packet.data().len());
650 }
651 }
652
653 match packet.flags.packet_type {
654 constants::PACKET_TYPE_LINKREQUEST => {
655 self.handle_linkrequest(&dest_hash, &packet, receiving_interface, rng)
656 }
657 constants::PACKET_TYPE_PROOF if packet.context == constants::CONTEXT_LRPROOF => {
658 self.handle_lrproof(&dest_hash, &packet, receiving_interface, rng)
660 }
661 constants::PACKET_TYPE_PROOF if packet.context == constants::CONTEXT_RESOURCE_PRF => {
662 self.handle_resource_prf(&dest_hash, packet.data(), rng)
665 }
666 constants::PACKET_TYPE_PROOF => self.handle_link_proof(&dest_hash, &packet, rng),
667 constants::PACKET_TYPE_DATA => {
668 self.handle_link_data(&dest_hash, &packet, packet_hash, receiving_interface, rng)
669 }
670 _ => Vec::new(),
671 }
672 }
673
674 fn handle_linkrequest(
676 &mut self,
677 dest_hash: &[u8; 16],
678 packet: &RawPacket,
679 receiving_interface: rns_core::transport::types::InterfaceId,
680 rng: &mut dyn Rng,
681 ) -> Vec<LinkManagerAction> {
682 let ld = match self.link_destinations.get(dest_hash) {
684 Some(ld) => ld,
685 None => return Vec::new(),
686 };
687
688 let hashable = packet.get_hashable_part();
689 let now = time::now();
690
691 let (engine, lrproof_data) = match LinkEngine::new_responder(
693 &ld.sig_prv,
694 &ld.sig_pub_bytes,
695 packet.data(),
696 &hashable,
697 dest_hash,
698 packet.hops,
699 now,
700 rng,
701 ) {
702 Ok(r) => r,
703 Err(e) => {
704 log::debug!("LINKREQUEST rejected: {}", e);
705 return vec![LinkManagerAction::ProtocolViolation {
706 receiving_interface,
707 }];
708 }
709 };
710
711 let link_id = *engine.link_id();
712 log::debug!(
713 "LINKREQUEST accepted: link={:02x?} iface={} header_type={} transport_id_present={} hops={}",
714 &link_id[..4],
715 receiving_interface.0,
716 packet.flags.header_type,
717 packet.transport_id.is_some(),
718 packet.hops
719 );
720
721 let managed = ManagedLink {
722 resource_generation: std::sync::Arc::new(()),
723 engine,
724 channel: None,
725 pre_rtt_packets: Vec::new(),
726 pending_channel_packets: HashMap::new(),
727 channel_send_ok: 0,
728 channel_send_not_ready: 0,
729 channel_send_too_big: 0,
730 channel_send_other_error: 0,
731 channel_messages_received: 0,
732 channel_proofs_sent: 0,
733 channel_proofs_received: 0,
734 dest_hash: *dest_hash,
735 remote_identity: None,
736 dest_sig_pub_bytes: None,
737 incoming_resources: Vec::new(),
738 outgoing_resources: Vec::new(),
739 pending_requests: HashMap::new(),
740 incoming_splits: HashMap::new(),
741 outgoing_splits: HashMap::new(),
742 outgoing_streams: HashMap::new(),
743 resource_strategy: ld.resource_strategy,
744 resource_receive_mode: ResourceReceiveMode::default(),
745 max_request_size: ld.max_request_size,
746 route_interface: Some(receiving_interface),
747 route_transport_id: if packet.flags.header_type == constants::HEADER_2 {
748 packet.transport_id
749 } else {
750 None
751 },
752 };
753 self.links.insert(link_id, managed);
754
755 let flags = PacketFlags {
757 header_type: constants::HEADER_1,
758 context_flag: constants::FLAG_UNSET,
759 transport_type: constants::TRANSPORT_BROADCAST,
760 destination_type: constants::DESTINATION_LINK,
761 packet_type: constants::PACKET_TYPE_PROOF,
762 };
763
764 let mut actions = Vec::new();
765
766 actions.push(LinkManagerAction::RegisterLinkDest { link_id });
768
769 if let Ok((raw, _packet_hash)) = RawPacket::pack_raw_with_hash(
770 flags,
771 0,
772 &link_id,
773 None,
774 constants::CONTEXT_LRPROOF,
775 &lrproof_data,
776 ) {
777 log::debug!(
778 "LRPROOF queued: link={:02x?} route_iface={} route_tid_present={} hops=0",
779 &link_id[..4],
780 receiving_interface.0,
781 packet.transport_id.is_some()
782 );
783 actions.push(LinkManagerAction::SendPacket {
784 raw,
785 dest_type: constants::DESTINATION_LINK,
786 attached_interface: None,
787 });
788 }
789
790 actions.push(LinkManagerAction::LinkRequestReceived {
792 link_id,
793 receiving_interface,
794 });
795
796 actions
797 }
798
799 fn handle_link_proof(
800 &mut self,
801 link_id: &LinkId,
802 packet: &RawPacket,
803 rng: &mut dyn Rng,
804 ) -> Vec<LinkManagerAction> {
805 if packet.data().len() != 96 {
806 return Vec::new();
807 }
808
809 let mut tracked_hash = [0u8; 32];
810 tracked_hash.copy_from_slice(&packet.data()[..32]);
811
812 let mut signature = [0u8; 64];
813 signature.copy_from_slice(&packet.data()[32..]);
814
815 let Some(link) = self.links.get_mut(link_id) else {
816 return Vec::new();
817 };
818 if !link.engine.validate_packet_proof(&tracked_hash, &signature) {
819 return Vec::new();
820 }
821 let Some(sequence) = link.pending_channel_packets.remove(&tracked_hash) else {
822 return Vec::new();
823 };
824 link.channel_proofs_received += 1;
825 let Some(channel) = link.channel.as_mut() else {
826 return Vec::new();
827 };
828
829 let chan_actions = channel.packet_delivered(sequence);
830 let _ = channel;
831 let _ = link;
832 self.process_channel_actions(link_id, chan_actions, rng)
833 }
834
835 fn build_link_packet_proof(
836 &mut self,
837 link_id: &LinkId,
838 packet_hash: &[u8; 32],
839 ) -> Vec<LinkManagerAction> {
840 let signature = match self.links.get_mut(link_id) {
841 Some(link) => {
842 link.channel_proofs_sent += 1;
843 link.engine.sign_packet_hash(packet_hash)
844 }
845 None => return Vec::new(),
846 };
847 let mut proof_data = Vec::with_capacity(96);
848 proof_data.extend_from_slice(packet_hash);
849 proof_data.extend_from_slice(&signature);
850
851 let flags = PacketFlags {
852 header_type: constants::HEADER_1,
853 context_flag: constants::FLAG_UNSET,
854 transport_type: constants::TRANSPORT_BROADCAST,
855 destination_type: constants::DESTINATION_LINK,
856 packet_type: constants::PACKET_TYPE_PROOF,
857 };
858 if let Ok((raw, _packet_hash)) = RawPacket::pack_raw_with_hash(
859 flags,
860 0,
861 link_id,
862 None,
863 constants::CONTEXT_NONE,
864 &proof_data,
865 ) {
866 vec![LinkManagerAction::SendPacket {
867 raw,
868 dest_type: constants::DESTINATION_LINK,
869 attached_interface: None,
870 }]
871 } else {
872 Vec::new()
873 }
874 }
875
876 fn handle_lrproof(
878 &mut self,
879 link_id_bytes: &[u8; 16],
880 packet: &RawPacket,
881 receiving_interface: rns_core::transport::types::InterfaceId,
882 rng: &mut dyn Rng,
883 ) -> Vec<LinkManagerAction> {
884 let link = match self.links.get_mut(link_id_bytes) {
885 Some(l) => l,
886 None => return Vec::new(),
887 };
888
889 link.route_interface = Some(receiving_interface);
890 if packet.flags.header_type == constants::HEADER_2 {
891 if let Some(transport_id) = packet.transport_id {
892 link.route_transport_id = Some(transport_id);
893 }
894 }
895 log::debug!(
896 "LRPROOF received: link={:02x?} iface={} header_type={} transport_id_present={}",
897 &link_id_bytes[..4],
898 receiving_interface.0,
899 packet.flags.header_type,
900 packet.transport_id.is_some()
901 );
902
903 if link.engine.state() != LinkState::Pending || !link.engine.is_initiator() {
904 return Vec::new();
905 }
906
907 let dest_sig_pub_bytes = match link.dest_sig_pub_bytes {
909 Some(b) => b,
910 None => {
911 log::debug!("LRPROOF: no destination signing key available");
912 return Vec::new();
913 }
914 };
915
916 let now = time::now();
917 let (lrrtt_encrypted, link_actions) = match link.engine.handle_lrproof_with_hops(
918 packet.data(),
919 &dest_sig_pub_bytes,
920 Some(packet.hops),
921 now,
922 rng,
923 ) {
924 Ok(r) => r,
925 Err(e) => {
926 log::debug!("LRPROOF validation failed: {}", e);
927 return Vec::new();
928 }
929 };
930
931 let link_id = *link.engine.link_id();
932 let mut actions = Vec::new();
933
934 actions.extend(self.process_link_actions(&link_id, &link_actions));
936
937 let flags = PacketFlags {
939 header_type: constants::HEADER_1,
940 context_flag: constants::FLAG_UNSET,
941 transport_type: constants::TRANSPORT_BROADCAST,
942 destination_type: constants::DESTINATION_LINK,
943 packet_type: constants::PACKET_TYPE_DATA,
944 };
945
946 if let Ok((raw, _packet_hash)) = RawPacket::pack_raw_with_hash(
947 flags,
948 0,
949 &link_id,
950 None,
951 constants::CONTEXT_LRRTT,
952 &lrrtt_encrypted,
953 ) {
954 actions.push(LinkManagerAction::SendPacket {
955 raw,
956 dest_type: constants::DESTINATION_LINK,
957 attached_interface: None,
958 });
959 }
960
961 if let Some(link) = self.links.get_mut(&link_id) {
963 if link.engine.state() == LinkState::Active {
964 let rtt = link.engine.rtt().unwrap_or(1.0);
965 link.channel = Some(Channel::new(rtt));
966 }
967 }
968
969 actions
970 }
971
972 fn handle_link_data(
978 &mut self,
979 link_id_bytes: &[u8; 16],
980 packet: &RawPacket,
981 packet_hash: [u8; 32],
982 receiving_interface: rns_core::transport::types::InterfaceId,
983 rng: &mut dyn Rng,
984 ) -> Vec<LinkManagerAction> {
985 enum LinkDataResult<'a> {
987 Lrrtt {
988 link_id: LinkId,
989 link_actions: Vec<LinkAction>,
990 },
991 Identify {
992 link_id: LinkId,
993 link_actions: Vec<LinkAction>,
994 },
995 Keepalive {
996 link_id: LinkId,
997 inbound_actions: Vec<LinkAction>,
998 reply: bool,
999 received_at: f64,
1000 },
1001 LinkClose {
1002 link_id: LinkId,
1003 teardown_actions: Vec<LinkAction>,
1004 },
1005 Channel {
1006 link_id: LinkId,
1007 inbound_actions: Vec<LinkAction>,
1008 plaintext: Vec<u8>,
1009 packet_hash: [u8; 32],
1010 },
1011 Request {
1012 link_id: LinkId,
1013 inbound_actions: Vec<LinkAction>,
1014 plaintext: Vec<u8>,
1015 request_id: [u8; 16],
1016 },
1017 Response {
1018 link_id: LinkId,
1019 inbound_actions: Vec<LinkAction>,
1020 plaintext: Vec<u8>,
1021 },
1022 Generic {
1023 link_id: LinkId,
1024 inbound_actions: Vec<LinkAction>,
1025 plaintext: Vec<u8>,
1026 context: u8,
1027 packet_hash: [u8; 32],
1028 },
1029 ResourceAdv {
1031 link_id: LinkId,
1032 inbound_actions: Vec<LinkAction>,
1033 plaintext: Vec<u8>,
1034 },
1035 ResourceReq {
1037 link_id: LinkId,
1038 inbound_actions: Vec<LinkAction>,
1039 plaintext: Vec<u8>,
1040 },
1041 ResourceHmu {
1043 link_id: LinkId,
1044 inbound_actions: Vec<LinkAction>,
1045 plaintext: Vec<u8>,
1046 },
1047 ResourcePart {
1049 link_id: LinkId,
1050 inbound_actions: Vec<LinkAction>,
1051 raw_data: &'a [u8],
1052 },
1053 ResourcePrf {
1055 link_id: LinkId,
1056 inbound_actions: Vec<LinkAction>,
1057 plaintext: Vec<u8>,
1058 },
1059 ResourceIcl {
1061 link_id: LinkId,
1062 inbound_actions: Vec<LinkAction>,
1063 resource_hash: Vec<u8>,
1064 },
1065 ResourceRcl {
1067 link_id: LinkId,
1068 inbound_actions: Vec<LinkAction>,
1069 resource_hash: Vec<u8>,
1070 },
1071 Error,
1072 }
1073
1074 let result = {
1075 let link = match self.links.get_mut(link_id_bytes) {
1076 Some(l) => l,
1077 None => return Vec::new(),
1078 };
1079
1080 if !link.engine.is_initiator()
1084 && link.engine.state() == LinkState::Handshake
1085 && matches!(
1086 packet.context,
1087 constants::CONTEXT_LINKIDENTIFY | constants::CONTEXT_REQUEST
1088 )
1089 {
1090 let packet_bytes = packet.raw.len() + packet.data().len();
1091 let queued_bytes: usize = link
1092 .pre_rtt_packets
1093 .iter()
1094 .map(|pending| pending.packet.raw.len() + pending.packet.data().len())
1095 .sum();
1096 if link.pre_rtt_packets.len() < MAX_PRE_RTT_PACKETS
1097 && packet_bytes <= MAX_PRE_RTT_BYTES.saturating_sub(queued_bytes)
1098 && link.engine.decrypt(packet.data()).is_ok()
1099 {
1100 link.pre_rtt_packets.push(PreRttPacket {
1101 packet: packet.clone(),
1102 packet_hash,
1103 receiving_interface,
1104 });
1105 }
1106 return Vec::new();
1107 }
1108
1109 link.route_interface = Some(receiving_interface);
1110 if packet.flags.header_type == constants::HEADER_2 {
1111 if let Some(transport_id) = packet.transport_id {
1112 link.route_transport_id = Some(transport_id);
1113 }
1114 } else {
1115 link.route_transport_id = None;
1116 }
1117
1118 match packet.context {
1119 constants::CONTEXT_LRRTT => {
1120 match link.engine.handle_lrrtt_with_hops(
1121 packet.data(),
1122 Some(packet.hops),
1123 time::now(),
1124 ) {
1125 Ok(link_actions) => {
1126 let link_id = *link.engine.link_id();
1127 LinkDataResult::Lrrtt {
1128 link_id,
1129 link_actions,
1130 }
1131 }
1132 Err(e) => {
1133 log::debug!("LRRTT handling failed: {}", e);
1134 LinkDataResult::Error
1135 }
1136 }
1137 }
1138 constants::CONTEXT_LINKIDENTIFY => {
1139 match link.engine.handle_identify(packet.data()) {
1140 Ok(link_actions) => {
1141 let link_id = *link.engine.link_id();
1142 link.remote_identity = link.engine.remote_identity().cloned();
1143 LinkDataResult::Identify {
1144 link_id,
1145 link_actions,
1146 }
1147 }
1148 Err(e) => {
1149 log::debug!("LINKIDENTIFY failed: {}", e);
1150 LinkDataResult::Error
1151 }
1152 }
1153 }
1154 constants::CONTEXT_KEEPALIVE => {
1155 let received_at = time::now();
1156 let reply = link
1157 .engine
1158 .should_reply_keepalive(packet.data(), received_at);
1159 let inbound_actions = link.engine.record_inbound(received_at);
1160 let link_id = *link.engine.link_id();
1161 LinkDataResult::Keepalive {
1162 link_id,
1163 inbound_actions,
1164 reply,
1165 received_at,
1166 }
1167 }
1168 constants::CONTEXT_LINKCLOSE => match link.engine.decrypt(packet.data()) {
1169 Ok(plaintext) if plaintext.as_slice() == link_id_bytes => {
1170 let teardown_actions = link.engine.handle_teardown();
1171 let link_id = *link.engine.link_id();
1172 LinkDataResult::LinkClose {
1173 link_id,
1174 teardown_actions,
1175 }
1176 }
1177 _ => LinkDataResult::Error,
1178 },
1179 constants::CONTEXT_CHANNEL => match link.engine.decrypt(packet.data()) {
1180 Ok(plaintext) => {
1181 let inbound_actions = link.engine.record_inbound(time::now());
1182 let link_id = *link.engine.link_id();
1183 LinkDataResult::Channel {
1184 link_id,
1185 inbound_actions,
1186 plaintext,
1187 packet_hash,
1188 }
1189 }
1190 Err(_) => LinkDataResult::Error,
1191 },
1192 constants::CONTEXT_REQUEST => match link.engine.decrypt(packet.data()) {
1193 Ok(plaintext) => {
1194 let inbound_actions = link.engine.record_inbound(time::now());
1195 let link_id = *link.engine.link_id();
1196 let request_id = packet.get_truncated_hash();
1197 LinkDataResult::Request {
1198 link_id,
1199 inbound_actions,
1200 plaintext,
1201 request_id,
1202 }
1203 }
1204 Err(_) => LinkDataResult::Error,
1205 },
1206 constants::CONTEXT_RESPONSE => match link.engine.decrypt(packet.data()) {
1207 Ok(plaintext) => {
1208 let inbound_actions = link.engine.record_inbound(time::now());
1209 let link_id = *link.engine.link_id();
1210 LinkDataResult::Response {
1211 link_id,
1212 inbound_actions,
1213 plaintext,
1214 }
1215 }
1216 Err(_) => LinkDataResult::Error,
1217 },
1218 constants::CONTEXT_RESOURCE_ADV => match link.engine.decrypt(packet.data()) {
1220 Ok(plaintext) => {
1221 let inbound_actions = link.engine.record_inbound(time::now());
1222 let link_id = *link.engine.link_id();
1223 LinkDataResult::ResourceAdv {
1224 link_id,
1225 inbound_actions,
1226 plaintext,
1227 }
1228 }
1229 Err(_) => LinkDataResult::Error,
1230 },
1231 constants::CONTEXT_RESOURCE_REQ => match link.engine.decrypt(packet.data()) {
1232 Ok(plaintext) => {
1233 let inbound_actions = link.engine.record_inbound(time::now());
1234 let link_id = *link.engine.link_id();
1235 LinkDataResult::ResourceReq {
1236 link_id,
1237 inbound_actions,
1238 plaintext,
1239 }
1240 }
1241 Err(_) => LinkDataResult::Error,
1242 },
1243 constants::CONTEXT_RESOURCE_HMU => match link.engine.decrypt(packet.data()) {
1244 Ok(plaintext) => {
1245 let inbound_actions = link.engine.record_inbound(time::now());
1246 let link_id = *link.engine.link_id();
1247 LinkDataResult::ResourceHmu {
1248 link_id,
1249 inbound_actions,
1250 plaintext,
1251 }
1252 }
1253 Err(_) => LinkDataResult::Error,
1254 },
1255 constants::CONTEXT_RESOURCE => {
1256 let inbound_actions = link.engine.record_inbound(time::now());
1258 let link_id = *link.engine.link_id();
1259 LinkDataResult::ResourcePart {
1260 link_id,
1261 inbound_actions,
1262 raw_data: packet.data(),
1263 }
1264 }
1265 constants::CONTEXT_RESOURCE_PRF => match link.engine.decrypt(packet.data()) {
1266 Ok(plaintext) => {
1267 let inbound_actions = link.engine.record_inbound(time::now());
1268 let link_id = *link.engine.link_id();
1269 LinkDataResult::ResourcePrf {
1270 link_id,
1271 inbound_actions,
1272 plaintext,
1273 }
1274 }
1275 Err(_) => LinkDataResult::Error,
1276 },
1277 constants::CONTEXT_RESOURCE_ICL => match link.engine.decrypt(packet.data()) {
1278 Ok(resource_hash) if resource_hash.len() == 32 => {
1279 let inbound_actions = link.engine.record_inbound(time::now());
1280 let link_id = *link.engine.link_id();
1281 LinkDataResult::ResourceIcl {
1282 link_id,
1283 inbound_actions,
1284 resource_hash,
1285 }
1286 }
1287 _ => LinkDataResult::Error,
1288 },
1289 constants::CONTEXT_RESOURCE_RCL => match link.engine.decrypt(packet.data()) {
1290 Ok(resource_hash) if resource_hash.len() == 32 => {
1291 let inbound_actions = link.engine.record_inbound(time::now());
1292 let link_id = *link.engine.link_id();
1293 LinkDataResult::ResourceRcl {
1294 link_id,
1295 inbound_actions,
1296 resource_hash,
1297 }
1298 }
1299 _ => LinkDataResult::Error,
1300 },
1301 _ => match link.engine.decrypt(packet.data()) {
1302 Ok(plaintext) => {
1303 let inbound_actions = link.engine.record_inbound(time::now());
1304 let link_id = *link.engine.link_id();
1305 LinkDataResult::Generic {
1306 link_id,
1307 inbound_actions,
1308 plaintext,
1309 context: packet.context,
1310 packet_hash,
1311 }
1312 }
1313 Err(_) => LinkDataResult::Error,
1314 },
1315 }
1316 }; let mut actions = Vec::new();
1320 match result {
1321 LinkDataResult::Lrrtt {
1322 link_id,
1323 link_actions,
1324 } => {
1325 actions.extend(self.process_link_actions(&link_id, &link_actions));
1326 if let Some(link) = self.links.get_mut(&link_id) {
1328 if link.engine.state() == LinkState::Active {
1329 let rtt = link.engine.rtt().unwrap_or(1.0);
1330 link.channel = Some(Channel::new(rtt));
1331 }
1332 }
1333 let pending = self
1334 .links
1335 .get_mut(&link_id)
1336 .map(|link| std::mem::take(&mut link.pre_rtt_packets))
1337 .unwrap_or_default();
1338 for pending in pending {
1339 actions.extend(self.handle_link_data(
1340 &link_id,
1341 &pending.packet,
1342 pending.packet_hash,
1343 pending.receiving_interface,
1344 rng,
1345 ));
1346 }
1347 }
1348 LinkDataResult::Identify {
1349 link_id,
1350 link_actions,
1351 } => {
1352 actions.extend(self.process_link_actions(&link_id, &link_actions));
1353 }
1354 LinkDataResult::Keepalive {
1355 link_id,
1356 inbound_actions,
1357 reply,
1358 received_at,
1359 } => {
1360 log::debug!(
1361 "Link keepalive received: link={:02x?} reply={reply}",
1362 &link_id[..4]
1363 );
1364 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
1365 if reply {
1366 let flags = PacketFlags {
1367 header_type: constants::HEADER_1,
1368 context_flag: constants::FLAG_UNSET,
1369 transport_type: constants::TRANSPORT_BROADCAST,
1370 destination_type: constants::DESTINATION_LINK,
1371 packet_type: constants::PACKET_TYPE_DATA,
1372 };
1373 if let Ok((raw, _)) = RawPacket::pack_raw_with_hash(
1374 flags,
1375 0,
1376 &link_id,
1377 None,
1378 constants::CONTEXT_KEEPALIVE,
1379 &[0xfe],
1380 ) {
1381 actions.push(LinkManagerAction::SendPacket {
1382 raw,
1383 dest_type: constants::DESTINATION_LINK,
1384 attached_interface: None,
1385 });
1386 if let Some(link) = self.links.get_mut(&link_id) {
1387 link.engine.record_outbound(received_at, true);
1388 }
1389 }
1390 }
1391 }
1392 LinkDataResult::LinkClose {
1393 link_id,
1394 teardown_actions,
1395 } => {
1396 actions.extend(self.process_link_actions(&link_id, &teardown_actions));
1397 }
1398 LinkDataResult::Channel {
1399 link_id,
1400 inbound_actions,
1401 plaintext,
1402 packet_hash,
1403 } => {
1404 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
1405 if let Some(link) = self.links.get_mut(&link_id) {
1407 if let Some(ref mut channel) = link.channel {
1408 let chan_actions = channel.receive(&plaintext, time::now());
1409 link.channel_messages_received += chan_actions
1410 .iter()
1411 .filter(|action| {
1412 matches!(
1413 action,
1414 rns_core::channel::ChannelAction::MessageReceived { .. }
1415 )
1416 })
1417 .count()
1418 as u64;
1419 let _ = link;
1421 actions.extend(self.process_channel_actions(&link_id, chan_actions, rng));
1422 }
1423 }
1424 actions.extend(self.build_link_packet_proof(&link_id, &packet_hash));
1425 }
1426 LinkDataResult::Request {
1427 link_id,
1428 inbound_actions,
1429 plaintext,
1430 request_id,
1431 } => {
1432 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
1433 let size_ok = self
1434 .links
1435 .get(&link_id)
1436 .and_then(|link| link.max_request_size)
1437 .is_none_or(|limit| plaintext.len() <= limit);
1438 if size_ok {
1439 actions.extend(self.handle_request(&link_id, &plaintext, request_id, rng));
1440 } else {
1441 log::debug!(
1442 "ignored request with excessive size {} bytes on link {:02x?}",
1443 plaintext.len(),
1444 &link_id[..4]
1445 );
1446 }
1447 }
1448 LinkDataResult::Response {
1449 link_id,
1450 inbound_actions,
1451 plaintext,
1452 } => {
1453 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
1454 actions.extend(self.handle_response(&link_id, &plaintext, None, None));
1456 }
1457 LinkDataResult::Generic {
1458 link_id,
1459 inbound_actions,
1460 plaintext,
1461 context,
1462 packet_hash,
1463 } => {
1464 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
1465 actions.push(LinkManagerAction::LinkDataReceived {
1466 link_id,
1467 context,
1468 data: plaintext,
1469 });
1470
1471 actions.extend(self.build_link_packet_proof(&link_id, &packet_hash));
1472 }
1473 LinkDataResult::ResourceAdv {
1474 link_id,
1475 inbound_actions,
1476 plaintext,
1477 } => {
1478 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
1479 actions.extend(self.handle_resource_adv(&link_id, &plaintext, rng));
1480 }
1481 LinkDataResult::ResourceReq {
1482 link_id,
1483 inbound_actions,
1484 plaintext,
1485 } => {
1486 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
1487 actions.extend(self.handle_resource_req(&link_id, &plaintext, rng));
1488 }
1489 LinkDataResult::ResourceHmu {
1490 link_id,
1491 inbound_actions,
1492 plaintext,
1493 } => {
1494 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
1495 actions.extend(self.handle_resource_hmu(&link_id, &plaintext, rng));
1496 }
1497 LinkDataResult::ResourcePart {
1498 link_id,
1499 inbound_actions,
1500 raw_data,
1501 } => {
1502 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
1503 actions.extend(self.handle_resource_part(&link_id, raw_data, rng));
1504 }
1505 LinkDataResult::ResourcePrf {
1506 link_id,
1507 inbound_actions,
1508 plaintext,
1509 } => {
1510 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
1511 actions.extend(self.handle_resource_prf(&link_id, &plaintext, rng));
1512 }
1513 LinkDataResult::ResourceIcl {
1514 link_id,
1515 inbound_actions,
1516 resource_hash,
1517 } => {
1518 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
1519 actions.extend(self.handle_resource_icl(&link_id, &resource_hash));
1520 }
1521 LinkDataResult::ResourceRcl {
1522 link_id,
1523 inbound_actions,
1524 resource_hash,
1525 } => {
1526 actions.extend(self.process_link_actions(&link_id, &inbound_actions));
1527 actions.extend(self.handle_resource_rcl(&link_id, &resource_hash));
1528 }
1529 LinkDataResult::Error => {}
1530 }
1531
1532 actions
1533 }
1534
1535 pub fn send_on_link(
1536 &self,
1537 link_id: &LinkId,
1538 plaintext: &[u8],
1539 context: u8,
1540 rng: &mut dyn Rng,
1541 ) -> Vec<LinkManagerAction> {
1542 self.try_send_on_link(link_id, plaintext, context, rng)
1543 .unwrap_or_default()
1544 }
1545
1546 pub fn try_send_on_link(
1548 &self,
1549 link_id: &LinkId,
1550 plaintext: &[u8],
1551 context: u8,
1552 rng: &mut dyn Rng,
1553 ) -> Result<Vec<LinkManagerAction>, crate::event::LinkDatagramError> {
1554 use crate::event::LinkDatagramError;
1555 let link = match self.links.get(link_id) {
1556 Some(l) => l,
1557 None => return Err(LinkDatagramError::LinkNotFound),
1558 };
1559
1560 if link.engine.state() != LinkState::Active {
1561 return Err(LinkDatagramError::LinkNotActive);
1562 }
1563 let maximum = link.engine.mdu();
1564 if plaintext.len() > maximum {
1565 return Err(LinkDatagramError::PayloadTooLarge {
1566 maximum,
1567 actual: plaintext.len(),
1568 });
1569 }
1570
1571 let encrypted = match link.engine.encrypt(plaintext, rng) {
1572 Ok(e) => e,
1573 Err(_) => return Err(LinkDatagramError::EncryptionFailed),
1574 };
1575
1576 let flags = PacketFlags {
1577 header_type: constants::HEADER_1,
1578 context_flag: constants::FLAG_UNSET,
1579 transport_type: constants::TRANSPORT_BROADCAST,
1580 destination_type: constants::DESTINATION_LINK,
1581 packet_type: constants::PACKET_TYPE_DATA,
1582 };
1583
1584 let mut actions = Vec::new();
1585 let (raw, _packet_hash) =
1586 RawPacket::pack_raw_with_hash(flags, 0, link_id, None, context, &encrypted)
1587 .map_err(|_| LinkDatagramError::PacketEncodingFailed)?;
1588 actions.push(LinkManagerAction::SendPacket {
1589 raw,
1590 dest_type: constants::DESTINATION_LINK,
1591 attached_interface: None,
1592 });
1593 Ok(actions)
1594 }
1595
1596 pub fn identify(
1598 &self,
1599 link_id: &LinkId,
1600 identity: &rns_crypto::identity::Identity,
1601 rng: &mut dyn Rng,
1602 ) -> Vec<LinkManagerAction> {
1603 let link = match self.links.get(link_id) {
1604 Some(l) => l,
1605 None => return Vec::new(),
1606 };
1607
1608 let encrypted = match link.engine.build_identify(identity, rng) {
1609 Ok(e) => e,
1610 Err(_) => return Vec::new(),
1611 };
1612
1613 let flags = PacketFlags {
1614 header_type: constants::HEADER_1,
1615 context_flag: constants::FLAG_UNSET,
1616 transport_type: constants::TRANSPORT_BROADCAST,
1617 destination_type: constants::DESTINATION_LINK,
1618 packet_type: constants::PACKET_TYPE_DATA,
1619 };
1620
1621 let mut actions = Vec::new();
1622 if let Ok((raw, _packet_hash)) = RawPacket::pack_raw_with_hash(
1623 flags,
1624 0,
1625 link_id,
1626 None,
1627 constants::CONTEXT_LINKIDENTIFY,
1628 &encrypted,
1629 ) {
1630 actions.push(LinkManagerAction::SendPacket {
1631 raw,
1632 dest_type: constants::DESTINATION_LINK,
1633 attached_interface: None,
1634 });
1635 }
1636 actions
1637 }
1638
1639 pub fn teardown_link(&mut self, link_id: &LinkId) -> Vec<LinkManagerAction> {
1641 let link = match self.links.get_mut(link_id) {
1642 Some(l) => l,
1643 None => return Vec::new(),
1644 };
1645
1646 let previous_state = link.engine.state();
1647 if previous_state == LinkState::Closed {
1648 return Vec::new();
1649 }
1650
1651 let encrypted_close = if previous_state == LinkState::Pending {
1652 None
1653 } else {
1654 let mut rng = OsRng;
1655 link.engine.encrypt(link_id, &mut rng).ok()
1656 };
1657 let teardown_actions = link.engine.teardown();
1658 if let Some(ref mut channel) = link.channel {
1659 channel.shutdown();
1660 }
1661
1662 let mut actions = self.process_link_actions(link_id, &teardown_actions);
1663
1664 if previous_state == LinkState::Pending {
1667 return actions;
1668 }
1669
1670 let flags = PacketFlags {
1672 header_type: constants::HEADER_1,
1673 context_flag: constants::FLAG_UNSET,
1674 transport_type: constants::TRANSPORT_BROADCAST,
1675 destination_type: constants::DESTINATION_LINK,
1676 packet_type: constants::PACKET_TYPE_DATA,
1677 };
1678 if let Some(encrypted_close) = encrypted_close {
1679 if let Ok((raw, _packet_hash)) = RawPacket::pack_raw_with_hash(
1680 flags,
1681 0,
1682 link_id,
1683 None,
1684 constants::CONTEXT_LINKCLOSE,
1685 &encrypted_close,
1686 ) {
1687 actions.push(LinkManagerAction::SendPacket {
1688 raw,
1689 dest_type: constants::DESTINATION_LINK,
1690 attached_interface: None,
1691 });
1692 }
1693 }
1694
1695 actions
1696 }
1697
1698 pub fn teardown_all_links(&mut self) -> Vec<LinkManagerAction> {
1700 let link_ids: Vec<LinkId> = self.links.keys().copied().collect();
1701 let mut actions = Vec::new();
1702 for link_id in link_ids {
1703 actions.extend(self.teardown_link(&link_id));
1704 }
1705 actions
1706 }
1707
1708 pub fn tick(&mut self, rng: &mut dyn Rng) -> Vec<LinkManagerAction> {
1710 let now = time::now();
1711 let mut all_actions = Vec::new();
1712
1713 let link_ids: Vec<LinkId> = self.links.keys().copied().collect();
1715
1716 for link_id in &link_ids {
1717 let link = match self.links.get_mut(link_id) {
1718 Some(l) => l,
1719 None => continue,
1720 };
1721
1722 let tick_actions = link.engine.tick(now);
1724 all_actions.extend(self.process_link_actions(link_id, &tick_actions));
1725
1726 let link = match self.links.get_mut(link_id) {
1728 Some(l) => l,
1729 None => continue,
1730 };
1731 if link.engine.needs_keepalive(now) {
1732 log::debug!("Link keepalive probe queued: link={:02x?}", &link_id[..4]);
1733 let flags = PacketFlags {
1736 header_type: constants::HEADER_1,
1737 context_flag: constants::FLAG_UNSET,
1738 transport_type: constants::TRANSPORT_BROADCAST,
1739 destination_type: constants::DESTINATION_LINK,
1740 packet_type: constants::PACKET_TYPE_DATA,
1741 };
1742 if let Ok((raw, _packet_hash)) = RawPacket::pack_raw_with_hash(
1743 flags,
1744 0,
1745 link_id,
1746 None,
1747 constants::CONTEXT_KEEPALIVE,
1748 &[0xff],
1749 ) {
1750 all_actions.push(LinkManagerAction::SendPacket {
1751 raw,
1752 dest_type: constants::DESTINATION_LINK,
1753 attached_interface: None,
1754 });
1755 link.engine.record_outbound(now, true);
1756 }
1757 }
1758
1759 if let Some(channel) = link.channel.as_mut() {
1760 let chan_actions = channel.tick(now);
1761 let _ = channel;
1762 let _ = link;
1763 all_actions.extend(self.process_channel_actions(link_id, chan_actions, rng));
1764 }
1765 }
1766
1767 for link_id in &link_ids {
1769 let link = match self.links.get_mut(link_id) {
1770 Some(l) => l,
1771 None => continue,
1772 };
1773
1774 let mut sender_actions = Vec::new();
1776 for sender in &mut link.outgoing_resources {
1777 sender_actions.extend(sender.tick(now));
1778 }
1779
1780 let mut receiver_actions = Vec::new();
1782 for receiver in &mut link.incoming_resources {
1783 let decrypt_fn = |ciphertext: &[u8]| -> Result<Vec<u8>, ()> {
1784 link.engine.decrypt(ciphertext).map_err(|_| ())
1785 };
1786 receiver_actions.extend(receiver.tick(now, &decrypt_fn, &Bzip2Compressor));
1787 }
1788
1789 let failed_request_ids: Vec<[u8; 16]> = link
1790 .outgoing_resources
1791 .iter()
1792 .filter(|sender| {
1793 sender.flags.is_request
1794 && sender.status >= rns_core::resource::ResourceStatus::Failed
1795 })
1796 .filter_map(|sender| Self::response_request_id(&sender.request_id))
1797 .collect();
1798 for request_id in failed_request_ids {
1799 link.pending_requests.remove(&request_id);
1800 }
1801 link.pending_requests
1802 .retain(|_, request| request.deadline.is_none_or(|expires_at| now <= expires_at));
1803
1804 link.outgoing_resources
1806 .retain(|s| s.status < rns_core::resource::ResourceStatus::Complete);
1807 link.incoming_resources
1808 .retain(|r| r.status < rns_core::resource::ResourceStatus::Complete);
1809 let active_split_hashes: Vec<[u8; 32]> = link
1810 .outgoing_resources
1811 .iter()
1812 .filter(|s| s.flags.split)
1813 .map(|s| s.original_hash)
1814 .collect();
1815 link.outgoing_splits.retain(|original_hash, split| {
1816 split.completed_segments < split.total_segments
1817 && active_split_hashes.contains(original_hash)
1818 });
1819
1820 let _ = link;
1821 all_actions.extend(self.process_resource_actions(link_id, sender_actions, rng));
1822 all_actions.extend(self.process_resource_actions(link_id, receiver_actions, rng));
1823 }
1824
1825 let closed: Vec<LinkId> = self
1827 .links
1828 .iter()
1829 .filter(|(_, l)| l.engine.state() == LinkState::Closed)
1830 .map(|(id, _)| *id)
1831 .collect();
1832 for id in closed {
1833 self.links.remove(&id);
1834 all_actions.push(LinkManagerAction::DeregisterLinkDest { link_id: id });
1835 }
1836
1837 all_actions
1838 }
1839
1840 pub fn is_link_destination(&self, dest_hash: &[u8; 16]) -> bool {
1842 self.links.contains_key(dest_hash) || self.link_destinations.contains_key(dest_hash)
1843 }
1844
1845 pub fn link_state(&self, link_id: &LinkId) -> Option<LinkState> {
1847 self.links.get(link_id).map(|l| l.engine.state())
1848 }
1849
1850 pub fn link_rtt(&self, link_id: &LinkId) -> Option<f64> {
1852 self.links.get(link_id).and_then(|l| l.engine.rtt())
1853 }
1854
1855 pub fn set_link_rtt(&mut self, link_id: &LinkId, rtt: f64) {
1857 if let Some(link) = self.links.get_mut(link_id) {
1858 link.engine.set_rtt(rtt);
1859 }
1860 }
1861
1862 pub fn record_link_inbound(&mut self, link_id: &LinkId) {
1864 if let Some(link) = self.links.get_mut(link_id) {
1865 link.engine.record_inbound(time::now());
1866 }
1867 }
1868
1869 pub fn set_link_mtu(&mut self, link_id: &LinkId, mtu: u32) {
1871 if let Some(link) = self.links.get_mut(link_id) {
1872 link.engine.set_mtu(mtu);
1873 }
1874 }
1875
1876 pub fn link_count(&self) -> usize {
1878 self.links.len()
1879 }
1880
1881 pub fn active_link_count(&self) -> usize {
1883 self.links
1884 .values()
1885 .filter(|link| link.engine.state() == LinkState::Active)
1886 .count()
1887 }
1888
1889 pub fn resource_transfer_count(&self) -> usize {
1891 self.links
1892 .values()
1893 .map(|managed| {
1894 managed
1895 .incoming_resources
1896 .iter()
1897 .filter(|resource| !resource.flags.split && resource.assembly_id().is_none())
1898 .count()
1899 + managed.incoming_splits.len()
1900 + managed
1901 .outgoing_resources
1902 .iter()
1903 .filter(|resource| !resource.flags.split)
1904 .count()
1905 + managed.outgoing_splits.len()
1906 })
1907 .sum::<usize>()
1908 + self
1909 .receive_worker
1910 .as_ref()
1911 .map_or(0, |worker| worker.len())
1912 }
1913
1914 pub fn cancel_all_resources(&mut self, rng: &mut dyn Rng) -> Vec<LinkManagerAction> {
1916 let link_ids: Vec<LinkId> = self.links.keys().copied().collect();
1917 let mut all_actions = Vec::new();
1918
1919 for link_id in &link_ids {
1920 let link = match self.links.get_mut(link_id) {
1921 Some(l) => l,
1922 None => continue,
1923 };
1924
1925 let mut sender_actions = Vec::new();
1926 for sender in &mut link.outgoing_resources {
1927 sender_actions.extend(sender.cancel());
1928 }
1929
1930 let mut receiver_actions = Vec::new();
1931 for receiver in &mut link.incoming_resources {
1932 receiver_actions.extend(receiver.cancel());
1933 }
1934
1935 link.outgoing_resources
1936 .retain(|s| s.status < rns_core::resource::ResourceStatus::Complete);
1937 link.incoming_resources
1938 .retain(|r| r.status < rns_core::resource::ResourceStatus::Complete);
1939 link.outgoing_splits.clear();
1940 all_actions.extend(link.outgoing_streams.drain().map(|(_, stream)| {
1941 LinkManagerAction::ResourceStreamFailed {
1942 link_id: *link_id,
1943 transfer_id: stream.transfer_id,
1944 error: ResourceTransferError::Cancelled,
1945 }
1946 }));
1947 link.incoming_splits.clear();
1948
1949 let _ = link;
1950 all_actions.extend(self.process_resource_actions(link_id, sender_actions, rng));
1951 all_actions.extend(self.process_resource_actions(link_id, receiver_actions, rng));
1952 }
1953
1954 all_actions
1955 }
1956
1957 pub fn link_entries(&self) -> Vec<crate::event::LinkInfoEntry> {
1959 self.links
1960 .iter()
1961 .map(|(link_id, managed)| {
1962 let state = match managed.engine.state() {
1963 LinkState::Pending => "pending",
1964 LinkState::Handshake => "handshake",
1965 LinkState::Active => "active",
1966 LinkState::Stale => "stale",
1967 LinkState::Closed => "closed",
1968 };
1969 crate::event::LinkInfoEntry {
1970 link_id: *link_id,
1971 pending_send_packets: 0,
1972 waiting_send_packets: 0,
1973 state: state.to_string(),
1974 is_initiator: managed.engine.is_initiator(),
1975 dest_hash: managed.dest_hash,
1976 remote_identity: managed.remote_identity.as_ref().map(|(h, _)| *h),
1977 rtt: managed.engine.rtt(),
1978 expected_hops: managed.engine.expected_hops(),
1979 mdu: managed.engine.mdu(),
1980 tx_packets: managed.engine.tx_packets(),
1981 rx_packets: managed.engine.rx_packets(),
1982 tx_bytes: managed.engine.tx_bytes(),
1983 rx_bytes: managed.engine.rx_bytes(),
1984 channel_window: managed.channel.as_ref().map(|c| c.window()),
1985 channel_outstanding: managed.channel.as_ref().map(|c| c.outstanding()),
1986 pending_channel_packets: managed.pending_channel_packets.len(),
1987 channel_send_ok: managed.channel_send_ok,
1988 channel_send_not_ready: managed.channel_send_not_ready,
1989 channel_send_too_big: managed.channel_send_too_big,
1990 channel_send_other_error: managed.channel_send_other_error,
1991 channel_messages_received: managed.channel_messages_received,
1992 channel_proofs_sent: managed.channel_proofs_sent,
1993 channel_proofs_received: managed.channel_proofs_received,
1994 }
1995 })
1996 .collect()
1997 }
1998
1999 pub fn record_outbound_packet(&mut self, packet: &RawPacket) {
2003 if packet.flags.destination_type == constants::DESTINATION_LINK {
2004 if let Some(link) = self.links.get_mut(&packet.destination_hash) {
2005 link.engine.record_outbound_traffic(packet.data().len());
2006 }
2007 }
2008 }
2009
2010 pub fn resource_entries(&self) -> Vec<crate::event::ResourceInfoEntry> {
2012 let mut entries = Vec::new();
2013 for (link_id, managed) in &self.links {
2014 let resource_sdu = Self::resource_sdu_for_link(managed);
2015 for split in managed.incoming_splits.values() {
2016 let (received, total) = Self::incoming_split_progress(split, resource_sdu);
2017 entries.push(crate::event::ResourceInfoEntry {
2018 link_id: *link_id,
2019 direction: "incoming".to_string(),
2020 total_parts: total,
2021 transferred_parts: received,
2022 complete: received >= total && total > 0,
2023 });
2024 }
2025 for recv in &managed.incoming_resources {
2026 if recv.flags.split {
2027 continue;
2028 }
2029 let (received, total) = recv.progress();
2030 entries.push(crate::event::ResourceInfoEntry {
2031 link_id: *link_id,
2032 direction: "incoming".to_string(),
2033 total_parts: total,
2034 transferred_parts: received,
2035 complete: received >= total && total > 0,
2036 });
2037 }
2038 for split in managed.outgoing_splits.values() {
2039 let (sent, total) = Self::outgoing_split_progress(split, resource_sdu);
2040 entries.push(crate::event::ResourceInfoEntry {
2041 link_id: *link_id,
2042 direction: "outgoing".to_string(),
2043 total_parts: total,
2044 transferred_parts: sent,
2045 complete: sent >= total && total > 0,
2046 });
2047 }
2048 for send in &managed.outgoing_resources {
2049 if send.flags.split {
2050 continue;
2051 }
2052 let total = send.total_parts();
2053 let sent = send.sent_parts;
2054 entries.push(crate::event::ResourceInfoEntry {
2055 link_id: *link_id,
2056 direction: "outgoing".to_string(),
2057 total_parts: total,
2058 transferred_parts: sent,
2059 complete: sent >= total && total > 0,
2060 });
2061 }
2062 }
2063 entries
2064 }
2065
2066 fn process_link_actions(
2068 &self,
2069 link_id: &LinkId,
2070 actions: &[LinkAction],
2071 ) -> Vec<LinkManagerAction> {
2072 let mut result = Vec::new();
2073 for action in actions {
2074 match action {
2075 LinkAction::StateChanged {
2076 new_state, reason, ..
2077 } => {
2078 log::debug!(
2079 "Link state changed: link={:02x?} state={new_state:?} reason={reason:?}",
2080 &link_id[..4]
2081 );
2082 if new_state == &LinkState::Closed {
2083 result.push(LinkManagerAction::LinkClosed {
2084 link_id: *link_id,
2085 reason: *reason,
2086 });
2087 }
2088 }
2089 LinkAction::LinkEstablished {
2090 rtt, is_initiator, ..
2091 } => {
2092 let keepalive = self
2093 .links
2094 .get(link_id)
2095 .map(|link| link.engine.keepalive_interval())
2096 .unwrap_or_default();
2097 log::debug!(
2098 "Link timers established: link={:02x?} rtt={rtt:.6} keepalive={keepalive:.6} stale={:.6} initiator={is_initiator}",
2099 &link_id[..4],
2100 keepalive * rns_core::constants::LINK_STALE_FACTOR
2101 );
2102 let dest_hash = self
2103 .links
2104 .get(link_id)
2105 .map(|l| l.dest_hash)
2106 .unwrap_or([0u8; 16]);
2107 let hops = self
2108 .links
2109 .get(link_id)
2110 .map(|link| link.engine.expected_hops())
2111 .unwrap_or(rns_core::constants::PATHFINDER_M);
2112 let rebalanced_at = self
2113 .links
2114 .get(link_id)
2115 .and_then(|link| link.engine.rebalanced_at());
2116 result.push(LinkManagerAction::LinkEstablished {
2117 link_id: *link_id,
2118 dest_hash,
2119 hops,
2120 rebalanced_at,
2121 rtt: *rtt,
2122 is_initiator: *is_initiator,
2123 });
2124 }
2125 LinkAction::RemoteIdentified {
2126 identity_hash,
2127 public_key,
2128 ..
2129 } => {
2130 result.push(LinkManagerAction::RemoteIdentified {
2131 link_id: *link_id,
2132 identity_hash: *identity_hash,
2133 public_key: *public_key,
2134 });
2135 }
2136 LinkAction::DataReceived { .. } => {
2137 }
2139 }
2140 }
2141 result
2142 }
2143}
2144
2145impl Default for LinkManager {
2146 fn default() -> Self {
2147 Self::new()
2148 }
2149}
2150
2151fn compute_path_hash(path: &str) -> [u8; 16] {
2154 let full = rns_core::hash::full_hash(path.as_bytes());
2155 let mut result = [0u8; 16];
2156 result.copy_from_slice(&full[..16]);
2157 result
2158}
2159
2160#[cfg(test)]
2161mod tests;