fix(core): harden exchange send path from full-codebase review
- Cut every fragment of a stream from one encoding (age frozen at the first fragment) and bounds-check the slice: re-encoding mid-stream corrupted fragments and could panic when the tick went backwards. - Fold the bloom summary to fit the MTU instead of sending a ~540-byte frame that small-MTU links reject; drop the sim's summary MTU exemption that hid this. - Finish a peer's in-flight stream before starting another, and count an addressed message as delivered only after its last fragment. - Alternate custody and broadcast per peer, rotate through addressed candidates, and evict the oldest bounce record when full, so neither path starves. - Add Exchange::on_send_error; Node::poll uses it so Busy/Unreachable sends are retried rather than silently dropped. - Clear bounce records per contact, record duplicates against their sender, and skip addressed messages that cannot fit the MTU. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -140,10 +140,10 @@ impl<S: Store, T: Transport> Node<S, T> {
|
||||
/// Drains all pending transport events, storing any newly received
|
||||
/// observations, then emits at most one outbound frame.
|
||||
///
|
||||
/// Returns the number of *new* observations stored this round. A
|
||||
/// [`crate::transport::SendError`] is ignored: the observation stays
|
||||
/// queued only when the transport was `Busy`, otherwise it is dropped and
|
||||
/// re-queued by the next summary round.
|
||||
/// Returns the number of *new* observations stored this round. If the
|
||||
/// transport refuses the frame with `Busy` or `Unreachable`, the exchange
|
||||
/// rolls back and offers the same frame on a later poll; a `TooLarge`
|
||||
/// frame is dropped (see [`Exchange::on_send_error`]).
|
||||
pub fn poll(&mut self, now: Tick) -> usize {
|
||||
let mut stored = 0usize;
|
||||
while let Some(ev) = self.transport.poll() {
|
||||
@@ -158,7 +158,9 @@ impl<S: Store, T: Transport> Node<S, T> {
|
||||
.exchange
|
||||
.next_frame(&self.store, mtu, now, &mut self.out)
|
||||
{
|
||||
let _ = self.transport.send(&addr, &self.out[..n]);
|
||||
if let Err(err) = self.transport.send(&addr, &self.out[..n]) {
|
||||
self.exchange.on_send_error(&err);
|
||||
}
|
||||
}
|
||||
stored
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user