caretta_sync_core/config/
iroh.rs1#[cfg(feature = "cli")]
2use clap::Args;
3use futures::StreamExt;
4use iroh::{
5 Endpoint, SecretKey,
6 discovery::{dns::DnsDiscovery, mdns::MdnsDiscovery},
7};
8use serde::{Deserialize, Serialize};
9use tokio::io::AsyncReadExt;
10
11use crate::{
12 error::Error,
13 utils::{emptiable::Emptiable, mergeable::Mergeable},
14};
15
16#[derive(Clone, Debug)]
17pub struct IrohConfig {
18 pub enable: bool,
19 pub secret_key: SecretKey,
20 pub use_n0_discovery_service: bool,
21}
22
23impl IrohConfig {
24 async fn into_endpoint(config: Self) -> Result<Option<Endpoint>, crate::error::Error> {
25 if config.enable {
26 let mut endpoint = Endpoint::builder()
27 .secret_key(config.secret_key)
28 .discovery(MdnsDiscovery::builder());
29 if config.use_n0_discovery_service {
30 endpoint = endpoint.discovery(DnsDiscovery::n0_dns());
31 }
32 Ok(Some(endpoint.bind().await?))
33 } else {
34 Ok(None)
35 }
36 }
37}
38
39impl TryFrom<PartialIrohConfig> for IrohConfig {
40 type Error = crate::error::Error;
41 fn try_from(raw: PartialIrohConfig) -> Result<IrohConfig, Self::Error> {
42 Ok(IrohConfig {
43 enable: raw.enable.ok_or(Error::MissingConfig("iroh.enable"))?,
44 secret_key: raw
45 .secret_key
46 .ok_or(Error::MissingConfig("iroh.secret_key"))?,
47 use_n0_discovery_service: raw
48 .use_n0_discovery_service
49 .ok_or(Error::MissingConfig("iroh.use_n0_discovery_service"))?,
50 })
51 }
52}
53
54#[cfg_attr(feature = "cli", derive(Args))]
55#[derive(Clone, Debug, Deserialize, Serialize)]
56pub struct PartialIrohConfig {
57 #[cfg_attr(feature = "cli", arg(long = "p2p_enable"))]
58 pub enable: Option<bool>,
59 #[cfg_attr(feature = "cli", arg(long))]
60 pub secret_key: Option<SecretKey>,
61 #[cfg_attr(feature = "cli", arg(long))]
62 pub use_n0_discovery_service: Option<bool>,
63}
64
65impl PartialIrohConfig {
66 pub fn with_new_secret_key(mut self) -> Self {
67 self.secret_key = Some(SecretKey::generate(&mut rand::rng()));
68 self
69 }
70 pub fn renew_secret_key(&mut self) {
71 self.secret_key = Some(SecretKey::generate(&mut rand::rng()))
72 }
73}
74
75impl From<IrohConfig> for PartialIrohConfig {
76 fn from(config: IrohConfig) -> Self {
77 Self {
78 enable: Some(config.enable),
79 secret_key: Some(config.secret_key),
80 use_n0_discovery_service: Some(config.use_n0_discovery_service),
81 }
82 }
83}
84
85impl Default for PartialIrohConfig {
86 fn default() -> Self {
87 Self {
88 enable: Some(true),
89 secret_key: None,
90 use_n0_discovery_service: Some(true),
91 }
92 }
93}
94
95impl Emptiable for PartialIrohConfig {
96 fn empty() -> Self {
97 Self {
98 enable: None,
99 secret_key: None,
100 use_n0_discovery_service: None,
101 }
102 }
103
104 fn is_empty(&self) -> bool {
105 self.enable.is_none()
106 && self.secret_key.is_none()
107 && self.use_n0_discovery_service.is_none()
108 }
109}
110
111impl Mergeable for PartialIrohConfig {
112 fn merge(&mut self, mut other: Self) {
113 if let Some(x) = other.enable.take() {
114 let _ = self.enable.insert(x);
115 };
116 if let Some(x) = other.secret_key.take() {
117 let _ = self.secret_key.insert(x);
118 };
119 if let Some(x) = other.use_n0_discovery_service.take() {
120 let _ = self.use_n0_discovery_service.insert(x);
121 };
122 }
123}
124impl Mergeable for Option<PartialIrohConfig> {
125 fn merge(&mut self, mut other: Self) {
126 if let Some(x) = other.take() {
127 if let Some(y) = self.as_mut() {
128 y.merge(x);
129 } else {
130 let _ = self.insert(x);
131 }
132 };
133 }
134}