fips_core/node/
io_impl.rs1use super::*;
2
3impl Node {
4 pub fn tun_tx(&self) -> Option<&TunTx> {
8 self.tun_tx.as_ref()
9 }
10
11 pub fn attach_external_packet_io(
18 &mut self,
19 capacity: usize,
20 ) -> Result<ExternalPacketIo, NodeError> {
21 if self.state != NodeState::Created {
22 return Err(NodeError::Config(ConfigError::Validation(
23 "external packet I/O must be attached before node start".to_string(),
24 )));
25 }
26 if self.config.tun.enabled {
27 return Err(NodeError::Config(ConfigError::Validation(
28 "external packet I/O requires tun.enabled=false".to_string(),
29 )));
30 }
31
32 let capacity = capacity.max(1);
33 let (outbound_tx, outbound_rx) = tokio::sync::mpsc::channel(capacity);
34 let (inbound_tx, inbound_rx) = tokio::sync::mpsc::channel(capacity);
35 self.tun_outbound_rx = Some(outbound_rx);
36 self.external_packet_tx = Some(inbound_tx);
37
38 Ok(ExternalPacketIo {
39 outbound_tx,
40 inbound_rx,
41 })
42 }
43
44 pub(crate) fn attach_endpoint_data_io(
49 &mut self,
50 capacity: usize,
51 ) -> Result<EndpointDataIo, NodeError> {
52 if self.state != NodeState::Created {
53 return Err(NodeError::Config(ConfigError::Validation(
54 "endpoint data I/O must be attached before node start".to_string(),
55 )));
56 }
57
58 let command_capacity = endpoint_data_command_capacity(capacity);
59 let (priority_command_tx, priority_command_rx) =
60 tokio::sync::mpsc::channel(command_capacity);
61 let (command_tx, command_rx) = tokio::sync::mpsc::channel(command_capacity);
62 let (event_tx, event_rx) = EndpointEventSender::channel(capacity);
65 #[cfg(unix)]
66 let (bulk_send_runtime, bulk_feedback_rx) = EndpointBulkSendRuntime::channel(capacity);
67 #[cfg(not(unix))]
68 let (_bulk_feedback_tx, bulk_feedback_rx) =
69 tokio::sync::mpsc::channel(endpoint_data_command_capacity(capacity).max(1));
70 self.endpoint_priority_command_rx = Some(priority_command_rx);
71 self.endpoint_command_rx = Some(command_rx);
72 self.endpoint_events.attach(event_tx.clone());
73 self.endpoint_bulk_feedback_rx = Some(bulk_feedback_rx);
74 #[cfg(unix)]
75 {
76 self.endpoint_bulk_send_runtime = Some(bulk_send_runtime.clone());
77 }
78
79 Ok(EndpointDataIo {
80 priority_command_tx,
81 command_tx,
82 event_rx,
83 event_tx,
84 #[cfg(unix)]
85 bulk_send_runtime,
86 })
87 }
88
89 pub(in crate::node) fn begin_endpoint_event_batch(&mut self) {
90 self.endpoint_events.begin_batch();
91 }
92
93 pub(in crate::node) fn finish_endpoint_event_batch(&mut self) {
94 self.endpoint_events.finish_batch();
95 }
96
97 #[allow(clippy::result_large_err)]
98 pub(in crate::node) fn deliver_endpoint_event_message(
99 &mut self,
100 message: EndpointDataDelivery,
101 ) -> Result<(), tokio::sync::mpsc::error::SendError<NodeEndpointEvent>> {
102 self.endpoint_events.deliver_endpoint_data(message)
103 }
104
105 pub(in crate::node) fn decrypt_direct_session_delivery_sink(
106 &self,
107 ) -> decrypt_worker::DecryptDirectSessionDeliverySink {
108 decrypt_worker::DecryptDirectSessionDeliverySink::new(
109 self.tun_tx.clone(),
110 self.external_packet_tx.clone(),
111 self.endpoint_events.sender(),
112 )
113 }
114
115 pub(crate) fn pubkey_for_node_addr(&self, addr: &NodeAddr) -> Option<secp256k1::PublicKey> {
116 self.identity_cache.pubkey_for_node_addr(addr)
117 }
118
119 pub(crate) fn npub_for_node_addr(&self, addr: &NodeAddr) -> Option<String> {
120 self.identity_cache.npub_for_node_addr(addr)
121 }
122
123 pub(in crate::node) fn deliver_external_ipv6_packet(
124 &self,
125 src_addr: &NodeAddr,
126 packet: Vec<u8>,
127 ) {
128 let Some(external_packet_tx) = &self.external_packet_tx else {
129 return;
130 };
131 if packet.len() < 40 {
132 return;
133 }
134 let Ok(destination) = FipsAddress::from_slice(&packet[24..40]) else {
135 return;
136 };
137 let delivered = NodeDeliveredPacket {
138 source_node_addr: *src_addr,
139 source_npub: self.npub_for_node_addr(src_addr),
140 destination,
141 packet,
142 };
143 if let Err(error) = external_packet_tx.try_send(delivered) {
144 debug!(error = %error, "Failed to deliver packet to external app sink");
145 }
146 }
147
148 pub(in crate::node) fn note_local_send_outcome(
154 &mut self,
155 node_addr: &NodeAddr,
156 result: &Result<usize, TransportError>,
157 ) {
158 self.local_send_failures
159 .note_send_outcome(node_addr, result, std::time::Instant::now());
160 }
161
162 pub(in crate::node) fn local_send_failure_dead_timeout_for_peer(
168 &self,
169 node_addr: &NodeAddr,
170 now: std::time::Instant,
171 dead_timeout: std::time::Duration,
172 fast_dead_timeout: std::time::Duration,
173 ) -> std::time::Duration {
174 self.local_send_failures.dead_timeout_for_peer(
175 node_addr,
176 now,
177 dead_timeout,
178 fast_dead_timeout,
179 )
180 }
181
182 pub(in crate::node) fn purge_expired_local_send_failures(&mut self, now: std::time::Instant) {
183 self.local_send_failures.purge_expired(now);
184 }
185
186 pub(in crate::node) fn mark_rx_loop_maintenance_timeout(&mut self) {
187 self.last_rx_loop_maintenance_timeout_at = Some(std::time::Instant::now());
188 }
189
190 pub(in crate::node) fn rx_loop_maintenance_timed_out_recently(&self) -> bool {
191 let Some(t) = self.last_rx_loop_maintenance_timeout_at else {
192 return false;
193 };
194 let grace = std::time::Duration::from_secs(self.config.node.link_dead_timeout_secs.max(1));
195 std::time::Instant::now().duration_since(t) <= grace
196 }
197}