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