1use std::collections::HashMap;
7use std::net::{IpAddr, SocketAddr};
8
9use serde::{Deserialize, Serialize};
10
11fn parse_external_advert_addr(raw: &str, bind_port: u16) -> Option<SocketAddr> {
19 if let Ok(sa) = raw.parse::<SocketAddr>() {
20 return Some(sa);
21 }
22 let ip: IpAddr = raw.parse().ok()?;
23 Some(SocketAddr::new(ip, bind_port))
24}
25
26fn parse_bind_port(raw: &str) -> Option<u16> {
29 raw.parse::<SocketAddr>().ok().map(|sa| sa.port())
30}
31
32const DEFAULT_UDP_BIND_ADDR: &str = "0.0.0.0:2121";
34
35const DEFAULT_UDP_MTU: u16 = 1280;
37
38const DEFAULT_UDP_RECV_BUF: usize = 16 * 1024 * 1024;
52
53const DEFAULT_UDP_SEND_BUF: usize = 8 * 1024 * 1024;
58
59#[derive(Debug, Clone, Default, Serialize, Deserialize)]
61#[serde(deny_unknown_fields)]
62pub struct UdpConfig {
63 #[serde(default, skip_serializing_if = "Option::is_none")]
68 pub bind_addr: Option<String>,
69
70 #[serde(default, skip_serializing_if = "Option::is_none")]
72 pub mtu: Option<u16>,
73
74 #[serde(default, skip_serializing_if = "Option::is_none")]
76 pub recv_buf_size: Option<usize>,
77
78 #[serde(default, skip_serializing_if = "Option::is_none")]
80 pub send_buf_size: Option<usize>,
81
82 #[serde(default, skip_serializing_if = "Option::is_none")]
85 pub advertise_on_nostr: Option<bool>,
86
87 #[serde(default, skip_serializing_if = "Option::is_none")]
93 pub public: Option<bool>,
94 #[serde(default, skip_serializing_if = "Option::is_none")]
103 pub external_addr: Option<String>,
104 #[serde(default, skip_serializing_if = "Option::is_none")]
112 pub outbound_only: Option<bool>,
113
114 #[serde(default, skip_serializing_if = "Option::is_none")]
123 pub accept_connections: Option<bool>,
124}
125
126impl UdpConfig {
127 pub fn bind_addr(&self) -> &str {
132 if self.outbound_only() {
133 "0.0.0.0:0"
134 } else {
135 self.bind_addr.as_deref().unwrap_or(DEFAULT_UDP_BIND_ADDR)
136 }
137 }
138
139 pub fn mtu(&self) -> u16 {
141 self.mtu.unwrap_or(DEFAULT_UDP_MTU)
142 }
143
144 pub fn recv_buf_size(&self) -> usize {
146 self.recv_buf_size.unwrap_or(DEFAULT_UDP_RECV_BUF)
147 }
148
149 pub fn send_buf_size(&self) -> usize {
151 self.send_buf_size.unwrap_or(DEFAULT_UDP_SEND_BUF)
152 }
153
154 pub fn advertise_on_nostr(&self) -> bool {
157 if self.outbound_only() {
158 false
159 } else {
160 self.advertise_on_nostr.unwrap_or(false)
161 }
162 }
163
164 pub fn is_public(&self) -> bool {
166 self.public.unwrap_or(false)
167 }
168
169 pub fn external_advert_addr(&self) -> Option<SocketAddr> {
174 let raw = self.external_addr.as_deref()?;
175 let bind_port = parse_bind_port(self.bind_addr())?;
176 parse_external_advert_addr(raw, bind_port)
177 }
178
179 pub fn outbound_only(&self) -> bool {
181 self.outbound_only.unwrap_or(false)
182 }
183
184 pub fn accept_connections(&self) -> bool {
186 self.accept_connections.unwrap_or(true)
187 }
188}
189
190#[cfg(feature = "sim-transport")]
192const DEFAULT_SIM_MTU: u16 = 1280;
193
194#[cfg(feature = "sim-transport")]
196const DEFAULT_SIM_NETWORK: &str = "default";
197
198#[cfg(feature = "sim-transport")]
205#[derive(Debug, Clone, Default, Serialize, Deserialize)]
206#[serde(deny_unknown_fields)]
207pub struct SimTransportConfig {
208 #[serde(default, skip_serializing_if = "Option::is_none")]
210 pub network: Option<String>,
211
212 #[serde(default, skip_serializing_if = "Option::is_none")]
214 pub addr: Option<String>,
215
216 #[serde(default, skip_serializing_if = "Option::is_none")]
218 pub mtu: Option<u16>,
219
220 #[serde(default, skip_serializing_if = "Option::is_none")]
222 pub auto_connect: Option<bool>,
223
224 #[serde(default, skip_serializing_if = "Option::is_none")]
226 pub accept_connections: Option<bool>,
227}
228
229#[cfg(feature = "sim-transport")]
230impl SimTransportConfig {
231 pub fn network(&self) -> &str {
233 self.network.as_deref().unwrap_or(DEFAULT_SIM_NETWORK)
234 }
235
236 pub fn mtu(&self) -> u16 {
238 self.mtu.unwrap_or(DEFAULT_SIM_MTU)
239 }
240
241 pub fn auto_connect(&self) -> bool {
243 self.auto_connect.unwrap_or(false)
244 }
245
246 pub fn accept_connections(&self) -> bool {
248 self.accept_connections.unwrap_or(true)
249 }
250}
251
252#[derive(Debug, Clone, Serialize, Deserialize)]
271#[serde(untagged)]
272pub enum TransportInstances<T> {
273 Single(T),
275 Named(HashMap<String, T>),
277}
278
279impl<T> TransportInstances<T> {
280 pub fn len(&self) -> usize {
282 match self {
283 TransportInstances::Single(_) => 1,
284 TransportInstances::Named(map) => map.len(),
285 }
286 }
287
288 pub fn is_empty(&self) -> bool {
290 match self {
291 TransportInstances::Single(_) => false,
292 TransportInstances::Named(map) => map.is_empty(),
293 }
294 }
295
296 pub fn iter(&self) -> impl Iterator<Item = (Option<&str>, &T)> {
301 match self {
302 TransportInstances::Single(config) => vec![(None, config)].into_iter(),
303 TransportInstances::Named(map) => map
304 .iter()
305 .map(|(k, v)| (Some(k.as_str()), v))
306 .collect::<Vec<_>>()
307 .into_iter(),
308 }
309 }
310}
311
312impl<T> Default for TransportInstances<T> {
313 fn default() -> Self {
314 TransportInstances::Named(HashMap::new())
315 }
316}
317
318const DEFAULT_ETHERNET_ETHERTYPE: u16 = 0x2121;
320
321const DEFAULT_ETHERNET_RECV_BUF: usize = 2 * 1024 * 1024;
323
324const DEFAULT_ETHERNET_SEND_BUF: usize = 2 * 1024 * 1024;
326
327const DEFAULT_BEACON_INTERVAL_SECS: u64 = 30;
329
330const MIN_BEACON_INTERVAL_SECS: u64 = 10;
332
333#[derive(Debug, Clone, Default, Serialize, Deserialize)]
338#[serde(deny_unknown_fields)]
339pub struct EthernetConfig {
340 pub interface: String,
342
343 #[serde(default, skip_serializing_if = "Option::is_none")]
345 pub ethertype: Option<u16>,
346
347 #[serde(default, skip_serializing_if = "Option::is_none")]
350 pub mtu: Option<u16>,
351
352 #[serde(default, skip_serializing_if = "Option::is_none")]
354 pub recv_buf_size: Option<usize>,
355
356 #[serde(default, skip_serializing_if = "Option::is_none")]
358 pub send_buf_size: Option<usize>,
359
360 #[serde(default, skip_serializing_if = "Option::is_none")]
362 pub discovery: Option<bool>,
363
364 #[serde(default, skip_serializing_if = "Option::is_none")]
366 pub announce: Option<bool>,
367
368 #[serde(default, skip_serializing_if = "Option::is_none")]
370 pub auto_connect: Option<bool>,
371
372 #[serde(default, skip_serializing_if = "Option::is_none")]
374 pub accept_connections: Option<bool>,
375
376 #[serde(default, skip_serializing_if = "Option::is_none")]
382 pub discovery_scope: Option<String>,
383
384 #[serde(default, skip_serializing_if = "Option::is_none")]
386 pub beacon_interval_secs: Option<u64>,
387}
388
389impl EthernetConfig {
390 pub fn ethertype(&self) -> u16 {
392 self.ethertype.unwrap_or(DEFAULT_ETHERNET_ETHERTYPE)
393 }
394
395 pub fn recv_buf_size(&self) -> usize {
397 self.recv_buf_size.unwrap_or(DEFAULT_ETHERNET_RECV_BUF)
398 }
399
400 pub fn send_buf_size(&self) -> usize {
402 self.send_buf_size.unwrap_or(DEFAULT_ETHERNET_SEND_BUF)
403 }
404
405 pub fn discovery(&self) -> bool {
407 self.discovery.unwrap_or(true)
408 }
409
410 pub fn announce(&self) -> bool {
412 self.announce.unwrap_or(false)
413 }
414
415 pub fn auto_connect(&self) -> bool {
417 self.auto_connect.unwrap_or(false)
418 }
419
420 pub fn accept_connections(&self) -> bool {
422 self.accept_connections.unwrap_or(false)
423 }
424
425 pub fn discovery_scope(&self) -> Option<&str> {
427 self.discovery_scope.as_deref().filter(|s| !s.is_empty())
428 }
429
430 pub fn beacon_interval_secs(&self) -> u64 {
432 self.beacon_interval_secs
433 .unwrap_or(DEFAULT_BEACON_INTERVAL_SECS)
434 .max(MIN_BEACON_INTERVAL_SECS)
435 }
436}
437
438const DEFAULT_TCP_MTU: u16 = 1400;
444
445const DEFAULT_TCP_CONNECT_TIMEOUT_MS: u64 = 5000;
447
448const DEFAULT_TCP_FIRST_FRAME_TIMEOUT_MS: u64 = 3000;
451
452const DEFAULT_TCP_KEEPALIVE_SECS: u64 = 30;
454
455const DEFAULT_TCP_RECV_BUF: usize = 2 * 1024 * 1024;
457
458const DEFAULT_TCP_SEND_BUF: usize = 2 * 1024 * 1024;
460
461const DEFAULT_TCP_MAX_INBOUND: usize = 256;
463
464const DEFAULT_WEBSOCKET_PATH: &str = "/fips";
466
467const DEFAULT_WEBSOCKET_MTU: u16 = 1400;
469
470const DEFAULT_WEBSOCKET_MAX_FRAME_BYTES: usize = 66 * 1024;
472
473const DEFAULT_WEBSOCKET_CONNECT_TIMEOUT_MS: u64 = 5_000;
474const DEFAULT_WEBSOCKET_KEY_HINT_TIMEOUT_MS: u64 = 3_000;
475const DEFAULT_WEBSOCKET_RECONNECT_INITIAL_MS: u64 = 1_000;
476const DEFAULT_WEBSOCKET_RECONNECT_MAX_MS: u64 = 30_000;
477const DEFAULT_WEBSOCKET_MAX_CONNECTIONS: usize = 256;
478const DEFAULT_WEBSOCKET_MAX_INBOUND: usize = 128;
479const DEFAULT_WEBSOCKET_MAX_SEND_QUEUE: usize = 256;
480const DEFAULT_WEBSOCKET_PING_INTERVAL_SECS: u64 = 20;
481const DEFAULT_WEBSOCKET_IDLE_TIMEOUT_SECS: u64 = 90;
482
483#[derive(Debug, Clone, Default, Serialize, Deserialize)]
485#[serde(deny_unknown_fields)]
486pub struct TcpConfig {
487 #[serde(default, skip_serializing_if = "Option::is_none")]
489 pub bind_addr: Option<String>,
490
491 #[serde(default, skip_serializing_if = "Option::is_none")]
495 pub mtu: Option<u16>,
496
497 #[serde(default, skip_serializing_if = "Option::is_none")]
499 pub connect_timeout_ms: Option<u64>,
500
501 #[serde(default, skip_serializing_if = "Option::is_none")]
505 pub first_frame_timeout_ms: Option<u64>,
506
507 #[serde(default, skip_serializing_if = "Option::is_none")]
509 pub nodelay: Option<bool>,
510
511 #[serde(default, skip_serializing_if = "Option::is_none")]
513 pub keepalive_secs: Option<u64>,
514
515 #[serde(default, skip_serializing_if = "Option::is_none")]
517 pub recv_buf_size: Option<usize>,
518
519 #[serde(default, skip_serializing_if = "Option::is_none")]
521 pub send_buf_size: Option<usize>,
522
523 #[serde(default, skip_serializing_if = "Option::is_none")]
525 pub max_inbound_connections: Option<usize>,
526
527 #[serde(default, skip_serializing_if = "Option::is_none")]
530 pub advertise_on_nostr: Option<bool>,
531
532 #[serde(default, skip_serializing_if = "Option::is_none")]
540 pub external_addr: Option<String>,
541}
542
543impl TcpConfig {
544 pub fn mtu(&self) -> u16 {
546 self.mtu.unwrap_or(DEFAULT_TCP_MTU)
547 }
548
549 pub fn connect_timeout_ms(&self) -> u64 {
551 self.connect_timeout_ms
552 .unwrap_or(DEFAULT_TCP_CONNECT_TIMEOUT_MS)
553 }
554
555 pub fn first_frame_timeout_ms(&self) -> u64 {
557 self.first_frame_timeout_ms
558 .unwrap_or(DEFAULT_TCP_FIRST_FRAME_TIMEOUT_MS)
559 }
560
561 pub fn nodelay(&self) -> bool {
563 self.nodelay.unwrap_or(true)
564 }
565
566 pub fn keepalive_secs(&self) -> u64 {
568 self.keepalive_secs.unwrap_or(DEFAULT_TCP_KEEPALIVE_SECS)
569 }
570
571 pub fn recv_buf_size(&self) -> usize {
573 self.recv_buf_size.unwrap_or(DEFAULT_TCP_RECV_BUF)
574 }
575
576 pub fn send_buf_size(&self) -> usize {
578 self.send_buf_size.unwrap_or(DEFAULT_TCP_SEND_BUF)
579 }
580
581 pub fn max_inbound_connections(&self) -> usize {
583 self.max_inbound_connections
584 .unwrap_or(DEFAULT_TCP_MAX_INBOUND)
585 }
586
587 pub fn advertise_on_nostr(&self) -> bool {
589 self.advertise_on_nostr.unwrap_or(false)
590 }
591
592 pub fn external_advert_addr(&self) -> Option<SocketAddr> {
597 let raw = self.external_addr.as_deref()?;
598 let bind_port = parse_bind_port(self.bind_addr.as_deref()?)?;
599 parse_external_advert_addr(raw, bind_port)
600 }
601}
602
603#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
613#[serde(deny_unknown_fields)]
614pub struct WebSocketConfig {
615 #[serde(default, skip_serializing_if = "Option::is_none")]
617 pub bind_addr: Option<String>,
618
619 #[serde(default, skip_serializing_if = "Option::is_none")]
621 pub public_url: Option<String>,
622
623 #[serde(default, skip_serializing_if = "Vec::is_empty")]
625 pub seed_urls: Vec<String>,
626
627 #[serde(default, skip_serializing_if = "Option::is_none")]
629 pub path: Option<String>,
630
631 #[serde(default, skip_serializing_if = "Option::is_none")]
633 pub mtu: Option<u16>,
634
635 #[serde(default, skip_serializing_if = "Option::is_none")]
637 pub max_frame_bytes: Option<usize>,
638
639 #[serde(default, skip_serializing_if = "Option::is_none")]
641 pub max_send_queue: Option<usize>,
642
643 #[serde(default, skip_serializing_if = "Option::is_none")]
645 pub max_connections: Option<usize>,
646
647 #[serde(default, skip_serializing_if = "Option::is_none")]
649 pub max_inbound_connections: Option<usize>,
650
651 #[serde(default, skip_serializing_if = "Option::is_none")]
653 pub connect_timeout_ms: Option<u64>,
654
655 #[serde(default, skip_serializing_if = "Option::is_none")]
657 pub key_hint_timeout_ms: Option<u64>,
658
659 #[serde(default, skip_serializing_if = "Option::is_none")]
661 pub reconnect_initial_ms: Option<u64>,
662
663 #[serde(default, skip_serializing_if = "Option::is_none")]
665 pub reconnect_max_ms: Option<u64>,
666
667 #[serde(default, skip_serializing_if = "Option::is_none")]
669 pub ping_interval_secs: Option<u64>,
670
671 #[serde(default, skip_serializing_if = "Option::is_none")]
673 pub idle_timeout_secs: Option<u64>,
674
675 #[serde(default, skip_serializing_if = "Option::is_none")]
679 pub accept_connections: Option<bool>,
680}
681
682impl WebSocketConfig {
683 pub fn path(&self) -> &str {
684 self.path.as_deref().unwrap_or(DEFAULT_WEBSOCKET_PATH)
685 }
686
687 pub fn mtu(&self) -> u16 {
688 self.mtu.unwrap_or(DEFAULT_WEBSOCKET_MTU)
689 }
690
691 pub fn max_frame_bytes(&self) -> usize {
692 self.max_frame_bytes
693 .unwrap_or(DEFAULT_WEBSOCKET_MAX_FRAME_BYTES)
694 }
695
696 pub fn max_send_queue(&self) -> usize {
697 self.max_send_queue
698 .unwrap_or(DEFAULT_WEBSOCKET_MAX_SEND_QUEUE)
699 .max(1)
700 }
701
702 pub fn max_connections(&self) -> usize {
703 self.max_connections
704 .unwrap_or(DEFAULT_WEBSOCKET_MAX_CONNECTIONS)
705 .max(1)
706 }
707
708 pub fn max_inbound_connections(&self) -> usize {
709 self.max_inbound_connections
710 .unwrap_or(DEFAULT_WEBSOCKET_MAX_INBOUND)
711 .max(1)
712 .min(self.max_connections())
713 }
714
715 pub fn connect_timeout_ms(&self) -> u64 {
716 self.connect_timeout_ms
717 .unwrap_or(DEFAULT_WEBSOCKET_CONNECT_TIMEOUT_MS)
718 .max(1)
719 }
720
721 pub fn key_hint_timeout_ms(&self) -> u64 {
722 self.key_hint_timeout_ms
723 .unwrap_or(DEFAULT_WEBSOCKET_KEY_HINT_TIMEOUT_MS)
724 .max(1)
725 }
726
727 pub fn reconnect_initial_ms(&self) -> u64 {
728 self.reconnect_initial_ms
729 .unwrap_or(DEFAULT_WEBSOCKET_RECONNECT_INITIAL_MS)
730 .max(1)
731 }
732
733 pub fn reconnect_max_ms(&self) -> u64 {
734 self.reconnect_max_ms
735 .unwrap_or(DEFAULT_WEBSOCKET_RECONNECT_MAX_MS)
736 .max(self.reconnect_initial_ms())
737 }
738
739 pub fn ping_interval_secs(&self) -> u64 {
740 self.ping_interval_secs
741 .unwrap_or(DEFAULT_WEBSOCKET_PING_INTERVAL_SECS)
742 }
743
744 pub fn idle_timeout_secs(&self) -> u64 {
745 self.idle_timeout_secs
746 .unwrap_or(DEFAULT_WEBSOCKET_IDLE_TIMEOUT_SECS)
747 }
748
749 pub fn accept_connections(&self) -> bool {
750 self.accept_connections
751 .unwrap_or_else(|| self.bind_addr.is_some() || !self.seed_urls.is_empty())
752 }
753
754 pub fn validate(&self) -> Result<(), String> {
755 if let Some(bind_addr) = self.bind_addr.as_deref() {
756 bind_addr
757 .parse::<SocketAddr>()
758 .map_err(|error| format!("invalid bind_addr {bind_addr:?}: {error}"))?;
759 }
760 if !self.path().starts_with('/') || self.path().contains('?') || self.path().contains('#') {
761 return Err("path must be an absolute HTTP path without query or fragment".into());
762 }
763 if let Some(public_url) = self.public_url.as_deref() {
764 validate_websocket_url(public_url, false)?;
765 let uri = public_url
766 .parse::<tokio_tungstenite::tungstenite::http::Uri>()
767 .map_err(|error| format!("invalid public_url: {error}"))?;
768 if uri.path() != self.path() {
769 return Err(format!(
770 "public_url path {:?} does not match configured path {:?}",
771 uri.path(),
772 self.path()
773 ));
774 }
775 if self.bind_addr.is_none() {
776 return Err("public_url requires bind_addr".into());
777 }
778 }
779 let mut unique = std::collections::HashSet::new();
780 for seed_url in &self.seed_urls {
781 validate_websocket_url(seed_url, true)?;
782 if !unique.insert(seed_url) {
783 return Err(format!("duplicate seed URL {seed_url:?}"));
784 }
785 }
786 let minimum_frame = usize::from(self.mtu()).saturating_add(64);
787 if self.max_frame_bytes() < minimum_frame || self.max_frame_bytes() > 1024 * 1024 {
788 return Err(format!(
789 "max_frame_bytes must be between {minimum_frame} and 1048576"
790 ));
791 }
792 if self.max_send_queue() > 4096 {
793 return Err("max_send_queue must not exceed 4096".into());
794 }
795 if self.max_connections() > 4096 {
796 return Err("max_connections must not exceed 4096".into());
797 }
798 if self.max_inbound_connections() > self.max_connections() {
799 return Err("max_inbound_connections must not exceed max_connections".into());
800 }
801 if self.ping_interval_secs() > 0
802 && self.idle_timeout_secs() > 0
803 && self.idle_timeout_secs() <= self.ping_interval_secs()
804 {
805 return Err("idle_timeout_secs must exceed ping_interval_secs".into());
806 }
807 Ok(())
808 }
809}
810
811fn validate_websocket_url(raw: &str, allow_loopback_plaintext: bool) -> Result<(), String> {
812 let uri = raw
813 .parse::<tokio_tungstenite::tungstenite::http::Uri>()
814 .map_err(|error| format!("invalid WebSocket URL {raw:?}: {error}"))?;
815 let scheme = uri
816 .scheme_str()
817 .ok_or_else(|| format!("WebSocket URL {raw:?} is missing a scheme"))?;
818 let host = uri
819 .host()
820 .ok_or_else(|| format!("WebSocket URL {raw:?} is missing a host"))?;
821 if uri.authority().is_none() || uri.path().is_empty() {
822 return Err(format!("invalid WebSocket URL {raw:?}"));
823 }
824 match scheme {
825 "wss" => Ok(()),
826 "ws" if allow_loopback_plaintext && websocket_host_is_loopback(host) => Ok(()),
827 "ws" => Err(format!(
828 "plaintext WebSocket URL {raw:?} is allowed only for loopback seeds"
829 )),
830 _ => Err(format!("WebSocket URL {raw:?} must use wss://")),
831 }
832}
833
834fn websocket_host_is_loopback(host: &str) -> bool {
835 host.eq_ignore_ascii_case("localhost")
836 || host
837 .trim_matches(['[', ']'])
838 .parse::<IpAddr>()
839 .is_ok_and(|ip| ip.is_loopback())
840}
841
842const DEFAULT_TOR_SOCKS5_ADDR: &str = "127.0.0.1:9050";
848
849const DEFAULT_TOR_CONTROL_ADDR: &str = "/run/tor/control";
851
852const DEFAULT_TOR_COOKIE_PATH: &str = "/var/run/tor/control.authcookie";
854
855const DEFAULT_TOR_CONNECT_TIMEOUT_MS: u64 = 120_000;
858
859const DEFAULT_TOR_MTU: u16 = 1400;
861
862const DEFAULT_TOR_MAX_INBOUND: usize = 64;
864
865const DEFAULT_HOSTNAME_FILE: &str = "/var/lib/tor/fips_onion_service/hostname";
867
868const DEFAULT_DIRECTORY_BIND_ADDR: &str = "127.0.0.1:8443";
870
871const DEFAULT_TOR_ADVERTISED_PORT: u16 = 443;
874
875#[derive(Debug, Clone, Default, Serialize, Deserialize)]
885#[serde(deny_unknown_fields)]
886pub struct TorConfig {
887 #[serde(default, skip_serializing_if = "Option::is_none")]
890 pub mode: Option<String>,
891
892 #[serde(default, skip_serializing_if = "Option::is_none")]
894 pub socks5_addr: Option<String>,
895
896 #[serde(default, skip_serializing_if = "Option::is_none")]
899 pub connect_timeout_ms: Option<u64>,
900
901 #[serde(default, skip_serializing_if = "Option::is_none")]
905 pub mtu: Option<u16>,
906
907 #[serde(default, skip_serializing_if = "Option::is_none")]
911 pub control_addr: Option<String>,
912
913 #[serde(default, skip_serializing_if = "Option::is_none")]
918 pub control_auth: Option<String>,
919
920 #[serde(default, skip_serializing_if = "Option::is_none")]
923 pub cookie_path: Option<String>,
924
925 #[serde(default, skip_serializing_if = "Option::is_none")]
927 pub max_inbound_connections: Option<usize>,
928
929 #[serde(default, skip_serializing_if = "Option::is_none")]
933 pub directory_service: Option<DirectoryServiceConfig>,
934
935 #[serde(default, skip_serializing_if = "Option::is_none")]
938 pub advertise_on_nostr: Option<bool>,
939
940 #[serde(default, skip_serializing_if = "Option::is_none")]
945 pub advertised_port: Option<u16>,
946}
947
948#[derive(Debug, Clone, Default, Serialize, Deserialize)]
955#[serde(deny_unknown_fields)]
956pub struct DirectoryServiceConfig {
957 #[serde(default, skip_serializing_if = "Option::is_none")]
960 pub hostname_file: Option<String>,
961
962 #[serde(default, skip_serializing_if = "Option::is_none")]
966 pub bind_addr: Option<String>,
967}
968
969impl DirectoryServiceConfig {
970 pub fn hostname_file(&self) -> &str {
972 self.hostname_file
973 .as_deref()
974 .unwrap_or(DEFAULT_HOSTNAME_FILE)
975 }
976
977 pub fn bind_addr(&self) -> &str {
979 self.bind_addr
980 .as_deref()
981 .unwrap_or(DEFAULT_DIRECTORY_BIND_ADDR)
982 }
983}
984
985impl TorConfig {
986 pub fn mode(&self) -> &str {
988 self.mode.as_deref().unwrap_or("socks5")
989 }
990
991 pub fn socks5_addr(&self) -> &str {
993 self.socks5_addr
994 .as_deref()
995 .unwrap_or(DEFAULT_TOR_SOCKS5_ADDR)
996 }
997
998 pub fn control_addr(&self) -> &str {
1000 self.control_addr
1001 .as_deref()
1002 .unwrap_or(DEFAULT_TOR_CONTROL_ADDR)
1003 }
1004
1005 pub fn control_auth(&self) -> &str {
1007 self.control_auth.as_deref().unwrap_or("cookie")
1008 }
1009
1010 pub fn cookie_path(&self) -> &str {
1012 self.cookie_path
1013 .as_deref()
1014 .unwrap_or(DEFAULT_TOR_COOKIE_PATH)
1015 }
1016
1017 pub fn connect_timeout_ms(&self) -> u64 {
1019 self.connect_timeout_ms
1020 .unwrap_or(DEFAULT_TOR_CONNECT_TIMEOUT_MS)
1021 }
1022
1023 pub fn mtu(&self) -> u16 {
1025 self.mtu.unwrap_or(DEFAULT_TOR_MTU)
1026 }
1027
1028 pub fn max_inbound_connections(&self) -> usize {
1030 self.max_inbound_connections
1031 .unwrap_or(DEFAULT_TOR_MAX_INBOUND)
1032 }
1033
1034 pub fn advertise_on_nostr(&self) -> bool {
1036 self.advertise_on_nostr.unwrap_or(false)
1037 }
1038
1039 pub fn advertised_port(&self) -> u16 {
1042 self.advertised_port.unwrap_or(DEFAULT_TOR_ADVERTISED_PORT)
1043 }
1044}
1045
1046const DEFAULT_WEBRTC_MTU: u16 = 1200;
1052
1053const DEFAULT_WEBRTC_CONNECT_TIMEOUT_MS: u64 = 30_000;
1055
1056const DEFAULT_WEBRTC_ICE_GATHER_TIMEOUT_MS: u64 = 2_000;
1058
1059const DEFAULT_WEBRTC_MAX_CONNECTIONS: usize = 6;
1061
1062const DEFAULT_WEBRTC_DATA_CHANNEL_LABEL: &str = "fips";
1064
1065#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1070#[serde(deny_unknown_fields)]
1071pub struct WebRtcConfig {
1072 #[serde(default, skip_serializing_if = "Option::is_none")]
1075 pub advertise_on_nostr: Option<bool>,
1076
1077 #[serde(default, skip_serializing_if = "Option::is_none")]
1080 pub auto_connect: Option<bool>,
1081
1082 #[serde(default, skip_serializing_if = "Option::is_none")]
1085 pub accept_connections: Option<bool>,
1086
1087 #[serde(default, skip_serializing_if = "Option::is_none")]
1089 pub mtu: Option<u16>,
1090
1091 #[serde(default, skip_serializing_if = "Option::is_none")]
1094 pub max_connections: Option<usize>,
1095
1096 #[serde(default, skip_serializing_if = "Option::is_none")]
1098 pub connect_timeout_ms: Option<u64>,
1099
1100 #[serde(default, skip_serializing_if = "Option::is_none")]
1102 pub ice_gather_timeout_ms: Option<u64>,
1103
1104 #[serde(default, skip_serializing_if = "Option::is_none")]
1106 pub data_channel_label: Option<String>,
1107
1108 #[serde(default, skip_serializing_if = "Option::is_none")]
1110 pub ordered: Option<bool>,
1111
1112 #[serde(default, skip_serializing_if = "Option::is_none")]
1115 pub max_retransmits: Option<u16>,
1116
1117 #[serde(default, skip_serializing_if = "Option::is_none")]
1120 pub stun_servers: Option<Vec<String>>,
1121
1122 #[serde(default, skip_serializing_if = "Option::is_none")]
1126 pub resolve_mdns_candidates: Option<bool>,
1127}
1128
1129impl WebRtcConfig {
1130 pub fn advertise_on_nostr(&self) -> bool {
1132 self.advertise_on_nostr.unwrap_or(false)
1133 }
1134
1135 pub fn auto_connect(&self) -> bool {
1137 self.auto_connect.unwrap_or(false)
1138 }
1139
1140 pub fn accept_connections(&self) -> bool {
1142 self.accept_connections
1143 .unwrap_or_else(|| self.advertise_on_nostr())
1144 }
1145
1146 pub fn mtu(&self) -> u16 {
1148 self.mtu.unwrap_or(DEFAULT_WEBRTC_MTU)
1149 }
1150
1151 pub fn max_connections(&self) -> usize {
1153 self.max_connections
1154 .unwrap_or(DEFAULT_WEBRTC_MAX_CONNECTIONS)
1155 }
1156
1157 pub fn connect_timeout_ms(&self) -> u64 {
1159 self.connect_timeout_ms
1160 .unwrap_or(DEFAULT_WEBRTC_CONNECT_TIMEOUT_MS)
1161 }
1162
1163 pub fn ice_gather_timeout_ms(&self) -> u64 {
1165 self.ice_gather_timeout_ms
1166 .unwrap_or(DEFAULT_WEBRTC_ICE_GATHER_TIMEOUT_MS)
1167 }
1168
1169 pub fn data_channel_label(&self) -> &str {
1171 self.data_channel_label
1172 .as_deref()
1173 .unwrap_or(DEFAULT_WEBRTC_DATA_CHANNEL_LABEL)
1174 }
1175
1176 pub fn ordered(&self) -> bool {
1178 self.ordered.unwrap_or(true)
1179 }
1180
1181 pub fn max_retransmits(&self) -> Option<u16> {
1183 self.max_retransmits
1184 }
1185
1186 pub fn resolve_mdns_candidates(&self) -> bool {
1188 self.resolve_mdns_candidates.unwrap_or(true)
1189 }
1190
1191 pub fn stun_servers<'a>(&'a self, fallback: &'a [String]) -> Vec<String> {
1193 self.stun_servers
1194 .as_ref()
1195 .cloned()
1196 .unwrap_or_else(|| fallback.to_vec())
1197 }
1198}
1199
1200mod aggregate;
1201mod ble;
1202#[cfg(test)]
1203mod tests;
1204
1205pub use aggregate::TransportsConfig;
1206pub use ble::BleConfig;