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")]
209 pub backoff_base_secs: u64,
210 #[serde(default = "DiscoveryConfig::default_backoff_max_secs")]
212 pub backoff_max_secs: u64,
213 #[serde(default = "DiscoveryConfig::default_forward_min_interval_secs")]
217 pub forward_min_interval_secs: u64,
218 #[serde(default = "DiscoveryConfig::default_nostr")]
220 pub nostr: NostrDiscoveryConfig,
221 #[serde(default = "DiscoveryConfig::default_lan")]
226 pub lan: crate::discovery::lan::LanDiscoveryConfig,
227 #[serde(default = "DiscoveryConfig::default_local")]
232 pub local: crate::discovery::local::LocalInstanceDiscoveryConfig,
233}
234
235impl Default for DiscoveryConfig {
236 fn default() -> Self {
237 Self {
238 ttl: 64,
239 attempt_timeouts_secs: vec![1, 2, 4, 8],
240 recent_expiry_secs: 10,
241 backoff_base_secs: 30,
242 backoff_max_secs: 300,
243 forward_min_interval_secs: 2,
244 nostr: NostrDiscoveryConfig::default(),
245 lan: crate::discovery::lan::LanDiscoveryConfig::default(),
246 local: crate::discovery::local::LocalInstanceDiscoveryConfig::default(),
247 }
248 }
249}
250
251impl DiscoveryConfig {
252 fn default_ttl() -> u8 {
253 64
254 }
255 fn default_attempt_timeouts_secs() -> Vec<u64> {
256 vec![1, 2, 4, 8]
257 }
258 fn default_recent_expiry_secs() -> u64 {
259 10
260 }
261 fn default_backoff_base_secs() -> u64 {
262 30
263 }
264 fn default_backoff_max_secs() -> u64 {
265 300
266 }
267 fn default_forward_min_interval_secs() -> u64 {
268 2
269 }
270 fn default_nostr() -> NostrDiscoveryConfig {
271 NostrDiscoveryConfig::default()
272 }
273 fn default_lan() -> crate::discovery::lan::LanDiscoveryConfig {
274 crate::discovery::lan::LanDiscoveryConfig::default()
275 }
276 fn default_local() -> crate::discovery::local::LocalInstanceDiscoveryConfig {
277 crate::discovery::local::LocalInstanceDiscoveryConfig::default()
278 }
279}
280
281#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
288#[serde(rename_all = "snake_case")]
289pub enum NostrDiscoveryPolicy {
290 Disabled,
291 #[default]
292 ConfiguredOnly,
293 Open,
294}
295
296#[derive(Debug, Clone, Serialize, Deserialize)]
298#[serde(deny_unknown_fields)]
299pub struct NostrDiscoveryConfig {
300 #[serde(default)]
302 pub enabled: bool,
303 #[serde(default = "NostrDiscoveryConfig::default_advertise")]
305 pub advertise: bool,
306 #[serde(default = "NostrDiscoveryConfig::default_advert_relays")]
308 pub advert_relays: Vec<String>,
309 #[serde(default = "NostrDiscoveryConfig::default_dm_relays")]
311 pub dm_relays: Vec<String>,
312 #[serde(default = "NostrDiscoveryConfig::default_stun_servers")]
316 pub stun_servers: Vec<String>,
317 #[serde(default)]
327 pub share_local_candidates: bool,
328 #[serde(default = "NostrDiscoveryConfig::default_app")]
330 pub app: String,
331 #[serde(default = "NostrDiscoveryConfig::default_signal_ttl_secs")]
333 pub signal_ttl_secs: u64,
334 #[serde(default)]
336 pub policy: NostrDiscoveryPolicy,
337 #[serde(default = "NostrDiscoveryConfig::default_open_discovery_max_pending")]
340 pub open_discovery_max_pending: usize,
341 #[serde(default = "NostrDiscoveryConfig::default_max_concurrent_incoming_offers")]
344 pub max_concurrent_incoming_offers: usize,
345 #[serde(default = "NostrDiscoveryConfig::default_advert_cache_max_entries")]
348 pub advert_cache_max_entries: usize,
349 #[serde(default = "NostrDiscoveryConfig::default_seen_sessions_max_entries")]
352 pub seen_sessions_max_entries: usize,
353 #[serde(default = "NostrDiscoveryConfig::default_attempt_timeout_secs")]
355 pub attempt_timeout_secs: u64,
356 #[serde(default = "NostrDiscoveryConfig::default_replay_window_secs")]
358 pub replay_window_secs: u64,
359 #[serde(default = "NostrDiscoveryConfig::default_punch_start_delay_ms")]
361 pub punch_start_delay_ms: u64,
362 #[serde(default = "NostrDiscoveryConfig::default_punch_interval_ms")]
364 pub punch_interval_ms: u64,
365 #[serde(default = "NostrDiscoveryConfig::default_punch_duration_ms")]
367 pub punch_duration_ms: u64,
368 #[serde(default = "NostrDiscoveryConfig::default_advert_ttl_secs")]
370 pub advert_ttl_secs: u64,
371 #[serde(default = "NostrDiscoveryConfig::default_advert_refresh_secs")]
373 pub advert_refresh_secs: u64,
374 #[serde(default = "NostrDiscoveryConfig::default_startup_sweep_delay_secs")]
379 pub startup_sweep_delay_secs: u64,
380 #[serde(default = "NostrDiscoveryConfig::default_startup_sweep_max_age_secs")]
385 pub startup_sweep_max_age_secs: u64,
386 #[serde(default = "NostrDiscoveryConfig::default_failure_streak_threshold")]
392 pub failure_streak_threshold: u32,
393 #[serde(default = "NostrDiscoveryConfig::default_extended_cooldown_secs")]
397 pub extended_cooldown_secs: u64,
398 #[serde(default = "NostrDiscoveryConfig::default_warn_log_interval_secs")]
403 pub warn_log_interval_secs: u64,
404 #[serde(default = "NostrDiscoveryConfig::default_failure_state_max_entries")]
408 pub failure_state_max_entries: usize,
409 #[serde(default = "NostrDiscoveryConfig::default_protocol_mismatch_cooldown_secs")]
416 pub protocol_mismatch_cooldown_secs: u64,
417}
418
419impl Default for NostrDiscoveryConfig {
420 fn default() -> Self {
421 Self {
422 enabled: false,
423 advertise: Self::default_advertise(),
424 advert_relays: Self::default_advert_relays(),
425 dm_relays: Self::default_dm_relays(),
426 stun_servers: Self::default_stun_servers(),
427 share_local_candidates: false,
428 app: Self::default_app(),
429 signal_ttl_secs: Self::default_signal_ttl_secs(),
430 policy: NostrDiscoveryPolicy::default(),
431 open_discovery_max_pending: Self::default_open_discovery_max_pending(),
432 max_concurrent_incoming_offers: Self::default_max_concurrent_incoming_offers(),
433 advert_cache_max_entries: Self::default_advert_cache_max_entries(),
434 seen_sessions_max_entries: Self::default_seen_sessions_max_entries(),
435 attempt_timeout_secs: Self::default_attempt_timeout_secs(),
436 replay_window_secs: Self::default_replay_window_secs(),
437 punch_start_delay_ms: Self::default_punch_start_delay_ms(),
438 punch_interval_ms: Self::default_punch_interval_ms(),
439 punch_duration_ms: Self::default_punch_duration_ms(),
440 advert_ttl_secs: Self::default_advert_ttl_secs(),
441 advert_refresh_secs: Self::default_advert_refresh_secs(),
442 startup_sweep_delay_secs: Self::default_startup_sweep_delay_secs(),
443 startup_sweep_max_age_secs: Self::default_startup_sweep_max_age_secs(),
444 failure_streak_threshold: Self::default_failure_streak_threshold(),
445 extended_cooldown_secs: Self::default_extended_cooldown_secs(),
446 warn_log_interval_secs: Self::default_warn_log_interval_secs(),
447 failure_state_max_entries: Self::default_failure_state_max_entries(),
448 protocol_mismatch_cooldown_secs: Self::default_protocol_mismatch_cooldown_secs(),
449 }
450 }
451}
452
453impl NostrDiscoveryConfig {
454 fn default_advertise() -> bool {
455 true
456 }
457
458 fn default_advert_relays() -> Vec<String> {
459 vec![
460 "wss://relay.damus.io".to_string(),
461 "wss://nos.lol".to_string(),
462 "wss://offchain.pub".to_string(),
463 "wss://temp.iris.to".to_string(),
464 ]
465 }
466
467 fn default_dm_relays() -> Vec<String> {
468 vec![
469 "wss://relay.damus.io".to_string(),
470 "wss://nos.lol".to_string(),
471 "wss://offchain.pub".to_string(),
472 "wss://temp.iris.to".to_string(),
473 ]
474 }
475
476 fn default_stun_servers() -> Vec<String> {
477 vec![
478 "stun:stun.l.google.com:19302".to_string(),
479 "stun:stun.cloudflare.com:3478".to_string(),
480 "stun:global.stun.twilio.com:3478".to_string(),
481 ]
482 }
483
484 fn default_app() -> String {
485 "fips-overlay-v1".to_string()
486 }
487
488 fn default_signal_ttl_secs() -> u64 {
489 120
490 }
491
492 fn default_open_discovery_max_pending() -> usize {
493 64
494 }
495
496 fn default_max_concurrent_incoming_offers() -> usize {
497 16
498 }
499
500 fn default_advert_cache_max_entries() -> usize {
501 2048
502 }
503
504 fn default_seen_sessions_max_entries() -> usize {
505 2048
506 }
507
508 fn default_attempt_timeout_secs() -> u64 {
509 10
510 }
511
512 fn default_replay_window_secs() -> u64 {
513 300
514 }
515
516 fn default_punch_start_delay_ms() -> u64 {
517 2_000
518 }
519
520 fn default_punch_interval_ms() -> u64 {
521 200
522 }
523
524 fn default_punch_duration_ms() -> u64 {
525 10_000
526 }
527
528 fn default_advert_ttl_secs() -> u64 {
529 3_600
530 }
531
532 fn default_advert_refresh_secs() -> u64 {
533 1_800
534 }
535
536 fn default_startup_sweep_delay_secs() -> u64 {
537 5
538 }
539
540 fn default_startup_sweep_max_age_secs() -> u64 {
541 3_600
542 }
543
544 fn default_failure_streak_threshold() -> u32 {
545 5
546 }
547
548 fn default_extended_cooldown_secs() -> u64 {
549 1_800
550 }
551
552 fn default_warn_log_interval_secs() -> u64 {
553 300
554 }
555
556 fn default_failure_state_max_entries() -> usize {
557 4_096
558 }
559
560 fn default_protocol_mismatch_cooldown_secs() -> u64 {
561 86_400
562 }
563}
564
565#[derive(Debug, Clone, Serialize, Deserialize)]
567pub struct TreeConfig {
568 #[serde(default = "TreeConfig::default_announce_min_interval_ms")]
570 pub announce_min_interval_ms: u64,
571 #[serde(default = "TreeConfig::default_parent_hysteresis")]
577 pub parent_hysteresis: f64,
578 #[serde(default = "TreeConfig::default_hold_down_secs")]
583 pub hold_down_secs: u64,
584 #[serde(default = "TreeConfig::default_reeval_interval_secs")]
590 pub reeval_interval_secs: u64,
591 #[serde(default = "TreeConfig::default_flap_threshold")]
593 pub flap_threshold: u32,
594 #[serde(default = "TreeConfig::default_flap_window_secs")]
596 pub flap_window_secs: u64,
597 #[serde(default = "TreeConfig::default_flap_dampening_secs")]
599 pub flap_dampening_secs: u64,
600}
601
602impl Default for TreeConfig {
603 fn default() -> Self {
604 Self {
605 announce_min_interval_ms: 500,
606 parent_hysteresis: 0.2,
607 hold_down_secs: 30,
608 reeval_interval_secs: 60,
609 flap_threshold: 4,
610 flap_window_secs: 60,
611 flap_dampening_secs: 120,
612 }
613 }
614}
615
616impl TreeConfig {
617 fn default_announce_min_interval_ms() -> u64 {
618 500
619 }
620 fn default_parent_hysteresis() -> f64 {
621 0.2
622 }
623 fn default_hold_down_secs() -> u64 {
624 30
625 }
626 fn default_reeval_interval_secs() -> u64 {
627 60
628 }
629 fn default_flap_threshold() -> u32 {
630 4
631 }
632 fn default_flap_window_secs() -> u64 {
633 60
634 }
635 fn default_flap_dampening_secs() -> u64 {
636 120
637 }
638}
639
640#[derive(Debug, Clone, Serialize, Deserialize)]
642pub struct RoutingConfig {
643 #[serde(default)]
645 pub mode: RoutingMode,
646 #[serde(default = "RoutingConfig::default_learned_ttl_secs")]
648 pub learned_ttl_secs: u64,
649 #[serde(default = "RoutingConfig::default_max_learned_routes_per_dest")]
653 pub max_learned_routes_per_dest: usize,
654 #[serde(default = "RoutingConfig::default_learned_fallback_explore_interval")]
657 pub learned_fallback_explore_interval: u64,
658}
659
660impl Default for RoutingConfig {
661 fn default() -> Self {
662 Self {
663 mode: RoutingMode::default(),
664 learned_ttl_secs: 300,
665 max_learned_routes_per_dest: 4,
666 learned_fallback_explore_interval: 16,
667 }
668 }
669}
670
671impl RoutingConfig {
672 fn default_learned_ttl_secs() -> u64 {
673 300
674 }
675
676 fn default_max_learned_routes_per_dest() -> usize {
677 4
678 }
679
680 fn default_learned_fallback_explore_interval() -> u64 {
681 16
682 }
683}
684
685#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
687#[serde(rename_all = "snake_case")]
688pub enum RoutingMode {
689 #[default]
691 Tree,
692 ReplyLearned,
697}
698
699impl std::fmt::Display for RoutingMode {
700 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
701 match self {
702 RoutingMode::Tree => write!(f, "tree"),
703 RoutingMode::ReplyLearned => write!(f, "reply_learned"),
704 }
705 }
706}
707
708#[derive(Debug, Clone, Serialize, Deserialize)]
710pub struct BloomConfig {
711 #[serde(default = "BloomConfig::default_update_debounce_ms")]
713 pub update_debounce_ms: u64,
714 #[serde(default = "BloomConfig::default_max_inbound_fpr")]
720 pub max_inbound_fpr: f64,
721}
722
723impl Default for BloomConfig {
724 fn default() -> Self {
725 Self {
726 update_debounce_ms: 500,
727 max_inbound_fpr: 0.05,
728 }
729 }
730}
731
732impl BloomConfig {
733 fn default_update_debounce_ms() -> u64 {
734 500
735 }
736 fn default_max_inbound_fpr() -> f64 {
737 0.05
738 }
739}
740
741#[derive(Debug, Clone, Serialize, Deserialize)]
743pub struct SessionConfig {
744 #[serde(default = "SessionConfig::default_ttl")]
746 pub default_ttl: u8,
747 #[serde(default = "SessionConfig::default_pending_packets_per_dest")]
749 pub pending_packets_per_dest: usize,
750 #[serde(default = "SessionConfig::default_pending_max_destinations")]
752 pub pending_max_destinations: usize,
753 #[serde(default = "SessionConfig::default_idle_timeout_secs")]
757 pub idle_timeout_secs: u64,
758 #[serde(default = "SessionConfig::default_coords_warmup_packets")]
762 pub coords_warmup_packets: u8,
763 #[serde(default = "SessionConfig::default_coords_response_interval_ms")]
767 pub coords_response_interval_ms: u64,
768}
769
770impl Default for SessionConfig {
771 fn default() -> Self {
772 Self {
773 default_ttl: 64,
774 pending_packets_per_dest: 16,
775 pending_max_destinations: 256,
776 idle_timeout_secs: 90,
777 coords_warmup_packets: 5,
778 coords_response_interval_ms: 2000,
779 }
780 }
781}
782
783impl SessionConfig {
784 fn default_ttl() -> u8 {
785 64
786 }
787 fn default_pending_packets_per_dest() -> usize {
788 16
789 }
790 fn default_pending_max_destinations() -> usize {
791 256
792 }
793 fn default_idle_timeout_secs() -> u64 {
794 90
795 }
796 fn default_coords_warmup_packets() -> u8 {
797 5
798 }
799 fn default_coords_response_interval_ms() -> u64 {
800 2000
801 }
802}
803
804#[derive(Debug, Clone, Serialize, Deserialize)]
811pub struct SessionMmpConfig {
812 #[serde(default)]
814 pub mode: MmpMode,
815
816 #[serde(default = "SessionMmpConfig::default_log_interval_secs")]
818 pub log_interval_secs: u64,
819
820 #[serde(default = "SessionMmpConfig::default_owd_window_size")]
822 pub owd_window_size: usize,
823}
824
825impl Default for SessionMmpConfig {
826 fn default() -> Self {
827 Self {
828 mode: MmpMode::default(),
829 log_interval_secs: DEFAULT_LOG_INTERVAL_SECS,
830 owd_window_size: DEFAULT_OWD_WINDOW_SIZE,
831 }
832 }
833}
834
835impl SessionMmpConfig {
836 fn default_log_interval_secs() -> u64 {
837 DEFAULT_LOG_INTERVAL_SECS
838 }
839 fn default_owd_window_size() -> usize {
840 DEFAULT_OWD_WINDOW_SIZE
841 }
842}
843
844#[derive(Debug, Clone, Serialize, Deserialize)]
846pub struct ControlConfig {
847 #[serde(default = "ControlConfig::default_enabled")]
849 pub enabled: bool,
850 #[serde(default = "ControlConfig::default_socket_path")]
852 pub socket_path: String,
853}
854
855impl Default for ControlConfig {
856 fn default() -> Self {
857 Self {
858 enabled: true,
859 socket_path: Self::default_socket_path(),
860 }
861 }
862}
863
864impl ControlConfig {
865 fn default_enabled() -> bool {
866 true
867 }
868
869 fn default_socket_path() -> String {
876 #[cfg(unix)]
877 {
878 super::resolve_default_socket("control.sock")
879 }
880 #[cfg(windows)]
881 {
882 "21210".to_string()
883 }
884 }
885}
886
887#[derive(Debug, Clone, Serialize, Deserialize)]
889pub struct BuffersConfig {
890 #[serde(default = "BuffersConfig::default_packet_channel")]
892 pub packet_channel: usize,
893 #[serde(default = "BuffersConfig::default_tun_channel")]
895 pub tun_channel: usize,
896 #[serde(default = "BuffersConfig::default_dns_channel")]
898 pub dns_channel: usize,
899}
900
901impl Default for BuffersConfig {
902 fn default() -> Self {
903 Self {
904 packet_channel: 1024,
905 tun_channel: 1024,
906 dns_channel: 64,
907 }
908 }
909}
910
911impl BuffersConfig {
912 fn default_packet_channel() -> usize {
913 1024
914 }
915 fn default_tun_channel() -> usize {
916 1024
917 }
918 fn default_dns_channel() -> usize {
919 64
920 }
921}
922
923const DEFAULT_REKEY_AFTER_MESSAGES: u64 = 1 << 48;
940
941#[derive(Debug, Clone, Serialize, Deserialize)]
942pub struct RekeyConfig {
943 #[serde(default = "RekeyConfig::default_enabled")]
945 pub enabled: bool,
946
947 #[serde(default = "RekeyConfig::default_after_secs")]
949 pub after_secs: u64,
950
951 #[serde(default = "RekeyConfig::default_after_messages")]
953 pub after_messages: u64,
954}
955
956impl Default for RekeyConfig {
957 fn default() -> Self {
958 Self {
959 enabled: true,
960 after_secs: 120,
961 after_messages: DEFAULT_REKEY_AFTER_MESSAGES,
962 }
963 }
964}
965
966impl RekeyConfig {
967 fn default_enabled() -> bool {
968 true
969 }
970 fn default_after_secs() -> u64 {
971 120
972 }
973 fn default_after_messages() -> u64 {
974 DEFAULT_REKEY_AFTER_MESSAGES
975 }
976}
977
978#[derive(Debug, Clone, Serialize, Deserialize)]
984pub struct EcnConfig {
985 #[serde(default = "EcnConfig::default_enabled")]
987 pub enabled: bool,
988
989 #[serde(default = "EcnConfig::default_loss_threshold")]
993 pub loss_threshold: f64,
994
995 #[serde(default = "EcnConfig::default_etx_threshold")]
999 pub etx_threshold: f64,
1000}
1001
1002impl Default for EcnConfig {
1003 fn default() -> Self {
1004 Self {
1005 enabled: true,
1006 loss_threshold: 0.05,
1007 etx_threshold: 3.0,
1008 }
1009 }
1010}
1011
1012impl EcnConfig {
1013 fn default_enabled() -> bool {
1014 true
1015 }
1016 fn default_loss_threshold() -> f64 {
1017 0.05
1018 }
1019 fn default_etx_threshold() -> f64 {
1020 3.0
1021 }
1022}
1023
1024#[derive(Debug, Clone, Serialize, Deserialize)]
1030pub struct NodeConfig {
1031 #[serde(default)]
1033 pub identity: IdentityConfig,
1034
1035 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
1037 pub leaf_only: bool,
1038
1039 #[serde(default = "NodeConfig::default_tick_interval_secs")]
1041 pub tick_interval_secs: u64,
1042
1043 #[serde(default = "NodeConfig::default_base_rtt_ms")]
1045 pub base_rtt_ms: u64,
1046
1047 #[serde(default = "NodeConfig::default_heartbeat_interval_secs")]
1049 pub heartbeat_interval_secs: u64,
1050
1051 #[serde(default = "NodeConfig::default_link_dead_timeout_secs")]
1054 pub link_dead_timeout_secs: u64,
1055
1056 #[serde(default = "NodeConfig::default_fast_link_dead_timeout_secs")]
1066 pub fast_link_dead_timeout_secs: u64,
1067
1068 #[serde(default)]
1070 pub limits: LimitsConfig,
1071
1072 #[serde(default)]
1074 pub rate_limit: RateLimitConfig,
1075
1076 #[serde(default)]
1078 pub retry: RetryConfig,
1079
1080 #[serde(default)]
1082 pub cache: CacheConfig,
1083
1084 #[serde(default)]
1086 pub discovery: DiscoveryConfig,
1087
1088 #[serde(default)]
1090 pub tree: TreeConfig,
1091
1092 #[serde(default)]
1094 pub routing: RoutingConfig,
1095
1096 #[serde(default)]
1098 pub bloom: BloomConfig,
1099
1100 #[serde(default)]
1102 pub session: SessionConfig,
1103
1104 #[serde(default)]
1106 pub buffers: BuffersConfig,
1107
1108 #[serde(default)]
1110 pub control: ControlConfig,
1111
1112 #[serde(default)]
1114 pub mmp: MmpConfig,
1115
1116 #[serde(default)]
1118 pub session_mmp: SessionMmpConfig,
1119
1120 #[serde(default)]
1122 pub ecn: EcnConfig,
1123
1124 #[serde(default)]
1126 pub rekey: RekeyConfig,
1127
1128 #[serde(default = "NodeConfig::default_system_files_enabled")]
1131 pub system_files_enabled: bool,
1132
1133 #[serde(default = "NodeConfig::default_worker_pools_enabled")]
1138 pub worker_pools_enabled: bool,
1139
1140 #[serde(default)]
1143 pub log_level: Option<String>,
1144}
1145
1146impl Default for NodeConfig {
1147 fn default() -> Self {
1148 Self {
1149 identity: IdentityConfig::default(),
1150 leaf_only: false,
1151 tick_interval_secs: 1,
1152 base_rtt_ms: 100,
1153 heartbeat_interval_secs: 10,
1154 link_dead_timeout_secs: 30,
1155 fast_link_dead_timeout_secs: 5,
1156 limits: LimitsConfig::default(),
1157 rate_limit: RateLimitConfig::default(),
1158 retry: RetryConfig::default(),
1159 cache: CacheConfig::default(),
1160 discovery: DiscoveryConfig::default(),
1161 tree: TreeConfig::default(),
1162 routing: RoutingConfig::default(),
1163 bloom: BloomConfig::default(),
1164 session: SessionConfig::default(),
1165 buffers: BuffersConfig::default(),
1166 control: ControlConfig::default(),
1167 mmp: MmpConfig::default(),
1168 session_mmp: SessionMmpConfig::default(),
1169 ecn: EcnConfig::default(),
1170 rekey: RekeyConfig::default(),
1171 system_files_enabled: true,
1172 worker_pools_enabled: true,
1173 log_level: None,
1174 }
1175 }
1176}
1177
1178impl NodeConfig {
1179 pub fn log_level(&self) -> tracing::Level {
1181 match self
1182 .log_level
1183 .as_deref()
1184 .map(|s| s.to_lowercase())
1185 .as_deref()
1186 {
1187 Some("trace") => tracing::Level::TRACE,
1188 Some("debug") => tracing::Level::DEBUG,
1189 Some("warn") | Some("warning") => tracing::Level::WARN,
1190 Some("error") => tracing::Level::ERROR,
1191 _ => tracing::Level::INFO,
1192 }
1193 }
1194
1195 fn default_tick_interval_secs() -> u64 {
1196 1
1197 }
1198 fn default_base_rtt_ms() -> u64 {
1199 100
1200 }
1201 fn default_heartbeat_interval_secs() -> u64 {
1202 10
1203 }
1204 fn default_link_dead_timeout_secs() -> u64 {
1205 30
1206 }
1207 fn default_fast_link_dead_timeout_secs() -> u64 {
1208 5
1209 }
1210 fn default_system_files_enabled() -> bool {
1211 true
1212 }
1213 fn default_worker_pools_enabled() -> bool {
1214 true
1215 }
1216}
1217
1218#[cfg(test)]
1219mod tests {
1220 use super::*;
1221
1222 #[test]
1223 fn test_ecn_config_defaults() {
1224 let c = EcnConfig::default();
1225 assert!(c.enabled);
1226 assert!((c.loss_threshold - 0.05).abs() < 1e-9);
1227 assert!((c.etx_threshold - 3.0).abs() < 1e-9);
1228 }
1229
1230 #[test]
1231 fn test_rekey_config_defaults() {
1232 let c = RekeyConfig::default();
1233 assert!(c.enabled);
1234 assert_eq!(c.after_secs, 120);
1235 assert_eq!(c.after_messages, 1 << 48);
1236 }
1237
1238 #[test]
1239 fn test_rekey_config_partial_yaml_uses_defaults() {
1240 let yaml = "after_secs: 30\n";
1241 let c: RekeyConfig = serde_yaml::from_str(yaml).unwrap();
1242 assert!(c.enabled);
1243 assert_eq!(c.after_secs, 30);
1244 assert_eq!(c.after_messages, 1 << 48);
1245 }
1246
1247 #[test]
1248 fn test_routing_config_defaults() {
1249 let c = RoutingConfig::default();
1250 assert_eq!(c.mode, RoutingMode::Tree);
1251 assert_eq!(c.learned_ttl_secs, 300);
1252 assert_eq!(c.max_learned_routes_per_dest, 4);
1253 assert_eq!(c.learned_fallback_explore_interval, 16);
1254 }
1255
1256 #[test]
1257 fn test_routing_config_yaml() {
1258 let yaml = "mode: reply_learned\nlearned_ttl_secs: 120\nmax_learned_routes_per_dest: 2\nlearned_fallback_explore_interval: 8\n";
1259 let c: RoutingConfig = serde_yaml::from_str(yaml).unwrap();
1260 assert_eq!(c.mode, RoutingMode::ReplyLearned);
1261 assert_eq!(c.learned_ttl_secs, 120);
1262 assert_eq!(c.max_learned_routes_per_dest, 2);
1263 assert_eq!(c.learned_fallback_explore_interval, 8);
1264 }
1265
1266 #[test]
1267 fn test_ecn_config_yaml_roundtrip() {
1268 let yaml = "loss_threshold: 0.10\netx_threshold: 2.5\nenabled: false\n";
1269 let c: EcnConfig = serde_yaml::from_str(yaml).unwrap();
1270 assert!(!c.enabled);
1271 assert!((c.loss_threshold - 0.10).abs() < 1e-9);
1272 assert!((c.etx_threshold - 2.5).abs() < 1e-9);
1273 }
1274
1275 #[test]
1276 fn test_ecn_config_partial_yaml() {
1277 let yaml = "loss_threshold: 0.02\n";
1279 let c: EcnConfig = serde_yaml::from_str(yaml).unwrap();
1280 assert!(c.enabled); assert!((c.loss_threshold - 0.02).abs() < 1e-9);
1282 assert!((c.etx_threshold - 3.0).abs() < 1e-9); }
1284
1285 #[test]
1286 fn test_nostr_discovery_startup_sweep_defaults() {
1287 let c = NostrDiscoveryConfig::default();
1288 assert_eq!(c.startup_sweep_delay_secs, 5);
1289 assert_eq!(c.startup_sweep_max_age_secs, 3_600);
1290 }
1291
1292 #[test]
1293 fn test_nostr_discovery_startup_sweep_yaml_override() {
1294 let yaml = "enabled: true\npolicy: open\nstartup_sweep_delay_secs: 10\nstartup_sweep_max_age_secs: 1800\n";
1295 let c: NostrDiscoveryConfig = serde_yaml::from_str(yaml).unwrap();
1296 assert!(c.enabled);
1297 assert_eq!(c.policy, NostrDiscoveryPolicy::Open);
1298 assert_eq!(c.startup_sweep_delay_secs, 10);
1299 assert_eq!(c.startup_sweep_max_age_secs, 1_800);
1300 }
1301
1302 #[test]
1303 fn test_nostr_discovery_startup_sweep_partial_yaml_uses_defaults() {
1304 let yaml = "enabled: true\nstartup_sweep_delay_secs: 30\n";
1306 let c: NostrDiscoveryConfig = serde_yaml::from_str(yaml).unwrap();
1307 assert_eq!(c.startup_sweep_delay_secs, 30);
1308 assert_eq!(c.startup_sweep_max_age_secs, 3_600);
1309 }
1310
1311 #[test]
1312 fn test_log_level_parser() {
1313 let cases: &[(Option<&str>, tracing::Level)] = &[
1319 (Some("trace"), tracing::Level::TRACE),
1321 (Some("debug"), tracing::Level::DEBUG),
1322 (Some("warn"), tracing::Level::WARN),
1323 (Some("warning"), tracing::Level::WARN),
1324 (Some("error"), tracing::Level::ERROR),
1325 (Some("info"), tracing::Level::INFO),
1327 (None, tracing::Level::INFO),
1329 (Some("TRACE"), tracing::Level::TRACE),
1331 (Some("Debug"), tracing::Level::DEBUG),
1332 (Some("Warning"), tracing::Level::WARN),
1333 (Some("WARN"), tracing::Level::WARN),
1334 (Some("ERROR"), tracing::Level::ERROR),
1335 (Some("INFO"), tracing::Level::INFO),
1336 (Some("verbose"), tracing::Level::INFO),
1338 (Some("nonsense"), tracing::Level::INFO),
1339 (Some(""), tracing::Level::INFO),
1340 ];
1341
1342 for (input, expected) in cases {
1343 let cfg = NodeConfig {
1344 log_level: input.map(|s| s.to_string()),
1345 ..NodeConfig::default()
1346 };
1347 assert_eq!(
1348 cfg.log_level(),
1349 *expected,
1350 "input {:?} should map to {:?}",
1351 input,
1352 expected
1353 );
1354 }
1355 }
1356
1357 #[cfg(windows)]
1358 #[test]
1359 fn test_default_socket_path_windows() {
1360 let config = ControlConfig::default();
1361 let port: u16 = config
1363 .socket_path
1364 .parse()
1365 .expect("should be a valid port number");
1366 assert_eq!(port, 21210);
1367 }
1368}