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}
228
229impl Default for DiscoveryConfig {
230 fn default() -> Self {
231 Self {
232 ttl: 64,
233 attempt_timeouts_secs: vec![1, 2, 4, 8],
234 recent_expiry_secs: 10,
235 backoff_base_secs: 30,
236 backoff_max_secs: 300,
237 forward_min_interval_secs: 2,
238 nostr: NostrDiscoveryConfig::default(),
239 lan: crate::discovery::lan::LanDiscoveryConfig::default(),
240 }
241 }
242}
243
244impl DiscoveryConfig {
245 fn default_ttl() -> u8 {
246 64
247 }
248 fn default_attempt_timeouts_secs() -> Vec<u64> {
249 vec![1, 2, 4, 8]
250 }
251 fn default_recent_expiry_secs() -> u64 {
252 10
253 }
254 fn default_backoff_base_secs() -> u64 {
255 30
256 }
257 fn default_backoff_max_secs() -> u64 {
258 300
259 }
260 fn default_forward_min_interval_secs() -> u64 {
261 2
262 }
263 fn default_nostr() -> NostrDiscoveryConfig {
264 NostrDiscoveryConfig::default()
265 }
266 fn default_lan() -> crate::discovery::lan::LanDiscoveryConfig {
267 crate::discovery::lan::LanDiscoveryConfig::default()
268 }
269}
270
271#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
278#[serde(rename_all = "snake_case")]
279pub enum NostrDiscoveryPolicy {
280 Disabled,
281 #[default]
282 ConfiguredOnly,
283 Open,
284}
285
286#[derive(Debug, Clone, Serialize, Deserialize)]
288#[serde(deny_unknown_fields)]
289pub struct NostrDiscoveryConfig {
290 #[serde(default)]
292 pub enabled: bool,
293 #[serde(default = "NostrDiscoveryConfig::default_advertise")]
295 pub advertise: bool,
296 #[serde(default = "NostrDiscoveryConfig::default_advert_relays")]
298 pub advert_relays: Vec<String>,
299 #[serde(default = "NostrDiscoveryConfig::default_dm_relays")]
301 pub dm_relays: Vec<String>,
302 #[serde(default = "NostrDiscoveryConfig::default_stun_servers")]
306 pub stun_servers: Vec<String>,
307 #[serde(default)]
317 pub share_local_candidates: bool,
318 #[serde(default = "NostrDiscoveryConfig::default_app")]
320 pub app: String,
321 #[serde(default = "NostrDiscoveryConfig::default_signal_ttl_secs")]
323 pub signal_ttl_secs: u64,
324 #[serde(default)]
326 pub policy: NostrDiscoveryPolicy,
327 #[serde(default = "NostrDiscoveryConfig::default_open_discovery_max_pending")]
330 pub open_discovery_max_pending: usize,
331 #[serde(default = "NostrDiscoveryConfig::default_max_concurrent_incoming_offers")]
334 pub max_concurrent_incoming_offers: usize,
335 #[serde(default = "NostrDiscoveryConfig::default_advert_cache_max_entries")]
338 pub advert_cache_max_entries: usize,
339 #[serde(default = "NostrDiscoveryConfig::default_seen_sessions_max_entries")]
342 pub seen_sessions_max_entries: usize,
343 #[serde(default = "NostrDiscoveryConfig::default_attempt_timeout_secs")]
345 pub attempt_timeout_secs: u64,
346 #[serde(default = "NostrDiscoveryConfig::default_replay_window_secs")]
348 pub replay_window_secs: u64,
349 #[serde(default = "NostrDiscoveryConfig::default_punch_start_delay_ms")]
351 pub punch_start_delay_ms: u64,
352 #[serde(default = "NostrDiscoveryConfig::default_punch_interval_ms")]
354 pub punch_interval_ms: u64,
355 #[serde(default = "NostrDiscoveryConfig::default_punch_duration_ms")]
357 pub punch_duration_ms: u64,
358 #[serde(default = "NostrDiscoveryConfig::default_advert_ttl_secs")]
360 pub advert_ttl_secs: u64,
361 #[serde(default = "NostrDiscoveryConfig::default_advert_refresh_secs")]
363 pub advert_refresh_secs: u64,
364 #[serde(default = "NostrDiscoveryConfig::default_startup_sweep_delay_secs")]
369 pub startup_sweep_delay_secs: u64,
370 #[serde(default = "NostrDiscoveryConfig::default_startup_sweep_max_age_secs")]
375 pub startup_sweep_max_age_secs: u64,
376 #[serde(default = "NostrDiscoveryConfig::default_failure_streak_threshold")]
382 pub failure_streak_threshold: u32,
383 #[serde(default = "NostrDiscoveryConfig::default_extended_cooldown_secs")]
387 pub extended_cooldown_secs: u64,
388 #[serde(default = "NostrDiscoveryConfig::default_warn_log_interval_secs")]
393 pub warn_log_interval_secs: u64,
394 #[serde(default = "NostrDiscoveryConfig::default_failure_state_max_entries")]
398 pub failure_state_max_entries: usize,
399 #[serde(default = "NostrDiscoveryConfig::default_protocol_mismatch_cooldown_secs")]
406 pub protocol_mismatch_cooldown_secs: u64,
407}
408
409impl Default for NostrDiscoveryConfig {
410 fn default() -> Self {
411 Self {
412 enabled: false,
413 advertise: Self::default_advertise(),
414 advert_relays: Self::default_advert_relays(),
415 dm_relays: Self::default_dm_relays(),
416 stun_servers: Self::default_stun_servers(),
417 share_local_candidates: false,
418 app: Self::default_app(),
419 signal_ttl_secs: Self::default_signal_ttl_secs(),
420 policy: NostrDiscoveryPolicy::default(),
421 open_discovery_max_pending: Self::default_open_discovery_max_pending(),
422 max_concurrent_incoming_offers: Self::default_max_concurrent_incoming_offers(),
423 advert_cache_max_entries: Self::default_advert_cache_max_entries(),
424 seen_sessions_max_entries: Self::default_seen_sessions_max_entries(),
425 attempt_timeout_secs: Self::default_attempt_timeout_secs(),
426 replay_window_secs: Self::default_replay_window_secs(),
427 punch_start_delay_ms: Self::default_punch_start_delay_ms(),
428 punch_interval_ms: Self::default_punch_interval_ms(),
429 punch_duration_ms: Self::default_punch_duration_ms(),
430 advert_ttl_secs: Self::default_advert_ttl_secs(),
431 advert_refresh_secs: Self::default_advert_refresh_secs(),
432 startup_sweep_delay_secs: Self::default_startup_sweep_delay_secs(),
433 startup_sweep_max_age_secs: Self::default_startup_sweep_max_age_secs(),
434 failure_streak_threshold: Self::default_failure_streak_threshold(),
435 extended_cooldown_secs: Self::default_extended_cooldown_secs(),
436 warn_log_interval_secs: Self::default_warn_log_interval_secs(),
437 failure_state_max_entries: Self::default_failure_state_max_entries(),
438 protocol_mismatch_cooldown_secs: Self::default_protocol_mismatch_cooldown_secs(),
439 }
440 }
441}
442
443impl NostrDiscoveryConfig {
444 fn default_advertise() -> bool {
445 true
446 }
447
448 fn default_advert_relays() -> Vec<String> {
449 vec![
450 "wss://relay.damus.io".to_string(),
451 "wss://nos.lol".to_string(),
452 "wss://offchain.pub".to_string(),
453 ]
454 }
455
456 fn default_dm_relays() -> Vec<String> {
457 vec![
458 "wss://relay.damus.io".to_string(),
459 "wss://nos.lol".to_string(),
460 "wss://offchain.pub".to_string(),
461 ]
462 }
463
464 fn default_stun_servers() -> Vec<String> {
465 vec![
466 "stun:stun.l.google.com:19302".to_string(),
467 "stun:stun.cloudflare.com:3478".to_string(),
468 "stun:global.stun.twilio.com:3478".to_string(),
469 ]
470 }
471
472 fn default_app() -> String {
473 "fips-overlay-v1".to_string()
474 }
475
476 fn default_signal_ttl_secs() -> u64 {
477 120
478 }
479
480 fn default_open_discovery_max_pending() -> usize {
481 64
482 }
483
484 fn default_max_concurrent_incoming_offers() -> usize {
485 16
486 }
487
488 fn default_advert_cache_max_entries() -> usize {
489 2048
490 }
491
492 fn default_seen_sessions_max_entries() -> usize {
493 2048
494 }
495
496 fn default_attempt_timeout_secs() -> u64 {
497 10
498 }
499
500 fn default_replay_window_secs() -> u64 {
501 300
502 }
503
504 fn default_punch_start_delay_ms() -> u64 {
505 2_000
506 }
507
508 fn default_punch_interval_ms() -> u64 {
509 200
510 }
511
512 fn default_punch_duration_ms() -> u64 {
513 10_000
514 }
515
516 fn default_advert_ttl_secs() -> u64 {
517 3_600
518 }
519
520 fn default_advert_refresh_secs() -> u64 {
521 1_800
522 }
523
524 fn default_startup_sweep_delay_secs() -> u64 {
525 5
526 }
527
528 fn default_startup_sweep_max_age_secs() -> u64 {
529 3_600
530 }
531
532 fn default_failure_streak_threshold() -> u32 {
533 5
534 }
535
536 fn default_extended_cooldown_secs() -> u64 {
537 1_800
538 }
539
540 fn default_warn_log_interval_secs() -> u64 {
541 300
542 }
543
544 fn default_failure_state_max_entries() -> usize {
545 4_096
546 }
547
548 fn default_protocol_mismatch_cooldown_secs() -> u64 {
549 86_400
550 }
551}
552
553#[derive(Debug, Clone, Serialize, Deserialize)]
555pub struct TreeConfig {
556 #[serde(default = "TreeConfig::default_announce_min_interval_ms")]
558 pub announce_min_interval_ms: u64,
559 #[serde(default = "TreeConfig::default_parent_hysteresis")]
565 pub parent_hysteresis: f64,
566 #[serde(default = "TreeConfig::default_hold_down_secs")]
571 pub hold_down_secs: u64,
572 #[serde(default = "TreeConfig::default_reeval_interval_secs")]
578 pub reeval_interval_secs: u64,
579 #[serde(default = "TreeConfig::default_flap_threshold")]
581 pub flap_threshold: u32,
582 #[serde(default = "TreeConfig::default_flap_window_secs")]
584 pub flap_window_secs: u64,
585 #[serde(default = "TreeConfig::default_flap_dampening_secs")]
587 pub flap_dampening_secs: u64,
588}
589
590impl Default for TreeConfig {
591 fn default() -> Self {
592 Self {
593 announce_min_interval_ms: 500,
594 parent_hysteresis: 0.2,
595 hold_down_secs: 30,
596 reeval_interval_secs: 60,
597 flap_threshold: 4,
598 flap_window_secs: 60,
599 flap_dampening_secs: 120,
600 }
601 }
602}
603
604impl TreeConfig {
605 fn default_announce_min_interval_ms() -> u64 {
606 500
607 }
608 fn default_parent_hysteresis() -> f64 {
609 0.2
610 }
611 fn default_hold_down_secs() -> u64 {
612 30
613 }
614 fn default_reeval_interval_secs() -> u64 {
615 60
616 }
617 fn default_flap_threshold() -> u32 {
618 4
619 }
620 fn default_flap_window_secs() -> u64 {
621 60
622 }
623 fn default_flap_dampening_secs() -> u64 {
624 120
625 }
626}
627
628#[derive(Debug, Clone, Serialize, Deserialize)]
630pub struct RoutingConfig {
631 #[serde(default)]
633 pub mode: RoutingMode,
634 #[serde(default = "RoutingConfig::default_learned_ttl_secs")]
636 pub learned_ttl_secs: u64,
637 #[serde(default = "RoutingConfig::default_max_learned_routes_per_dest")]
641 pub max_learned_routes_per_dest: usize,
642 #[serde(default = "RoutingConfig::default_learned_fallback_explore_interval")]
645 pub learned_fallback_explore_interval: u64,
646}
647
648impl Default for RoutingConfig {
649 fn default() -> Self {
650 Self {
651 mode: RoutingMode::default(),
652 learned_ttl_secs: 300,
653 max_learned_routes_per_dest: 4,
654 learned_fallback_explore_interval: 16,
655 }
656 }
657}
658
659impl RoutingConfig {
660 fn default_learned_ttl_secs() -> u64 {
661 300
662 }
663
664 fn default_max_learned_routes_per_dest() -> usize {
665 4
666 }
667
668 fn default_learned_fallback_explore_interval() -> u64 {
669 16
670 }
671}
672
673#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
675#[serde(rename_all = "snake_case")]
676pub enum RoutingMode {
677 #[default]
679 Tree,
680 ReplyLearned,
685}
686
687impl std::fmt::Display for RoutingMode {
688 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
689 match self {
690 RoutingMode::Tree => write!(f, "tree"),
691 RoutingMode::ReplyLearned => write!(f, "reply_learned"),
692 }
693 }
694}
695
696#[derive(Debug, Clone, Serialize, Deserialize)]
698pub struct BloomConfig {
699 #[serde(default = "BloomConfig::default_update_debounce_ms")]
701 pub update_debounce_ms: u64,
702 #[serde(default = "BloomConfig::default_max_inbound_fpr")]
708 pub max_inbound_fpr: f64,
709}
710
711impl Default for BloomConfig {
712 fn default() -> Self {
713 Self {
714 update_debounce_ms: 500,
715 max_inbound_fpr: 0.05,
716 }
717 }
718}
719
720impl BloomConfig {
721 fn default_update_debounce_ms() -> u64 {
722 500
723 }
724 fn default_max_inbound_fpr() -> f64 {
725 0.05
726 }
727}
728
729#[derive(Debug, Clone, Serialize, Deserialize)]
731pub struct SessionConfig {
732 #[serde(default = "SessionConfig::default_ttl")]
734 pub default_ttl: u8,
735 #[serde(default = "SessionConfig::default_pending_packets_per_dest")]
737 pub pending_packets_per_dest: usize,
738 #[serde(default = "SessionConfig::default_pending_max_destinations")]
740 pub pending_max_destinations: usize,
741 #[serde(default = "SessionConfig::default_idle_timeout_secs")]
745 pub idle_timeout_secs: u64,
746 #[serde(default = "SessionConfig::default_coords_warmup_packets")]
750 pub coords_warmup_packets: u8,
751 #[serde(default = "SessionConfig::default_coords_response_interval_ms")]
755 pub coords_response_interval_ms: u64,
756}
757
758impl Default for SessionConfig {
759 fn default() -> Self {
760 Self {
761 default_ttl: 64,
762 pending_packets_per_dest: 16,
763 pending_max_destinations: 256,
764 idle_timeout_secs: 90,
765 coords_warmup_packets: 5,
766 coords_response_interval_ms: 2000,
767 }
768 }
769}
770
771impl SessionConfig {
772 fn default_ttl() -> u8 {
773 64
774 }
775 fn default_pending_packets_per_dest() -> usize {
776 16
777 }
778 fn default_pending_max_destinations() -> usize {
779 256
780 }
781 fn default_idle_timeout_secs() -> u64 {
782 90
783 }
784 fn default_coords_warmup_packets() -> u8 {
785 5
786 }
787 fn default_coords_response_interval_ms() -> u64 {
788 2000
789 }
790}
791
792#[derive(Debug, Clone, Serialize, Deserialize)]
799pub struct SessionMmpConfig {
800 #[serde(default)]
802 pub mode: MmpMode,
803
804 #[serde(default = "SessionMmpConfig::default_log_interval_secs")]
806 pub log_interval_secs: u64,
807
808 #[serde(default = "SessionMmpConfig::default_owd_window_size")]
810 pub owd_window_size: usize,
811}
812
813impl Default for SessionMmpConfig {
814 fn default() -> Self {
815 Self {
816 mode: MmpMode::default(),
817 log_interval_secs: DEFAULT_LOG_INTERVAL_SECS,
818 owd_window_size: DEFAULT_OWD_WINDOW_SIZE,
819 }
820 }
821}
822
823impl SessionMmpConfig {
824 fn default_log_interval_secs() -> u64 {
825 DEFAULT_LOG_INTERVAL_SECS
826 }
827 fn default_owd_window_size() -> usize {
828 DEFAULT_OWD_WINDOW_SIZE
829 }
830}
831
832#[derive(Debug, Clone, Serialize, Deserialize)]
834pub struct ControlConfig {
835 #[serde(default = "ControlConfig::default_enabled")]
837 pub enabled: bool,
838 #[serde(default = "ControlConfig::default_socket_path")]
840 pub socket_path: String,
841}
842
843impl Default for ControlConfig {
844 fn default() -> Self {
845 Self {
846 enabled: true,
847 socket_path: Self::default_socket_path(),
848 }
849 }
850}
851
852impl ControlConfig {
853 fn default_enabled() -> bool {
854 true
855 }
856
857 fn default_socket_path() -> String {
864 #[cfg(unix)]
865 {
866 super::resolve_default_socket("control.sock")
867 }
868 #[cfg(windows)]
869 {
870 "21210".to_string()
871 }
872 }
873}
874
875#[derive(Debug, Clone, Serialize, Deserialize)]
877pub struct BuffersConfig {
878 #[serde(default = "BuffersConfig::default_packet_channel")]
880 pub packet_channel: usize,
881 #[serde(default = "BuffersConfig::default_tun_channel")]
883 pub tun_channel: usize,
884 #[serde(default = "BuffersConfig::default_dns_channel")]
886 pub dns_channel: usize,
887}
888
889impl Default for BuffersConfig {
890 fn default() -> Self {
891 Self {
892 packet_channel: 1024,
893 tun_channel: 1024,
894 dns_channel: 64,
895 }
896 }
897}
898
899impl BuffersConfig {
900 fn default_packet_channel() -> usize {
901 1024
902 }
903 fn default_tun_channel() -> usize {
904 1024
905 }
906 fn default_dns_channel() -> usize {
907 64
908 }
909}
910
911const DEFAULT_REKEY_AFTER_MESSAGES: u64 = 1 << 48;
928
929#[derive(Debug, Clone, Serialize, Deserialize)]
930pub struct RekeyConfig {
931 #[serde(default = "RekeyConfig::default_enabled")]
933 pub enabled: bool,
934
935 #[serde(default = "RekeyConfig::default_after_secs")]
937 pub after_secs: u64,
938
939 #[serde(default = "RekeyConfig::default_after_messages")]
941 pub after_messages: u64,
942}
943
944impl Default for RekeyConfig {
945 fn default() -> Self {
946 Self {
947 enabled: true,
948 after_secs: 120,
949 after_messages: DEFAULT_REKEY_AFTER_MESSAGES,
950 }
951 }
952}
953
954impl RekeyConfig {
955 fn default_enabled() -> bool {
956 true
957 }
958 fn default_after_secs() -> u64 {
959 120
960 }
961 fn default_after_messages() -> u64 {
962 DEFAULT_REKEY_AFTER_MESSAGES
963 }
964}
965
966#[derive(Debug, Clone, Serialize, Deserialize)]
972pub struct EcnConfig {
973 #[serde(default = "EcnConfig::default_enabled")]
975 pub enabled: bool,
976
977 #[serde(default = "EcnConfig::default_loss_threshold")]
981 pub loss_threshold: f64,
982
983 #[serde(default = "EcnConfig::default_etx_threshold")]
987 pub etx_threshold: f64,
988}
989
990impl Default for EcnConfig {
991 fn default() -> Self {
992 Self {
993 enabled: true,
994 loss_threshold: 0.05,
995 etx_threshold: 3.0,
996 }
997 }
998}
999
1000impl EcnConfig {
1001 fn default_enabled() -> bool {
1002 true
1003 }
1004 fn default_loss_threshold() -> f64 {
1005 0.05
1006 }
1007 fn default_etx_threshold() -> f64 {
1008 3.0
1009 }
1010}
1011
1012#[derive(Debug, Clone, Serialize, Deserialize)]
1018pub struct NodeConfig {
1019 #[serde(default)]
1021 pub identity: IdentityConfig,
1022
1023 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
1025 pub leaf_only: bool,
1026
1027 #[serde(default = "NodeConfig::default_tick_interval_secs")]
1029 pub tick_interval_secs: u64,
1030
1031 #[serde(default = "NodeConfig::default_base_rtt_ms")]
1033 pub base_rtt_ms: u64,
1034
1035 #[serde(default = "NodeConfig::default_heartbeat_interval_secs")]
1037 pub heartbeat_interval_secs: u64,
1038
1039 #[serde(default = "NodeConfig::default_link_dead_timeout_secs")]
1042 pub link_dead_timeout_secs: u64,
1043
1044 #[serde(default = "NodeConfig::default_fast_link_dead_timeout_secs")]
1054 pub fast_link_dead_timeout_secs: u64,
1055
1056 #[serde(default)]
1058 pub limits: LimitsConfig,
1059
1060 #[serde(default)]
1062 pub rate_limit: RateLimitConfig,
1063
1064 #[serde(default)]
1066 pub retry: RetryConfig,
1067
1068 #[serde(default)]
1070 pub cache: CacheConfig,
1071
1072 #[serde(default)]
1074 pub discovery: DiscoveryConfig,
1075
1076 #[serde(default)]
1078 pub tree: TreeConfig,
1079
1080 #[serde(default)]
1082 pub routing: RoutingConfig,
1083
1084 #[serde(default)]
1086 pub bloom: BloomConfig,
1087
1088 #[serde(default)]
1090 pub session: SessionConfig,
1091
1092 #[serde(default)]
1094 pub buffers: BuffersConfig,
1095
1096 #[serde(default)]
1098 pub control: ControlConfig,
1099
1100 #[serde(default)]
1102 pub mmp: MmpConfig,
1103
1104 #[serde(default)]
1106 pub session_mmp: SessionMmpConfig,
1107
1108 #[serde(default)]
1110 pub ecn: EcnConfig,
1111
1112 #[serde(default)]
1114 pub rekey: RekeyConfig,
1115
1116 #[serde(default = "NodeConfig::default_system_files_enabled")]
1119 pub system_files_enabled: bool,
1120
1121 #[serde(default = "NodeConfig::default_worker_pools_enabled")]
1126 pub worker_pools_enabled: bool,
1127
1128 #[serde(default)]
1131 pub log_level: Option<String>,
1132}
1133
1134impl Default for NodeConfig {
1135 fn default() -> Self {
1136 Self {
1137 identity: IdentityConfig::default(),
1138 leaf_only: false,
1139 tick_interval_secs: 1,
1140 base_rtt_ms: 100,
1141 heartbeat_interval_secs: 10,
1142 link_dead_timeout_secs: 30,
1143 fast_link_dead_timeout_secs: 5,
1144 limits: LimitsConfig::default(),
1145 rate_limit: RateLimitConfig::default(),
1146 retry: RetryConfig::default(),
1147 cache: CacheConfig::default(),
1148 discovery: DiscoveryConfig::default(),
1149 tree: TreeConfig::default(),
1150 routing: RoutingConfig::default(),
1151 bloom: BloomConfig::default(),
1152 session: SessionConfig::default(),
1153 buffers: BuffersConfig::default(),
1154 control: ControlConfig::default(),
1155 mmp: MmpConfig::default(),
1156 session_mmp: SessionMmpConfig::default(),
1157 ecn: EcnConfig::default(),
1158 rekey: RekeyConfig::default(),
1159 system_files_enabled: true,
1160 worker_pools_enabled: true,
1161 log_level: None,
1162 }
1163 }
1164}
1165
1166impl NodeConfig {
1167 pub fn log_level(&self) -> tracing::Level {
1169 match self
1170 .log_level
1171 .as_deref()
1172 .map(|s| s.to_lowercase())
1173 .as_deref()
1174 {
1175 Some("trace") => tracing::Level::TRACE,
1176 Some("debug") => tracing::Level::DEBUG,
1177 Some("warn") | Some("warning") => tracing::Level::WARN,
1178 Some("error") => tracing::Level::ERROR,
1179 _ => tracing::Level::INFO,
1180 }
1181 }
1182
1183 fn default_tick_interval_secs() -> u64 {
1184 1
1185 }
1186 fn default_base_rtt_ms() -> u64 {
1187 100
1188 }
1189 fn default_heartbeat_interval_secs() -> u64 {
1190 10
1191 }
1192 fn default_link_dead_timeout_secs() -> u64 {
1193 30
1194 }
1195 fn default_fast_link_dead_timeout_secs() -> u64 {
1196 5
1197 }
1198 fn default_system_files_enabled() -> bool {
1199 true
1200 }
1201 fn default_worker_pools_enabled() -> bool {
1202 true
1203 }
1204}
1205
1206#[cfg(test)]
1207mod tests {
1208 use super::*;
1209
1210 #[test]
1211 fn test_ecn_config_defaults() {
1212 let c = EcnConfig::default();
1213 assert!(c.enabled);
1214 assert!((c.loss_threshold - 0.05).abs() < 1e-9);
1215 assert!((c.etx_threshold - 3.0).abs() < 1e-9);
1216 }
1217
1218 #[test]
1219 fn test_rekey_config_defaults() {
1220 let c = RekeyConfig::default();
1221 assert!(c.enabled);
1222 assert_eq!(c.after_secs, 120);
1223 assert_eq!(c.after_messages, 1 << 48);
1224 }
1225
1226 #[test]
1227 fn test_rekey_config_partial_yaml_uses_defaults() {
1228 let yaml = "after_secs: 30\n";
1229 let c: RekeyConfig = serde_yaml::from_str(yaml).unwrap();
1230 assert!(c.enabled);
1231 assert_eq!(c.after_secs, 30);
1232 assert_eq!(c.after_messages, 1 << 48);
1233 }
1234
1235 #[test]
1236 fn test_routing_config_defaults() {
1237 let c = RoutingConfig::default();
1238 assert_eq!(c.mode, RoutingMode::Tree);
1239 assert_eq!(c.learned_ttl_secs, 300);
1240 assert_eq!(c.max_learned_routes_per_dest, 4);
1241 assert_eq!(c.learned_fallback_explore_interval, 16);
1242 }
1243
1244 #[test]
1245 fn test_routing_config_yaml() {
1246 let yaml = "mode: reply_learned\nlearned_ttl_secs: 120\nmax_learned_routes_per_dest: 2\nlearned_fallback_explore_interval: 8\n";
1247 let c: RoutingConfig = serde_yaml::from_str(yaml).unwrap();
1248 assert_eq!(c.mode, RoutingMode::ReplyLearned);
1249 assert_eq!(c.learned_ttl_secs, 120);
1250 assert_eq!(c.max_learned_routes_per_dest, 2);
1251 assert_eq!(c.learned_fallback_explore_interval, 8);
1252 }
1253
1254 #[test]
1255 fn test_ecn_config_yaml_roundtrip() {
1256 let yaml = "loss_threshold: 0.10\netx_threshold: 2.5\nenabled: false\n";
1257 let c: EcnConfig = serde_yaml::from_str(yaml).unwrap();
1258 assert!(!c.enabled);
1259 assert!((c.loss_threshold - 0.10).abs() < 1e-9);
1260 assert!((c.etx_threshold - 2.5).abs() < 1e-9);
1261 }
1262
1263 #[test]
1264 fn test_ecn_config_partial_yaml() {
1265 let yaml = "loss_threshold: 0.02\n";
1267 let c: EcnConfig = serde_yaml::from_str(yaml).unwrap();
1268 assert!(c.enabled); assert!((c.loss_threshold - 0.02).abs() < 1e-9);
1270 assert!((c.etx_threshold - 3.0).abs() < 1e-9); }
1272
1273 #[test]
1274 fn test_nostr_discovery_startup_sweep_defaults() {
1275 let c = NostrDiscoveryConfig::default();
1276 assert_eq!(c.startup_sweep_delay_secs, 5);
1277 assert_eq!(c.startup_sweep_max_age_secs, 3_600);
1278 }
1279
1280 #[test]
1281 fn test_nostr_discovery_startup_sweep_yaml_override() {
1282 let yaml = "enabled: true\npolicy: open\nstartup_sweep_delay_secs: 10\nstartup_sweep_max_age_secs: 1800\n";
1283 let c: NostrDiscoveryConfig = serde_yaml::from_str(yaml).unwrap();
1284 assert!(c.enabled);
1285 assert_eq!(c.policy, NostrDiscoveryPolicy::Open);
1286 assert_eq!(c.startup_sweep_delay_secs, 10);
1287 assert_eq!(c.startup_sweep_max_age_secs, 1_800);
1288 }
1289
1290 #[test]
1291 fn test_nostr_discovery_startup_sweep_partial_yaml_uses_defaults() {
1292 let yaml = "enabled: true\nstartup_sweep_delay_secs: 30\n";
1294 let c: NostrDiscoveryConfig = serde_yaml::from_str(yaml).unwrap();
1295 assert_eq!(c.startup_sweep_delay_secs, 30);
1296 assert_eq!(c.startup_sweep_max_age_secs, 3_600);
1297 }
1298
1299 #[test]
1300 fn test_log_level_parser() {
1301 let cases: &[(Option<&str>, tracing::Level)] = &[
1307 (Some("trace"), tracing::Level::TRACE),
1309 (Some("debug"), tracing::Level::DEBUG),
1310 (Some("warn"), tracing::Level::WARN),
1311 (Some("warning"), tracing::Level::WARN),
1312 (Some("error"), tracing::Level::ERROR),
1313 (Some("info"), tracing::Level::INFO),
1315 (None, tracing::Level::INFO),
1317 (Some("TRACE"), tracing::Level::TRACE),
1319 (Some("Debug"), tracing::Level::DEBUG),
1320 (Some("Warning"), tracing::Level::WARN),
1321 (Some("WARN"), tracing::Level::WARN),
1322 (Some("ERROR"), tracing::Level::ERROR),
1323 (Some("INFO"), tracing::Level::INFO),
1324 (Some("verbose"), tracing::Level::INFO),
1326 (Some("nonsense"), tracing::Level::INFO),
1327 (Some(""), tracing::Level::INFO),
1328 ];
1329
1330 for (input, expected) in cases {
1331 let cfg = NodeConfig {
1332 log_level: input.map(|s| s.to_string()),
1333 ..NodeConfig::default()
1334 };
1335 assert_eq!(
1336 cfg.log_level(),
1337 *expected,
1338 "input {:?} should map to {:?}",
1339 input,
1340 expected
1341 );
1342 }
1343 }
1344
1345 #[cfg(windows)]
1346 #[test]
1347 fn test_default_socket_path_windows() {
1348 let config = ControlConfig::default();
1349 let port: u16 = config
1351 .socket_path
1352 .parse()
1353 .expect("should be a valid port number");
1354 assert_eq!(port, 21210);
1355 }
1356}