Skip to main content

rns_net/common/
event.rs

1//! Event types for the driver loop — generic over the writer type.
2
3use std::fmt;
4use std::net::IpAddr;
5use std::sync::mpsc;
6use std::time::Duration;
7
8use rns_core::announce::ValidatedAnnounce;
9use rns_core::transport::announce_verify_queue::AnnounceVerifyKey;
10use rns_core::transport::types::{InterfaceId, InterfaceInfo};
11
12use crate::common::link_manager::RequestResponse;
13
14#[derive(Debug, Clone, Default, PartialEq)]
15pub struct InterfaceTelemetry {
16    pub cpu_load: Option<f64>,
17    pub mem_load: Option<f64>,
18    pub switch_id: Option<[u8; 4]>,
19    pub endpoint_id: Option<[u8; 8]>,
20    pub via_switch_id: Option<[u8; 4]>,
21    pub peers: Option<usize>,
22}
23
24#[derive(Debug, Clone)]
25pub struct DynamicInterfaceRegistration {
26    pub info: InterfaceInfo,
27    pub interface_type: String,
28    pub parent_id: InterfaceId,
29    pub telemetry: InterfaceTelemetry,
30    pub ifac: Option<crate::ifac::IfacState>,
31}
32
33/// Policy for handling incoming direct-connect proposals.
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
35pub enum HolePunchPolicy {
36    /// Reject all proposals.
37    Reject,
38    /// Accept all proposals automatically.
39    AcceptAll,
40    /// Ask the application callback.
41    AskApp,
42}
43
44impl Default for HolePunchPolicy {
45    fn default() -> Self {
46        HolePunchPolicy::AcceptAll
47    }
48}
49
50/// Scalar runtime-config value.
51#[derive(Debug, Clone, PartialEq)]
52pub enum RuntimeConfigValue {
53    Int(i64),
54    Float(f64),
55    Bool(bool),
56    String(String),
57    Null,
58}
59
60/// Source of a runtime-config value.
61#[derive(Debug, Clone, Copy, PartialEq, Eq)]
62pub enum RuntimeConfigSource {
63    Startup,
64    RuntimeOverride,
65}
66
67/// How a runtime-config change applies.
68#[derive(Debug, Clone, Copy, PartialEq, Eq)]
69pub enum RuntimeConfigApplyMode {
70    Immediate,
71    NewConnectionsOnly,
72    NextReconnect,
73    RestartRequired,
74}
75
76/// A runtime-config entry exposed by the daemon.
77#[derive(Debug, Clone, PartialEq)]
78pub struct RuntimeConfigEntry {
79    pub key: String,
80    pub value: RuntimeConfigValue,
81    pub default: RuntimeConfigValue,
82    pub source: RuntimeConfigSource,
83    pub apply_mode: RuntimeConfigApplyMode,
84    pub description: Option<String>,
85}
86
87/// Runtime-config mutation error.
88#[derive(Debug, Clone, PartialEq, Eq)]
89pub struct RuntimeConfigError {
90    pub code: RuntimeConfigErrorCode,
91    pub message: String,
92}
93
94/// Category of runtime-config mutation error.
95#[derive(Debug, Clone, Copy, PartialEq, Eq)]
96pub enum RuntimeConfigErrorCode {
97    UnknownKey,
98    InvalidType,
99    InvalidValue,
100    Unsupported,
101    NotFound,
102    ApplyFailed,
103}
104
105#[derive(Debug, Clone, Copy, PartialEq, Eq)]
106pub enum LifecycleState {
107    Active,
108    Draining,
109    Stopping,
110    Stopped,
111}
112
113#[derive(Debug, Clone, PartialEq)]
114pub struct DrainStatus {
115    pub state: LifecycleState,
116    pub drain_age_seconds: Option<f64>,
117    pub deadline_remaining_seconds: Option<f64>,
118    pub drain_complete: bool,
119    pub interface_writer_queued_frames: usize,
120    pub provider_backlog_events: usize,
121    pub provider_consumer_queued_events: usize,
122    pub detail: Option<String>,
123}
124
125/// Events sent to the driver thread.
126///
127/// `W` is the writer type (e.g. `Box<dyn Writer>` for sync,
128/// or a channel sender for async).
129pub enum Event<W: Send> {
130    /// A decoded frame arrived from an interface.
131    Frame {
132        interface_id: InterfaceId,
133        data: Vec<u8>,
134        rssi: Option<i16>,
135        snr: Option<f32>,
136    },
137    /// (Internal) An announce was verified off-thread and is ready for driver-side processing.
138    AnnounceVerified {
139        key: AnnounceVerifyKey,
140        validated: ValidatedAnnounce,
141        sig_cache_key: [u8; 32],
142    },
143    /// (Internal) An announce failed off-thread verification.
144    AnnounceVerifyFailed {
145        key: AnnounceVerifyKey,
146        sig_cache_key: [u8; 32],
147    },
148    /// An interface came online after (re)connecting.
149    /// Carries a new writer if the connection was re-established.
150    /// Carries InterfaceInfo if this is a new dynamic interface (e.g. TCP server client).
151    InterfaceUp(InterfaceId, Option<W>, Option<InterfaceInfo>),
152    /// Register a dynamic interface with an exact type and parent identity.
153    DynamicInterfaceUp {
154        id: InterfaceId,
155        writer: W,
156        registration: DynamicInterfaceRegistration,
157    },
158    /// Update optional device/interface telemetry without replacing counters.
159    InterfaceTelemetry {
160        interface_id: InterfaceId,
161        telemetry: InterfaceTelemetry,
162    },
163    /// An interface went offline (socket closed, error).
164    InterfaceDown(InterfaceId),
165    /// Periodic maintenance tick (1s interval).
166    Tick,
167    /// Enter drain mode and stop admitting new work.
168    BeginDrain { timeout: Duration },
169    /// Shut down the driver loop.
170    Shutdown,
171    /// Send an outbound packet.
172    SendOutbound {
173        raw: Vec<u8>,
174        dest_type: u8,
175        attached_interface: Option<InterfaceId>,
176    },
177    /// Register a local destination.
178    RegisterDestination { dest_hash: [u8; 16], dest_type: u8 },
179    /// Remember the latest explicit SINGLE announce for shared-client replay.
180    StoreSharedAnnounce {
181        dest_hash: [u8; 16],
182        name_hash: [u8; 10],
183        identity_prv_key: [u8; 64],
184        app_data: Option<Vec<u8>>,
185    },
186    /// Deregister a local destination.
187    DeregisterDestination { dest_hash: [u8; 16] },
188    /// Deregister a link destination (stop accepting incoming links).
189    DeregisterLinkDestination { dest_hash: [u8; 16] },
190    /// Query driver state. Response is sent via the provided channel.
191    Query(QueryRequest, mpsc::Sender<QueryResponse>),
192    /// Register a link destination (accepts incoming LINKREQUEST).
193    RegisterLinkDestination {
194        dest_hash: [u8; 16],
195        sig_prv_bytes: [u8; 32],
196        sig_pub_bytes: [u8; 32],
197        resource_strategy: u8,
198        max_request_size: Option<usize>,
199    },
200    /// Register a request handler for a path on established links.
201    RegisterRequestHandler {
202        path: String,
203        allowed_list: Option<Vec<[u8; 16]>>,
204        handler: Box<
205            dyn Fn([u8; 16], &str, &[u8], Option<&([u8; 16], [u8; 64])>) -> Option<Vec<u8>> + Send,
206        >,
207    },
208    /// Register a request handler that may return resource responses with metadata.
209    RegisterRequestHandlerResponse {
210        path: String,
211        allowed_list: Option<Vec<[u8; 16]>>,
212        handler: Box<
213            dyn Fn([u8; 16], &str, &[u8], Option<&([u8; 16], [u8; 64])>) -> Option<RequestResponse>
214                + Send,
215        >,
216    },
217    /// Create an outbound link. Response sends (link_id) back.
218    CreateLink {
219        dest_hash: [u8; 16],
220        dest_sig_pub_bytes: [u8; 32],
221        response_tx: mpsc::Sender<[u8; 16]>,
222    },
223    /// Send a request on an established link.
224    SendRequest {
225        link_id: [u8; 16],
226        path: String,
227        data: Vec<u8>,
228        max_response_size: Option<usize>,
229    },
230    /// Identify on a link (send identity to remote peer).
231    IdentifyOnLink {
232        link_id: [u8; 16],
233        identity_prv_key: [u8; 64],
234    },
235    /// Tear down a link.
236    TeardownLink { link_id: [u8; 16] },
237    /// Send a resource on a link.
238    SendResource {
239        link_id: [u8; 16],
240        data: Vec<u8>,
241        metadata: Option<Vec<u8>>,
242        auto_compress: bool,
243    },
244    /// Set the resource acceptance strategy for a link.
245    SetResourceStrategy { link_id: [u8; 16], strategy: u8 },
246    /// Accept or reject a pending resource (for AcceptApp strategy).
247    AcceptResource {
248        link_id: [u8; 16],
249        resource_hash: Vec<u8>,
250        accept: bool,
251    },
252    /// Send a channel message on a link.
253    SendChannelMessage {
254        link_id: [u8; 16],
255        msgtype: u16,
256        payload: Vec<u8>,
257        response_tx: mpsc::Sender<Result<(), String>>,
258    },
259    /// Send generic data on a link with a given context.
260    SendOnLink {
261        link_id: [u8; 16],
262        data: Vec<u8>,
263        context: u8,
264    },
265    /// Request a path to a destination from the network.
266    RequestPath { dest_hash: [u8; 16] },
267    /// Register a proof strategy for a destination.
268    RegisterProofStrategy {
269        dest_hash: [u8; 16],
270        strategy: rns_core::types::ProofStrategy,
271        /// Full identity private key (64 bytes) for signing proofs.
272        signing_key: Option<[u8; 64]>,
273    },
274    /// Propose a direct connection to a peer via hole punching.
275    ProposeDirectConnect { link_id: [u8; 16] },
276    /// Set the direct-connect policy.
277    SetDirectConnectPolicy { policy: HolePunchPolicy },
278    /// (Internal) Probe result arrived from a worker thread.
279    HolePunchProbeResult {
280        link_id: [u8; 16],
281        session_id: [u8; 16],
282        observed_addr: std::net::SocketAddr,
283        socket: std::net::UdpSocket,
284        /// The probe server that responded successfully.
285        probe_server: std::net::SocketAddr,
286    },
287    /// (Internal) Probe failed.
288    HolePunchProbeFailed {
289        link_id: [u8; 16],
290        session_id: [u8; 16],
291    },
292    /// An interface's configuration changed (placeholder for future use).
293    InterfaceConfigChanged(InterfaceId),
294    /// A backbone server accepted a new inbound peer connection.
295    BackbonePeerConnected {
296        server_interface_id: InterfaceId,
297        peer_interface_id: InterfaceId,
298        peer_ip: IpAddr,
299        peer_port: u16,
300    },
301    /// A backbone peer connection closed for any reason.
302    BackbonePeerDisconnected {
303        server_interface_id: InterfaceId,
304        peer_interface_id: InterfaceId,
305        peer_ip: IpAddr,
306        peer_port: u16,
307        connected_for: Duration,
308        had_received_data: bool,
309    },
310    /// A backbone peer was disconnected for idling without sending data.
311    BackbonePeerIdleTimeout {
312        server_interface_id: InterfaceId,
313        peer_interface_id: InterfaceId,
314        peer_ip: IpAddr,
315        peer_port: u16,
316        connected_for: Duration,
317    },
318    /// A backbone peer was disconnected because its writer stalled.
319    BackbonePeerWriteStall {
320        server_interface_id: InterfaceId,
321        peer_interface_id: InterfaceId,
322        peer_ip: IpAddr,
323        peer_port: u16,
324        connected_for: Duration,
325    },
326    /// A backbone peer IP was penalized due to abusive behavior.
327    BackbonePeerPenalty {
328        server_interface_id: InterfaceId,
329        peer_ip: IpAddr,
330        penalty_level: u8,
331        blacklist_for: Duration,
332    },
333    /// Load an in-memory WASM hook at runtime.
334    LoadHook {
335        name: String,
336        wasm_bytes: Vec<u8>,
337        attach_point: String,
338        priority: i32,
339        response_tx: mpsc::Sender<Result<(), String>>,
340    },
341    /// Load a hook from a server-local filesystem path at runtime.
342    LoadHookFile {
343        name: String,
344        path: String,
345        hook_type: String,
346        attach_point: String,
347        priority: i32,
348        response_tx: mpsc::Sender<Result<(), String>>,
349    },
350    /// Load a registered built-in hook by ID at runtime.
351    LoadBuiltinHook {
352        name: String,
353        builtin_id: String,
354        attach_point: String,
355        priority: i32,
356        response_tx: mpsc::Sender<Result<(), String>>,
357    },
358    /// Unload a hook at runtime.
359    UnloadHook {
360        name: String,
361        attach_point: String,
362        response_tx: mpsc::Sender<Result<(), String>>,
363    },
364    /// Reload an in-memory WASM hook at runtime (detach + recompile + reattach with same priority).
365    ReloadHook {
366        name: String,
367        attach_point: String,
368        wasm_bytes: Vec<u8>,
369        response_tx: mpsc::Sender<Result<(), String>>,
370    },
371    /// Reload a hook from a server-local filesystem path at runtime.
372    ReloadHookFile {
373        name: String,
374        attach_point: String,
375        path: String,
376        hook_type: String,
377        response_tx: mpsc::Sender<Result<(), String>>,
378    },
379    /// Reload a registered built-in hook by ID at runtime.
380    ReloadBuiltinHook {
381        name: String,
382        attach_point: String,
383        builtin_id: String,
384        response_tx: mpsc::Sender<Result<(), String>>,
385    },
386    /// Enable or disable a loaded hook at runtime.
387    SetHookEnabled {
388        name: String,
389        attach_point: String,
390        enabled: bool,
391        response_tx: mpsc::Sender<Result<(), String>>,
392    },
393    /// Update the priority of a loaded hook at runtime.
394    SetHookPriority {
395        name: String,
396        attach_point: String,
397        priority: i32,
398        response_tx: mpsc::Sender<Result<(), String>>,
399    },
400    /// List all loaded hooks.
401    ListHooks {
402        response_tx: mpsc::Sender<Vec<HookInfo>>,
403    },
404}
405
406/// Information about a loaded hook program.
407#[derive(Debug, Clone)]
408pub struct HookInfo {
409    pub name: String,
410    pub hook_type: String,
411    pub attach_point: String,
412    pub priority: i32,
413    pub enabled: bool,
414    pub consecutive_traps: u32,
415}
416
417/// Live behavioral state for a backbone peer IP.
418#[derive(Debug, Clone, PartialEq)]
419pub struct BackbonePeerStateEntry {
420    pub interface_name: String,
421    pub peer_ip: IpAddr,
422    pub connected_count: usize,
423    pub blacklisted_remaining_secs: Option<f64>,
424    pub blacklist_reason: Option<String>,
425    pub reject_count: u64,
426}
427
428/// Hook-visible snapshot of a backbone peer lifecycle event.
429#[derive(Debug, Clone, PartialEq, Eq)]
430pub struct BackbonePeerHookEvent {
431    pub server_interface_id: InterfaceId,
432    pub peer_interface_id: Option<InterfaceId>,
433    pub peer_ip: IpAddr,
434    pub peer_port: u16,
435    pub connected_for: Duration,
436    pub had_received_data: bool,
437    pub penalty_level: u8,
438    pub blacklist_for: Duration,
439}
440
441#[derive(Debug, Clone, PartialEq, Eq)]
442pub struct BackboneInterfaceEntry {
443    pub interface_id: InterfaceId,
444    pub interface_name: String,
445}
446
447#[derive(Debug, Clone, PartialEq)]
448pub struct KnownDestinationEntry {
449    pub dest_hash: [u8; 16],
450    pub identity_hash: [u8; 16],
451    pub public_key: [u8; 64],
452    pub app_data: Option<Vec<u8>>,
453    pub hops: u8,
454    pub received_at: f64,
455    pub receiving_interface: InterfaceId,
456    pub was_used: bool,
457    pub last_used_at: Option<f64>,
458    pub retained: bool,
459}
460
461#[derive(Debug, Clone, PartialEq, Eq)]
462pub struct ProviderBridgeConsumerStats {
463    pub id: u64,
464    pub connected: bool,
465    pub queue_len: usize,
466    pub queued_bytes: usize,
467    pub dropped_pending: u64,
468    pub dropped_total: u64,
469    pub queue_max_events: usize,
470    pub queue_max_bytes: usize,
471}
472
473#[derive(Debug, Clone, PartialEq, Eq)]
474pub struct ProviderBridgeStats {
475    pub connected: bool,
476    pub consumer_count: usize,
477    pub queue_max_events: usize,
478    pub queue_max_bytes: usize,
479    pub backlog_len: usize,
480    pub backlog_bytes: usize,
481    pub backlog_dropped_pending: u64,
482    pub backlog_dropped_total: u64,
483    pub total_disconnect_count: u64,
484    pub consumers: Vec<ProviderBridgeConsumerStats>,
485}
486
487/// Queries that can be sent to the driver.
488#[derive(Debug)]
489pub enum QueryRequest {
490    /// Get interface statistics and transport info.
491    InterfaceStats,
492    /// Get path table entries, optionally filtered by max hops.
493    PathTable { max_hops: Option<u8> },
494    /// Get rate table entries.
495    RateTable,
496    /// Look up the next hop for a destination.
497    NextHop { dest_hash: [u8; 16] },
498    /// Look up the next hop interface name for a destination.
499    NextHopIfName { dest_hash: [u8; 16] },
500    /// Get link table entry count.
501    LinkCount,
502    /// Drop a specific path.
503    DropPath { dest_hash: [u8; 16] },
504    /// Drop all paths that route via a given transport hash.
505    DropAllVia { transport_hash: [u8; 16] },
506    /// Drop all announce queues.
507    DropAnnounceQueues,
508    /// Get the transport identity hash.
509    TransportIdentity,
510    /// Snapshot restart-relevant transport routing state.
511    TransportStateSnapshot,
512    /// Get all blackholed identities.
513    GetBlackholed,
514    /// Add an identity to the blackhole list.
515    BlackholeIdentity {
516        identity_hash: [u8; 16],
517        duration_hours: Option<f64>,
518        reason: Option<String>,
519    },
520    /// Remove an identity from the blackhole list.
521    UnblackholeIdentity { identity_hash: [u8; 16] },
522    /// Check if a path exists to a destination.
523    HasPath { dest_hash: [u8; 16] },
524    /// Get hop count to a destination.
525    HopsTo { dest_hash: [u8; 16] },
526    /// Recall identity info for a destination.
527    RecallIdentity { dest_hash: [u8; 16] },
528    /// List known-destination lifecycle state.
529    KnownDestinations,
530    /// Get locally registered destinations.
531    LocalDestinations,
532    /// Get active links.
533    Links,
534    /// Get active resource transfers.
535    Resources,
536    /// Inject a path entry into the path table.
537    InjectPath {
538        dest_hash: [u8; 16],
539        next_hop: [u8; 16],
540        hops: u8,
541        expires: f64,
542        interface_name: String,
543        packet_hash: [u8; 32],
544    },
545    /// Inject an identity into the known destinations cache.
546    InjectIdentity {
547        dest_hash: [u8; 16],
548        identity_hash: [u8; 16],
549        public_key: [u8; 64],
550        app_data: Option<Vec<u8>>,
551        hops: u8,
552        received_at: f64,
553    },
554    /// Restore a known destination with full lifecycle state.
555    RestoreKnownDestination(KnownDestinationEntry),
556    /// Mark a known destination as explicitly retained.
557    RetainKnownDestination { dest_hash: [u8; 16] },
558    /// Mark all known destinations announced by an identity as retained.
559    RetainIdentity { identity_hash: [u8; 16] },
560    /// Clear the retained flag on a known destination.
561    UnretainKnownDestination { dest_hash: [u8; 16] },
562    /// Mark a known destination as used.
563    MarkKnownDestinationUsed { dest_hash: [u8; 16] },
564    /// Get discovered interfaces.
565    DiscoveredInterfaces {
566        only_available: bool,
567        only_transport: bool,
568    },
569    /// Send a probe packet to a destination and return (packet_hash, hops).
570    SendProbe {
571        dest_hash: [u8; 16],
572        payload_size: usize,
573    },
574    /// Check if a proof was received for a probe packet.
575    CheckProof { packet_hash: [u8; 32] },
576    /// List runtime-config entries currently supported by the daemon.
577    ListRuntimeConfig,
578    /// Get a single runtime-config entry by key.
579    GetRuntimeConfig { key: String },
580    /// Set a runtime-config value by key.
581    SetRuntimeConfig {
582        key: String,
583        value: RuntimeConfigValue,
584    },
585    /// Reset a runtime-config value to its startup/default value.
586    ResetRuntimeConfig { key: String },
587    /// List live backbone peer state, optionally filtered to one interface.
588    BackbonePeerState { interface_name: Option<String> },
589    /// List registered backbone server interfaces.
590    BackboneInterfaces,
591    /// Report live provider-bridge queue/drop state.
592    ProviderBridgeStats,
593    /// Report current lifecycle/drain status.
594    DrainStatus,
595    /// Clear live backbone peer state for one interface/IP pair.
596    ClearBackbonePeerState {
597        interface_name: String,
598        peer_ip: IpAddr,
599    },
600    /// Blacklist a backbone peer IP for a duration.
601    BlacklistBackbonePeer {
602        interface_name: String,
603        peer_ip: IpAddr,
604        duration: Duration,
605        reason: String,
606        penalty_level: u8,
607    },
608}
609
610/// Responses to queries.
611#[derive(Debug)]
612pub enum QueryResponse {
613    InterfaceStats(InterfaceStatsResponse),
614    PathTable(Vec<PathTableEntry>),
615    RateTable(Vec<RateTableEntry>),
616    NextHop(Option<NextHopResponse>),
617    NextHopIfName(Option<String>),
618    LinkCount(usize),
619    DropPath(bool),
620    DropAllVia(usize),
621    DropAnnounceQueues,
622    TransportIdentity(Option<[u8; 16]>),
623    TransportStateSnapshot(rns_core::transport::persistence::TransportStateSnapshot),
624    Blackholed(Vec<BlackholeInfo>),
625    BlackholeResult(bool),
626    UnblackholeResult(bool),
627    HasPath(bool),
628    HopsTo(Option<u8>),
629    RecallIdentity(Option<crate::common::destination::AnnouncedIdentity>),
630    KnownDestinations(Vec<KnownDestinationEntry>),
631    LocalDestinations(Vec<LocalDestinationEntry>),
632    Links(Vec<LinkInfoEntry>),
633    Resources(Vec<ResourceInfoEntry>),
634    InjectPath(bool),
635    InjectIdentity(bool),
636    RestoreKnownDestination(bool),
637    RetainKnownDestination(bool),
638    RetainIdentity(bool),
639    UnretainKnownDestination(bool),
640    MarkKnownDestinationUsed(bool),
641    /// List of discovered interfaces.
642    DiscoveredInterfaces(Vec<crate::common::discovery::DiscoveredInterface>),
643    /// Probe sent: (packet_hash, hops) or None if identity unknown.
644    SendProbe(Option<([u8; 32], u8)>),
645    /// Proof check: RTT if received, None if still pending.
646    CheckProof(Option<f64>),
647    /// Runtime-config entries currently supported by the daemon.
648    RuntimeConfigList(Vec<RuntimeConfigEntry>),
649    /// A specific runtime-config entry, or None if the key is unknown.
650    RuntimeConfigEntry(Option<RuntimeConfigEntry>),
651    /// Result of setting a runtime-config value.
652    RuntimeConfigSet(Result<RuntimeConfigEntry, RuntimeConfigError>),
653    /// Result of resetting a runtime-config value.
654    RuntimeConfigReset(Result<RuntimeConfigEntry, RuntimeConfigError>),
655    /// Live backbone peer state entries.
656    BackbonePeerState(Vec<BackbonePeerStateEntry>),
657    /// Registered backbone server interfaces.
658    BackboneInterfaces(Vec<BackboneInterfaceEntry>),
659    /// Live provider-bridge queue/drop state if enabled.
660    ProviderBridgeStats(Option<ProviderBridgeStats>),
661    /// Current lifecycle/drain status.
662    DrainStatus(DrainStatus),
663    /// Result of clearing one backbone peer state entry.
664    ClearBackbonePeerState(bool),
665    /// Result of blacklisting a backbone peer.
666    BlacklistBackbonePeer(bool),
667}
668
669/// Interface statistics response.
670#[derive(Debug, Clone)]
671pub struct InterfaceStatsResponse {
672    pub interfaces: Vec<SingleInterfaceStat>,
673    pub transport_id: Option<[u8; 16]>,
674    pub transport_enabled: bool,
675    pub transport_uptime: f64,
676    /// Total received bytes across all interfaces.
677    pub total_rxb: u64,
678    /// Total transmitted bytes across all interfaces.
679    pub total_txb: u64,
680    /// Probe responder destination hash (if enabled).
681    pub probe_responder: Option<[u8; 16]>,
682    /// Outbound Backbone peer-pool state, if enabled.
683    pub backbone_peer_pool: Option<BackbonePeerPoolStatus>,
684}
685
686/// Runtime status for the outbound Backbone peer pool.
687#[derive(Debug, Clone)]
688pub struct BackbonePeerPoolStatus {
689    pub max_connected: usize,
690    pub active_count: usize,
691    pub standby_count: usize,
692    pub cooldown_count: usize,
693    pub members: Vec<BackbonePeerPoolMemberStatus>,
694}
695
696/// Runtime status for one outbound Backbone peer-pool member.
697#[derive(Debug, Clone)]
698pub struct BackbonePeerPoolMemberStatus {
699    pub name: String,
700    pub remote: String,
701    pub source: String,
702    pub priority: u8,
703    pub state: String,
704    pub interface_id: Option<u64>,
705    pub failure_count: usize,
706    pub last_error: Option<String>,
707    pub cooldown_remaining_seconds: Option<f64>,
708}
709
710/// Statistics for a single interface.
711#[derive(Debug, Clone)]
712pub struct SingleInterfaceStat {
713    pub id: u64,
714    pub name: String,
715    pub status: bool,
716    pub mode: u8,
717    /// Signed interface preference used by path selection.
718    pub gravity: i64,
719    /// Whether boundary ingress announces may propagate to internal interfaces.
720    pub announces_to_internal: Option<bool>,
721    pub rxb: u64,
722    pub txb: u64,
723    pub rx_packets: u64,
724    pub tx_packets: u64,
725    pub cpu_load: Option<f64>,
726    pub mem_load: Option<f64>,
727    pub switch_id: Option<[u8; 4]>,
728    pub endpoint_id: Option<[u8; 8]>,
729    pub via_switch_id: Option<[u8; 4]>,
730    pub peers: Option<usize>,
731    pub bitrate: Option<u64>,
732    pub ifac_size: Option<usize>,
733    pub started: f64,
734    /// Incoming announce frequency (per second).
735    pub ia_freq: f64,
736    /// Outgoing announce frequency (per second).
737    pub oa_freq: f64,
738    /// Incoming path request frequency (per second).
739    pub ip_freq: f64,
740    /// Outgoing path request frequency (per second).
741    pub op_freq: f64,
742    /// Outgoing path request samples currently retained.
743    pub op_samples: usize,
744    /// Whether announce ingress-control burst limiting is currently active.
745    pub burst_active: bool,
746    /// Timestamp when announce ingress-control burst limiting activated.
747    pub burst_activated: f64,
748    /// Whether path-request ingress-control burst limiting is currently active.
749    pub pr_burst_active: bool,
750    /// Timestamp when path-request burst limiting activated.
751    pub pr_burst_activated: f64,
752    /// Connected client count for aggregate server interfaces, if reported.
753    pub clients: Option<u64>,
754    /// Fast-flapping IPs currently blocked by an aggregate server interface.
755    pub blocked_ips: Option<u64>,
756    /// Sorted textual IP addresses currently blocked for fast flapping.
757    pub blocked_ip_list: Option<Vec<String>>,
758    /// Target interval for outgoing announce rate control, in seconds.
759    pub announce_rate_target: Option<f64>,
760    /// Announce-rate control grace count.
761    pub announce_rate_grace: u32,
762    /// Announce-rate control penalty, in seconds.
763    pub announce_rate_penalty: f64,
764    /// Human-readable interface type string (e.g. "TCPClientInterface").
765    pub interface_type: String,
766}
767
768/// A locally registered destination.
769#[derive(Debug, Clone)]
770pub struct LocalDestinationEntry {
771    pub hash: [u8; 16],
772    pub dest_type: u8,
773}
774
775/// Information about an active link.
776#[derive(Debug, Clone)]
777pub struct LinkInfoEntry {
778    pub link_id: [u8; 16],
779    pub state: String,
780    pub is_initiator: bool,
781    pub dest_hash: [u8; 16],
782    pub remote_identity: Option<[u8; 16]>,
783    pub rtt: Option<f64>,
784    pub expected_hops: u8,
785    pub tx_packets: u64,
786    pub rx_packets: u64,
787    pub tx_bytes: u64,
788    pub rx_bytes: u64,
789    pub channel_window: Option<u16>,
790    pub channel_outstanding: Option<usize>,
791    pub pending_channel_packets: usize,
792    pub channel_send_ok: u64,
793    pub channel_send_not_ready: u64,
794    pub channel_send_too_big: u64,
795    pub channel_send_other_error: u64,
796    pub channel_messages_received: u64,
797    pub channel_proofs_sent: u64,
798    pub channel_proofs_received: u64,
799}
800
801/// Information about an active resource transfer.
802#[derive(Debug, Clone)]
803pub struct ResourceInfoEntry {
804    pub link_id: [u8; 16],
805    pub direction: String,
806    pub total_parts: usize,
807    pub transferred_parts: usize,
808    pub complete: bool,
809}
810
811/// A single path table entry for query responses.
812#[derive(Debug, Clone)]
813pub struct PathTableEntry {
814    pub hash: [u8; 16],
815    pub timestamp: f64,
816    pub via: [u8; 16],
817    pub hops: u8,
818    pub expires: f64,
819    pub interface: InterfaceId,
820    pub interface_name: String,
821}
822
823/// A single rate table entry for query responses.
824#[derive(Debug, Clone)]
825pub struct RateTableEntry {
826    pub hash: [u8; 16],
827    pub last: f64,
828    pub rate_violations: u32,
829    pub blocked_until: f64,
830    pub timestamps: Vec<f64>,
831}
832
833/// A blackholed identity for query responses.
834#[derive(Debug, Clone)]
835pub struct BlackholeInfo {
836    pub identity_hash: [u8; 16],
837    pub created: f64,
838    pub expires: f64,
839    pub reason: Option<String>,
840}
841
842/// Next hop lookup result.
843#[derive(Debug, Clone)]
844pub struct NextHopResponse {
845    pub next_hop: [u8; 16],
846    pub hops: u8,
847    pub interface: InterfaceId,
848}
849
850impl<W: Send> fmt::Debug for Event<W> {
851    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
852        match self {
853            Event::Frame {
854                interface_id,
855                data,
856                rssi,
857                snr,
858            } => f
859                .debug_struct("Frame")
860                .field("interface_id", interface_id)
861                .field("data_len", &data.len())
862                .field("rssi", rssi)
863                .field("snr", snr)
864                .finish(),
865            Event::AnnounceVerified { key, .. } => f
866                .debug_struct("AnnounceVerified")
867                .field("destination_hash", &key.destination_hash)
868                .field("received_from", &key.received_from)
869                .finish(),
870            Event::AnnounceVerifyFailed { key, .. } => f
871                .debug_struct("AnnounceVerifyFailed")
872                .field("destination_hash", &key.destination_hash)
873                .field("received_from", &key.received_from)
874                .finish(),
875            Event::InterfaceUp(id, writer, info) => f
876                .debug_tuple("InterfaceUp")
877                .field(id)
878                .field(&writer.is_some())
879                .field(&info.is_some())
880                .finish(),
881            Event::DynamicInterfaceUp {
882                id, registration, ..
883            } => f
884                .debug_struct("DynamicInterfaceUp")
885                .field("id", id)
886                .field("type", &registration.interface_type)
887                .field("parent_id", &registration.parent_id)
888                .finish(),
889            Event::InterfaceTelemetry {
890                interface_id,
891                telemetry,
892            } => f
893                .debug_struct("InterfaceTelemetry")
894                .field("interface_id", interface_id)
895                .field("telemetry", telemetry)
896                .finish(),
897            Event::InterfaceDown(id) => f.debug_tuple("InterfaceDown").field(id).finish(),
898            Event::Tick => write!(f, "Tick"),
899            Event::BeginDrain { timeout } => f
900                .debug_struct("BeginDrain")
901                .field("timeout", timeout)
902                .finish(),
903            Event::Shutdown => write!(f, "Shutdown"),
904            Event::SendOutbound { raw, dest_type, .. } => f
905                .debug_struct("SendOutbound")
906                .field("raw_len", &raw.len())
907                .field("dest_type", dest_type)
908                .finish(),
909            Event::RegisterDestination {
910                dest_hash,
911                dest_type,
912            } => f
913                .debug_struct("RegisterDestination")
914                .field("dest_hash", dest_hash)
915                .field("dest_type", dest_type)
916                .finish(),
917            Event::StoreSharedAnnounce {
918                dest_hash,
919                name_hash,
920                app_data,
921                ..
922            } => f
923                .debug_struct("StoreSharedAnnounce")
924                .field("dest_hash", dest_hash)
925                .field("name_hash", name_hash)
926                .field("app_data_len", &app_data.as_ref().map(|d| d.len()))
927                .finish(),
928            Event::DeregisterDestination { dest_hash } => f
929                .debug_struct("DeregisterDestination")
930                .field("dest_hash", dest_hash)
931                .finish(),
932            Event::DeregisterLinkDestination { dest_hash } => f
933                .debug_struct("DeregisterLinkDestination")
934                .field("dest_hash", dest_hash)
935                .finish(),
936            Event::Query(req, _) => f.debug_tuple("Query").field(req).finish(),
937            Event::RegisterLinkDestination { dest_hash, .. } => f
938                .debug_struct("RegisterLinkDestination")
939                .field("dest_hash", dest_hash)
940                .finish(),
941            Event::RegisterRequestHandler { path, .. } => f
942                .debug_struct("RegisterRequestHandler")
943                .field("path", path)
944                .finish(),
945            Event::RegisterRequestHandlerResponse { path, .. } => f
946                .debug_struct("RegisterRequestHandlerResponse")
947                .field("path", path)
948                .finish(),
949            Event::CreateLink { dest_hash, .. } => f
950                .debug_struct("CreateLink")
951                .field("dest_hash", dest_hash)
952                .finish(),
953            Event::SendRequest { link_id, path, .. } => f
954                .debug_struct("SendRequest")
955                .field("link_id", link_id)
956                .field("path", path)
957                .finish(),
958            Event::IdentifyOnLink { link_id, .. } => f
959                .debug_struct("IdentifyOnLink")
960                .field("link_id", link_id)
961                .finish(),
962            Event::TeardownLink { link_id } => f
963                .debug_struct("TeardownLink")
964                .field("link_id", link_id)
965                .finish(),
966            Event::SendResource { link_id, data, .. } => f
967                .debug_struct("SendResource")
968                .field("link_id", link_id)
969                .field("data_len", &data.len())
970                .finish(),
971            Event::SetResourceStrategy { link_id, strategy } => f
972                .debug_struct("SetResourceStrategy")
973                .field("link_id", link_id)
974                .field("strategy", strategy)
975                .finish(),
976            Event::AcceptResource {
977                link_id, accept, ..
978            } => f
979                .debug_struct("AcceptResource")
980                .field("link_id", link_id)
981                .field("accept", accept)
982                .finish(),
983            Event::SendChannelMessage {
984                link_id,
985                msgtype,
986                payload,
987                ..
988            } => f
989                .debug_struct("SendChannelMessage")
990                .field("link_id", link_id)
991                .field("msgtype", msgtype)
992                .field("payload_len", &payload.len())
993                .finish(),
994            Event::SendOnLink {
995                link_id,
996                data,
997                context,
998            } => f
999                .debug_struct("SendOnLink")
1000                .field("link_id", link_id)
1001                .field("data_len", &data.len())
1002                .field("context", context)
1003                .finish(),
1004            Event::RequestPath { dest_hash } => f
1005                .debug_struct("RequestPath")
1006                .field("dest_hash", dest_hash)
1007                .finish(),
1008            Event::RegisterProofStrategy {
1009                dest_hash,
1010                strategy,
1011                ..
1012            } => f
1013                .debug_struct("RegisterProofStrategy")
1014                .field("dest_hash", dest_hash)
1015                .field("strategy", strategy)
1016                .finish(),
1017            Event::ProposeDirectConnect { link_id } => f
1018                .debug_struct("ProposeDirectConnect")
1019                .field("link_id", link_id)
1020                .finish(),
1021            Event::SetDirectConnectPolicy { .. } => {
1022                write!(f, "SetDirectConnectPolicy")
1023            }
1024            Event::HolePunchProbeResult {
1025                link_id,
1026                session_id,
1027                observed_addr,
1028                probe_server,
1029                ..
1030            } => f
1031                .debug_struct("HolePunchProbeResult")
1032                .field("link_id", link_id)
1033                .field("session_id", session_id)
1034                .field("observed_addr", observed_addr)
1035                .field("probe_server", probe_server)
1036                .finish(),
1037            Event::HolePunchProbeFailed {
1038                link_id,
1039                session_id,
1040            } => f
1041                .debug_struct("HolePunchProbeFailed")
1042                .field("link_id", link_id)
1043                .field("session_id", session_id)
1044                .finish(),
1045            Event::InterfaceConfigChanged(id) => {
1046                f.debug_tuple("InterfaceConfigChanged").field(id).finish()
1047            }
1048            Event::BackbonePeerConnected {
1049                server_interface_id,
1050                peer_interface_id,
1051                peer_ip,
1052                peer_port,
1053            } => f
1054                .debug_struct("BackbonePeerConnected")
1055                .field("server_interface_id", server_interface_id)
1056                .field("peer_interface_id", peer_interface_id)
1057                .field("peer_ip", peer_ip)
1058                .field("peer_port", peer_port)
1059                .finish(),
1060            Event::BackbonePeerDisconnected {
1061                server_interface_id,
1062                peer_interface_id,
1063                peer_ip,
1064                peer_port,
1065                connected_for,
1066                had_received_data,
1067            } => f
1068                .debug_struct("BackbonePeerDisconnected")
1069                .field("server_interface_id", server_interface_id)
1070                .field("peer_interface_id", peer_interface_id)
1071                .field("peer_ip", peer_ip)
1072                .field("peer_port", peer_port)
1073                .field("connected_for", connected_for)
1074                .field("had_received_data", had_received_data)
1075                .finish(),
1076            Event::BackbonePeerIdleTimeout {
1077                server_interface_id,
1078                peer_interface_id,
1079                peer_ip,
1080                peer_port,
1081                connected_for,
1082            } => f
1083                .debug_struct("BackbonePeerIdleTimeout")
1084                .field("server_interface_id", server_interface_id)
1085                .field("peer_interface_id", peer_interface_id)
1086                .field("peer_ip", peer_ip)
1087                .field("peer_port", peer_port)
1088                .field("connected_for", connected_for)
1089                .finish(),
1090            Event::BackbonePeerWriteStall {
1091                server_interface_id,
1092                peer_interface_id,
1093                peer_ip,
1094                peer_port,
1095                connected_for,
1096            } => f
1097                .debug_struct("BackbonePeerWriteStall")
1098                .field("server_interface_id", server_interface_id)
1099                .field("peer_interface_id", peer_interface_id)
1100                .field("peer_ip", peer_ip)
1101                .field("peer_port", peer_port)
1102                .field("connected_for", connected_for)
1103                .finish(),
1104            Event::BackbonePeerPenalty {
1105                server_interface_id,
1106                peer_ip,
1107                penalty_level,
1108                blacklist_for,
1109            } => f
1110                .debug_struct("BackbonePeerPenalty")
1111                .field("server_interface_id", server_interface_id)
1112                .field("peer_ip", peer_ip)
1113                .field("penalty_level", penalty_level)
1114                .field("blacklist_for", blacklist_for)
1115                .finish(),
1116            Event::LoadHook {
1117                name,
1118                attach_point,
1119                priority,
1120                ..
1121            } => f
1122                .debug_struct("LoadHook")
1123                .field("name", name)
1124                .field("attach_point", attach_point)
1125                .field("priority", priority)
1126                .finish(),
1127            Event::LoadHookFile {
1128                name,
1129                path,
1130                hook_type,
1131                attach_point,
1132                priority,
1133                ..
1134            } => f
1135                .debug_struct("LoadHookFile")
1136                .field("name", name)
1137                .field("path", path)
1138                .field("hook_type", hook_type)
1139                .field("attach_point", attach_point)
1140                .field("priority", priority)
1141                .finish(),
1142            Event::LoadBuiltinHook {
1143                name,
1144                builtin_id,
1145                attach_point,
1146                priority,
1147                ..
1148            } => f
1149                .debug_struct("LoadBuiltinHook")
1150                .field("name", name)
1151                .field("builtin_id", builtin_id)
1152                .field("attach_point", attach_point)
1153                .field("priority", priority)
1154                .finish(),
1155            Event::UnloadHook {
1156                name, attach_point, ..
1157            } => f
1158                .debug_struct("UnloadHook")
1159                .field("name", name)
1160                .field("attach_point", attach_point)
1161                .finish(),
1162            Event::ReloadHook {
1163                name, attach_point, ..
1164            } => f
1165                .debug_struct("ReloadHook")
1166                .field("name", name)
1167                .field("attach_point", attach_point)
1168                .finish(),
1169            Event::ReloadHookFile {
1170                name,
1171                attach_point,
1172                path,
1173                hook_type,
1174                ..
1175            } => f
1176                .debug_struct("ReloadHookFile")
1177                .field("name", name)
1178                .field("attach_point", attach_point)
1179                .field("path", path)
1180                .field("hook_type", hook_type)
1181                .finish(),
1182            Event::ReloadBuiltinHook {
1183                name,
1184                attach_point,
1185                builtin_id,
1186                ..
1187            } => f
1188                .debug_struct("ReloadBuiltinHook")
1189                .field("name", name)
1190                .field("attach_point", attach_point)
1191                .field("builtin_id", builtin_id)
1192                .finish(),
1193            Event::SetHookEnabled {
1194                name,
1195                attach_point,
1196                enabled,
1197                ..
1198            } => f
1199                .debug_struct("SetHookEnabled")
1200                .field("name", name)
1201                .field("attach_point", attach_point)
1202                .field("enabled", enabled)
1203                .finish(),
1204            Event::SetHookPriority {
1205                name,
1206                attach_point,
1207                priority,
1208                ..
1209            } => f
1210                .debug_struct("SetHookPriority")
1211                .field("name", name)
1212                .field("attach_point", attach_point)
1213                .field("priority", priority)
1214                .finish(),
1215            Event::ListHooks { .. } => write!(f, "ListHooks"),
1216        }
1217    }
1218}