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:
@@ -11,7 +11,6 @@ use rand::Rng;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use tines_core::transport::{Event, FrameBuf, SendError, Transport};
|
||||
use tines_core::Frame;
|
||||
|
||||
/// A node's view of a shared `SimWorld`.
|
||||
pub struct SimTransport {
|
||||
@@ -39,17 +38,12 @@ impl Transport for SimTransport {
|
||||
/// Order of checks: reachability, then MTU, then the loss roll. A frame that
|
||||
/// survives loss is enqueued; a surviving frame is duplicated with the dup
|
||||
/// roll (counting each enqueue toward `frames_sent`).
|
||||
///
|
||||
/// Summary frames are control messages that carry no wire fragmentation: the
|
||||
/// core emits a fixed-size bloom summary that can exceed a small link MTU,
|
||||
/// so control frames are exempt from the per-frame MTU check that governs
|
||||
/// data (`Obs`/`Frag`) frames.
|
||||
fn send(&mut self, to: &Self::Addr, frame: &[u8]) -> Result<(), SendError> {
|
||||
let mut w = self.world.borrow_mut();
|
||||
if !w.trace.in_contact(self.me, *to, w.prev_t) {
|
||||
return Err(SendError::Unreachable);
|
||||
}
|
||||
if frame.len() > w.cfg.mtu && !matches!(Frame::decode(frame), Ok(Frame::Summary { .. })) {
|
||||
if frame.len() > w.cfg.mtu {
|
||||
return Err(SendError::TooLarge);
|
||||
}
|
||||
if w.rng.gen::<f64>() < w.cfg.loss {
|
||||
|
||||
Reference in New Issue
Block a user