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