fips-core 0.3.92

Reusable FIPS mesh, endpoint, transport, and protocol library
Documentation
impl Node {
    pub(in crate::node) fn collect_deferred_session_forward_terminals(
        &mut self,
        turn: &mut crate::dataplane::DataplaneLiveNodeTurn,
    ) -> usize {
        let mut completed = 0usize;
        turn.consume_transport_sent_receipts(|receipt| {
            let Some(send_token) = receipt.send_token else {
                return false;
            };
            let Some(forward) = self.deferred_session_forwards.take_pending(send_token) else {
                return false;
            };
            let next_hop_addr = forward.next_hop_addr;
            let result = if let Some(timestamp_ms) = receipt.fmp_timestamp_ms {
                let bytes_sent = receipt.payload_len;
                self.dataplane.record_fmp_mmp_send_result(
                    &next_hop_addr,
                    receipt.counter,
                    timestamp_ms,
                    bytes_sent,
                );
                let _ = self
                    .peers
                    .record_fmp_send_bookkeeping(&next_hop_addr, bytes_sent);
                let send_result: Result<usize, crate::transport::TransportError> = Ok(bytes_sent);
                self.note_local_send_outcome(&next_hop_addr, &send_result);
                Ok(())
            } else {
                Err(NodeError::SendFailed {
                    node_addr: next_hop_addr,
                    reason: "dataplane FMP timestamp missing".into(),
                })
            };
            self.deferred_session_forwards
                .push_completed(forward, result);
            completed = completed.saturating_add(1);
            true
        });

        turn.consume_output_drops(|drop| {
            let Some(send_token) = drop.send_token() else {
                return false;
            };
            let Some(forward) = self.deferred_session_forwards.take_pending(send_token) else {
                return false;
            };
            let next_hop_addr = forward.next_hop_addr;
            let error = self.dataplane_fmp_output_drop_error(next_hop_addr, drop);
            self.deferred_session_forwards
                .push_completed(forward, Err(error));
            completed = completed.saturating_add(1);
            true
        });

        turn.consume_drops(|drop| {
            let Some(send_token) = drop.send_token() else {
                return false;
            };
            let Some(forward) = self.deferred_session_forwards.take_pending(send_token) else {
                return false;
            };
            let next_hop_addr = forward.next_hop_addr;
            let error = NodeError::SendFailed {
                node_addr: next_hop_addr,
                reason: format!("dataplane FMP packet dropped: {:?}", drop.reason()),
            };
            self.deferred_session_forwards
                .push_completed(forward, Err(error));
            completed = completed.saturating_add(1);
            true
        });
        completed
    }

    pub(in crate::node) async fn finish_completed_session_forwards(&mut self) -> usize {
        let mut processed = 0usize;
        let mut failed_routes = std::collections::HashSet::new();
        while let Some((forward, result)) = self.deferred_session_forwards.pop_completed() {
            let record_route_failure = claim_route_failure_once(
                &mut failed_routes,
                forward.dest_addr,
                forward.next_hop_addr,
                result.is_err(),
            );
            self.finish_prepared_session_forward(forward, result, record_route_failure)
                .await;
            processed = processed.saturating_add(1);
        }
        processed
    }

    async fn drain_one_deferred_session_forward_turn(&mut self) -> usize {
        let pending_before = self.deferred_session_forwards.pending_len();
        if pending_before == 0 {
            return self.finish_completed_session_forwards().await;
        }
        let turn = self
            .pump_dataplane_pending_outbound_firsts(
                crate::dataplane::DataplaneLiveOutboundFirsts {
                    collect_transport_sent_receipts: true,
                    ..Default::default()
                },
                0,
                0,
                pending_before.min(forwarding_submission_limit(
                    self.dataplane_transport_send_batch_packets,
                )),
            )
            .await;
        self.defer_dataplane_control_turn(turn);
        let processed = self.finish_completed_session_forwards().await;
        if self.deferred_session_forwards.pending_len() >= pending_before {
            self.wait_for_dataplane_completion().await;
        }
        processed
    }

    pub(in crate::node) async fn drain_deferred_session_forwards(&mut self) -> usize {
        let mut processed = self.finish_completed_session_forwards().await;
        while self.deferred_session_forwards.pending_len() > 0 {
            processed =
                processed.saturating_add(self.drain_one_deferred_session_forward_turn().await);
        }
        processed
    }

    pub(in crate::node) async fn abort_deferred_session_forwards(
        &mut self,
        reason: &'static str,
    ) -> usize {
        self.deferred_session_forwards.abort_pending(reason);
        self.finish_completed_session_forwards().await
    }
}