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 clamp_forwarded_link_request_mtu, create_link_entry, create_reverse_entry,
37 forward_transport_packet, route_proof_via_reverse, 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, trusted_timebase_from_random_blobs,
43 MultiPathDecision,
44};
45use self::rate_limit::AnnounceRateLimiter;
46use self::tables::{AnnounceEntry, DiscoveryPathRequest, LinkEntry, PathEntry, PathSet};
47use self::tunnel::TunnelTable;
48use self::types::{
49 BlackholeEntry, InterfaceId, InterfaceInfo, PacketBytes, TransportAction, TransportConfig,
50};
51
52pub type PathTableRow = ([u8; 16], f64, [u8; 16], u8, f64, String);
53pub type RateTableRow = ([u8; 16], f64, u32, f64, Vec<f64>);
54pub type LrproofRebalanceCandidate = ([u8; 16], [u8; 16], u8, Vec<u8>);
56
57fn lrproof_hop_mismatch_diagnostic(packet_hops: u8, entry: &LinkEntry) -> String {
58 alloc::format!(
59 "Received link request proof with hop mismatch ({}/{}:{}->{}), not transporting it",
60 packet_hops,
61 entry.remaining_hops,
62 entry.next_hop_interface.0,
63 entry.received_interface.0,
64 )
65}
66
67fn link_route_hops_match(
68 packet_hops: u8,
69 entry: &LinkEntry,
70 receiving_interface: InterfaceId,
71) -> bool {
72 if entry.next_hop_interface == entry.received_interface {
73 packet_hops == entry.remaining_hops || packet_hops == entry.taken_hops
74 } else if receiving_interface == entry.next_hop_interface {
75 packet_hops == entry.remaining_hops
76 } else if receiving_interface == entry.received_interface {
77 packet_hops == entry.taken_hops
78 } else {
79 true
81 }
82}
83
84#[derive(Debug, Clone, Copy, PartialEq, Default)]
85pub struct RxMetadata {
86 pub rssi: Option<i16>,
87 pub snr: Option<f32>,
88}
89
90#[derive(Debug, Clone, Copy, PartialEq)]
91pub struct InboundFrame<'a> {
92 pub raw: &'a [u8],
93 pub iface: InterfaceId,
94 pub now: f64,
95 pub rx: RxMetadata,
96}
97
98impl<'a> InboundFrame<'a> {
99 pub fn new(raw: &'a [u8], iface: InterfaceId, now: f64) -> Self {
100 Self {
101 raw,
102 iface,
103 now,
104 rx: RxMetadata::default(),
105 }
106 }
107
108 pub fn with_rx(mut self, rx: RxMetadata) -> Self {
109 self.rx = rx;
110 self
111 }
112}
113
114pub struct DecodedPacket {
117 packet: RawPacket,
118 hash_deferred: bool,
122}
123
124impl DecodedPacket {
125 pub fn unpack(raw: &[u8]) -> Result<Self, crate::packet::PacketError> {
126 RawPacket::unpack(raw).map(Self::hashed)
127 }
128
129 pub fn unpack_owned(raw: Vec<u8>) -> Result<Self, crate::packet::PacketError> {
131 RawPacket::unpack_owned(raw).map(Self::hashed)
132 }
133
134 fn hashed(packet: RawPacket) -> Self {
135 Self {
136 packet,
137 hash_deferred: false,
138 }
139 }
140
141 pub fn packet(&self) -> &RawPacket {
144 &self.packet
145 }
146
147 pub fn packet_hash(&self) -> Option<&[u8; 32]> {
149 (!self.hash_deferred).then_some(&self.packet.packet_hash)
150 }
151}
152
153pub struct DecodedInboundFrame {
155 pub decoded: DecodedPacket,
156 pub iface: InterfaceId,
157 pub now: f64,
158 pub rx: RxMetadata,
159}
160
161struct InboundPacketCtx {
162 packet: RawPacket,
163 hash_deferred: bool,
166 original_raw: Option<Vec<u8>>,
167 iface: InterfaceId,
168 now: f64,
169 from_local_client: bool,
170}
171
172struct VerifiedAnnounceCtx<'a> {
173 packet: &'a RawPacket,
174 original_raw: &'a [u8],
175 iface: InterfaceId,
176 now: f64,
177 validated: crate::announce::ValidatedAnnounce,
178 received_from: [u8; 16],
179 random_blob: [u8; 10],
180 announce_emitted: u64,
181}
182
183struct TickCtx<'a> {
184 now: f64,
185 rng: &'a mut dyn Rng,
186 actions: Vec<TransportAction>,
187}
188
189#[doc(hidden)]
194pub struct AcceptedPathRequest {
195 tag: [u8; 16],
196 tag_len: usize,
197 interface_id: InterfaceId,
198 now: f64,
199 destination_hash: [u8; 16],
200 already_in_flight: bool,
201}
202
203pub struct TransportEngine {
208 config: TransportConfig,
209 path_table: BTreeMap<[u8; 16], PathSet>,
210 announce_table: BTreeMap<[u8; 16], AnnounceEntry>,
211 reverse_table: tables::ReverseTable,
212 link_table: BTreeMap<[u8; 16], LinkEntry>,
213 held_announces: BTreeMap<[u8; 16], AnnounceEntry>,
214 packet_hashlist: PacketHashlist,
215 announce_sig_cache: AnnounceSignatureCache,
216 rate_limiter: AnnounceRateLimiter,
217 path_states: BTreeMap<[u8; 16], u8>,
218 interfaces: BTreeMap<InterfaceId, InterfaceInfo>,
219 interface_hashes: BTreeMap<InterfaceId, [u8; 32]>,
220 local_destinations: BTreeMap<[u8; 16], u8>,
221 blackholed_identities: BTreeMap<[u8; 16], BlackholeEntry>,
222 announce_queues: AnnounceQueues,
223 ingress_control: IngressControl,
224 tunnel_table: TunnelTable,
225 discovery_pr_tags: VecDeque<[u8; 32]>,
226 discovery_pr_tag_set: BTreeSet<[u8; 32]>,
227 path_requests: BTreeMap<[u8; 16], f64>,
228 discovery_path_requests: BTreeMap<[u8; 16], DiscoveryPathRequest>,
229 discovery_path_request_deadlines: BTreeMap<[u8; 16], f64>,
230 pending_local_path_requests: BTreeMap<[u8; 16], (InterfaceId, f64)>,
234 path_destination_cap_evict_count: usize,
235 announces_last_checked: f64,
237 tables_last_culled: f64,
238}
239
240mod engine_state;
241mod inbound_engine;
242mod maintenance;
243mod outbound_engine;
244
245#[cfg(test)]
246mod tests;