Skip to main content

rns_core/transport/
mod.rs

1pub mod announce_proc;
2pub mod announce_queue;
3pub mod announce_verify_queue;
4pub mod dedup;
5pub mod inbound;
6pub mod ingress_control;
7pub mod jobs;
8pub mod outbound;
9pub mod path_requests;
10pub mod pathfinder;
11pub mod persistence;
12pub mod queries;
13pub mod rate_limit;
14pub mod retention;
15pub mod tables;
16pub mod tunnel;
17pub mod types;
18
19use alloc::collections::{BTreeMap, BTreeSet, VecDeque};
20use alloc::string::String;
21use alloc::vec::Vec;
22use core::mem::size_of;
23
24use rns_crypto::Rng;
25
26use crate::announce::AnnounceData;
27use crate::constants;
28use crate::hash;
29use crate::packet::RawPacket;
30
31use self::announce_proc::compute_path_expires;
32use self::announce_queue::AnnounceQueues;
33use self::announce_verify_queue::{AnnounceVerifyKey, AnnounceVerifyQueue, PendingAnnounce};
34use self::dedup::{AnnounceSignatureCache, PacketHashlist};
35use self::inbound::{
36    create_link_entry, create_reverse_entry, forward_transport_packet, route_proof_via_reverse,
37    route_via_link_table, LocalHopRewrite,
38};
39use self::ingress_control::IngressControl;
40use self::outbound::{route_outbound_with_options, should_transmit_announce, OutboundRouteOptions};
41use self::pathfinder::{
42    extract_random_blob, timebase_from_random_blob, timebase_from_random_blobs, MultiPathDecision,
43};
44use self::rate_limit::AnnounceRateLimiter;
45use self::tables::{AnnounceEntry, DiscoveryPathRequest, LinkEntry, PathEntry, PathSet};
46use self::tunnel::TunnelTable;
47use self::types::{
48    BlackholeEntry, InterfaceId, InterfaceInfo, PacketBytes, TransportAction, TransportConfig,
49};
50
51pub type PathTableRow = ([u8; 16], f64, [u8; 16], u8, f64, String);
52pub type RateTableRow = ([u8; 16], f64, u32, f64, Vec<f64>);
53/// Parsed LRPROOF data used to rebalance an existing link route.
54pub type LrproofRebalanceCandidate = ([u8; 16], [u8; 16], u8, Vec<u8>);
55
56fn lrproof_hop_mismatch_diagnostic(packet_hops: u8, entry: &LinkEntry) -> String {
57    alloc::format!(
58        "Received link request proof with hop mismatch ({}/{}:{}->{}), not transporting it",
59        packet_hops,
60        entry.remaining_hops,
61        entry.next_hop_interface.0,
62        entry.received_interface.0,
63    )
64}
65
66fn link_route_hops_match(
67    packet_hops: u8,
68    entry: &LinkEntry,
69    receiving_interface: InterfaceId,
70) -> bool {
71    if entry.next_hop_interface == entry.received_interface {
72        packet_hops == entry.remaining_hops || packet_hops == entry.taken_hops
73    } else if receiving_interface == entry.next_hop_interface {
74        packet_hops == entry.remaining_hops
75    } else if receiving_interface == entry.received_interface {
76        packet_hops == entry.taken_hops
77    } else {
78        // The routing failure is the interface, not a hop mismatch.
79        true
80    }
81}
82
83#[derive(Debug, Clone, Copy, PartialEq, Default)]
84pub struct RxMetadata {
85    pub rssi: Option<i16>,
86    pub snr: Option<f32>,
87}
88
89#[derive(Debug, Clone, Copy, PartialEq)]
90pub struct InboundFrame<'a> {
91    pub raw: &'a [u8],
92    pub iface: InterfaceId,
93    pub now: f64,
94    pub rx: RxMetadata,
95}
96
97impl<'a> InboundFrame<'a> {
98    pub fn new(raw: &'a [u8], iface: InterfaceId, now: f64) -> Self {
99        Self {
100            raw,
101            iface,
102            now,
103            rx: RxMetadata::default(),
104        }
105    }
106
107    pub fn with_rx(mut self, rx: RxMetadata) -> Self {
108        self.rx = rx;
109        self
110    }
111}
112
113struct InboundPacketCtx {
114    packet: RawPacket,
115    original_raw: Option<Vec<u8>>,
116    iface: InterfaceId,
117    now: f64,
118    from_local_client: bool,
119}
120
121struct VerifiedAnnounceCtx<'a> {
122    packet: &'a RawPacket,
123    original_raw: &'a [u8],
124    iface: InterfaceId,
125    now: f64,
126    validated: crate::announce::ValidatedAnnounce,
127    received_from: [u8; 16],
128    random_blob: [u8; 10],
129    announce_emitted: u64,
130}
131
132struct TickCtx<'a> {
133    now: f64,
134    rng: &'a mut dyn Rng,
135    actions: Vec<TransportAction>,
136}
137
138/// Validated, uniquely tagged path request awaiting ingress accounting.
139///
140/// This two-phase token is intended for the network driver; applications
141/// should use [`TransportEngine::handle_path_request`] instead.
142#[doc(hidden)]
143pub struct AcceptedPathRequest {
144    tag: [u8; 16],
145    tag_len: usize,
146    interface_id: InterfaceId,
147    now: f64,
148    destination_hash: [u8; 16],
149    already_in_flight: bool,
150}
151
152/// The core transport/routing engine.
153///
154/// Maintains routing tables and processes packets without performing any I/O.
155/// Returns `Vec<TransportAction>` that the caller must execute.
156pub struct TransportEngine {
157    config: TransportConfig,
158    path_table: BTreeMap<[u8; 16], PathSet>,
159    announce_table: BTreeMap<[u8; 16], AnnounceEntry>,
160    reverse_table: BTreeMap<[u8; 16], tables::ReverseEntry>,
161    link_table: BTreeMap<[u8; 16], LinkEntry>,
162    held_announces: BTreeMap<[u8; 16], AnnounceEntry>,
163    packet_hashlist: PacketHashlist,
164    announce_sig_cache: AnnounceSignatureCache,
165    rate_limiter: AnnounceRateLimiter,
166    path_states: BTreeMap<[u8; 16], u8>,
167    interfaces: BTreeMap<InterfaceId, InterfaceInfo>,
168    interface_hashes: BTreeMap<InterfaceId, [u8; 32]>,
169    local_destinations: BTreeMap<[u8; 16], u8>,
170    blackholed_identities: BTreeMap<[u8; 16], BlackholeEntry>,
171    announce_queues: AnnounceQueues,
172    ingress_control: IngressControl,
173    tunnel_table: TunnelTable,
174    discovery_pr_tags: VecDeque<[u8; 32]>,
175    discovery_pr_tag_set: BTreeSet<[u8; 32]>,
176    path_requests: BTreeMap<[u8; 16], f64>,
177    discovery_path_requests: BTreeMap<[u8; 16], DiscoveryPathRequest>,
178    discovery_path_request_deadlines: BTreeMap<[u8; 16], f64>,
179    path_destination_cap_evict_count: usize,
180    // Job timing
181    announces_last_checked: f64,
182    tables_last_culled: f64,
183}
184
185mod engine_state;
186mod inbound_engine;
187mod maintenance;
188mod outbound_engine;
189
190#[cfg(test)]
191mod tests;