Skip to main content

rns_net/
event.rs

1//! Event types for the driver loop.
2
3use std::fmt;
4use std::sync::mpsc;
5
6use rns_core::transport::types::{InterfaceId, InterfaceInfo};
7
8use crate::interface::Writer;
9
10/// Events sent to the driver thread.
11pub enum Event {
12    /// A decoded frame arrived from an interface.
13    Frame { interface_id: InterfaceId, data: Vec<u8> },
14    /// An interface came online after (re)connecting.
15    /// Carries a new writer if the connection was re-established.
16    /// Carries InterfaceInfo if this is a new dynamic interface (e.g. TCP server client).
17    InterfaceUp(InterfaceId, Option<Box<dyn Writer>>, Option<InterfaceInfo>),
18    /// An interface went offline (socket closed, error).
19    InterfaceDown(InterfaceId),
20    /// Periodic maintenance tick (1s interval).
21    Tick,
22    /// Shut down the driver loop.
23    Shutdown,
24    /// Send an outbound packet.
25    SendOutbound {
26        raw: Vec<u8>,
27        dest_type: u8,
28        attached_interface: Option<InterfaceId>,
29    },
30    /// Register a local destination.
31    RegisterDestination {
32        dest_hash: [u8; 16],
33        dest_type: u8,
34    },
35    /// Deregister a local destination.
36    DeregisterDestination {
37        dest_hash: [u8; 16],
38    },
39    /// Deregister a link destination (stop accepting incoming links).
40    DeregisterLinkDestination {
41        dest_hash: [u8; 16],
42    },
43    /// Query driver state. Response is sent via the provided channel.
44    Query(QueryRequest, mpsc::Sender<QueryResponse>),
45    /// Register a link destination (accepts incoming LINKREQUEST).
46    RegisterLinkDestination {
47        dest_hash: [u8; 16],
48        sig_prv_bytes: [u8; 32],
49        sig_pub_bytes: [u8; 32],
50    },
51    /// Register a request handler for a path on established links.
52    RegisterRequestHandler {
53        path: String,
54        allowed_list: Option<Vec<[u8; 16]>>,
55        handler: Box<dyn Fn([u8; 16], &str, &[u8], Option<&([u8; 16], [u8; 64])>) -> Option<Vec<u8>> + Send>,
56    },
57    /// Create an outbound link. Response sends (link_id) back.
58    CreateLink {
59        dest_hash: [u8; 16],
60        dest_sig_pub_bytes: [u8; 32],
61        response_tx: mpsc::Sender<[u8; 16]>,
62    },
63    /// Send a request on an established link.
64    SendRequest {
65        link_id: [u8; 16],
66        path: String,
67        data: Vec<u8>,
68    },
69    /// Identify on a link (send identity to remote peer).
70    IdentifyOnLink {
71        link_id: [u8; 16],
72        identity_prv_key: [u8; 64],
73    },
74    /// Tear down a link.
75    TeardownLink {
76        link_id: [u8; 16],
77    },
78    /// Send a resource on a link.
79    SendResource {
80        link_id: [u8; 16],
81        data: Vec<u8>,
82        metadata: Option<Vec<u8>>,
83    },
84    /// Set the resource acceptance strategy for a link.
85    SetResourceStrategy {
86        link_id: [u8; 16],
87        strategy: u8,
88    },
89    /// Accept or reject a pending resource (for AcceptApp strategy).
90    AcceptResource {
91        link_id: [u8; 16],
92        resource_hash: Vec<u8>,
93        accept: bool,
94    },
95    /// Send a channel message on a link.
96    SendChannelMessage {
97        link_id: [u8; 16],
98        msgtype: u16,
99        payload: Vec<u8>,
100    },
101    /// Send generic data on a link with a given context.
102    SendOnLink {
103        link_id: [u8; 16],
104        data: Vec<u8>,
105        context: u8,
106    },
107    /// Request a path to a destination from the network.
108    RequestPath {
109        dest_hash: [u8; 16],
110    },
111    /// Register a proof strategy for a destination.
112    RegisterProofStrategy {
113        dest_hash: [u8; 16],
114        strategy: rns_core::types::ProofStrategy,
115        /// Full identity private key (64 bytes) for signing proofs.
116        signing_key: Option<[u8; 64]>,
117    },
118    /// Propose a direct connection to a peer via hole punching.
119    ProposeDirectConnect {
120        link_id: [u8; 16],
121    },
122    /// Set the direct-connect policy.
123    SetDirectConnectPolicy {
124        policy: crate::holepunch::orchestrator::HolePunchPolicy,
125    },
126    /// (Internal) Probe result arrived from a worker thread.
127    HolePunchProbeResult {
128        link_id: [u8; 16],
129        session_id: [u8; 16],
130        observed_addr: std::net::SocketAddr,
131        socket: std::net::UdpSocket,
132    },
133    /// (Internal) Probe failed.
134    HolePunchProbeFailed {
135        link_id: [u8; 16],
136        session_id: [u8; 16],
137    },
138}
139
140/// Queries that can be sent to the driver.
141#[derive(Debug)]
142pub enum QueryRequest {
143    /// Get interface statistics and transport info.
144    InterfaceStats,
145    /// Get path table entries, optionally filtered by max hops.
146    PathTable { max_hops: Option<u8> },
147    /// Get rate table entries.
148    RateTable,
149    /// Look up the next hop for a destination.
150    NextHop { dest_hash: [u8; 16] },
151    /// Look up the next hop interface name for a destination.
152    NextHopIfName { dest_hash: [u8; 16] },
153    /// Get link table entry count.
154    LinkCount,
155    /// Drop a specific path.
156    DropPath { dest_hash: [u8; 16] },
157    /// Drop all paths that route via a given transport hash.
158    DropAllVia { transport_hash: [u8; 16] },
159    /// Drop all announce queues.
160    DropAnnounceQueues,
161    /// Get the transport identity hash.
162    TransportIdentity,
163    /// Get all blackholed identities.
164    GetBlackholed,
165    /// Add an identity to the blackhole list.
166    BlackholeIdentity {
167        identity_hash: [u8; 16],
168        duration_hours: Option<f64>,
169        reason: Option<String>,
170    },
171    /// Remove an identity from the blackhole list.
172    UnblackholeIdentity {
173        identity_hash: [u8; 16],
174    },
175    /// Check if a path exists to a destination.
176    HasPath { dest_hash: [u8; 16] },
177    /// Get hop count to a destination.
178    HopsTo { dest_hash: [u8; 16] },
179    /// Recall identity info for a destination.
180    RecallIdentity { dest_hash: [u8; 16] },
181    /// Get locally registered destinations.
182    LocalDestinations,
183    /// Get active links.
184    Links,
185    /// Get active resource transfers.
186    Resources,
187}
188
189/// Responses to queries.
190#[derive(Debug)]
191pub enum QueryResponse {
192    InterfaceStats(InterfaceStatsResponse),
193    PathTable(Vec<PathTableEntry>),
194    RateTable(Vec<RateTableEntry>),
195    NextHop(Option<NextHopResponse>),
196    NextHopIfName(Option<String>),
197    LinkCount(usize),
198    DropPath(bool),
199    DropAllVia(usize),
200    DropAnnounceQueues,
201    TransportIdentity(Option<[u8; 16]>),
202    Blackholed(Vec<BlackholeInfo>),
203    BlackholeResult(bool),
204    UnblackholeResult(bool),
205    HasPath(bool),
206    HopsTo(Option<u8>),
207    RecallIdentity(Option<crate::destination::AnnouncedIdentity>),
208    LocalDestinations(Vec<LocalDestinationEntry>),
209    Links(Vec<LinkInfoEntry>),
210    Resources(Vec<ResourceInfoEntry>),
211}
212
213/// Interface statistics response.
214#[derive(Debug, Clone)]
215pub struct InterfaceStatsResponse {
216    pub interfaces: Vec<SingleInterfaceStat>,
217    pub transport_id: Option<[u8; 16]>,
218    pub transport_enabled: bool,
219    pub transport_uptime: f64,
220    /// Total received bytes across all interfaces.
221    pub total_rxb: u64,
222    /// Total transmitted bytes across all interfaces.
223    pub total_txb: u64,
224}
225
226/// Statistics for a single interface.
227#[derive(Debug, Clone)]
228pub struct SingleInterfaceStat {
229    pub name: String,
230    pub status: bool,
231    pub mode: u8,
232    pub rxb: u64,
233    pub txb: u64,
234    pub rx_packets: u64,
235    pub tx_packets: u64,
236    pub bitrate: Option<u64>,
237    pub ifac_size: Option<usize>,
238    pub started: f64,
239    /// Incoming announce frequency (per second).
240    pub ia_freq: f64,
241    /// Outgoing announce frequency (per second).
242    pub oa_freq: f64,
243    /// Human-readable interface type string (e.g. "TCPClientInterface").
244    pub interface_type: String,
245}
246
247/// A locally registered destination.
248#[derive(Debug, Clone)]
249pub struct LocalDestinationEntry {
250    pub hash: [u8; 16],
251    pub dest_type: u8,
252}
253
254/// Information about an active link.
255#[derive(Debug, Clone)]
256pub struct LinkInfoEntry {
257    pub link_id: [u8; 16],
258    pub state: String,
259    pub is_initiator: bool,
260    pub dest_hash: [u8; 16],
261    pub remote_identity: Option<[u8; 16]>,
262    pub rtt: Option<f64>,
263}
264
265/// Information about an active resource transfer.
266#[derive(Debug, Clone)]
267pub struct ResourceInfoEntry {
268    pub link_id: [u8; 16],
269    pub direction: String,
270    pub total_parts: usize,
271    pub transferred_parts: usize,
272    pub complete: bool,
273}
274
275/// A single path table entry for query responses.
276#[derive(Debug, Clone)]
277pub struct PathTableEntry {
278    pub hash: [u8; 16],
279    pub timestamp: f64,
280    pub via: [u8; 16],
281    pub hops: u8,
282    pub expires: f64,
283    pub interface: InterfaceId,
284    pub interface_name: String,
285}
286
287/// A single rate table entry for query responses.
288#[derive(Debug, Clone)]
289pub struct RateTableEntry {
290    pub hash: [u8; 16],
291    pub last: f64,
292    pub rate_violations: u32,
293    pub blocked_until: f64,
294    pub timestamps: Vec<f64>,
295}
296
297/// A blackholed identity for query responses.
298#[derive(Debug, Clone)]
299pub struct BlackholeInfo {
300    pub identity_hash: [u8; 16],
301    pub created: f64,
302    pub expires: f64,
303    pub reason: Option<String>,
304}
305
306/// Next hop lookup result.
307#[derive(Debug, Clone)]
308pub struct NextHopResponse {
309    pub next_hop: [u8; 16],
310    pub hops: u8,
311    pub interface: InterfaceId,
312}
313
314impl fmt::Debug for Event {
315    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
316        match self {
317            Event::Frame { interface_id, data } => {
318                f.debug_struct("Frame")
319                    .field("interface_id", interface_id)
320                    .field("data_len", &data.len())
321                    .finish()
322            }
323            Event::InterfaceUp(id, writer, info) => {
324                f.debug_tuple("InterfaceUp")
325                    .field(id)
326                    .field(&writer.is_some())
327                    .field(&info.is_some())
328                    .finish()
329            }
330            Event::InterfaceDown(id) => f.debug_tuple("InterfaceDown").field(id).finish(),
331            Event::Tick => write!(f, "Tick"),
332            Event::Shutdown => write!(f, "Shutdown"),
333            Event::SendOutbound { raw, dest_type, .. } => {
334                f.debug_struct("SendOutbound")
335                    .field("raw_len", &raw.len())
336                    .field("dest_type", dest_type)
337                    .finish()
338            }
339            Event::RegisterDestination { dest_hash, dest_type } => {
340                f.debug_struct("RegisterDestination")
341                    .field("dest_hash", dest_hash)
342                    .field("dest_type", dest_type)
343                    .finish()
344            }
345            Event::DeregisterDestination { dest_hash } => {
346                f.debug_struct("DeregisterDestination")
347                    .field("dest_hash", dest_hash)
348                    .finish()
349            }
350            Event::DeregisterLinkDestination { dest_hash } => {
351                f.debug_struct("DeregisterLinkDestination")
352                    .field("dest_hash", dest_hash)
353                    .finish()
354            }
355            Event::Query(req, _) => {
356                f.debug_tuple("Query")
357                    .field(req)
358                    .finish()
359            }
360            Event::RegisterLinkDestination { dest_hash, .. } => {
361                f.debug_struct("RegisterLinkDestination")
362                    .field("dest_hash", dest_hash)
363                    .finish()
364            }
365            Event::RegisterRequestHandler { path, .. } => {
366                f.debug_struct("RegisterRequestHandler")
367                    .field("path", path)
368                    .finish()
369            }
370            Event::CreateLink { dest_hash, .. } => {
371                f.debug_struct("CreateLink")
372                    .field("dest_hash", dest_hash)
373                    .finish()
374            }
375            Event::SendRequest { link_id, path, .. } => {
376                f.debug_struct("SendRequest")
377                    .field("link_id", link_id)
378                    .field("path", path)
379                    .finish()
380            }
381            Event::IdentifyOnLink { link_id, .. } => {
382                f.debug_struct("IdentifyOnLink")
383                    .field("link_id", link_id)
384                    .finish()
385            }
386            Event::TeardownLink { link_id } => {
387                f.debug_struct("TeardownLink")
388                    .field("link_id", link_id)
389                    .finish()
390            }
391            Event::SendResource { link_id, data, .. } => {
392                f.debug_struct("SendResource")
393                    .field("link_id", link_id)
394                    .field("data_len", &data.len())
395                    .finish()
396            }
397            Event::SetResourceStrategy { link_id, strategy } => {
398                f.debug_struct("SetResourceStrategy")
399                    .field("link_id", link_id)
400                    .field("strategy", strategy)
401                    .finish()
402            }
403            Event::AcceptResource { link_id, accept, .. } => {
404                f.debug_struct("AcceptResource")
405                    .field("link_id", link_id)
406                    .field("accept", accept)
407                    .finish()
408            }
409            Event::SendChannelMessage { link_id, msgtype, payload } => {
410                f.debug_struct("SendChannelMessage")
411                    .field("link_id", link_id)
412                    .field("msgtype", msgtype)
413                    .field("payload_len", &payload.len())
414                    .finish()
415            }
416            Event::SendOnLink { link_id, data, context } => {
417                f.debug_struct("SendOnLink")
418                    .field("link_id", link_id)
419                    .field("data_len", &data.len())
420                    .field("context", context)
421                    .finish()
422            }
423            Event::RequestPath { dest_hash } => {
424                f.debug_struct("RequestPath")
425                    .field("dest_hash", dest_hash)
426                    .finish()
427            }
428            Event::RegisterProofStrategy { dest_hash, strategy, .. } => {
429                f.debug_struct("RegisterProofStrategy")
430                    .field("dest_hash", dest_hash)
431                    .field("strategy", strategy)
432                    .finish()
433            }
434            Event::ProposeDirectConnect { link_id } => {
435                f.debug_struct("ProposeDirectConnect")
436                    .field("link_id", link_id)
437                    .finish()
438            }
439            Event::SetDirectConnectPolicy { .. } => {
440                write!(f, "SetDirectConnectPolicy")
441            }
442            Event::HolePunchProbeResult { link_id, session_id, observed_addr, .. } => {
443                f.debug_struct("HolePunchProbeResult")
444                    .field("link_id", link_id)
445                    .field("session_id", session_id)
446                    .field("observed_addr", observed_addr)
447                    .finish()
448            }
449            Event::HolePunchProbeFailed { link_id, session_id } => {
450                f.debug_struct("HolePunchProbeFailed")
451                    .field("link_id", link_id)
452                    .field("session_id", session_id)
453                    .finish()
454            }
455        }
456    }
457}
458
459pub type EventSender = mpsc::Sender<Event>;
460pub type EventReceiver = mpsc::Receiver<Event>;
461
462pub fn channel() -> (EventSender, EventReceiver) {
463    mpsc::channel()
464}