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,
121}
122
123impl DecodedPacket {
124 pub fn unpack(raw: &[u8]) -> Result<Self, crate::packet::PacketError> {
125 RawPacket::unpack(raw).map(Self::hashed)
126 }
127
128 pub fn unpack_owned(raw: Vec<u8>) -> Result<Self, crate::packet::PacketError> {
130 RawPacket::unpack_owned(raw).map(Self::hashed)
131 }
132
133 fn hashed(packet: RawPacket) -> Self {
134 Self {
135 packet,
136 hash_deferred: false,
137 }
138 }
139
140 pub fn packet(&self) -> &RawPacket {
143 &self.packet
144 }
145
146 pub fn packet_hash(&self) -> Option<&[u8; 32]> {
148 (!self.hash_deferred).then_some(&self.packet.packet_hash)
149 }
150}
151
152pub struct DecodedInboundFrame {
154 pub decoded: DecodedPacket,
155 pub iface: InterfaceId,
156 pub now: f64,
157 pub rx: RxMetadata,
158}
159
160struct InboundPacketCtx {
161 packet: RawPacket,
162 hash_deferred: bool,
165 original_raw: Option<Vec<u8>>,
166 iface: InterfaceId,
167 now: f64,
168 from_local_client: bool,
169}
170
171struct VerifiedAnnounceCtx<'a> {
172 packet: &'a RawPacket,
173 original_raw: &'a [u8],
174 iface: InterfaceId,
175 now: f64,
176 validated: crate::announce::ValidatedAnnounce,
177 received_from: [u8; 16],
178 random_blob: [u8; 10],
179 announce_emitted: u64,
180}
181
182struct TickCtx<'a> {
183 now: f64,
184 rng: &'a mut dyn Rng,
185 actions: Vec<TransportAction>,
186}
187
188#[doc(hidden)]
193pub struct AcceptedPathRequest {
194 tag: [u8; 16],
195 tag_len: usize,
196 interface_id: InterfaceId,
197 now: f64,
198 destination_hash: [u8; 16],
199 already_in_flight: bool,
200}
201
202pub struct TransportEngine {
207 config: TransportConfig,
208 path_table: BTreeMap<[u8; 16], PathSet>,
209 announce_table: BTreeMap<[u8; 16], AnnounceEntry>,
210 reverse_table: tables::ReverseTable,
211 link_table: BTreeMap<[u8; 16], LinkEntry>,
212 held_announces: BTreeMap<[u8; 16], AnnounceEntry>,
213 packet_hashlist: PacketHashlist,
214 announce_sig_cache: AnnounceSignatureCache,
215 rate_limiter: AnnounceRateLimiter,
216 path_states: BTreeMap<[u8; 16], u8>,
217 interfaces: BTreeMap<InterfaceId, InterfaceInfo>,
218 interface_hashes: BTreeMap<InterfaceId, [u8; 32]>,
219 local_destinations: BTreeMap<[u8; 16], u8>,
220 blackholed_identities: BTreeMap<[u8; 16], BlackholeEntry>,
221 announce_queues: AnnounceQueues,
222 ingress_control: IngressControl,
223 tunnel_table: TunnelTable,
224 discovery_pr_tags: VecDeque<[u8; 32]>,
225 discovery_pr_tag_set: BTreeSet<[u8; 32]>,
226 path_requests: BTreeMap<[u8; 16], f64>,
227 discovery_path_requests: BTreeMap<[u8; 16], DiscoveryPathRequest>,
228 discovery_path_request_deadlines: BTreeMap<[u8; 16], f64>,
229 pending_local_path_requests: BTreeMap<[u8; 16], (InterfaceId, f64)>,
233 path_destination_cap_evict_count: usize,
234 announces_last_checked: f64,
236 tables_last_culled: f64,
237}
238
239mod engine_state;
240mod inbound_engine;
241mod maintenance;
242mod outbound_engine;
243
244#[cfg(test)]
245mod tests;