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