fips_core/endpoint/
builder.rs1use super::*;
2
3#[derive(Debug, Clone)]
5pub struct FipsEndpointBuilder {
6 config: Config,
7 identity_nsec: Option<String>,
8 discovery_scope: Option<String>,
9 local_ethernet_interfaces: Vec<String>,
10 disable_system_networking: bool,
11 packet_channel_capacity: usize,
12}
13
14const DEFAULT_ENDPOINT_PACKET_CHANNEL_CAPACITY: usize = 4096;
15
16impl Default for FipsEndpointBuilder {
17 fn default() -> Self {
18 Self {
19 config: Config::new(),
20 identity_nsec: None,
21 discovery_scope: None,
22 local_ethernet_interfaces: Vec::new(),
23 disable_system_networking: true,
24 packet_channel_capacity: DEFAULT_ENDPOINT_PACKET_CHANNEL_CAPACITY,
25 }
26 }
27}
28
29impl FipsEndpointBuilder {
30 pub fn config(mut self, config: Config) -> Self {
32 self.config = config;
33 self
34 }
35
36 pub fn identity_nsec(mut self, nsec: impl Into<String>) -> Self {
38 self.identity_nsec = Some(nsec.into());
39 self
40 }
41
42 pub fn discovery_scope(mut self, scope: impl Into<String>) -> Self {
50 self.discovery_scope = Some(scope.into());
51 self
52 }
53
54 pub fn local_ethernet(mut self, interface: impl Into<String>) -> Self {
61 self.local_ethernet_interfaces.push(interface.into());
62 self
63 }
64
65 pub fn without_system_tun(mut self) -> Self {
67 self.disable_system_networking = true;
68 self
69 }
70
71 pub fn packet_channel_capacity(mut self, capacity: usize) -> Self {
73 self.packet_channel_capacity = capacity.max(1);
74 self
75 }
76
77 pub(super) fn prepared_config(&self) -> Config {
78 let mut config = self.config.clone();
79 if let Some(nsec) = &self.identity_nsec {
80 config.node.identity = IdentityConfig {
81 nsec: Some(nsec.clone()),
82 persistent: false,
83 };
84 }
85 if self.disable_system_networking {
86 config.tun.enabled = false;
87 config.dns.enabled = false;
88 config.node.system_files_enabled = false;
89 }
90 if let Some(scope) = self.discovery_scope.as_deref() {
91 config.node.discovery.lan.scope = Some(scope.to_string());
92 config.node.discovery.local.enabled = true;
93 apply_default_scoped_discovery(&mut config, scope);
94 }
95 for interface in &self.local_ethernet_interfaces {
96 add_endpoint_ethernet_transport(
97 &mut config,
98 interface,
99 self.discovery_scope.as_deref(),
100 );
101 }
102 config
103 }
104
105 pub async fn bind(self) -> Result<FipsEndpoint, FipsEndpointError> {
107 self.bind_inner(None).await
108 }
109
110 pub async fn bind_with_direct_sink<S>(self, sink: S) -> Result<FipsEndpoint, FipsEndpointError>
116 where
117 S: FipsEndpointDirectSink,
118 {
119 self.bind_inner(Some(EndpointDirectSink::new(sink))).await
120 }
121
122 async fn bind_inner(
123 self,
124 direct_sink: Option<EndpointDirectSink>,
125 ) -> Result<FipsEndpoint, FipsEndpointError> {
126 endpoint_debug_log("FipsEndpointBuilder::bind begin");
127 let config = self.prepared_config();
128 endpoint_debug_log("FipsEndpointBuilder::bind config prepared");
129
130 let mut node = Node::new(config)?;
131 endpoint_debug_log("FipsEndpointBuilder::bind node created");
132 let identity = PeerIdentity::from_pubkey_full(node.identity().pubkey_full());
133 let npub = identity.npub();
134 let node_addr = *identity.node_addr();
135 let address = *identity.address();
136 let packet_io = node.attach_external_packet_io(self.packet_channel_capacity)?;
137 endpoint_debug_log("FipsEndpointBuilder::bind packet io attached");
138 let endpoint_data_io = match direct_sink {
139 Some(sink) => {
140 node.attach_endpoint_data_io_with_direct_sink(self.packet_channel_capacity, sink)?
141 }
142 None => node.attach_endpoint_data_io(self.packet_channel_capacity)?,
143 };
144 endpoint_debug_log("FipsEndpointBuilder::bind endpoint data io attached");
145 endpoint_debug_log("FipsEndpointBuilder::bind node.start begin");
146 node.start().await?;
147 endpoint_debug_log("FipsEndpointBuilder::bind node.start complete");
148
149 let (shutdown_tx, shutdown_rx) = oneshot::channel();
150 let task = spawn_node_task(node, shutdown_rx);
151 endpoint_debug_log("FipsEndpointBuilder::bind node task spawned");
152 let endpoint_control_tx = endpoint_data_io.control_tx;
153 let endpoint_data_batches = endpoint_data_io.data_batch_tx;
154
155 Ok(FipsEndpoint {
156 identity,
157 npub,
158 node_addr,
159 address,
160 discovery_scope: self.discovery_scope,
161 outbound_packets: packet_io.outbound_tx,
162 delivered_packets: Arc::new(Mutex::new(packet_io.inbound_rx)),
163 endpoint_control_tx,
164 endpoint_data_batches,
165 inbound_endpoint_tx: endpoint_data_io.event_tx,
166 inbound_endpoint_rx: Arc::new(Mutex::new(EndpointReceiveState::new(
167 endpoint_data_io.event_rx,
168 ))),
169 peer_identity_cache: std::sync::Mutex::new(std::collections::HashMap::new()),
170 shutdown_tx: std::sync::Mutex::new(Some(shutdown_tx)),
171 task: std::sync::Mutex::new(Some(task)),
172 })
173 }
174}