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 RateLimitConfig {
62 #[serde(default = "RateLimitConfig::default_handshake_burst")]
64 pub handshake_burst: u32,
65 #[serde(default = "RateLimitConfig::default_handshake_rate")]
67 pub handshake_rate: f64,
68 #[serde(default = "RateLimitConfig::default_handshake_timeout_secs")]
70 pub handshake_timeout_secs: u64,
71 #[serde(default = "RateLimitConfig::default_handshake_resend_interval_ms")]
74 pub handshake_resend_interval_ms: u64,
75 #[serde(default = "RateLimitConfig::default_handshake_resend_backoff")]
77 pub handshake_resend_backoff: f64,
78 #[serde(default = "RateLimitConfig::default_handshake_max_resends")]
80 pub handshake_max_resends: u32,
81}
82
83impl Default for RateLimitConfig {
84 fn default() -> Self {
85 Self {
86 handshake_burst: 100,
87 handshake_rate: 10.0,
88 handshake_timeout_secs: 30,
89 handshake_resend_interval_ms: 1000,
90 handshake_resend_backoff: 2.0,
91 handshake_max_resends: 5,
92 }
93 }
94}
95
96impl RateLimitConfig {
97 fn default_handshake_burst() -> u32 {
98 100
99 }
100 fn default_handshake_rate() -> f64 {
101 10.0
102 }
103 fn default_handshake_timeout_secs() -> u64 {
104 30
105 }
106 fn default_handshake_resend_interval_ms() -> u64 {
107 1000
108 }
109 fn default_handshake_resend_backoff() -> f64 {
110 2.0
111 }
112 fn default_handshake_max_resends() -> u32 {
113 5
114 }
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize)]
119pub struct RetryConfig {
120 #[serde(default = "RetryConfig::default_max_retries")]
122 pub max_retries: u32,
123 #[serde(default = "RetryConfig::default_base_interval_secs")]
125 pub base_interval_secs: u64,
126 #[serde(default = "RetryConfig::default_max_backoff_secs")]
128 pub max_backoff_secs: u64,
129}
130
131impl Default for RetryConfig {
132 fn default() -> Self {
133 Self {
134 max_retries: 5,
135 base_interval_secs: 5,
136 max_backoff_secs: 300,
137 }
138 }
139}
140
141impl RetryConfig {
142 fn default_max_retries() -> u32 {
143 5
144 }
145 fn default_base_interval_secs() -> u64 {
146 5
147 }
148 fn default_max_backoff_secs() -> u64 {
149 300
150 }
151}
152
153#[derive(Debug, Clone, Serialize, Deserialize)]
155pub struct CacheConfig {
156 #[serde(default = "CacheConfig::default_coord_size")]
158 pub coord_size: usize,
159 #[serde(default = "CacheConfig::default_coord_ttl_secs")]
161 pub coord_ttl_secs: u64,
162 #[serde(default = "CacheConfig::default_identity_size")]
164 pub identity_size: usize,
165}
166
167impl Default for CacheConfig {
168 fn default() -> Self {
169 Self {
170 coord_size: 50_000,
171 coord_ttl_secs: 300,
172 identity_size: 10_000,
173 }
174 }
175}
176
177impl CacheConfig {
178 fn default_coord_size() -> usize {
179 50_000
180 }
181 fn default_coord_ttl_secs() -> u64 {
182 300
183 }
184 fn default_identity_size() -> usize {
185 10_000
186 }
187}
188
189#[derive(Debug, Clone, Serialize, Deserialize)]
191pub struct DiscoveryConfig {
192 #[serde(default = "DiscoveryConfig::default_ttl")]
194 pub ttl: u8,
195 #[serde(default = "DiscoveryConfig::default_attempt_timeouts_secs")]
201 pub attempt_timeouts_secs: Vec<u64>,
202 #[serde(default = "DiscoveryConfig::default_recent_expiry_secs")]
204 pub recent_expiry_secs: u64,
205 #[serde(default = "DiscoveryConfig::default_backoff_base_secs")]
210 pub backoff_base_secs: u64,
211 #[serde(default = "DiscoveryConfig::default_backoff_max_secs")]
213 pub backoff_max_secs: u64,
214 #[serde(default = "DiscoveryConfig::default_forward_min_interval_secs")]
218 pub forward_min_interval_secs: u64,
219 #[serde(default = "DiscoveryConfig::default_nostr")]
221 pub nostr: NostrDiscoveryConfig,
222 #[serde(default = "DiscoveryConfig::default_lan")]
227 pub lan: crate::discovery::lan::LanDiscoveryConfig,
228}
229
230impl Default for DiscoveryConfig {
231 fn default() -> Self {
232 Self {
233 ttl: 64,
234 attempt_timeouts_secs: vec![1, 2, 4, 8],
235 recent_expiry_secs: 10,
236 backoff_base_secs: 0,
237 backoff_max_secs: 0,
238 forward_min_interval_secs: 2,
239 nostr: NostrDiscoveryConfig::default(),
240 lan: crate::discovery::lan::LanDiscoveryConfig::default(),
241 }
242 }
243}
244
245impl DiscoveryConfig {
246 fn default_ttl() -> u8 {
247 64
248 }
249 fn default_attempt_timeouts_secs() -> Vec<u64> {
250 vec![1, 2, 4, 8]
251 }
252 fn default_recent_expiry_secs() -> u64 {
253 10
254 }
255 fn default_backoff_base_secs() -> u64 {
256 0
257 }
258 fn default_backoff_max_secs() -> u64 {
259 0
260 }
261 fn default_forward_min_interval_secs() -> u64 {
262 2
263 }
264 fn default_nostr() -> NostrDiscoveryConfig {
265 NostrDiscoveryConfig::default()
266 }
267 fn default_lan() -> crate::discovery::lan::LanDiscoveryConfig {
268 crate::discovery::lan::LanDiscoveryConfig::default()
269 }
270}
271
272#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
279#[serde(rename_all = "snake_case")]
280pub enum NostrDiscoveryPolicy {
281 Disabled,
282 #[default]
283 ConfiguredOnly,
284 Open,
285}
286
287#[derive(Debug, Clone, Serialize, Deserialize)]
289#[serde(deny_unknown_fields)]
290pub struct NostrDiscoveryConfig {
291 #[serde(default)]
293 pub enabled: bool,
294 #[serde(default = "NostrDiscoveryConfig::default_advertise")]
296 pub advertise: bool,
297 #[serde(default = "NostrDiscoveryConfig::default_advert_relays")]
299 pub advert_relays: Vec<String>,
300 #[serde(default = "NostrDiscoveryConfig::default_dm_relays")]
302 pub dm_relays: Vec<String>,
303 #[serde(default = "NostrDiscoveryConfig::default_stun_servers")]
307 pub stun_servers: Vec<String>,
308 #[serde(default)]
318 pub share_local_candidates: bool,
319 #[serde(default = "NostrDiscoveryConfig::default_app")]
321 pub app: String,
322 #[serde(default = "NostrDiscoveryConfig::default_signal_ttl_secs")]
324 pub signal_ttl_secs: u64,
325 #[serde(default)]
327 pub policy: NostrDiscoveryPolicy,
328 #[serde(default = "NostrDiscoveryConfig::default_open_discovery_max_pending")]
331 pub open_discovery_max_pending: usize,
332 #[serde(default = "NostrDiscoveryConfig::default_max_concurrent_incoming_offers")]
335 pub max_concurrent_incoming_offers: usize,
336 #[serde(default = "NostrDiscoveryConfig::default_advert_cache_max_entries")]
339 pub advert_cache_max_entries: usize,
340 #[serde(default = "NostrDiscoveryConfig::default_seen_sessions_max_entries")]
343 pub seen_sessions_max_entries: usize,
344 #[serde(default = "NostrDiscoveryConfig::default_attempt_timeout_secs")]
346 pub attempt_timeout_secs: u64,
347 #[serde(default = "NostrDiscoveryConfig::default_replay_window_secs")]
349 pub replay_window_secs: u64,
350 #[serde(default = "NostrDiscoveryConfig::default_punch_start_delay_ms")]
352 pub punch_start_delay_ms: u64,
353 #[serde(default = "NostrDiscoveryConfig::default_punch_interval_ms")]
355 pub punch_interval_ms: u64,
356 #[serde(default = "NostrDiscoveryConfig::default_punch_duration_ms")]
358 pub punch_duration_ms: u64,
359 #[serde(default = "NostrDiscoveryConfig::default_advert_ttl_secs")]
361 pub advert_ttl_secs: u64,
362 #[serde(default = "NostrDiscoveryConfig::default_advert_refresh_secs")]
364 pub advert_refresh_secs: u64,
365 #[serde(default = "NostrDiscoveryConfig::default_startup_sweep_delay_secs")]
370 pub startup_sweep_delay_secs: u64,
371 #[serde(default = "NostrDiscoveryConfig::default_startup_sweep_max_age_secs")]
376 pub startup_sweep_max_age_secs: u64,
377 #[serde(default = "NostrDiscoveryConfig::default_failure_streak_threshold")]
383 pub failure_streak_threshold: u32,
384 #[serde(default = "NostrDiscoveryConfig::default_extended_cooldown_secs")]
388 pub extended_cooldown_secs: u64,
389 #[serde(default = "NostrDiscoveryConfig::default_warn_log_interval_secs")]
394 pub warn_log_interval_secs: u64,
395 #[serde(default = "NostrDiscoveryConfig::default_failure_state_max_entries")]
399 pub failure_state_max_entries: usize,
400 #[serde(default = "NostrDiscoveryConfig::default_protocol_mismatch_cooldown_secs")]
407 pub protocol_mismatch_cooldown_secs: u64,
408}
409
410impl Default for NostrDiscoveryConfig {
411 fn default() -> Self {
412 Self {
413 enabled: false,
414 advertise: Self::default_advertise(),
415 advert_relays: Self::default_advert_relays(),
416 dm_relays: Self::default_dm_relays(),
417 stun_servers: Self::default_stun_servers(),
418 share_local_candidates: false,
419 app: Self::default_app(),
420 signal_ttl_secs: Self::default_signal_ttl_secs(),
421 policy: NostrDiscoveryPolicy::default(),
422 open_discovery_max_pending: Self::default_open_discovery_max_pending(),
423 max_concurrent_incoming_offers: Self::default_max_concurrent_incoming_offers(),
424 advert_cache_max_entries: Self::default_advert_cache_max_entries(),
425 seen_sessions_max_entries: Self::default_seen_sessions_max_entries(),
426 attempt_timeout_secs: Self::default_attempt_timeout_secs(),
427 replay_window_secs: Self::default_replay_window_secs(),
428 punch_start_delay_ms: Self::default_punch_start_delay_ms(),
429 punch_interval_ms: Self::default_punch_interval_ms(),
430 punch_duration_ms: Self::default_punch_duration_ms(),
431 advert_ttl_secs: Self::default_advert_ttl_secs(),
432 advert_refresh_secs: Self::default_advert_refresh_secs(),
433 startup_sweep_delay_secs: Self::default_startup_sweep_delay_secs(),
434 startup_sweep_max_age_secs: Self::default_startup_sweep_max_age_secs(),
435 failure_streak_threshold: Self::default_failure_streak_threshold(),
436 extended_cooldown_secs: Self::default_extended_cooldown_secs(),
437 warn_log_interval_secs: Self::default_warn_log_interval_secs(),
438 failure_state_max_entries: Self::default_failure_state_max_entries(),
439 protocol_mismatch_cooldown_secs: Self::default_protocol_mismatch_cooldown_secs(),
440 }
441 }
442}
443
444impl NostrDiscoveryConfig {
445 fn default_advertise() -> bool {
446 true
447 }
448
449 fn default_advert_relays() -> Vec<String> {
450 vec![
451 "wss://relay.damus.io".to_string(),
452 "wss://nos.lol".to_string(),
453 "wss://offchain.pub".to_string(),
454 ]
455 }
456
457 fn default_dm_relays() -> Vec<String> {
458 vec![
459 "wss://relay.damus.io".to_string(),
460 "wss://nos.lol".to_string(),
461 "wss://offchain.pub".to_string(),
462 ]
463 }
464
465 fn default_stun_servers() -> Vec<String> {
466 vec![
467 "stun:stun.l.google.com:19302".to_string(),
468 "stun:stun.cloudflare.com:3478".to_string(),
469 "stun:global.stun.twilio.com:3478".to_string(),
470 ]
471 }
472
473 fn default_app() -> String {
474 "fips-overlay-v1".to_string()
475 }
476
477 fn default_signal_ttl_secs() -> u64 {
478 120
479 }
480
481 fn default_open_discovery_max_pending() -> usize {
482 64
483 }
484
485 fn default_max_concurrent_incoming_offers() -> usize {
486 16
487 }
488
489 fn default_advert_cache_max_entries() -> usize {
490 2048
491 }
492
493 fn default_seen_sessions_max_entries() -> usize {
494 2048
495 }
496
497 fn default_attempt_timeout_secs() -> u64 {
498 10
499 }
500
501 fn default_replay_window_secs() -> u64 {
502 300
503 }
504
505 fn default_punch_start_delay_ms() -> u64 {
506 2_000
507 }
508
509 fn default_punch_interval_ms() -> u64 {
510 200
511 }
512
513 fn default_punch_duration_ms() -> u64 {
514 10_000
515 }
516
517 fn default_advert_ttl_secs() -> u64 {
518 3_600
519 }
520
521 fn default_advert_refresh_secs() -> u64 {
522 1_800
523 }
524
525 fn default_startup_sweep_delay_secs() -> u64 {
526 5
527 }
528
529 fn default_startup_sweep_max_age_secs() -> u64 {
530 3_600
531 }
532
533 fn default_failure_streak_threshold() -> u32 {
534 5
535 }
536
537 fn default_extended_cooldown_secs() -> u64 {
538 1_800
539 }
540
541 fn default_warn_log_interval_secs() -> u64 {
542 300
543 }
544
545 fn default_failure_state_max_entries() -> usize {
546 4_096
547 }
548
549 fn default_protocol_mismatch_cooldown_secs() -> u64 {
550 86_400
551 }
552}
553
554#[derive(Debug, Clone, Serialize, Deserialize)]
556pub struct TreeConfig {
557 #[serde(default = "TreeConfig::default_announce_min_interval_ms")]
559 pub announce_min_interval_ms: u64,
560 #[serde(default = "TreeConfig::default_parent_hysteresis")]
566 pub parent_hysteresis: f64,
567 #[serde(default = "TreeConfig::default_hold_down_secs")]
572 pub hold_down_secs: u64,
573 #[serde(default = "TreeConfig::default_reeval_interval_secs")]
579 pub reeval_interval_secs: u64,
580 #[serde(default = "TreeConfig::default_flap_threshold")]
582 pub flap_threshold: u32,
583 #[serde(default = "TreeConfig::default_flap_window_secs")]
585 pub flap_window_secs: u64,
586 #[serde(default = "TreeConfig::default_flap_dampening_secs")]
588 pub flap_dampening_secs: u64,
589}
590
591impl Default for TreeConfig {
592 fn default() -> Self {
593 Self {
594 announce_min_interval_ms: 500,
595 parent_hysteresis: 0.2,
596 hold_down_secs: 30,
597 reeval_interval_secs: 60,
598 flap_threshold: 4,
599 flap_window_secs: 60,
600 flap_dampening_secs: 120,
601 }
602 }
603}
604
605impl TreeConfig {
606 fn default_announce_min_interval_ms() -> u64 {
607 500
608 }
609 fn default_parent_hysteresis() -> f64 {
610 0.2
611 }
612 fn default_hold_down_secs() -> u64 {
613 30
614 }
615 fn default_reeval_interval_secs() -> u64 {
616 60
617 }
618 fn default_flap_threshold() -> u32 {
619 4
620 }
621 fn default_flap_window_secs() -> u64 {
622 60
623 }
624 fn default_flap_dampening_secs() -> u64 {
625 120
626 }
627}
628
629#[derive(Debug, Clone, Serialize, Deserialize)]
631pub struct RoutingConfig {
632 #[serde(default)]
634 pub mode: RoutingMode,
635 #[serde(default = "RoutingConfig::default_learned_ttl_secs")]
637 pub learned_ttl_secs: u64,
638 #[serde(default = "RoutingConfig::default_max_learned_routes_per_dest")]
642 pub max_learned_routes_per_dest: usize,
643 #[serde(default = "RoutingConfig::default_learned_fallback_explore_interval")]
646 pub learned_fallback_explore_interval: u64,
647}
648
649impl Default for RoutingConfig {
650 fn default() -> Self {
651 Self {
652 mode: RoutingMode::default(),
653 learned_ttl_secs: 300,
654 max_learned_routes_per_dest: 4,
655 learned_fallback_explore_interval: 16,
656 }
657 }
658}
659
660impl RoutingConfig {
661 fn default_learned_ttl_secs() -> u64 {
662 300
663 }
664
665 fn default_max_learned_routes_per_dest() -> usize {
666 4
667 }
668
669 fn default_learned_fallback_explore_interval() -> u64 {
670 16
671 }
672}
673
674#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
676#[serde(rename_all = "snake_case")]
677pub enum RoutingMode {
678 #[default]
680 Tree,
681 ReplyLearned,
686}
687
688impl std::fmt::Display for RoutingMode {
689 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
690 match self {
691 RoutingMode::Tree => write!(f, "tree"),
692 RoutingMode::ReplyLearned => write!(f, "reply_learned"),
693 }
694 }
695}
696
697#[derive(Debug, Clone, Serialize, Deserialize)]
699pub struct BloomConfig {
700 #[serde(default = "BloomConfig::default_update_debounce_ms")]
702 pub update_debounce_ms: u64,
703 #[serde(default = "BloomConfig::default_max_inbound_fpr")]
709 pub max_inbound_fpr: f64,
710}
711
712impl Default for BloomConfig {
713 fn default() -> Self {
714 Self {
715 update_debounce_ms: 500,
716 max_inbound_fpr: 0.05,
717 }
718 }
719}
720
721impl BloomConfig {
722 fn default_update_debounce_ms() -> u64 {
723 500
724 }
725 fn default_max_inbound_fpr() -> f64 {
726 0.05
727 }
728}
729
730#[derive(Debug, Clone, Serialize, Deserialize)]
732pub struct SessionConfig {
733 #[serde(default = "SessionConfig::default_ttl")]
735 pub default_ttl: u8,
736 #[serde(default = "SessionConfig::default_pending_packets_per_dest")]
738 pub pending_packets_per_dest: usize,
739 #[serde(default = "SessionConfig::default_pending_max_destinations")]
741 pub pending_max_destinations: usize,
742 #[serde(default = "SessionConfig::default_idle_timeout_secs")]
746 pub idle_timeout_secs: u64,
747 #[serde(default = "SessionConfig::default_coords_warmup_packets")]
751 pub coords_warmup_packets: u8,
752 #[serde(default = "SessionConfig::default_coords_response_interval_ms")]
756 pub coords_response_interval_ms: u64,
757}
758
759impl Default for SessionConfig {
760 fn default() -> Self {
761 Self {
762 default_ttl: 64,
763 pending_packets_per_dest: 16,
764 pending_max_destinations: 256,
765 idle_timeout_secs: 90,
766 coords_warmup_packets: 5,
767 coords_response_interval_ms: 2000,
768 }
769 }
770}
771
772impl SessionConfig {
773 fn default_ttl() -> u8 {
774 64
775 }
776 fn default_pending_packets_per_dest() -> usize {
777 16
778 }
779 fn default_pending_max_destinations() -> usize {
780 256
781 }
782 fn default_idle_timeout_secs() -> u64 {
783 90
784 }
785 fn default_coords_warmup_packets() -> u8 {
786 5
787 }
788 fn default_coords_response_interval_ms() -> u64 {
789 2000
790 }
791}
792
793#[derive(Debug, Clone, Serialize, Deserialize)]
800pub struct SessionMmpConfig {
801 #[serde(default)]
803 pub mode: MmpMode,
804
805 #[serde(default = "SessionMmpConfig::default_log_interval_secs")]
807 pub log_interval_secs: u64,
808
809 #[serde(default = "SessionMmpConfig::default_owd_window_size")]
811 pub owd_window_size: usize,
812}
813
814impl Default for SessionMmpConfig {
815 fn default() -> Self {
816 Self {
817 mode: MmpMode::default(),
818 log_interval_secs: DEFAULT_LOG_INTERVAL_SECS,
819 owd_window_size: DEFAULT_OWD_WINDOW_SIZE,
820 }
821 }
822}
823
824impl SessionMmpConfig {
825 fn default_log_interval_secs() -> u64 {
826 DEFAULT_LOG_INTERVAL_SECS
827 }
828 fn default_owd_window_size() -> usize {
829 DEFAULT_OWD_WINDOW_SIZE
830 }
831}
832
833#[derive(Debug, Clone, Serialize, Deserialize)]
835pub struct ControlConfig {
836 #[serde(default = "ControlConfig::default_enabled")]
838 pub enabled: bool,
839 #[serde(default = "ControlConfig::default_socket_path")]
841 pub socket_path: String,
842}
843
844impl Default for ControlConfig {
845 fn default() -> Self {
846 Self {
847 enabled: true,
848 socket_path: Self::default_socket_path(),
849 }
850 }
851}
852
853impl ControlConfig {
854 fn default_enabled() -> bool {
855 true
856 }
857
858 fn default_socket_path() -> String {
865 #[cfg(unix)]
866 {
867 super::resolve_default_socket("control.sock")
868 }
869 #[cfg(windows)]
870 {
871 "21210".to_string()
872 }
873 }
874}
875
876#[derive(Debug, Clone, Serialize, Deserialize)]
878pub struct BuffersConfig {
879 #[serde(default = "BuffersConfig::default_packet_channel")]
881 pub packet_channel: usize,
882 #[serde(default = "BuffersConfig::default_tun_channel")]
884 pub tun_channel: usize,
885 #[serde(default = "BuffersConfig::default_dns_channel")]
887 pub dns_channel: usize,
888}
889
890impl Default for BuffersConfig {
891 fn default() -> Self {
892 Self {
893 packet_channel: 1024,
894 tun_channel: 1024,
895 dns_channel: 64,
896 }
897 }
898}
899
900impl BuffersConfig {
901 fn default_packet_channel() -> usize {
902 1024
903 }
904 fn default_tun_channel() -> usize {
905 1024
906 }
907 fn default_dns_channel() -> usize {
908 64
909 }
910}
911
912const DEFAULT_REKEY_AFTER_MESSAGES: u64 = 1 << 48;
929
930#[derive(Debug, Clone, Serialize, Deserialize)]
931pub struct RekeyConfig {
932 #[serde(default = "RekeyConfig::default_enabled")]
934 pub enabled: bool,
935
936 #[serde(default = "RekeyConfig::default_after_secs")]
938 pub after_secs: u64,
939
940 #[serde(default = "RekeyConfig::default_after_messages")]
942 pub after_messages: u64,
943}
944
945impl Default for RekeyConfig {
946 fn default() -> Self {
947 Self {
948 enabled: true,
949 after_secs: 120,
950 after_messages: DEFAULT_REKEY_AFTER_MESSAGES,
951 }
952 }
953}
954
955impl RekeyConfig {
956 fn default_enabled() -> bool {
957 true
958 }
959 fn default_after_secs() -> u64 {
960 120
961 }
962 fn default_after_messages() -> u64 {
963 DEFAULT_REKEY_AFTER_MESSAGES
964 }
965}
966
967#[derive(Debug, Clone, Serialize, Deserialize)]
973pub struct EcnConfig {
974 #[serde(default = "EcnConfig::default_enabled")]
976 pub enabled: bool,
977
978 #[serde(default = "EcnConfig::default_loss_threshold")]
982 pub loss_threshold: f64,
983
984 #[serde(default = "EcnConfig::default_etx_threshold")]
988 pub etx_threshold: f64,
989}
990
991impl Default for EcnConfig {
992 fn default() -> Self {
993 Self {
994 enabled: true,
995 loss_threshold: 0.05,
996 etx_threshold: 3.0,
997 }
998 }
999}
1000
1001impl EcnConfig {
1002 fn default_enabled() -> bool {
1003 true
1004 }
1005 fn default_loss_threshold() -> f64 {
1006 0.05
1007 }
1008 fn default_etx_threshold() -> f64 {
1009 3.0
1010 }
1011}
1012
1013#[derive(Debug, Clone, Serialize, Deserialize)]
1019pub struct NodeConfig {
1020 #[serde(default)]
1022 pub identity: IdentityConfig,
1023
1024 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
1026 pub leaf_only: bool,
1027
1028 #[serde(default = "NodeConfig::default_tick_interval_secs")]
1030 pub tick_interval_secs: u64,
1031
1032 #[serde(default = "NodeConfig::default_base_rtt_ms")]
1034 pub base_rtt_ms: u64,
1035
1036 #[serde(default = "NodeConfig::default_heartbeat_interval_secs")]
1038 pub heartbeat_interval_secs: u64,
1039
1040 #[serde(default = "NodeConfig::default_link_dead_timeout_secs")]
1043 pub link_dead_timeout_secs: u64,
1044
1045 #[serde(default = "NodeConfig::default_fast_link_dead_timeout_secs")]
1055 pub fast_link_dead_timeout_secs: u64,
1056
1057 #[serde(default)]
1059 pub limits: LimitsConfig,
1060
1061 #[serde(default)]
1063 pub rate_limit: RateLimitConfig,
1064
1065 #[serde(default)]
1067 pub retry: RetryConfig,
1068
1069 #[serde(default)]
1071 pub cache: CacheConfig,
1072
1073 #[serde(default)]
1075 pub discovery: DiscoveryConfig,
1076
1077 #[serde(default)]
1079 pub tree: TreeConfig,
1080
1081 #[serde(default)]
1083 pub routing: RoutingConfig,
1084
1085 #[serde(default)]
1087 pub bloom: BloomConfig,
1088
1089 #[serde(default)]
1091 pub session: SessionConfig,
1092
1093 #[serde(default)]
1095 pub buffers: BuffersConfig,
1096
1097 #[serde(default)]
1099 pub control: ControlConfig,
1100
1101 #[serde(default)]
1103 pub mmp: MmpConfig,
1104
1105 #[serde(default)]
1107 pub session_mmp: SessionMmpConfig,
1108
1109 #[serde(default)]
1111 pub ecn: EcnConfig,
1112
1113 #[serde(default)]
1115 pub rekey: RekeyConfig,
1116
1117 #[serde(default = "NodeConfig::default_system_files_enabled")]
1120 pub system_files_enabled: bool,
1121
1122 #[serde(default = "NodeConfig::default_worker_pools_enabled")]
1127 pub worker_pools_enabled: bool,
1128
1129 #[serde(default)]
1132 pub log_level: Option<String>,
1133}
1134
1135impl Default for NodeConfig {
1136 fn default() -> Self {
1137 Self {
1138 identity: IdentityConfig::default(),
1139 leaf_only: false,
1140 tick_interval_secs: 1,
1141 base_rtt_ms: 100,
1142 heartbeat_interval_secs: 10,
1143 link_dead_timeout_secs: 30,
1144 fast_link_dead_timeout_secs: 5,
1145 limits: LimitsConfig::default(),
1146 rate_limit: RateLimitConfig::default(),
1147 retry: RetryConfig::default(),
1148 cache: CacheConfig::default(),
1149 discovery: DiscoveryConfig::default(),
1150 tree: TreeConfig::default(),
1151 routing: RoutingConfig::default(),
1152 bloom: BloomConfig::default(),
1153 session: SessionConfig::default(),
1154 buffers: BuffersConfig::default(),
1155 control: ControlConfig::default(),
1156 mmp: MmpConfig::default(),
1157 session_mmp: SessionMmpConfig::default(),
1158 ecn: EcnConfig::default(),
1159 rekey: RekeyConfig::default(),
1160 system_files_enabled: true,
1161 worker_pools_enabled: true,
1162 log_level: None,
1163 }
1164 }
1165}
1166
1167impl NodeConfig {
1168 pub fn log_level(&self) -> tracing::Level {
1170 match self
1171 .log_level
1172 .as_deref()
1173 .map(|s| s.to_lowercase())
1174 .as_deref()
1175 {
1176 Some("trace") => tracing::Level::TRACE,
1177 Some("debug") => tracing::Level::DEBUG,
1178 Some("warn") | Some("warning") => tracing::Level::WARN,
1179 Some("error") => tracing::Level::ERROR,
1180 _ => tracing::Level::INFO,
1181 }
1182 }
1183
1184 fn default_tick_interval_secs() -> u64 {
1185 1
1186 }
1187 fn default_base_rtt_ms() -> u64 {
1188 100
1189 }
1190 fn default_heartbeat_interval_secs() -> u64 {
1191 10
1192 }
1193 fn default_link_dead_timeout_secs() -> u64 {
1194 30
1195 }
1196 fn default_fast_link_dead_timeout_secs() -> u64 {
1197 5
1198 }
1199 fn default_system_files_enabled() -> bool {
1200 true
1201 }
1202 fn default_worker_pools_enabled() -> bool {
1203 true
1204 }
1205}
1206
1207#[cfg(test)]
1208mod tests {
1209 use super::*;
1210
1211 #[test]
1212 fn test_ecn_config_defaults() {
1213 let c = EcnConfig::default();
1214 assert!(c.enabled);
1215 assert!((c.loss_threshold - 0.05).abs() < 1e-9);
1216 assert!((c.etx_threshold - 3.0).abs() < 1e-9);
1217 }
1218
1219 #[test]
1220 fn test_rekey_config_defaults() {
1221 let c = RekeyConfig::default();
1222 assert!(c.enabled);
1223 assert_eq!(c.after_secs, 120);
1224 assert_eq!(c.after_messages, 1 << 48);
1225 }
1226
1227 #[test]
1228 fn test_rekey_config_partial_yaml_uses_defaults() {
1229 let yaml = "after_secs: 30\n";
1230 let c: RekeyConfig = serde_yaml::from_str(yaml).unwrap();
1231 assert!(c.enabled);
1232 assert_eq!(c.after_secs, 30);
1233 assert_eq!(c.after_messages, 1 << 48);
1234 }
1235
1236 #[test]
1237 fn test_routing_config_defaults() {
1238 let c = RoutingConfig::default();
1239 assert_eq!(c.mode, RoutingMode::Tree);
1240 assert_eq!(c.learned_ttl_secs, 300);
1241 assert_eq!(c.max_learned_routes_per_dest, 4);
1242 assert_eq!(c.learned_fallback_explore_interval, 16);
1243 }
1244
1245 #[test]
1246 fn test_routing_config_yaml() {
1247 let yaml = "mode: reply_learned\nlearned_ttl_secs: 120\nmax_learned_routes_per_dest: 2\nlearned_fallback_explore_interval: 8\n";
1248 let c: RoutingConfig = serde_yaml::from_str(yaml).unwrap();
1249 assert_eq!(c.mode, RoutingMode::ReplyLearned);
1250 assert_eq!(c.learned_ttl_secs, 120);
1251 assert_eq!(c.max_learned_routes_per_dest, 2);
1252 assert_eq!(c.learned_fallback_explore_interval, 8);
1253 }
1254
1255 #[test]
1256 fn test_ecn_config_yaml_roundtrip() {
1257 let yaml = "loss_threshold: 0.10\netx_threshold: 2.5\nenabled: false\n";
1258 let c: EcnConfig = serde_yaml::from_str(yaml).unwrap();
1259 assert!(!c.enabled);
1260 assert!((c.loss_threshold - 0.10).abs() < 1e-9);
1261 assert!((c.etx_threshold - 2.5).abs() < 1e-9);
1262 }
1263
1264 #[test]
1265 fn test_ecn_config_partial_yaml() {
1266 let yaml = "loss_threshold: 0.02\n";
1268 let c: EcnConfig = serde_yaml::from_str(yaml).unwrap();
1269 assert!(c.enabled); assert!((c.loss_threshold - 0.02).abs() < 1e-9);
1271 assert!((c.etx_threshold - 3.0).abs() < 1e-9); }
1273
1274 #[test]
1275 fn test_nostr_discovery_startup_sweep_defaults() {
1276 let c = NostrDiscoveryConfig::default();
1277 assert_eq!(c.startup_sweep_delay_secs, 5);
1278 assert_eq!(c.startup_sweep_max_age_secs, 3_600);
1279 }
1280
1281 #[test]
1282 fn test_nostr_discovery_startup_sweep_yaml_override() {
1283 let yaml = "enabled: true\npolicy: open\nstartup_sweep_delay_secs: 10\nstartup_sweep_max_age_secs: 1800\n";
1284 let c: NostrDiscoveryConfig = serde_yaml::from_str(yaml).unwrap();
1285 assert!(c.enabled);
1286 assert_eq!(c.policy, NostrDiscoveryPolicy::Open);
1287 assert_eq!(c.startup_sweep_delay_secs, 10);
1288 assert_eq!(c.startup_sweep_max_age_secs, 1_800);
1289 }
1290
1291 #[test]
1292 fn test_nostr_discovery_startup_sweep_partial_yaml_uses_defaults() {
1293 let yaml = "enabled: true\nstartup_sweep_delay_secs: 30\n";
1295 let c: NostrDiscoveryConfig = serde_yaml::from_str(yaml).unwrap();
1296 assert_eq!(c.startup_sweep_delay_secs, 30);
1297 assert_eq!(c.startup_sweep_max_age_secs, 3_600);
1298 }
1299
1300 #[test]
1301 fn test_log_level_parser() {
1302 let cases: &[(Option<&str>, tracing::Level)] = &[
1308 (Some("trace"), tracing::Level::TRACE),
1310 (Some("debug"), tracing::Level::DEBUG),
1311 (Some("warn"), tracing::Level::WARN),
1312 (Some("warning"), tracing::Level::WARN),
1313 (Some("error"), tracing::Level::ERROR),
1314 (Some("info"), tracing::Level::INFO),
1316 (None, tracing::Level::INFO),
1318 (Some("TRACE"), tracing::Level::TRACE),
1320 (Some("Debug"), tracing::Level::DEBUG),
1321 (Some("Warning"), tracing::Level::WARN),
1322 (Some("WARN"), tracing::Level::WARN),
1323 (Some("ERROR"), tracing::Level::ERROR),
1324 (Some("INFO"), tracing::Level::INFO),
1325 (Some("verbose"), tracing::Level::INFO),
1327 (Some("nonsense"), tracing::Level::INFO),
1328 (Some(""), tracing::Level::INFO),
1329 ];
1330
1331 for (input, expected) in cases {
1332 let cfg = NodeConfig {
1333 log_level: input.map(|s| s.to_string()),
1334 ..NodeConfig::default()
1335 };
1336 assert_eq!(
1337 cfg.log_level(),
1338 *expected,
1339 "input {:?} should map to {:?}",
1340 input,
1341 expected
1342 );
1343 }
1344 }
1345
1346 #[cfg(windows)]
1347 #[test]
1348 fn test_default_socket_path_windows() {
1349 let config = ControlConfig::default();
1350 let port: u16 = config
1352 .socket_path
1353 .parse()
1354 .expect("should be a valid port number");
1355 assert_eq!(port, 21210);
1356 }
1357}