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