1use serde::{Deserialize, Serialize};
8
9use super::IdentityConfig;
10use crate::mmp::{DEFAULT_LOG_INTERVAL_SECS, DEFAULT_OWD_WINDOW_SIZE, MmpConfig, MmpMode};
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
18pub struct LimitsConfig {
19 #[serde(default = "LimitsConfig::default_max_connections")]
21 pub max_connections: usize,
22 #[serde(default = "LimitsConfig::default_max_peers")]
24 pub max_peers: usize,
25 #[serde(default = "LimitsConfig::default_max_links")]
27 pub max_links: usize,
28 #[serde(default = "LimitsConfig::default_max_pending_inbound")]
30 pub max_pending_inbound: usize,
31}
32
33impl Default for LimitsConfig {
34 fn default() -> Self {
35 Self {
36 max_connections: 256,
37 max_peers: 128,
38 max_links: 256,
39 max_pending_inbound: 1000,
40 }
41 }
42}
43
44impl LimitsConfig {
45 fn default_max_connections() -> usize {
46 256
47 }
48 fn default_max_peers() -> usize {
49 128
50 }
51 fn default_max_links() -> usize {
52 256
53 }
54 fn default_max_pending_inbound() -> usize {
55 1000
56 }
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize)]
61pub struct ConnectedUdpConfig {
62 #[serde(default = "ConnectedUdpConfig::default_enabled")]
69 pub enabled: bool,
70
71 #[serde(default = "ConnectedUdpConfig::default_fd_reserve")]
79 pub fd_reserve: usize,
80}
81
82impl Default for ConnectedUdpConfig {
83 fn default() -> Self {
84 Self {
85 enabled: Self::default_enabled(),
86 fd_reserve: Self::default_fd_reserve(),
87 }
88 }
89}
90
91impl ConnectedUdpConfig {
92 fn default_enabled() -> bool {
93 true
94 }
95
96 fn default_fd_reserve() -> usize {
97 128
98 }
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
103pub struct RateLimitConfig {
104 #[serde(default = "RateLimitConfig::default_handshake_burst")]
106 pub handshake_burst: u32,
107 #[serde(default = "RateLimitConfig::default_handshake_rate")]
109 pub handshake_rate: f64,
110 #[serde(default = "RateLimitConfig::default_handshake_timeout_secs")]
112 pub handshake_timeout_secs: u64,
113 #[serde(default = "RateLimitConfig::default_handshake_resend_interval_ms")]
116 pub handshake_resend_interval_ms: u64,
117 #[serde(default = "RateLimitConfig::default_handshake_resend_backoff")]
119 pub handshake_resend_backoff: f64,
120 #[serde(default = "RateLimitConfig::default_handshake_max_resends")]
122 pub handshake_max_resends: u32,
123}
124
125impl Default for RateLimitConfig {
126 fn default() -> Self {
127 Self {
128 handshake_burst: 100,
129 handshake_rate: 10.0,
130 handshake_timeout_secs: 30,
131 handshake_resend_interval_ms: 1000,
132 handshake_resend_backoff: 2.0,
133 handshake_max_resends: 5,
134 }
135 }
136}
137
138impl RateLimitConfig {
139 fn default_handshake_burst() -> u32 {
140 100
141 }
142 fn default_handshake_rate() -> f64 {
143 10.0
144 }
145 fn default_handshake_timeout_secs() -> u64 {
146 30
147 }
148 fn default_handshake_resend_interval_ms() -> u64 {
149 1000
150 }
151 fn default_handshake_resend_backoff() -> f64 {
152 2.0
153 }
154 fn default_handshake_max_resends() -> u32 {
155 5
156 }
157}
158
159#[derive(Debug, Clone, Serialize, Deserialize)]
161pub struct RetryConfig {
162 #[serde(default = "RetryConfig::default_max_retries")]
164 pub max_retries: u32,
165 #[serde(default = "RetryConfig::default_base_interval_secs")]
167 pub base_interval_secs: u64,
168 #[serde(default = "RetryConfig::default_max_backoff_secs")]
170 pub max_backoff_secs: u64,
171}
172
173impl Default for RetryConfig {
174 fn default() -> Self {
175 Self {
176 max_retries: 5,
177 base_interval_secs: 5,
178 max_backoff_secs: 300,
179 }
180 }
181}
182
183impl RetryConfig {
184 fn default_max_retries() -> u32 {
185 5
186 }
187 fn default_base_interval_secs() -> u64 {
188 5
189 }
190 fn default_max_backoff_secs() -> u64 {
191 300
192 }
193}
194
195#[derive(Debug, Clone, Serialize, Deserialize)]
197pub struct CacheConfig {
198 #[serde(default = "CacheConfig::default_coord_size")]
200 pub coord_size: usize,
201 #[serde(default = "CacheConfig::default_coord_ttl_secs")]
203 pub coord_ttl_secs: u64,
204 #[serde(default = "CacheConfig::default_identity_size")]
206 pub identity_size: usize,
207}
208
209impl Default for CacheConfig {
210 fn default() -> Self {
211 Self {
212 coord_size: 50_000,
213 coord_ttl_secs: 300,
214 identity_size: 10_000,
215 }
216 }
217}
218
219impl CacheConfig {
220 fn default_coord_size() -> usize {
221 50_000
222 }
223 fn default_coord_ttl_secs() -> u64 {
224 300
225 }
226 fn default_identity_size() -> usize {
227 10_000
228 }
229}
230
231#[derive(Debug, Clone, Serialize, Deserialize)]
233pub struct DiscoveryConfig {
234 #[serde(default = "DiscoveryConfig::default_ttl")]
236 pub ttl: u8,
237 #[serde(default = "DiscoveryConfig::default_attempt_timeouts_secs")]
243 pub attempt_timeouts_secs: Vec<u64>,
244 #[serde(default = "DiscoveryConfig::default_recent_expiry_secs")]
246 pub recent_expiry_secs: u64,
247 #[serde(default = "DiscoveryConfig::default_backoff_base_secs")]
251 pub backoff_base_secs: u64,
252 #[serde(default = "DiscoveryConfig::default_backoff_max_secs")]
254 pub backoff_max_secs: u64,
255 #[serde(default = "DiscoveryConfig::default_forward_min_interval_secs")]
259 pub forward_min_interval_secs: u64,
260 #[serde(default = "DiscoveryConfig::default_nostr")]
262 pub nostr: NostrDiscoveryConfig,
263 #[serde(default = "DiscoveryConfig::default_lan")]
268 pub lan: crate::discovery::lan::LanDiscoveryConfig,
269 #[serde(default = "DiscoveryConfig::default_local")]
274 pub local: crate::discovery::local::LocalInstanceDiscoveryConfig,
275}
276
277impl Default for DiscoveryConfig {
278 fn default() -> Self {
279 Self {
280 ttl: 64,
281 attempt_timeouts_secs: vec![1, 2, 4, 8],
282 recent_expiry_secs: 10,
283 backoff_base_secs: 30,
284 backoff_max_secs: 300,
285 forward_min_interval_secs: 2,
286 nostr: NostrDiscoveryConfig::default(),
287 lan: crate::discovery::lan::LanDiscoveryConfig::default(),
288 local: crate::discovery::local::LocalInstanceDiscoveryConfig::default(),
289 }
290 }
291}
292
293impl DiscoveryConfig {
294 fn default_ttl() -> u8 {
295 64
296 }
297 fn default_attempt_timeouts_secs() -> Vec<u64> {
298 vec![1, 2, 4, 8]
299 }
300 fn default_recent_expiry_secs() -> u64 {
301 10
302 }
303 fn default_backoff_base_secs() -> u64 {
304 30
305 }
306 fn default_backoff_max_secs() -> u64 {
307 300
308 }
309 fn default_forward_min_interval_secs() -> u64 {
310 2
311 }
312 fn default_nostr() -> NostrDiscoveryConfig {
313 NostrDiscoveryConfig::default()
314 }
315 fn default_lan() -> crate::discovery::lan::LanDiscoveryConfig {
316 crate::discovery::lan::LanDiscoveryConfig::default()
317 }
318 fn default_local() -> crate::discovery::local::LocalInstanceDiscoveryConfig {
319 crate::discovery::local::LocalInstanceDiscoveryConfig::default()
320 }
321}
322
323#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
330#[serde(rename_all = "snake_case")]
331pub enum NostrDiscoveryPolicy {
332 Disabled,
333 #[default]
334 ConfiguredOnly,
335 Open,
336}
337
338#[derive(Debug, Clone, Serialize, Deserialize)]
340#[serde(deny_unknown_fields)]
341pub struct NostrDiscoveryConfig {
342 #[serde(default)]
344 pub enabled: bool,
345 #[serde(default = "NostrDiscoveryConfig::default_advertise")]
347 pub advertise: bool,
348 #[serde(default = "NostrDiscoveryConfig::default_advert_relays")]
350 pub advert_relays: Vec<String>,
351 #[serde(default = "NostrDiscoveryConfig::default_dm_relays")]
353 pub dm_relays: Vec<String>,
354 #[serde(default = "NostrDiscoveryConfig::default_stun_servers")]
358 pub stun_servers: Vec<String>,
359 #[serde(default)]
369 pub share_local_candidates: bool,
370 #[serde(default = "NostrDiscoveryConfig::default_app")]
372 pub app: String,
373 #[serde(default = "NostrDiscoveryConfig::default_signal_ttl_secs")]
375 pub signal_ttl_secs: u64,
376 #[serde(default)]
378 pub policy: NostrDiscoveryPolicy,
379 #[serde(default = "NostrDiscoveryConfig::default_open_discovery_max_pending")]
382 pub open_discovery_max_pending: usize,
383 #[serde(default = "NostrDiscoveryConfig::default_max_concurrent_incoming_offers")]
386 pub max_concurrent_incoming_offers: usize,
387 #[serde(default = "NostrDiscoveryConfig::default_advert_cache_max_entries")]
390 pub advert_cache_max_entries: usize,
391 #[serde(default = "NostrDiscoveryConfig::default_seen_sessions_max_entries")]
394 pub seen_sessions_max_entries: usize,
395 #[serde(default = "NostrDiscoveryConfig::default_attempt_timeout_secs")]
397 pub attempt_timeout_secs: u64,
398 #[serde(default = "NostrDiscoveryConfig::default_replay_window_secs")]
400 pub replay_window_secs: u64,
401 #[serde(default = "NostrDiscoveryConfig::default_punch_start_delay_ms")]
403 pub punch_start_delay_ms: u64,
404 #[serde(default = "NostrDiscoveryConfig::default_punch_interval_ms")]
406 pub punch_interval_ms: u64,
407 #[serde(default = "NostrDiscoveryConfig::default_punch_duration_ms")]
409 pub punch_duration_ms: u64,
410 #[serde(default = "NostrDiscoveryConfig::default_advert_ttl_secs")]
412 pub advert_ttl_secs: u64,
413 #[serde(default = "NostrDiscoveryConfig::default_advert_refresh_secs")]
415 pub advert_refresh_secs: u64,
416 #[serde(default = "NostrDiscoveryConfig::default_startup_sweep_delay_secs")]
421 pub startup_sweep_delay_secs: u64,
422 #[serde(default = "NostrDiscoveryConfig::default_startup_sweep_max_age_secs")]
427 pub startup_sweep_max_age_secs: u64,
428 #[serde(default = "NostrDiscoveryConfig::default_failure_streak_threshold")]
434 pub failure_streak_threshold: u32,
435 #[serde(default = "NostrDiscoveryConfig::default_extended_cooldown_secs")]
439 pub extended_cooldown_secs: u64,
440 #[serde(default = "NostrDiscoveryConfig::default_warn_log_interval_secs")]
445 pub warn_log_interval_secs: u64,
446 #[serde(default = "NostrDiscoveryConfig::default_failure_state_max_entries")]
450 pub failure_state_max_entries: usize,
451 #[serde(default = "NostrDiscoveryConfig::default_protocol_mismatch_cooldown_secs")]
458 pub protocol_mismatch_cooldown_secs: u64,
459}
460
461impl Default for NostrDiscoveryConfig {
462 fn default() -> Self {
463 Self {
464 enabled: false,
465 advertise: Self::default_advertise(),
466 advert_relays: Self::default_advert_relays(),
467 dm_relays: Self::default_dm_relays(),
468 stun_servers: Self::default_stun_servers(),
469 share_local_candidates: false,
470 app: Self::default_app(),
471 signal_ttl_secs: Self::default_signal_ttl_secs(),
472 policy: NostrDiscoveryPolicy::default(),
473 open_discovery_max_pending: Self::default_open_discovery_max_pending(),
474 max_concurrent_incoming_offers: Self::default_max_concurrent_incoming_offers(),
475 advert_cache_max_entries: Self::default_advert_cache_max_entries(),
476 seen_sessions_max_entries: Self::default_seen_sessions_max_entries(),
477 attempt_timeout_secs: Self::default_attempt_timeout_secs(),
478 replay_window_secs: Self::default_replay_window_secs(),
479 punch_start_delay_ms: Self::default_punch_start_delay_ms(),
480 punch_interval_ms: Self::default_punch_interval_ms(),
481 punch_duration_ms: Self::default_punch_duration_ms(),
482 advert_ttl_secs: Self::default_advert_ttl_secs(),
483 advert_refresh_secs: Self::default_advert_refresh_secs(),
484 startup_sweep_delay_secs: Self::default_startup_sweep_delay_secs(),
485 startup_sweep_max_age_secs: Self::default_startup_sweep_max_age_secs(),
486 failure_streak_threshold: Self::default_failure_streak_threshold(),
487 extended_cooldown_secs: Self::default_extended_cooldown_secs(),
488 warn_log_interval_secs: Self::default_warn_log_interval_secs(),
489 failure_state_max_entries: Self::default_failure_state_max_entries(),
490 protocol_mismatch_cooldown_secs: Self::default_protocol_mismatch_cooldown_secs(),
491 }
492 }
493}
494
495impl NostrDiscoveryConfig {
496 fn default_advertise() -> bool {
497 true
498 }
499
500 fn default_advert_relays() -> Vec<String> {
501 vec![
502 "wss://relay.damus.io".to_string(),
503 "wss://nos.lol".to_string(),
504 "wss://offchain.pub".to_string(),
505 "wss://temp.iris.to".to_string(),
506 ]
507 }
508
509 fn default_dm_relays() -> Vec<String> {
510 vec![
511 "wss://relay.damus.io".to_string(),
512 "wss://nos.lol".to_string(),
513 "wss://offchain.pub".to_string(),
514 "wss://temp.iris.to".to_string(),
515 ]
516 }
517
518 fn default_stun_servers() -> Vec<String> {
519 vec![
520 "stun:stun.l.google.com:19302".to_string(),
521 "stun:stun.cloudflare.com:3478".to_string(),
522 "stun:global.stun.twilio.com:3478".to_string(),
523 ]
524 }
525
526 fn default_app() -> String {
527 "fips-overlay-v1".to_string()
528 }
529
530 fn default_signal_ttl_secs() -> u64 {
531 120
532 }
533
534 fn default_open_discovery_max_pending() -> usize {
535 64
536 }
537
538 fn default_max_concurrent_incoming_offers() -> usize {
539 16
540 }
541
542 fn default_advert_cache_max_entries() -> usize {
543 2048
544 }
545
546 fn default_seen_sessions_max_entries() -> usize {
547 2048
548 }
549
550 fn default_attempt_timeout_secs() -> u64 {
551 10
552 }
553
554 fn default_replay_window_secs() -> u64 {
555 300
556 }
557
558 fn default_punch_start_delay_ms() -> u64 {
559 2_000
560 }
561
562 fn default_punch_interval_ms() -> u64 {
563 200
564 }
565
566 fn default_punch_duration_ms() -> u64 {
567 10_000
568 }
569
570 fn default_advert_ttl_secs() -> u64 {
571 3_600
572 }
573
574 fn default_advert_refresh_secs() -> u64 {
575 1_800
576 }
577
578 fn default_startup_sweep_delay_secs() -> u64 {
579 5
580 }
581
582 fn default_startup_sweep_max_age_secs() -> u64 {
583 3_600
584 }
585
586 fn default_failure_streak_threshold() -> u32 {
587 5
588 }
589
590 fn default_extended_cooldown_secs() -> u64 {
591 1_800
592 }
593
594 fn default_warn_log_interval_secs() -> u64 {
595 300
596 }
597
598 fn default_failure_state_max_entries() -> usize {
599 4_096
600 }
601
602 fn default_protocol_mismatch_cooldown_secs() -> u64 {
603 86_400
604 }
605}
606
607#[derive(Debug, Clone, Serialize, Deserialize)]
609pub struct TreeConfig {
610 #[serde(default = "TreeConfig::default_announce_min_interval_ms")]
612 pub announce_min_interval_ms: u64,
613 #[serde(default = "TreeConfig::default_parent_hysteresis")]
619 pub parent_hysteresis: f64,
620 #[serde(default = "TreeConfig::default_hold_down_secs")]
625 pub hold_down_secs: u64,
626 #[serde(default = "TreeConfig::default_reeval_interval_secs")]
632 pub reeval_interval_secs: u64,
633 #[serde(default = "TreeConfig::default_flap_threshold")]
635 pub flap_threshold: u32,
636 #[serde(default = "TreeConfig::default_flap_window_secs")]
638 pub flap_window_secs: u64,
639 #[serde(default = "TreeConfig::default_flap_dampening_secs")]
641 pub flap_dampening_secs: u64,
642}
643
644impl Default for TreeConfig {
645 fn default() -> Self {
646 Self {
647 announce_min_interval_ms: 500,
648 parent_hysteresis: 0.2,
649 hold_down_secs: 30,
650 reeval_interval_secs: 60,
651 flap_threshold: 4,
652 flap_window_secs: 60,
653 flap_dampening_secs: 120,
654 }
655 }
656}
657
658impl TreeConfig {
659 fn default_announce_min_interval_ms() -> u64 {
660 500
661 }
662 fn default_parent_hysteresis() -> f64 {
663 0.2
664 }
665 fn default_hold_down_secs() -> u64 {
666 30
667 }
668 fn default_reeval_interval_secs() -> u64 {
669 60
670 }
671 fn default_flap_threshold() -> u32 {
672 4
673 }
674 fn default_flap_window_secs() -> u64 {
675 60
676 }
677 fn default_flap_dampening_secs() -> u64 {
678 120
679 }
680}
681
682#[derive(Debug, Clone, Serialize, Deserialize)]
684pub struct RoutingConfig {
685 #[serde(default)]
687 pub mode: RoutingMode,
688 #[serde(default = "RoutingConfig::default_learned_ttl_secs")]
690 pub learned_ttl_secs: u64,
691 #[serde(default = "RoutingConfig::default_max_learned_routes_per_dest")]
695 pub max_learned_routes_per_dest: usize,
696 #[serde(default = "RoutingConfig::default_learned_fallback_explore_interval")]
699 pub learned_fallback_explore_interval: u64,
700}
701
702impl Default for RoutingConfig {
703 fn default() -> Self {
704 Self {
705 mode: RoutingMode::default(),
706 learned_ttl_secs: 300,
707 max_learned_routes_per_dest: 4,
708 learned_fallback_explore_interval: 16,
709 }
710 }
711}
712
713impl RoutingConfig {
714 fn default_learned_ttl_secs() -> u64 {
715 300
716 }
717
718 fn default_max_learned_routes_per_dest() -> usize {
719 4
720 }
721
722 fn default_learned_fallback_explore_interval() -> u64 {
723 16
724 }
725}
726
727#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
729#[serde(rename_all = "snake_case")]
730pub enum RoutingMode {
731 #[default]
733 Tree,
734 ReplyLearned,
739}
740
741impl std::fmt::Display for RoutingMode {
742 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
743 match self {
744 RoutingMode::Tree => write!(f, "tree"),
745 RoutingMode::ReplyLearned => write!(f, "reply_learned"),
746 }
747 }
748}
749
750#[derive(Debug, Clone, Serialize, Deserialize)]
752pub struct BloomConfig {
753 #[serde(default = "BloomConfig::default_update_debounce_ms")]
755 pub update_debounce_ms: u64,
756 #[serde(default = "BloomConfig::default_max_inbound_fpr")]
762 pub max_inbound_fpr: f64,
763}
764
765impl Default for BloomConfig {
766 fn default() -> Self {
767 Self {
768 update_debounce_ms: 500,
769 max_inbound_fpr: 0.05,
770 }
771 }
772}
773
774impl BloomConfig {
775 fn default_update_debounce_ms() -> u64 {
776 500
777 }
778 fn default_max_inbound_fpr() -> f64 {
779 0.05
780 }
781}
782
783#[derive(Debug, Clone, Serialize, Deserialize)]
785pub struct SessionConfig {
786 #[serde(default = "SessionConfig::default_ttl")]
788 pub default_ttl: u8,
789 #[serde(default = "SessionConfig::default_pending_packets_per_dest")]
791 pub pending_packets_per_dest: usize,
792 #[serde(default = "SessionConfig::default_pending_max_destinations")]
794 pub pending_max_destinations: usize,
795 #[serde(default = "SessionConfig::default_idle_timeout_secs")]
799 pub idle_timeout_secs: u64,
800 #[serde(default = "SessionConfig::default_coords_warmup_packets")]
804 pub coords_warmup_packets: u8,
805 #[serde(default = "SessionConfig::default_coords_response_interval_ms")]
809 pub coords_response_interval_ms: u64,
810}
811
812impl Default for SessionConfig {
813 fn default() -> Self {
814 Self {
815 default_ttl: 64,
816 pending_packets_per_dest: 16,
817 pending_max_destinations: 256,
818 idle_timeout_secs: 90,
819 coords_warmup_packets: 5,
820 coords_response_interval_ms: 2000,
821 }
822 }
823}
824
825impl SessionConfig {
826 fn default_ttl() -> u8 {
827 64
828 }
829 fn default_pending_packets_per_dest() -> usize {
830 16
831 }
832 fn default_pending_max_destinations() -> usize {
833 256
834 }
835 fn default_idle_timeout_secs() -> u64 {
836 90
837 }
838 fn default_coords_warmup_packets() -> u8 {
839 5
840 }
841 fn default_coords_response_interval_ms() -> u64 {
842 2000
843 }
844}
845
846#[derive(Debug, Clone, Serialize, Deserialize)]
853pub struct SessionMmpConfig {
854 #[serde(default)]
856 pub mode: MmpMode,
857
858 #[serde(default = "SessionMmpConfig::default_log_interval_secs")]
860 pub log_interval_secs: u64,
861
862 #[serde(default = "SessionMmpConfig::default_owd_window_size")]
864 pub owd_window_size: usize,
865}
866
867impl Default for SessionMmpConfig {
868 fn default() -> Self {
869 Self {
870 mode: MmpMode::default(),
871 log_interval_secs: DEFAULT_LOG_INTERVAL_SECS,
872 owd_window_size: DEFAULT_OWD_WINDOW_SIZE,
873 }
874 }
875}
876
877impl SessionMmpConfig {
878 fn default_log_interval_secs() -> u64 {
879 DEFAULT_LOG_INTERVAL_SECS
880 }
881 fn default_owd_window_size() -> usize {
882 DEFAULT_OWD_WINDOW_SIZE
883 }
884}
885
886#[derive(Debug, Clone, Serialize, Deserialize)]
888pub struct ControlConfig {
889 #[serde(default = "ControlConfig::default_enabled")]
891 pub enabled: bool,
892 #[serde(default = "ControlConfig::default_socket_path")]
894 pub socket_path: String,
895}
896
897impl Default for ControlConfig {
898 fn default() -> Self {
899 Self {
900 enabled: true,
901 socket_path: Self::default_socket_path(),
902 }
903 }
904}
905
906impl ControlConfig {
907 fn default_enabled() -> bool {
908 true
909 }
910
911 fn default_socket_path() -> String {
918 #[cfg(unix)]
919 {
920 super::resolve_default_socket("control.sock")
921 }
922 #[cfg(windows)]
923 {
924 "21210".to_string()
925 }
926 }
927}
928
929#[derive(Debug, Clone, Serialize, Deserialize)]
931pub struct BuffersConfig {
932 #[serde(default = "BuffersConfig::default_packet_channel")]
934 pub packet_channel: usize,
935 #[serde(default = "BuffersConfig::default_tun_channel")]
937 pub tun_channel: usize,
938 #[serde(default = "BuffersConfig::default_dns_channel")]
940 pub dns_channel: usize,
941}
942
943impl Default for BuffersConfig {
944 fn default() -> Self {
945 Self {
946 packet_channel: 1024,
947 tun_channel: 1024,
948 dns_channel: 64,
949 }
950 }
951}
952
953impl BuffersConfig {
954 fn default_packet_channel() -> usize {
955 1024
956 }
957 fn default_tun_channel() -> usize {
958 1024
959 }
960 fn default_dns_channel() -> usize {
961 64
962 }
963}
964
965const DEFAULT_REKEY_AFTER_MESSAGES: u64 = 1 << 48;
982
983#[derive(Debug, Clone, Serialize, Deserialize)]
984pub struct RekeyConfig {
985 #[serde(default = "RekeyConfig::default_enabled")]
987 pub enabled: bool,
988
989 #[serde(default = "RekeyConfig::default_after_secs")]
991 pub after_secs: u64,
992
993 #[serde(default = "RekeyConfig::default_after_messages")]
995 pub after_messages: u64,
996}
997
998impl Default for RekeyConfig {
999 fn default() -> Self {
1000 Self {
1001 enabled: true,
1002 after_secs: 120,
1003 after_messages: DEFAULT_REKEY_AFTER_MESSAGES,
1004 }
1005 }
1006}
1007
1008impl RekeyConfig {
1009 fn default_enabled() -> bool {
1010 true
1011 }
1012 fn default_after_secs() -> u64 {
1013 120
1014 }
1015 fn default_after_messages() -> u64 {
1016 DEFAULT_REKEY_AFTER_MESSAGES
1017 }
1018}
1019
1020#[derive(Debug, Clone, Serialize, Deserialize)]
1026pub struct EcnConfig {
1027 #[serde(default = "EcnConfig::default_enabled")]
1029 pub enabled: bool,
1030
1031 #[serde(default = "EcnConfig::default_loss_threshold")]
1035 pub loss_threshold: f64,
1036
1037 #[serde(default = "EcnConfig::default_etx_threshold")]
1041 pub etx_threshold: f64,
1042}
1043
1044impl Default for EcnConfig {
1045 fn default() -> Self {
1046 Self {
1047 enabled: true,
1048 loss_threshold: 0.05,
1049 etx_threshold: 3.0,
1050 }
1051 }
1052}
1053
1054impl EcnConfig {
1055 fn default_enabled() -> bool {
1056 true
1057 }
1058 fn default_loss_threshold() -> f64 {
1059 0.05
1060 }
1061 fn default_etx_threshold() -> f64 {
1062 3.0
1063 }
1064}
1065
1066#[derive(Debug, Clone, Serialize, Deserialize)]
1072pub struct NodeConfig {
1073 #[serde(default)]
1075 pub identity: IdentityConfig,
1076
1077 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
1079 pub leaf_only: bool,
1080
1081 #[serde(default = "NodeConfig::default_tick_interval_secs")]
1083 pub tick_interval_secs: u64,
1084
1085 #[serde(default = "NodeConfig::default_base_rtt_ms")]
1087 pub base_rtt_ms: u64,
1088
1089 #[serde(default = "NodeConfig::default_heartbeat_interval_secs")]
1091 pub heartbeat_interval_secs: u64,
1092
1093 #[serde(default = "NodeConfig::default_link_dead_timeout_secs")]
1096 pub link_dead_timeout_secs: u64,
1097
1098 #[serde(default = "NodeConfig::default_fast_link_dead_timeout_secs")]
1108 pub fast_link_dead_timeout_secs: u64,
1109
1110 #[serde(default)]
1112 pub limits: LimitsConfig,
1113
1114 #[serde(default)]
1116 pub connected_udp: ConnectedUdpConfig,
1117
1118 #[serde(default)]
1120 pub rate_limit: RateLimitConfig,
1121
1122 #[serde(default)]
1124 pub retry: RetryConfig,
1125
1126 #[serde(default)]
1128 pub cache: CacheConfig,
1129
1130 #[serde(default)]
1132 pub discovery: DiscoveryConfig,
1133
1134 #[serde(default)]
1136 pub tree: TreeConfig,
1137
1138 #[serde(default)]
1140 pub routing: RoutingConfig,
1141
1142 #[serde(default)]
1144 pub bloom: BloomConfig,
1145
1146 #[serde(default)]
1148 pub session: SessionConfig,
1149
1150 #[serde(default)]
1152 pub buffers: BuffersConfig,
1153
1154 #[serde(default)]
1156 pub control: ControlConfig,
1157
1158 #[serde(default)]
1160 pub mmp: MmpConfig,
1161
1162 #[serde(default)]
1164 pub session_mmp: SessionMmpConfig,
1165
1166 #[serde(default)]
1168 pub ecn: EcnConfig,
1169
1170 #[serde(default)]
1172 pub rekey: RekeyConfig,
1173
1174 #[serde(default = "NodeConfig::default_system_files_enabled")]
1177 pub system_files_enabled: bool,
1178
1179 #[serde(default = "NodeConfig::default_worker_pools_enabled")]
1184 pub worker_pools_enabled: bool,
1185
1186 #[serde(default)]
1189 pub log_level: Option<String>,
1190}
1191
1192impl Default for NodeConfig {
1193 fn default() -> Self {
1194 Self {
1195 identity: IdentityConfig::default(),
1196 leaf_only: false,
1197 tick_interval_secs: 1,
1198 base_rtt_ms: 100,
1199 heartbeat_interval_secs: 10,
1200 link_dead_timeout_secs: 30,
1201 fast_link_dead_timeout_secs: 5,
1202 limits: LimitsConfig::default(),
1203 connected_udp: ConnectedUdpConfig::default(),
1204 rate_limit: RateLimitConfig::default(),
1205 retry: RetryConfig::default(),
1206 cache: CacheConfig::default(),
1207 discovery: DiscoveryConfig::default(),
1208 tree: TreeConfig::default(),
1209 routing: RoutingConfig::default(),
1210 bloom: BloomConfig::default(),
1211 session: SessionConfig::default(),
1212 buffers: BuffersConfig::default(),
1213 control: ControlConfig::default(),
1214 mmp: MmpConfig::default(),
1215 session_mmp: SessionMmpConfig::default(),
1216 ecn: EcnConfig::default(),
1217 rekey: RekeyConfig::default(),
1218 system_files_enabled: true,
1219 worker_pools_enabled: true,
1220 log_level: None,
1221 }
1222 }
1223}
1224
1225impl NodeConfig {
1226 pub fn log_level(&self) -> tracing::Level {
1228 match self
1229 .log_level
1230 .as_deref()
1231 .map(|s| s.to_lowercase())
1232 .as_deref()
1233 {
1234 Some("trace") => tracing::Level::TRACE,
1235 Some("debug") => tracing::Level::DEBUG,
1236 Some("warn") | Some("warning") => tracing::Level::WARN,
1237 Some("error") => tracing::Level::ERROR,
1238 _ => tracing::Level::INFO,
1239 }
1240 }
1241
1242 fn default_tick_interval_secs() -> u64 {
1243 1
1244 }
1245 fn default_base_rtt_ms() -> u64 {
1246 100
1247 }
1248 fn default_heartbeat_interval_secs() -> u64 {
1249 10
1250 }
1251 fn default_link_dead_timeout_secs() -> u64 {
1252 30
1253 }
1254 fn default_fast_link_dead_timeout_secs() -> u64 {
1255 5
1256 }
1257 fn default_system_files_enabled() -> bool {
1258 true
1259 }
1260 fn default_worker_pools_enabled() -> bool {
1261 true
1262 }
1263}
1264
1265#[cfg(test)]
1266mod tests {
1267 use super::*;
1268
1269 #[test]
1270 fn test_ecn_config_defaults() {
1271 let c = EcnConfig::default();
1272 assert!(c.enabled);
1273 assert!((c.loss_threshold - 0.05).abs() < 1e-9);
1274 assert!((c.etx_threshold - 3.0).abs() < 1e-9);
1275 }
1276
1277 #[test]
1278 fn test_rekey_config_defaults() {
1279 let c = RekeyConfig::default();
1280 assert!(c.enabled);
1281 assert_eq!(c.after_secs, 120);
1282 assert_eq!(c.after_messages, 1 << 48);
1283 }
1284
1285 #[test]
1286 fn test_rekey_config_partial_yaml_uses_defaults() {
1287 let yaml = "after_secs: 30\n";
1288 let c: RekeyConfig = serde_yaml::from_str(yaml).unwrap();
1289 assert!(c.enabled);
1290 assert_eq!(c.after_secs, 30);
1291 assert_eq!(c.after_messages, 1 << 48);
1292 }
1293
1294 #[test]
1295 fn test_connected_udp_config_defaults() {
1296 let c = ConnectedUdpConfig::default();
1297 assert!(c.enabled);
1298 assert_eq!(c.fd_reserve, 128);
1299 }
1300
1301 #[test]
1302 fn test_connected_udp_config_yaml() {
1303 let yaml = "enabled: false\nfd_reserve: 4096\n";
1304 let c: ConnectedUdpConfig = serde_yaml::from_str(yaml).unwrap();
1305 assert!(!c.enabled);
1306 assert_eq!(c.fd_reserve, 4096);
1307 }
1308
1309 #[test]
1310 fn test_routing_config_defaults() {
1311 let c = RoutingConfig::default();
1312 assert_eq!(c.mode, RoutingMode::Tree);
1313 assert_eq!(c.learned_ttl_secs, 300);
1314 assert_eq!(c.max_learned_routes_per_dest, 4);
1315 assert_eq!(c.learned_fallback_explore_interval, 16);
1316 }
1317
1318 #[test]
1319 fn test_routing_config_yaml() {
1320 let yaml = "mode: reply_learned\nlearned_ttl_secs: 120\nmax_learned_routes_per_dest: 2\nlearned_fallback_explore_interval: 8\n";
1321 let c: RoutingConfig = serde_yaml::from_str(yaml).unwrap();
1322 assert_eq!(c.mode, RoutingMode::ReplyLearned);
1323 assert_eq!(c.learned_ttl_secs, 120);
1324 assert_eq!(c.max_learned_routes_per_dest, 2);
1325 assert_eq!(c.learned_fallback_explore_interval, 8);
1326 }
1327
1328 #[test]
1329 fn test_ecn_config_yaml_roundtrip() {
1330 let yaml = "loss_threshold: 0.10\netx_threshold: 2.5\nenabled: false\n";
1331 let c: EcnConfig = serde_yaml::from_str(yaml).unwrap();
1332 assert!(!c.enabled);
1333 assert!((c.loss_threshold - 0.10).abs() < 1e-9);
1334 assert!((c.etx_threshold - 2.5).abs() < 1e-9);
1335 }
1336
1337 #[test]
1338 fn test_ecn_config_partial_yaml() {
1339 let yaml = "loss_threshold: 0.02\n";
1341 let c: EcnConfig = serde_yaml::from_str(yaml).unwrap();
1342 assert!(c.enabled); assert!((c.loss_threshold - 0.02).abs() < 1e-9);
1344 assert!((c.etx_threshold - 3.0).abs() < 1e-9); }
1346
1347 #[test]
1348 fn test_nostr_discovery_startup_sweep_defaults() {
1349 let c = NostrDiscoveryConfig::default();
1350 assert_eq!(c.startup_sweep_delay_secs, 5);
1351 assert_eq!(c.startup_sweep_max_age_secs, 3_600);
1352 }
1353
1354 #[test]
1355 fn test_nostr_discovery_startup_sweep_yaml_override() {
1356 let yaml = "enabled: true\npolicy: open\nstartup_sweep_delay_secs: 10\nstartup_sweep_max_age_secs: 1800\n";
1357 let c: NostrDiscoveryConfig = serde_yaml::from_str(yaml).unwrap();
1358 assert!(c.enabled);
1359 assert_eq!(c.policy, NostrDiscoveryPolicy::Open);
1360 assert_eq!(c.startup_sweep_delay_secs, 10);
1361 assert_eq!(c.startup_sweep_max_age_secs, 1_800);
1362 }
1363
1364 #[test]
1365 fn test_nostr_discovery_startup_sweep_partial_yaml_uses_defaults() {
1366 let yaml = "enabled: true\nstartup_sweep_delay_secs: 30\n";
1368 let c: NostrDiscoveryConfig = serde_yaml::from_str(yaml).unwrap();
1369 assert_eq!(c.startup_sweep_delay_secs, 30);
1370 assert_eq!(c.startup_sweep_max_age_secs, 3_600);
1371 }
1372
1373 #[test]
1374 fn test_log_level_parser() {
1375 let cases: &[(Option<&str>, tracing::Level)] = &[
1381 (Some("trace"), tracing::Level::TRACE),
1383 (Some("debug"), tracing::Level::DEBUG),
1384 (Some("warn"), tracing::Level::WARN),
1385 (Some("warning"), tracing::Level::WARN),
1386 (Some("error"), tracing::Level::ERROR),
1387 (Some("info"), tracing::Level::INFO),
1389 (None, tracing::Level::INFO),
1391 (Some("TRACE"), tracing::Level::TRACE),
1393 (Some("Debug"), tracing::Level::DEBUG),
1394 (Some("Warning"), tracing::Level::WARN),
1395 (Some("WARN"), tracing::Level::WARN),
1396 (Some("ERROR"), tracing::Level::ERROR),
1397 (Some("INFO"), tracing::Level::INFO),
1398 (Some("verbose"), tracing::Level::INFO),
1400 (Some("nonsense"), tracing::Level::INFO),
1401 (Some(""), tracing::Level::INFO),
1402 ];
1403
1404 for (input, expected) in cases {
1405 let cfg = NodeConfig {
1406 log_level: input.map(|s| s.to_string()),
1407 ..NodeConfig::default()
1408 };
1409 assert_eq!(
1410 cfg.log_level(),
1411 *expected,
1412 "input {:?} should map to {:?}",
1413 input,
1414 expected
1415 );
1416 }
1417 }
1418
1419 #[cfg(windows)]
1420 #[test]
1421 fn test_default_socket_path_windows() {
1422 let config = ControlConfig::default();
1423 let port: u16 = config
1425 .socket_path
1426 .parse()
1427 .expect("should be a valid port number");
1428 assert_eq!(port, 21210);
1429 }
1430}