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