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 "wss://temp.iris.to".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 "wss://temp.iris.to".to_string(),
463 ]
464 }
465
466 fn default_stun_servers() -> Vec<String> {
467 vec![
468 "stun:stun.l.google.com:19302".to_string(),
469 "stun:stun.cloudflare.com:3478".to_string(),
470 "stun:global.stun.twilio.com:3478".to_string(),
471 ]
472 }
473
474 fn default_app() -> String {
475 "fips-overlay-v1".to_string()
476 }
477
478 fn default_signal_ttl_secs() -> u64 {
479 120
480 }
481
482 fn default_open_discovery_max_pending() -> usize {
483 64
484 }
485
486 fn default_max_concurrent_incoming_offers() -> usize {
487 16
488 }
489
490 fn default_advert_cache_max_entries() -> usize {
491 2048
492 }
493
494 fn default_seen_sessions_max_entries() -> usize {
495 2048
496 }
497
498 fn default_attempt_timeout_secs() -> u64 {
499 10
500 }
501
502 fn default_replay_window_secs() -> u64 {
503 300
504 }
505
506 fn default_punch_start_delay_ms() -> u64 {
507 2_000
508 }
509
510 fn default_punch_interval_ms() -> u64 {
511 200
512 }
513
514 fn default_punch_duration_ms() -> u64 {
515 10_000
516 }
517
518 fn default_advert_ttl_secs() -> u64 {
519 3_600
520 }
521
522 fn default_advert_refresh_secs() -> u64 {
523 1_800
524 }
525
526 fn default_startup_sweep_delay_secs() -> u64 {
527 5
528 }
529
530 fn default_startup_sweep_max_age_secs() -> u64 {
531 3_600
532 }
533
534 fn default_failure_streak_threshold() -> u32 {
535 5
536 }
537
538 fn default_extended_cooldown_secs() -> u64 {
539 1_800
540 }
541
542 fn default_warn_log_interval_secs() -> u64 {
543 300
544 }
545
546 fn default_failure_state_max_entries() -> usize {
547 4_096
548 }
549
550 fn default_protocol_mismatch_cooldown_secs() -> u64 {
551 86_400
552 }
553}
554
555#[derive(Debug, Clone, Serialize, Deserialize)]
557pub struct TreeConfig {
558 #[serde(default = "TreeConfig::default_announce_min_interval_ms")]
560 pub announce_min_interval_ms: u64,
561 #[serde(default = "TreeConfig::default_parent_hysteresis")]
567 pub parent_hysteresis: f64,
568 #[serde(default = "TreeConfig::default_hold_down_secs")]
573 pub hold_down_secs: u64,
574 #[serde(default = "TreeConfig::default_reeval_interval_secs")]
580 pub reeval_interval_secs: u64,
581 #[serde(default = "TreeConfig::default_flap_threshold")]
583 pub flap_threshold: u32,
584 #[serde(default = "TreeConfig::default_flap_window_secs")]
586 pub flap_window_secs: u64,
587 #[serde(default = "TreeConfig::default_flap_dampening_secs")]
589 pub flap_dampening_secs: u64,
590}
591
592impl Default for TreeConfig {
593 fn default() -> Self {
594 Self {
595 announce_min_interval_ms: 500,
596 parent_hysteresis: 0.2,
597 hold_down_secs: 30,
598 reeval_interval_secs: 60,
599 flap_threshold: 4,
600 flap_window_secs: 60,
601 flap_dampening_secs: 120,
602 }
603 }
604}
605
606impl TreeConfig {
607 fn default_announce_min_interval_ms() -> u64 {
608 500
609 }
610 fn default_parent_hysteresis() -> f64 {
611 0.2
612 }
613 fn default_hold_down_secs() -> u64 {
614 30
615 }
616 fn default_reeval_interval_secs() -> u64 {
617 60
618 }
619 fn default_flap_threshold() -> u32 {
620 4
621 }
622 fn default_flap_window_secs() -> u64 {
623 60
624 }
625 fn default_flap_dampening_secs() -> u64 {
626 120
627 }
628}
629
630#[derive(Debug, Clone, Serialize, Deserialize)]
632pub struct RoutingConfig {
633 #[serde(default)]
635 pub mode: RoutingMode,
636 #[serde(default = "RoutingConfig::default_learned_ttl_secs")]
638 pub learned_ttl_secs: u64,
639 #[serde(default = "RoutingConfig::default_max_learned_routes_per_dest")]
643 pub max_learned_routes_per_dest: usize,
644 #[serde(default = "RoutingConfig::default_learned_fallback_explore_interval")]
647 pub learned_fallback_explore_interval: u64,
648}
649
650impl Default for RoutingConfig {
651 fn default() -> Self {
652 Self {
653 mode: RoutingMode::default(),
654 learned_ttl_secs: 300,
655 max_learned_routes_per_dest: 4,
656 learned_fallback_explore_interval: 16,
657 }
658 }
659}
660
661impl RoutingConfig {
662 fn default_learned_ttl_secs() -> u64 {
663 300
664 }
665
666 fn default_max_learned_routes_per_dest() -> usize {
667 4
668 }
669
670 fn default_learned_fallback_explore_interval() -> u64 {
671 16
672 }
673}
674
675#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
677#[serde(rename_all = "snake_case")]
678pub enum RoutingMode {
679 #[default]
681 Tree,
682 ReplyLearned,
687}
688
689impl std::fmt::Display for RoutingMode {
690 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
691 match self {
692 RoutingMode::Tree => write!(f, "tree"),
693 RoutingMode::ReplyLearned => write!(f, "reply_learned"),
694 }
695 }
696}
697
698#[derive(Debug, Clone, Serialize, Deserialize)]
700pub struct BloomConfig {
701 #[serde(default = "BloomConfig::default_update_debounce_ms")]
703 pub update_debounce_ms: u64,
704 #[serde(default = "BloomConfig::default_max_inbound_fpr")]
710 pub max_inbound_fpr: f64,
711}
712
713impl Default for BloomConfig {
714 fn default() -> Self {
715 Self {
716 update_debounce_ms: 500,
717 max_inbound_fpr: 0.05,
718 }
719 }
720}
721
722impl BloomConfig {
723 fn default_update_debounce_ms() -> u64 {
724 500
725 }
726 fn default_max_inbound_fpr() -> f64 {
727 0.05
728 }
729}
730
731#[derive(Debug, Clone, Serialize, Deserialize)]
733pub struct SessionConfig {
734 #[serde(default = "SessionConfig::default_ttl")]
736 pub default_ttl: u8,
737 #[serde(default = "SessionConfig::default_pending_packets_per_dest")]
739 pub pending_packets_per_dest: usize,
740 #[serde(default = "SessionConfig::default_pending_max_destinations")]
742 pub pending_max_destinations: usize,
743 #[serde(default = "SessionConfig::default_idle_timeout_secs")]
747 pub idle_timeout_secs: u64,
748 #[serde(default = "SessionConfig::default_coords_warmup_packets")]
752 pub coords_warmup_packets: u8,
753 #[serde(default = "SessionConfig::default_coords_response_interval_ms")]
757 pub coords_response_interval_ms: u64,
758}
759
760impl Default for SessionConfig {
761 fn default() -> Self {
762 Self {
763 default_ttl: 64,
764 pending_packets_per_dest: 16,
765 pending_max_destinations: 256,
766 idle_timeout_secs: 90,
767 coords_warmup_packets: 5,
768 coords_response_interval_ms: 2000,
769 }
770 }
771}
772
773impl SessionConfig {
774 fn default_ttl() -> u8 {
775 64
776 }
777 fn default_pending_packets_per_dest() -> usize {
778 16
779 }
780 fn default_pending_max_destinations() -> usize {
781 256
782 }
783 fn default_idle_timeout_secs() -> u64 {
784 90
785 }
786 fn default_coords_warmup_packets() -> u8 {
787 5
788 }
789 fn default_coords_response_interval_ms() -> u64 {
790 2000
791 }
792}
793
794#[derive(Debug, Clone, Serialize, Deserialize)]
801pub struct SessionMmpConfig {
802 #[serde(default)]
804 pub mode: MmpMode,
805
806 #[serde(default = "SessionMmpConfig::default_log_interval_secs")]
808 pub log_interval_secs: u64,
809
810 #[serde(default = "SessionMmpConfig::default_owd_window_size")]
812 pub owd_window_size: usize,
813}
814
815impl Default for SessionMmpConfig {
816 fn default() -> Self {
817 Self {
818 mode: MmpMode::default(),
819 log_interval_secs: DEFAULT_LOG_INTERVAL_SECS,
820 owd_window_size: DEFAULT_OWD_WINDOW_SIZE,
821 }
822 }
823}
824
825impl SessionMmpConfig {
826 fn default_log_interval_secs() -> u64 {
827 DEFAULT_LOG_INTERVAL_SECS
828 }
829 fn default_owd_window_size() -> usize {
830 DEFAULT_OWD_WINDOW_SIZE
831 }
832}
833
834#[derive(Debug, Clone, Serialize, Deserialize)]
836pub struct ControlConfig {
837 #[serde(default = "ControlConfig::default_enabled")]
839 pub enabled: bool,
840 #[serde(default = "ControlConfig::default_socket_path")]
842 pub socket_path: String,
843}
844
845impl Default for ControlConfig {
846 fn default() -> Self {
847 Self {
848 enabled: true,
849 socket_path: Self::default_socket_path(),
850 }
851 }
852}
853
854impl ControlConfig {
855 fn default_enabled() -> bool {
856 true
857 }
858
859 fn default_socket_path() -> String {
866 #[cfg(unix)]
867 {
868 super::resolve_default_socket("control.sock")
869 }
870 #[cfg(windows)]
871 {
872 "21210".to_string()
873 }
874 }
875}
876
877#[derive(Debug, Clone, Serialize, Deserialize)]
879pub struct BuffersConfig {
880 #[serde(default = "BuffersConfig::default_packet_channel")]
882 pub packet_channel: usize,
883 #[serde(default = "BuffersConfig::default_tun_channel")]
885 pub tun_channel: usize,
886 #[serde(default = "BuffersConfig::default_dns_channel")]
888 pub dns_channel: usize,
889}
890
891impl Default for BuffersConfig {
892 fn default() -> Self {
893 Self {
894 packet_channel: 1024,
895 tun_channel: 1024,
896 dns_channel: 64,
897 }
898 }
899}
900
901impl BuffersConfig {
902 fn default_packet_channel() -> usize {
903 1024
904 }
905 fn default_tun_channel() -> usize {
906 1024
907 }
908 fn default_dns_channel() -> usize {
909 64
910 }
911}
912
913const DEFAULT_REKEY_AFTER_MESSAGES: u64 = 1 << 48;
930
931#[derive(Debug, Clone, Serialize, Deserialize)]
932pub struct RekeyConfig {
933 #[serde(default = "RekeyConfig::default_enabled")]
935 pub enabled: bool,
936
937 #[serde(default = "RekeyConfig::default_after_secs")]
939 pub after_secs: u64,
940
941 #[serde(default = "RekeyConfig::default_after_messages")]
943 pub after_messages: u64,
944}
945
946impl Default for RekeyConfig {
947 fn default() -> Self {
948 Self {
949 enabled: true,
950 after_secs: 120,
951 after_messages: DEFAULT_REKEY_AFTER_MESSAGES,
952 }
953 }
954}
955
956impl RekeyConfig {
957 fn default_enabled() -> bool {
958 true
959 }
960 fn default_after_secs() -> u64 {
961 120
962 }
963 fn default_after_messages() -> u64 {
964 DEFAULT_REKEY_AFTER_MESSAGES
965 }
966}
967
968#[derive(Debug, Clone, Serialize, Deserialize)]
974pub struct EcnConfig {
975 #[serde(default = "EcnConfig::default_enabled")]
977 pub enabled: bool,
978
979 #[serde(default = "EcnConfig::default_loss_threshold")]
983 pub loss_threshold: f64,
984
985 #[serde(default = "EcnConfig::default_etx_threshold")]
989 pub etx_threshold: f64,
990}
991
992impl Default for EcnConfig {
993 fn default() -> Self {
994 Self {
995 enabled: true,
996 loss_threshold: 0.05,
997 etx_threshold: 3.0,
998 }
999 }
1000}
1001
1002impl EcnConfig {
1003 fn default_enabled() -> bool {
1004 true
1005 }
1006 fn default_loss_threshold() -> f64 {
1007 0.05
1008 }
1009 fn default_etx_threshold() -> f64 {
1010 3.0
1011 }
1012}
1013
1014#[derive(Debug, Clone, Serialize, Deserialize)]
1020pub struct NodeConfig {
1021 #[serde(default)]
1023 pub identity: IdentityConfig,
1024
1025 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
1027 pub leaf_only: bool,
1028
1029 #[serde(default = "NodeConfig::default_tick_interval_secs")]
1031 pub tick_interval_secs: u64,
1032
1033 #[serde(default = "NodeConfig::default_base_rtt_ms")]
1035 pub base_rtt_ms: u64,
1036
1037 #[serde(default = "NodeConfig::default_heartbeat_interval_secs")]
1039 pub heartbeat_interval_secs: u64,
1040
1041 #[serde(default = "NodeConfig::default_link_dead_timeout_secs")]
1044 pub link_dead_timeout_secs: u64,
1045
1046 #[serde(default = "NodeConfig::default_fast_link_dead_timeout_secs")]
1056 pub fast_link_dead_timeout_secs: u64,
1057
1058 #[serde(default)]
1060 pub limits: LimitsConfig,
1061
1062 #[serde(default)]
1064 pub rate_limit: RateLimitConfig,
1065
1066 #[serde(default)]
1068 pub retry: RetryConfig,
1069
1070 #[serde(default)]
1072 pub cache: CacheConfig,
1073
1074 #[serde(default)]
1076 pub discovery: DiscoveryConfig,
1077
1078 #[serde(default)]
1080 pub tree: TreeConfig,
1081
1082 #[serde(default)]
1084 pub routing: RoutingConfig,
1085
1086 #[serde(default)]
1088 pub bloom: BloomConfig,
1089
1090 #[serde(default)]
1092 pub session: SessionConfig,
1093
1094 #[serde(default)]
1096 pub buffers: BuffersConfig,
1097
1098 #[serde(default)]
1100 pub control: ControlConfig,
1101
1102 #[serde(default)]
1104 pub mmp: MmpConfig,
1105
1106 #[serde(default)]
1108 pub session_mmp: SessionMmpConfig,
1109
1110 #[serde(default)]
1112 pub ecn: EcnConfig,
1113
1114 #[serde(default)]
1116 pub rekey: RekeyConfig,
1117
1118 #[serde(default = "NodeConfig::default_system_files_enabled")]
1121 pub system_files_enabled: bool,
1122
1123 #[serde(default = "NodeConfig::default_worker_pools_enabled")]
1128 pub worker_pools_enabled: bool,
1129
1130 #[serde(default)]
1133 pub log_level: Option<String>,
1134}
1135
1136impl Default for NodeConfig {
1137 fn default() -> Self {
1138 Self {
1139 identity: IdentityConfig::default(),
1140 leaf_only: false,
1141 tick_interval_secs: 1,
1142 base_rtt_ms: 100,
1143 heartbeat_interval_secs: 10,
1144 link_dead_timeout_secs: 30,
1145 fast_link_dead_timeout_secs: 5,
1146 limits: LimitsConfig::default(),
1147 rate_limit: RateLimitConfig::default(),
1148 retry: RetryConfig::default(),
1149 cache: CacheConfig::default(),
1150 discovery: DiscoveryConfig::default(),
1151 tree: TreeConfig::default(),
1152 routing: RoutingConfig::default(),
1153 bloom: BloomConfig::default(),
1154 session: SessionConfig::default(),
1155 buffers: BuffersConfig::default(),
1156 control: ControlConfig::default(),
1157 mmp: MmpConfig::default(),
1158 session_mmp: SessionMmpConfig::default(),
1159 ecn: EcnConfig::default(),
1160 rekey: RekeyConfig::default(),
1161 system_files_enabled: true,
1162 worker_pools_enabled: true,
1163 log_level: None,
1164 }
1165 }
1166}
1167
1168impl NodeConfig {
1169 pub fn log_level(&self) -> tracing::Level {
1171 match self
1172 .log_level
1173 .as_deref()
1174 .map(|s| s.to_lowercase())
1175 .as_deref()
1176 {
1177 Some("trace") => tracing::Level::TRACE,
1178 Some("debug") => tracing::Level::DEBUG,
1179 Some("warn") | Some("warning") => tracing::Level::WARN,
1180 Some("error") => tracing::Level::ERROR,
1181 _ => tracing::Level::INFO,
1182 }
1183 }
1184
1185 fn default_tick_interval_secs() -> u64 {
1186 1
1187 }
1188 fn default_base_rtt_ms() -> u64 {
1189 100
1190 }
1191 fn default_heartbeat_interval_secs() -> u64 {
1192 10
1193 }
1194 fn default_link_dead_timeout_secs() -> u64 {
1195 30
1196 }
1197 fn default_fast_link_dead_timeout_secs() -> u64 {
1198 5
1199 }
1200 fn default_system_files_enabled() -> bool {
1201 true
1202 }
1203 fn default_worker_pools_enabled() -> bool {
1204 true
1205 }
1206}
1207
1208#[cfg(test)]
1209mod tests {
1210 use super::*;
1211
1212 #[test]
1213 fn test_ecn_config_defaults() {
1214 let c = EcnConfig::default();
1215 assert!(c.enabled);
1216 assert!((c.loss_threshold - 0.05).abs() < 1e-9);
1217 assert!((c.etx_threshold - 3.0).abs() < 1e-9);
1218 }
1219
1220 #[test]
1221 fn test_rekey_config_defaults() {
1222 let c = RekeyConfig::default();
1223 assert!(c.enabled);
1224 assert_eq!(c.after_secs, 120);
1225 assert_eq!(c.after_messages, 1 << 48);
1226 }
1227
1228 #[test]
1229 fn test_rekey_config_partial_yaml_uses_defaults() {
1230 let yaml = "after_secs: 30\n";
1231 let c: RekeyConfig = serde_yaml::from_str(yaml).unwrap();
1232 assert!(c.enabled);
1233 assert_eq!(c.after_secs, 30);
1234 assert_eq!(c.after_messages, 1 << 48);
1235 }
1236
1237 #[test]
1238 fn test_routing_config_defaults() {
1239 let c = RoutingConfig::default();
1240 assert_eq!(c.mode, RoutingMode::Tree);
1241 assert_eq!(c.learned_ttl_secs, 300);
1242 assert_eq!(c.max_learned_routes_per_dest, 4);
1243 assert_eq!(c.learned_fallback_explore_interval, 16);
1244 }
1245
1246 #[test]
1247 fn test_routing_config_yaml() {
1248 let yaml = "mode: reply_learned\nlearned_ttl_secs: 120\nmax_learned_routes_per_dest: 2\nlearned_fallback_explore_interval: 8\n";
1249 let c: RoutingConfig = serde_yaml::from_str(yaml).unwrap();
1250 assert_eq!(c.mode, RoutingMode::ReplyLearned);
1251 assert_eq!(c.learned_ttl_secs, 120);
1252 assert_eq!(c.max_learned_routes_per_dest, 2);
1253 assert_eq!(c.learned_fallback_explore_interval, 8);
1254 }
1255
1256 #[test]
1257 fn test_ecn_config_yaml_roundtrip() {
1258 let yaml = "loss_threshold: 0.10\netx_threshold: 2.5\nenabled: false\n";
1259 let c: EcnConfig = serde_yaml::from_str(yaml).unwrap();
1260 assert!(!c.enabled);
1261 assert!((c.loss_threshold - 0.10).abs() < 1e-9);
1262 assert!((c.etx_threshold - 2.5).abs() < 1e-9);
1263 }
1264
1265 #[test]
1266 fn test_ecn_config_partial_yaml() {
1267 let yaml = "loss_threshold: 0.02\n";
1269 let c: EcnConfig = serde_yaml::from_str(yaml).unwrap();
1270 assert!(c.enabled); assert!((c.loss_threshold - 0.02).abs() < 1e-9);
1272 assert!((c.etx_threshold - 3.0).abs() < 1e-9); }
1274
1275 #[test]
1276 fn test_nostr_discovery_startup_sweep_defaults() {
1277 let c = NostrDiscoveryConfig::default();
1278 assert_eq!(c.startup_sweep_delay_secs, 5);
1279 assert_eq!(c.startup_sweep_max_age_secs, 3_600);
1280 }
1281
1282 #[test]
1283 fn test_nostr_discovery_startup_sweep_yaml_override() {
1284 let yaml = "enabled: true\npolicy: open\nstartup_sweep_delay_secs: 10\nstartup_sweep_max_age_secs: 1800\n";
1285 let c: NostrDiscoveryConfig = serde_yaml::from_str(yaml).unwrap();
1286 assert!(c.enabled);
1287 assert_eq!(c.policy, NostrDiscoveryPolicy::Open);
1288 assert_eq!(c.startup_sweep_delay_secs, 10);
1289 assert_eq!(c.startup_sweep_max_age_secs, 1_800);
1290 }
1291
1292 #[test]
1293 fn test_nostr_discovery_startup_sweep_partial_yaml_uses_defaults() {
1294 let yaml = "enabled: true\nstartup_sweep_delay_secs: 30\n";
1296 let c: NostrDiscoveryConfig = serde_yaml::from_str(yaml).unwrap();
1297 assert_eq!(c.startup_sweep_delay_secs, 30);
1298 assert_eq!(c.startup_sweep_max_age_secs, 3_600);
1299 }
1300
1301 #[test]
1302 fn test_log_level_parser() {
1303 let cases: &[(Option<&str>, tracing::Level)] = &[
1309 (Some("trace"), tracing::Level::TRACE),
1311 (Some("debug"), tracing::Level::DEBUG),
1312 (Some("warn"), tracing::Level::WARN),
1313 (Some("warning"), tracing::Level::WARN),
1314 (Some("error"), tracing::Level::ERROR),
1315 (Some("info"), tracing::Level::INFO),
1317 (None, tracing::Level::INFO),
1319 (Some("TRACE"), tracing::Level::TRACE),
1321 (Some("Debug"), tracing::Level::DEBUG),
1322 (Some("Warning"), tracing::Level::WARN),
1323 (Some("WARN"), tracing::Level::WARN),
1324 (Some("ERROR"), tracing::Level::ERROR),
1325 (Some("INFO"), tracing::Level::INFO),
1326 (Some("verbose"), tracing::Level::INFO),
1328 (Some("nonsense"), tracing::Level::INFO),
1329 (Some(""), tracing::Level::INFO),
1330 ];
1331
1332 for (input, expected) in cases {
1333 let cfg = NodeConfig {
1334 log_level: input.map(|s| s.to_string()),
1335 ..NodeConfig::default()
1336 };
1337 assert_eq!(
1338 cfg.log_level(),
1339 *expected,
1340 "input {:?} should map to {:?}",
1341 input,
1342 expected
1343 );
1344 }
1345 }
1346
1347 #[cfg(windows)]
1348 #[test]
1349 fn test_default_socket_path_windows() {
1350 let config = ControlConfig::default();
1351 let port: u16 = config
1353 .socket_path
1354 .parse()
1355 .expect("should be a valid port number");
1356 assert_eq!(port, 21210);
1357 }
1358}