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) = crate::upper::tun::tun_outbound_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 self.attach_endpoint_data_io_inner(capacity, None)
53 }
54
55 pub(crate) fn attach_endpoint_data_io_with_direct_sink(
56 &mut self,
57 capacity: usize,
58 direct_sink: EndpointDirectSink,
59 ) -> Result<EndpointDataIo, NodeError> {
60 self.attach_endpoint_data_io_inner(capacity, Some(direct_sink))
61 }
62
63 fn attach_endpoint_data_io_inner(
64 &mut self,
65 capacity: usize,
66 direct_sink: Option<EndpointDirectSink>,
67 ) -> Result<EndpointDataIo, NodeError> {
68 if self.state != NodeState::Created {
69 return Err(NodeError::Config(ConfigError::Validation(
70 "endpoint data I/O must be attached before node start".to_string(),
71 )));
72 }
73
74 let command_capacity = capacity.max(1);
75 let (control_tx, control_rx) = tokio::sync::mpsc::channel(command_capacity);
76 let (data_batch_tx, data_rx) = endpoint_data_batch_channel(command_capacity);
77 let (event_tx, event_rx) =
81 EndpointEventSender::channel_with_direct_sink(capacity, direct_sink);
82 self.endpoint_control_rx = Some(control_rx);
83 self.endpoint_data_rx = Some(data_rx);
84 self.endpoint_events.attach(event_tx.clone());
85
86 Ok(EndpointDataIo {
87 control_tx,
88 data_batch_tx,
89 event_rx,
90 event_tx,
91 })
92 }
93
94 pub(crate) fn pubkey_for_node_addr(&self, addr: &NodeAddr) -> Option<secp256k1::PublicKey> {
95 self.identity_cache.pubkey_for_node_addr(addr)
96 }
97
98 pub(crate) fn npub_for_node_addr(&self, addr: &NodeAddr) -> Option<String> {
99 self.identity_cache.npub_for_node_addr(addr)
100 }
101
102 pub(in crate::node) fn deliver_external_ipv6_packet(
103 &self,
104 src_addr: &NodeAddr,
105 packet: Vec<u8>,
106 ) {
107 let Some(external_packet_tx) = &self.external_packet_tx else {
108 return;
109 };
110 if packet.len() < 40 {
111 return;
112 }
113 let Ok(destination) = FipsAddress::from_slice(&packet[24..40]) else {
114 return;
115 };
116 let delivered = NodeDeliveredPacket {
117 source_node_addr: *src_addr,
118 source_npub: self.npub_for_node_addr(src_addr),
119 destination,
120 packet,
121 };
122 if let Err(error) = external_packet_tx.try_send(delivered) {
123 debug!(error = %error, "Failed to deliver packet to external app sink");
124 }
125 }
126
127 pub(in crate::node) fn note_local_send_outcome(
133 &mut self,
134 node_addr: &NodeAddr,
135 result: &Result<usize, TransportError>,
136 ) {
137 self.local_send_failures
138 .note_send_outcome(node_addr, result, std::time::Instant::now());
139 }
140
141 pub(in crate::node) fn note_candidate_send_outcome(
147 &mut self,
148 node_addr: &NodeAddr,
149 candidate_addr: &TransportAddr,
150 result: &Result<usize, TransportError>,
151 ) {
152 if result.is_ok() {
153 self.note_local_send_outcome(node_addr, result);
154 return;
155 }
156
157 let candidate_is_active_path = self.peers.get(node_addr).map_or(true, |peer| {
158 !peer.can_send() || peer.current_addr() == Some(candidate_addr)
159 });
160 if candidate_is_active_path {
161 self.note_local_send_outcome(node_addr, result);
162 }
163 }
164
165 pub(in crate::node) fn local_send_failure_dead_timeout_for_peer(
171 &self,
172 node_addr: &NodeAddr,
173 now: std::time::Instant,
174 dead_timeout: std::time::Duration,
175 fast_dead_timeout: std::time::Duration,
176 ) -> std::time::Duration {
177 self.local_send_failures.dead_timeout_for_peer(
178 node_addr,
179 now,
180 dead_timeout,
181 fast_dead_timeout,
182 )
183 }
184
185 pub(in crate::node) fn purge_expired_local_send_failures(&mut self, now: std::time::Instant) {
186 self.local_send_failures.purge_expired(now);
187 }
188
189 pub(in crate::node) fn mark_rx_loop_maintenance_timeout(&mut self) {
190 self.last_rx_loop_maintenance_timeout_at = Some(std::time::Instant::now());
191 }
192
193 pub(in crate::node) fn rx_loop_maintenance_timed_out_recently(&self) -> bool {
194 let Some(t) = self.last_rx_loop_maintenance_timeout_at else {
195 return false;
196 };
197 let grace = std::time::Duration::from_secs(self.config.node.link_dead_timeout_secs.max(1));
198 std::time::Instant::now().duration_since(t) <= grace
199 }
200}