1use serde::{Deserialize, Serialize};
8
9use super::IdentityConfig;
10use crate::mmp::{DEFAULT_LOG_INTERVAL_SECS, DEFAULT_OWD_WINDOW_SIZE, MmpConfig, MmpMode};
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
18pub struct LimitsConfig {
19 #[serde(default = "LimitsConfig::default_max_connections")]
21 pub max_connections: usize,
22 #[serde(default = "LimitsConfig::default_max_peers")]
24 pub max_peers: usize,
25 #[serde(default = "LimitsConfig::default_max_links")]
27 pub max_links: usize,
28 #[serde(default = "LimitsConfig::default_max_pending_inbound")]
30 pub max_pending_inbound: usize,
31}
32
33impl Default for LimitsConfig {
34 fn default() -> Self {
35 Self {
36 max_connections: 256,
37 max_peers: 128,
38 max_links: 256,
39 max_pending_inbound: 1000,
40 }
41 }
42}
43
44impl LimitsConfig {
45 fn default_max_connections() -> usize {
46 256
47 }
48 fn default_max_peers() -> usize {
49 128
50 }
51 fn default_max_links() -> usize {
52 256
53 }
54 fn default_max_pending_inbound() -> usize {
55 1000
56 }
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize)]
61pub struct ConnectedUdpConfig {
62 #[serde(default = "ConnectedUdpConfig::default_enabled")]
67 pub enabled: bool,
68
69 #[serde(default = "ConnectedUdpConfig::default_fd_reserve")]
77 pub fd_reserve: usize,
78}
79
80impl Default for ConnectedUdpConfig {
81 fn default() -> Self {
82 Self {
83 enabled: Self::default_enabled(),
84 fd_reserve: Self::default_fd_reserve(),
85 }
86 }
87}
88
89impl ConnectedUdpConfig {
90 fn default_enabled() -> bool {
91 true
92 }
93
94 fn default_fd_reserve() -> usize {
95 128
96 }
97}
98
99#[derive(Debug, Clone, Serialize, Deserialize)]
101pub struct RateLimitConfig {
102 #[serde(default = "RateLimitConfig::default_handshake_burst")]
104 pub handshake_burst: u32,
105 #[serde(default = "RateLimitConfig::default_handshake_rate")]
107 pub handshake_rate: f64,
108 #[serde(default = "RateLimitConfig::default_handshake_timeout_secs")]
110 pub handshake_timeout_secs: u64,
111 #[serde(default = "RateLimitConfig::default_handshake_resend_interval_ms")]
114 pub handshake_resend_interval_ms: u64,
115 #[serde(default = "RateLimitConfig::default_handshake_resend_backoff")]
117 pub handshake_resend_backoff: f64,
118 #[serde(default = "RateLimitConfig::default_handshake_max_resends")]
120 pub handshake_max_resends: u32,
121}
122
123impl Default for RateLimitConfig {
124 fn default() -> Self {
125 Self {
126 handshake_burst: 100,
127 handshake_rate: 10.0,
128 handshake_timeout_secs: 30,
129 handshake_resend_interval_ms: 1000,
130 handshake_resend_backoff: 2.0,
131 handshake_max_resends: 5,
132 }
133 }
134}
135
136impl RateLimitConfig {
137 fn default_handshake_burst() -> u32 {
138 100
139 }
140 fn default_handshake_rate() -> f64 {
141 10.0
142 }
143 fn default_handshake_timeout_secs() -> u64 {
144 30
145 }
146 fn default_handshake_resend_interval_ms() -> u64 {
147 1000
148 }
149 fn default_handshake_resend_backoff() -> f64 {
150 2.0
151 }
152 fn default_handshake_max_resends() -> u32 {
153 5
154 }
155}
156
157#[derive(Debug, Clone, Serialize, Deserialize)]
159pub struct RetryConfig {
160 #[serde(default = "RetryConfig::default_max_retries")]
162 pub max_retries: u32,
163 #[serde(default = "RetryConfig::default_base_interval_secs")]
165 pub base_interval_secs: u64,
166 #[serde(default = "RetryConfig::default_max_backoff_secs")]
168 pub max_backoff_secs: u64,
169}
170
171impl Default for RetryConfig {
172 fn default() -> Self {
173 Self {
174 max_retries: 5,
175 base_interval_secs: 5,
176 max_backoff_secs: 300,
177 }
178 }
179}
180
181impl RetryConfig {
182 fn default_max_retries() -> u32 {
183 5
184 }
185 fn default_base_interval_secs() -> u64 {
186 5
187 }
188 fn default_max_backoff_secs() -> u64 {
189 300
190 }
191}
192
193#[derive(Debug, Clone, Serialize, Deserialize)]
195pub struct CacheConfig {
196 #[serde(default = "CacheConfig::default_coord_size")]
198 pub coord_size: usize,
199 #[serde(default = "CacheConfig::default_coord_ttl_secs")]
201 pub coord_ttl_secs: u64,
202 #[serde(default = "CacheConfig::default_identity_size")]
204 pub identity_size: usize,
205}
206
207impl Default for CacheConfig {
208 fn default() -> Self {
209 Self {
210 coord_size: 50_000,
211 coord_ttl_secs: 300,
212 identity_size: 10_000,
213 }
214 }
215}
216
217impl CacheConfig {
218 fn default_coord_size() -> usize {
219 50_000
220 }
221 fn default_coord_ttl_secs() -> u64 {
222 300
223 }
224 fn default_identity_size() -> usize {
225 10_000
226 }
227}
228
229#[derive(Debug, Clone, Serialize, Deserialize)]
231pub struct DiscoveryConfig {
232 #[serde(default = "DiscoveryConfig::default_ttl")]
234 pub ttl: u8,
235 #[serde(default = "DiscoveryConfig::default_attempt_timeouts_secs")]
241 pub attempt_timeouts_secs: Vec<u64>,
242 #[serde(default = "DiscoveryConfig::default_recent_expiry_secs")]
244 pub recent_expiry_secs: u64,
245 #[serde(default = "DiscoveryConfig::default_backoff_base_secs")]
249 pub backoff_base_secs: u64,
250 #[serde(default = "DiscoveryConfig::default_backoff_max_secs")]
252 pub backoff_max_secs: u64,
253 #[serde(default = "DiscoveryConfig::default_forward_min_interval_secs")]
257 pub forward_min_interval_secs: u64,
258 #[serde(default = "DiscoveryConfig::default_nostr")]
260 pub nostr: NostrDiscoveryConfig,
261 #[serde(default = "DiscoveryConfig::default_lan")]
266 pub lan: crate::discovery::lan::LanDiscoveryConfig,
267 #[serde(default = "DiscoveryConfig::default_local")]
272 pub local: crate::discovery::local::LocalInstanceDiscoveryConfig,
273}
274
275impl Default for DiscoveryConfig {
276 fn default() -> Self {
277 Self {
278 ttl: 64,
279 attempt_timeouts_secs: vec![1, 2, 4, 8],
280 recent_expiry_secs: 10,
281 backoff_base_secs: 30,
282 backoff_max_secs: 300,
283 forward_min_interval_secs: 2,
284 nostr: NostrDiscoveryConfig::default(),
285 lan: crate::discovery::lan::LanDiscoveryConfig::default(),
286 local: crate::discovery::local::LocalInstanceDiscoveryConfig::default(),
287 }
288 }
289}
290
291impl DiscoveryConfig {
292 fn default_ttl() -> u8 {
293 64
294 }
295 fn default_attempt_timeouts_secs() -> Vec<u64> {
296 vec![1, 2, 4, 8]
297 }
298 fn default_recent_expiry_secs() -> u64 {
299 10
300 }
301 fn default_backoff_base_secs() -> u64 {
302 30
303 }
304 fn default_backoff_max_secs() -> u64 {
305 300
306 }
307 fn default_forward_min_interval_secs() -> u64 {
308 2
309 }
310 fn default_nostr() -> NostrDiscoveryConfig {
311 NostrDiscoveryConfig::default()
312 }
313 fn default_lan() -> crate::discovery::lan::LanDiscoveryConfig {
314 crate::discovery::lan::LanDiscoveryConfig::default()
315 }
316 fn default_local() -> crate::discovery::local::LocalInstanceDiscoveryConfig {
317 crate::discovery::local::LocalInstanceDiscoveryConfig::default()
318 }
319}
320
321#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
328#[serde(rename_all = "snake_case")]
329pub enum NostrDiscoveryPolicy {
330 Disabled,
331 #[default]
332 ConfiguredOnly,
333 Open,
334}
335
336#[derive(Debug, Clone, Serialize, Deserialize)]
338#[serde(deny_unknown_fields)]
339pub struct NostrDiscoveryConfig {
340 #[serde(default)]
342 pub enabled: bool,
343 #[serde(default = "NostrDiscoveryConfig::default_advertise")]
345 pub advertise: bool,
346 #[serde(default = "NostrDiscoveryConfig::default_advert_relays")]
348 pub advert_relays: Vec<String>,
349 #[serde(default = "NostrDiscoveryConfig::default_dm_relays")]
351 pub dm_relays: Vec<String>,
352 #[serde(default = "NostrDiscoveryConfig::default_stun_servers")]
356 pub stun_servers: Vec<String>,
357 #[serde(default)]
367 pub share_local_candidates: bool,
368 #[serde(default = "NostrDiscoveryConfig::default_app")]
370 pub app: String,
371 #[serde(default = "NostrDiscoveryConfig::default_signal_ttl_secs")]
373 pub signal_ttl_secs: u64,
374 #[serde(default)]
376 pub policy: NostrDiscoveryPolicy,
377 #[serde(default = "NostrDiscoveryConfig::default_open_discovery_max_pending")]
380 pub open_discovery_max_pending: usize,
381 #[serde(default = "NostrDiscoveryConfig::default_max_concurrent_incoming_offers")]
384 pub max_concurrent_incoming_offers: usize,
385 #[serde(default = "NostrDiscoveryConfig::default_advert_cache_max_entries")]
388 pub advert_cache_max_entries: usize,
389 #[serde(default = "NostrDiscoveryConfig::default_seen_sessions_max_entries")]
392 pub seen_sessions_max_entries: usize,
393 #[serde(default = "NostrDiscoveryConfig::default_attempt_timeout_secs")]
395 pub attempt_timeout_secs: u64,
396 #[serde(default = "NostrDiscoveryConfig::default_replay_window_secs")]
398 pub replay_window_secs: u64,
399 #[serde(default = "NostrDiscoveryConfig::default_punch_start_delay_ms")]
401 pub punch_start_delay_ms: u64,
402 #[serde(default = "NostrDiscoveryConfig::default_punch_interval_ms")]
404 pub punch_interval_ms: u64,
405 #[serde(default = "NostrDiscoveryConfig::default_punch_duration_ms")]
407 pub punch_duration_ms: u64,
408 #[serde(default = "NostrDiscoveryConfig::default_advert_ttl_secs")]
410 pub advert_ttl_secs: u64,
411 #[serde(default = "NostrDiscoveryConfig::default_advert_refresh_secs")]
413 pub advert_refresh_secs: u64,
414 #[serde(default = "NostrDiscoveryConfig::default_startup_sweep_delay_secs")]
419 pub startup_sweep_delay_secs: u64,
420 #[serde(default = "NostrDiscoveryConfig::default_startup_sweep_max_age_secs")]
425 pub startup_sweep_max_age_secs: u64,
426 #[serde(default = "NostrDiscoveryConfig::default_failure_streak_threshold")]
432 pub failure_streak_threshold: u32,
433 #[serde(default = "NostrDiscoveryConfig::default_extended_cooldown_secs")]
437 pub extended_cooldown_secs: u64,
438 #[serde(default = "NostrDiscoveryConfig::default_warn_log_interval_secs")]
443 pub warn_log_interval_secs: u64,
444 #[serde(default = "NostrDiscoveryConfig::default_failure_state_max_entries")]
448 pub failure_state_max_entries: usize,
449 #[serde(default = "NostrDiscoveryConfig::default_protocol_mismatch_cooldown_secs")]
456 pub protocol_mismatch_cooldown_secs: u64,
457}
458
459impl Default for NostrDiscoveryConfig {
460 fn default() -> Self {
461 Self {
462 enabled: false,
463 advertise: Self::default_advertise(),
464 advert_relays: Self::default_advert_relays(),
465 dm_relays: Self::default_dm_relays(),
466 stun_servers: Self::default_stun_servers(),
467 share_local_candidates: false,
468 app: Self::default_app(),
469 signal_ttl_secs: Self::default_signal_ttl_secs(),
470 policy: NostrDiscoveryPolicy::default(),
471 open_discovery_max_pending: Self::default_open_discovery_max_pending(),
472 max_concurrent_incoming_offers: Self::default_max_concurrent_incoming_offers(),
473 advert_cache_max_entries: Self::default_advert_cache_max_entries(),
474 seen_sessions_max_entries: Self::default_seen_sessions_max_entries(),
475 attempt_timeout_secs: Self::default_attempt_timeout_secs(),
476 replay_window_secs: Self::default_replay_window_secs(),
477 punch_start_delay_ms: Self::default_punch_start_delay_ms(),
478 punch_interval_ms: Self::default_punch_interval_ms(),
479 punch_duration_ms: Self::default_punch_duration_ms(),
480 advert_ttl_secs: Self::default_advert_ttl_secs(),
481 advert_refresh_secs: Self::default_advert_refresh_secs(),
482 startup_sweep_delay_secs: Self::default_startup_sweep_delay_secs(),
483 startup_sweep_max_age_secs: Self::default_startup_sweep_max_age_secs(),
484 failure_streak_threshold: Self::default_failure_streak_threshold(),
485 extended_cooldown_secs: Self::default_extended_cooldown_secs(),
486 warn_log_interval_secs: Self::default_warn_log_interval_secs(),
487 failure_state_max_entries: Self::default_failure_state_max_entries(),
488 protocol_mismatch_cooldown_secs: Self::default_protocol_mismatch_cooldown_secs(),
489 }
490 }
491}
492
493impl NostrDiscoveryConfig {
494 fn default_advertise() -> bool {
495 true
496 }
497
498 fn default_advert_relays() -> Vec<String> {
499 vec![
500 "wss://relay.damus.io".to_string(),
501 "wss://nos.lol".to_string(),
502 "wss://offchain.pub".to_string(),
503 "wss://temp.iris.to".to_string(),
504 ]
505 }
506
507 fn default_dm_relays() -> Vec<String> {
508 vec![
509 "wss://relay.damus.io".to_string(),
510 "wss://nos.lol".to_string(),
511 "wss://offchain.pub".to_string(),
512 "wss://temp.iris.to".to_string(),
513 ]
514 }
515
516 fn default_stun_servers() -> Vec<String> {
517 vec![
518 "stun:stun.l.google.com:19302".to_string(),
519 "stun:stun.cloudflare.com:3478".to_string(),
520 "stun:global.stun.twilio.com:3478".to_string(),
521 ]
522 }
523
524 fn default_app() -> String {
525 "fips-overlay-v1".to_string()
526 }
527
528 fn default_signal_ttl_secs() -> u64 {
529 120
530 }
531
532 fn default_open_discovery_max_pending() -> usize {
533 64
534 }
535
536 fn default_max_concurrent_incoming_offers() -> usize {
537 16
538 }
539
540 fn default_advert_cache_max_entries() -> usize {
541 2048
542 }
543
544 fn default_seen_sessions_max_entries() -> usize {
545 2048
546 }
547
548 fn default_attempt_timeout_secs() -> u64 {
549 10
550 }
551
552 fn default_replay_window_secs() -> u64 {
553 300
554 }
555
556 fn default_punch_start_delay_ms() -> u64 {
557 2_000
558 }
559
560 fn default_punch_interval_ms() -> u64 {
561 200
562 }
563
564 fn default_punch_duration_ms() -> u64 {
565 10_000
566 }
567
568 fn default_advert_ttl_secs() -> u64 {
569 3_600
570 }
571
572 fn default_advert_refresh_secs() -> u64 {
573 1_800
574 }
575
576 fn default_startup_sweep_delay_secs() -> u64 {
577 5
578 }
579
580 fn default_startup_sweep_max_age_secs() -> u64 {
581 3_600
582 }
583
584 fn default_failure_streak_threshold() -> u32 {
585 5
586 }
587
588 fn default_extended_cooldown_secs() -> u64 {
589 1_800
590 }
591
592 fn default_warn_log_interval_secs() -> u64 {
593 300
594 }
595
596 fn default_failure_state_max_entries() -> usize {
597 4_096
598 }
599
600 fn default_protocol_mismatch_cooldown_secs() -> u64 {
601 86_400
602 }
603}
604
605#[derive(Debug, Clone, Serialize, Deserialize)]
607pub struct TreeConfig {
608 #[serde(default = "TreeConfig::default_announce_min_interval_ms")]
610 pub announce_min_interval_ms: u64,
611 #[serde(default = "TreeConfig::default_parent_hysteresis")]
617 pub parent_hysteresis: f64,
618 #[serde(default = "TreeConfig::default_hold_down_secs")]
623 pub hold_down_secs: u64,
624 #[serde(default = "TreeConfig::default_reeval_interval_secs")]
630 pub reeval_interval_secs: u64,
631 #[serde(default = "TreeConfig::default_flap_threshold")]
633 pub flap_threshold: u32,
634 #[serde(default = "TreeConfig::default_flap_window_secs")]
636 pub flap_window_secs: u64,
637 #[serde(default = "TreeConfig::default_flap_dampening_secs")]
639 pub flap_dampening_secs: u64,
640}
641
642impl Default for TreeConfig {
643 fn default() -> Self {
644 Self {
645 announce_min_interval_ms: 500,
646 parent_hysteresis: 0.2,
647 hold_down_secs: 30,
648 reeval_interval_secs: 60,
649 flap_threshold: 4,
650 flap_window_secs: 60,
651 flap_dampening_secs: 120,
652 }
653 }
654}
655
656impl TreeConfig {
657 fn default_announce_min_interval_ms() -> u64 {
658 500
659 }
660 fn default_parent_hysteresis() -> f64 {
661 0.2
662 }
663 fn default_hold_down_secs() -> u64 {
664 30
665 }
666 fn default_reeval_interval_secs() -> u64 {
667 60
668 }
669 fn default_flap_threshold() -> u32 {
670 4
671 }
672 fn default_flap_window_secs() -> u64 {
673 60
674 }
675 fn default_flap_dampening_secs() -> u64 {
676 120
677 }
678}
679
680#[derive(Debug, Clone, Serialize, Deserialize)]
682pub struct RoutingConfig {
683 #[serde(default)]
685 pub mode: RoutingMode,
686 #[serde(default = "RoutingConfig::default_learned_ttl_secs")]
688 pub learned_ttl_secs: u64,
689 #[serde(default = "RoutingConfig::default_max_learned_routes_per_dest")]
693 pub max_learned_routes_per_dest: usize,
694 #[serde(default = "RoutingConfig::default_learned_fallback_explore_interval")]
697 pub learned_fallback_explore_interval: u64,
698}
699
700impl Default for RoutingConfig {
701 fn default() -> Self {
702 Self {
703 mode: RoutingMode::default(),
704 learned_ttl_secs: 300,
705 max_learned_routes_per_dest: 4,
706 learned_fallback_explore_interval: 16,
707 }
708 }
709}
710
711impl RoutingConfig {
712 fn default_learned_ttl_secs() -> u64 {
713 300
714 }
715
716 fn default_max_learned_routes_per_dest() -> usize {
717 4
718 }
719
720 fn default_learned_fallback_explore_interval() -> u64 {
721 16
722 }
723}
724
725#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
727#[serde(rename_all = "snake_case")]
728pub enum RoutingMode {
729 #[default]
731 Tree,
732 ReplyLearned,
737}
738
739impl std::fmt::Display for RoutingMode {
740 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
741 match self {
742 RoutingMode::Tree => write!(f, "tree"),
743 RoutingMode::ReplyLearned => write!(f, "reply_learned"),
744 }
745 }
746}
747
748#[derive(Debug, Clone, Serialize, Deserialize)]
750pub struct BloomConfig {
751 #[serde(default = "BloomConfig::default_update_debounce_ms")]
753 pub update_debounce_ms: u64,
754 #[serde(default = "BloomConfig::default_max_inbound_fpr")]
760 pub max_inbound_fpr: f64,
761}
762
763impl Default for BloomConfig {
764 fn default() -> Self {
765 Self {
766 update_debounce_ms: 500,
767 max_inbound_fpr: 0.05,
768 }
769 }
770}
771
772impl BloomConfig {
773 fn default_update_debounce_ms() -> u64 {
774 500
775 }
776 fn default_max_inbound_fpr() -> f64 {
777 0.05
778 }
779}
780
781#[derive(Debug, Clone, Serialize, Deserialize)]
783pub struct SessionConfig {
784 #[serde(default = "SessionConfig::default_ttl")]
786 pub default_ttl: u8,
787 #[serde(default = "SessionConfig::default_pending_packets_per_dest")]
789 pub pending_packets_per_dest: usize,
790 #[serde(default = "SessionConfig::default_pending_max_destinations")]
792 pub pending_max_destinations: usize,
793 #[serde(default = "SessionConfig::default_idle_timeout_secs")]
797 pub idle_timeout_secs: u64,
798 #[serde(default = "SessionConfig::default_coords_warmup_packets")]
802 pub coords_warmup_packets: u8,
803 #[serde(default = "SessionConfig::default_coords_response_interval_ms")]
807 pub coords_response_interval_ms: u64,
808}
809
810impl Default for SessionConfig {
811 fn default() -> Self {
812 Self {
813 default_ttl: 64,
814 pending_packets_per_dest: 16,
815 pending_max_destinations: 256,
816 idle_timeout_secs: 90,
817 coords_warmup_packets: 5,
818 coords_response_interval_ms: 2000,
819 }
820 }
821}
822
823impl SessionConfig {
824 fn default_ttl() -> u8 {
825 64
826 }
827 fn default_pending_packets_per_dest() -> usize {
828 16
829 }
830 fn default_pending_max_destinations() -> usize {
831 256
832 }
833 fn default_idle_timeout_secs() -> u64 {
834 90
835 }
836 fn default_coords_warmup_packets() -> u8 {
837 5
838 }
839 fn default_coords_response_interval_ms() -> u64 {
840 2000
841 }
842}
843
844#[derive(Debug, Clone, Serialize, Deserialize)]
851pub struct SessionMmpConfig {
852 #[serde(default)]
854 pub mode: MmpMode,
855
856 #[serde(default = "SessionMmpConfig::default_log_interval_secs")]
858 pub log_interval_secs: u64,
859
860 #[serde(default = "SessionMmpConfig::default_owd_window_size")]
862 pub owd_window_size: usize,
863}
864
865impl Default for SessionMmpConfig {
866 fn default() -> Self {
867 Self {
868 mode: MmpMode::default(),
869 log_interval_secs: DEFAULT_LOG_INTERVAL_SECS,
870 owd_window_size: DEFAULT_OWD_WINDOW_SIZE,
871 }
872 }
873}
874
875impl SessionMmpConfig {
876 fn default_log_interval_secs() -> u64 {
877 DEFAULT_LOG_INTERVAL_SECS
878 }
879 fn default_owd_window_size() -> usize {
880 DEFAULT_OWD_WINDOW_SIZE
881 }
882}
883
884#[derive(Debug, Clone, Serialize, Deserialize)]
886pub struct ControlConfig {
887 #[serde(default = "ControlConfig::default_enabled")]
889 pub enabled: bool,
890 #[serde(default = "ControlConfig::default_socket_path")]
892 pub socket_path: String,
893}
894
895impl Default for ControlConfig {
896 fn default() -> Self {
897 Self {
898 enabled: true,
899 socket_path: Self::default_socket_path(),
900 }
901 }
902}
903
904impl ControlConfig {
905 fn default_enabled() -> bool {
906 true
907 }
908
909 fn default_socket_path() -> String {
916 #[cfg(unix)]
917 {
918 super::resolve_default_socket("control.sock")
919 }
920 #[cfg(windows)]
921 {
922 "21210".to_string()
923 }
924 }
925}
926
927#[derive(Debug, Clone, Serialize, Deserialize)]
929pub struct BuffersConfig {
930 #[serde(default = "BuffersConfig::default_packet_channel")]
932 pub packet_channel: usize,
933 #[serde(default = "BuffersConfig::default_tun_channel")]
935 pub tun_channel: usize,
936 #[serde(default = "BuffersConfig::default_dns_channel")]
938 pub dns_channel: usize,
939}
940
941impl Default for BuffersConfig {
942 fn default() -> Self {
943 Self {
944 packet_channel: 1024,
945 tun_channel: 1024,
946 dns_channel: 64,
947 }
948 }
949}
950
951impl BuffersConfig {
952 fn default_packet_channel() -> usize {
953 1024
954 }
955 fn default_tun_channel() -> usize {
956 1024
957 }
958 fn default_dns_channel() -> usize {
959 64
960 }
961}
962
963const DEFAULT_REKEY_AFTER_MESSAGES: u64 = 1 << 48;
980
981#[derive(Debug, Clone, Serialize, Deserialize)]
982pub struct RekeyConfig {
983 #[serde(default = "RekeyConfig::default_enabled")]
985 pub enabled: bool,
986
987 #[serde(default = "RekeyConfig::default_after_secs")]
989 pub after_secs: u64,
990
991 #[serde(default = "RekeyConfig::default_after_messages")]
993 pub after_messages: u64,
994}
995
996impl Default for RekeyConfig {
997 fn default() -> Self {
998 Self {
999 enabled: true,
1000 after_secs: 120,
1001 after_messages: DEFAULT_REKEY_AFTER_MESSAGES,
1002 }
1003 }
1004}
1005
1006impl RekeyConfig {
1007 fn default_enabled() -> bool {
1008 true
1009 }
1010 fn default_after_secs() -> u64 {
1011 120
1012 }
1013 fn default_after_messages() -> u64 {
1014 DEFAULT_REKEY_AFTER_MESSAGES
1015 }
1016}
1017
1018#[derive(Debug, Clone, Serialize, Deserialize)]
1024pub struct EcnConfig {
1025 #[serde(default = "EcnConfig::default_enabled")]
1027 pub enabled: bool,
1028
1029 #[serde(default = "EcnConfig::default_loss_threshold")]
1033 pub loss_threshold: f64,
1034
1035 #[serde(default = "EcnConfig::default_etx_threshold")]
1039 pub etx_threshold: f64,
1040}
1041
1042impl Default for EcnConfig {
1043 fn default() -> Self {
1044 Self {
1045 enabled: true,
1046 loss_threshold: 0.05,
1047 etx_threshold: 3.0,
1048 }
1049 }
1050}
1051
1052impl EcnConfig {
1053 fn default_enabled() -> bool {
1054 true
1055 }
1056 fn default_loss_threshold() -> f64 {
1057 0.05
1058 }
1059 fn default_etx_threshold() -> f64 {
1060 3.0
1061 }
1062}
1063
1064#[derive(Debug, Clone, Serialize, Deserialize)]
1070pub struct NodeConfig {
1071 #[serde(default)]
1073 pub identity: IdentityConfig,
1074
1075 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
1077 pub leaf_only: bool,
1078
1079 #[serde(default = "NodeConfig::default_tick_interval_secs")]
1081 pub tick_interval_secs: u64,
1082
1083 #[serde(default = "NodeConfig::default_base_rtt_ms")]
1085 pub base_rtt_ms: u64,
1086
1087 #[serde(default = "NodeConfig::default_heartbeat_interval_secs")]
1089 pub heartbeat_interval_secs: u64,
1090
1091 #[serde(default = "NodeConfig::default_link_dead_timeout_secs")]
1094 pub link_dead_timeout_secs: u64,
1095
1096 #[serde(default = "NodeConfig::default_fast_link_dead_timeout_secs")]
1106 pub fast_link_dead_timeout_secs: u64,
1107
1108 #[serde(default)]
1110 pub limits: LimitsConfig,
1111
1112 #[serde(default)]
1114 pub connected_udp: ConnectedUdpConfig,
1115
1116 #[serde(default)]
1118 pub rate_limit: RateLimitConfig,
1119
1120 #[serde(default)]
1122 pub retry: RetryConfig,
1123
1124 #[serde(default)]
1126 pub cache: CacheConfig,
1127
1128 #[serde(default)]
1130 pub discovery: DiscoveryConfig,
1131
1132 #[serde(default)]
1134 pub tree: TreeConfig,
1135
1136 #[serde(default)]
1138 pub routing: RoutingConfig,
1139
1140 #[serde(default)]
1142 pub bloom: BloomConfig,
1143
1144 #[serde(default)]
1146 pub session: SessionConfig,
1147
1148 #[serde(default)]
1150 pub buffers: BuffersConfig,
1151
1152 #[serde(default)]
1154 pub control: ControlConfig,
1155
1156 #[serde(default)]
1158 pub mmp: MmpConfig,
1159
1160 #[serde(default)]
1162 pub session_mmp: SessionMmpConfig,
1163
1164 #[serde(default)]
1166 pub ecn: EcnConfig,
1167
1168 #[serde(default)]
1170 pub rekey: RekeyConfig,
1171
1172 #[serde(default = "NodeConfig::default_system_files_enabled")]
1175 pub system_files_enabled: bool,
1176
1177 #[serde(default = "NodeConfig::default_worker_pools_enabled")]
1182 pub worker_pools_enabled: bool,
1183
1184 #[serde(default)]
1187 pub log_level: Option<String>,
1188}
1189
1190impl Default for NodeConfig {
1191 fn default() -> Self {
1192 Self {
1193 identity: IdentityConfig::default(),
1194 leaf_only: false,
1195 tick_interval_secs: 1,
1196 base_rtt_ms: 100,
1197 heartbeat_interval_secs: 10,
1198 link_dead_timeout_secs: 30,
1199 fast_link_dead_timeout_secs: 5,
1200 limits: LimitsConfig::default(),
1201 connected_udp: ConnectedUdpConfig::default(),
1202 rate_limit: RateLimitConfig::default(),
1203 retry: RetryConfig::default(),
1204 cache: CacheConfig::default(),
1205 discovery: DiscoveryConfig::default(),
1206 tree: TreeConfig::default(),
1207 routing: RoutingConfig::default(),
1208 bloom: BloomConfig::default(),
1209 session: SessionConfig::default(),
1210 buffers: BuffersConfig::default(),
1211 control: ControlConfig::default(),
1212 mmp: MmpConfig::default(),
1213 session_mmp: SessionMmpConfig::default(),
1214 ecn: EcnConfig::default(),
1215 rekey: RekeyConfig::default(),
1216 system_files_enabled: true,
1217 worker_pools_enabled: true,
1218 log_level: None,
1219 }
1220 }
1221}
1222
1223impl NodeConfig {
1224 pub fn log_level(&self) -> tracing::Level {
1226 match self
1227 .log_level
1228 .as_deref()
1229 .map(|s| s.to_lowercase())
1230 .as_deref()
1231 {
1232 Some("trace") => tracing::Level::TRACE,
1233 Some("debug") => tracing::Level::DEBUG,
1234 Some("warn") | Some("warning") => tracing::Level::WARN,
1235 Some("error") => tracing::Level::ERROR,
1236 _ => tracing::Level::INFO,
1237 }
1238 }
1239
1240 fn default_tick_interval_secs() -> u64 {
1241 1
1242 }
1243 fn default_base_rtt_ms() -> u64 {
1244 100
1245 }
1246 fn default_heartbeat_interval_secs() -> u64 {
1247 10
1248 }
1249 fn default_link_dead_timeout_secs() -> u64 {
1250 30
1251 }
1252 fn default_fast_link_dead_timeout_secs() -> u64 {
1253 5
1254 }
1255 fn default_system_files_enabled() -> bool {
1256 true
1257 }
1258 fn default_worker_pools_enabled() -> bool {
1259 true
1260 }
1261}
1262
1263#[cfg(test)]
1264mod tests {
1265 use super::*;
1266
1267 #[test]
1268 fn test_ecn_config_defaults() {
1269 let c = EcnConfig::default();
1270 assert!(c.enabled);
1271 assert!((c.loss_threshold - 0.05).abs() < 1e-9);
1272 assert!((c.etx_threshold - 3.0).abs() < 1e-9);
1273 }
1274
1275 #[test]
1276 fn test_rekey_config_defaults() {
1277 let c = RekeyConfig::default();
1278 assert!(c.enabled);
1279 assert_eq!(c.after_secs, 120);
1280 assert_eq!(c.after_messages, 1 << 48);
1281 }
1282
1283 #[test]
1284 fn test_rekey_config_partial_yaml_uses_defaults() {
1285 let yaml = "after_secs: 30\n";
1286 let c: RekeyConfig = serde_yaml::from_str(yaml).unwrap();
1287 assert!(c.enabled);
1288 assert_eq!(c.after_secs, 30);
1289 assert_eq!(c.after_messages, 1 << 48);
1290 }
1291
1292 #[test]
1293 fn test_connected_udp_config_defaults() {
1294 let c = ConnectedUdpConfig::default();
1295 assert!(c.enabled);
1296 assert_eq!(c.fd_reserve, 128);
1297 }
1298
1299 #[test]
1300 fn test_connected_udp_config_yaml() {
1301 let yaml = "enabled: false\nfd_reserve: 4096\n";
1302 let c: ConnectedUdpConfig = serde_yaml::from_str(yaml).unwrap();
1303 assert!(!c.enabled);
1304 assert_eq!(c.fd_reserve, 4096);
1305 }
1306
1307 #[test]
1308 fn test_routing_config_defaults() {
1309 let c = RoutingConfig::default();
1310 assert_eq!(c.mode, RoutingMode::Tree);
1311 assert_eq!(c.learned_ttl_secs, 300);
1312 assert_eq!(c.max_learned_routes_per_dest, 4);
1313 assert_eq!(c.learned_fallback_explore_interval, 16);
1314 }
1315
1316 #[test]
1317 fn test_routing_config_yaml() {
1318 let yaml = "mode: reply_learned\nlearned_ttl_secs: 120\nmax_learned_routes_per_dest: 2\nlearned_fallback_explore_interval: 8\n";
1319 let c: RoutingConfig = serde_yaml::from_str(yaml).unwrap();
1320 assert_eq!(c.mode, RoutingMode::ReplyLearned);
1321 assert_eq!(c.learned_ttl_secs, 120);
1322 assert_eq!(c.max_learned_routes_per_dest, 2);
1323 assert_eq!(c.learned_fallback_explore_interval, 8);
1324 }
1325
1326 #[test]
1327 fn test_ecn_config_yaml_roundtrip() {
1328 let yaml = "loss_threshold: 0.10\netx_threshold: 2.5\nenabled: false\n";
1329 let c: EcnConfig = serde_yaml::from_str(yaml).unwrap();
1330 assert!(!c.enabled);
1331 assert!((c.loss_threshold - 0.10).abs() < 1e-9);
1332 assert!((c.etx_threshold - 2.5).abs() < 1e-9);
1333 }
1334
1335 #[test]
1336 fn test_ecn_config_partial_yaml() {
1337 let yaml = "loss_threshold: 0.02\n";
1339 let c: EcnConfig = serde_yaml::from_str(yaml).unwrap();
1340 assert!(c.enabled); assert!((c.loss_threshold - 0.02).abs() < 1e-9);
1342 assert!((c.etx_threshold - 3.0).abs() < 1e-9); }
1344
1345 #[test]
1346 fn test_nostr_discovery_startup_sweep_defaults() {
1347 let c = NostrDiscoveryConfig::default();
1348 assert_eq!(c.startup_sweep_delay_secs, 5);
1349 assert_eq!(c.startup_sweep_max_age_secs, 3_600);
1350 }
1351
1352 #[test]
1353 fn test_nostr_discovery_startup_sweep_yaml_override() {
1354 let yaml = "enabled: true\npolicy: open\nstartup_sweep_delay_secs: 10\nstartup_sweep_max_age_secs: 1800\n";
1355 let c: NostrDiscoveryConfig = serde_yaml::from_str(yaml).unwrap();
1356 assert!(c.enabled);
1357 assert_eq!(c.policy, NostrDiscoveryPolicy::Open);
1358 assert_eq!(c.startup_sweep_delay_secs, 10);
1359 assert_eq!(c.startup_sweep_max_age_secs, 1_800);
1360 }
1361
1362 #[test]
1363 fn test_nostr_discovery_startup_sweep_partial_yaml_uses_defaults() {
1364 let yaml = "enabled: true\nstartup_sweep_delay_secs: 30\n";
1366 let c: NostrDiscoveryConfig = serde_yaml::from_str(yaml).unwrap();
1367 assert_eq!(c.startup_sweep_delay_secs, 30);
1368 assert_eq!(c.startup_sweep_max_age_secs, 3_600);
1369 }
1370
1371 #[test]
1372 fn test_log_level_parser() {
1373 let cases: &[(Option<&str>, tracing::Level)] = &[
1379 (Some("trace"), tracing::Level::TRACE),
1381 (Some("debug"), tracing::Level::DEBUG),
1382 (Some("warn"), tracing::Level::WARN),
1383 (Some("warning"), tracing::Level::WARN),
1384 (Some("error"), tracing::Level::ERROR),
1385 (Some("info"), tracing::Level::INFO),
1387 (None, tracing::Level::INFO),
1389 (Some("TRACE"), tracing::Level::TRACE),
1391 (Some("Debug"), tracing::Level::DEBUG),
1392 (Some("Warning"), tracing::Level::WARN),
1393 (Some("WARN"), tracing::Level::WARN),
1394 (Some("ERROR"), tracing::Level::ERROR),
1395 (Some("INFO"), tracing::Level::INFO),
1396 (Some("verbose"), tracing::Level::INFO),
1398 (Some("nonsense"), tracing::Level::INFO),
1399 (Some(""), tracing::Level::INFO),
1400 ];
1401
1402 for (input, expected) in cases {
1403 let cfg = NodeConfig {
1404 log_level: input.map(|s| s.to_string()),
1405 ..NodeConfig::default()
1406 };
1407 assert_eq!(
1408 cfg.log_level(),
1409 *expected,
1410 "input {:?} should map to {:?}",
1411 input,
1412 expected
1413 );
1414 }
1415 }
1416
1417 #[cfg(windows)]
1418 #[test]
1419 fn test_default_socket_path_windows() {
1420 let config = ControlConfig::default();
1421 let port: u16 = config
1423 .socket_path
1424 .parse()
1425 .expect("should be a valid port number");
1426 assert_eq!(port, 21210);
1427 }
1428}