diff --git a/src/transport.rs b/src/transport.rs index afe5f18..3550590 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -39,7 +39,10 @@ pub const DEFAULT_KEEPALIVE_AFTER: Duration = Duration::from_secs(2); pub const DEFAULT_RETIRED_STREAM_TOMBSTONES: usize = 16 * 1024; pub const STREAM_CONTROL_RETRANSMIT_MAX_ATTEMPTS: u32 = 8; pub const SERVICE_TARGET_PREFIX: &str = "@dosh-"; -pub const MAX_STREAM_DATA_BYTES: usize = 60 * 1024; +/// Maximum application bytes in one encrypted UDP stream packet. Keeping this +/// aligned with terminal output framing avoids IP fragmentation and stays +/// below macOS route MTUs after Dosh, AEAD, UDP, and IP overhead. +pub const MAX_STREAM_DATA_BYTES: usize = 1024; #[derive(Debug, Clone, PartialEq, Eq)] pub struct TransportConfig { @@ -1675,6 +1678,31 @@ mod tests { assert_eq!(third.bytes.len(), 13); } + #[test] + fn maximum_stream_chunk_fits_a_safe_udp_datagram() { + let body = protocol::to_body(&StreamData { + stream_id: u64::MAX, + offset: u64::MAX, + bytes: vec![0xff; MAX_STREAM_DATA_BYTES], + }) + .unwrap(); + let packet = protocol::encode_encrypted( + PacketKind::StreamData, + [0xff; 16], + u64::MAX, + u64::MAX, + &[0xff; 32], + CLIENT_TO_SERVER, + &body, + ) + .unwrap(); + assert!( + packet.len() <= 1200, + "encrypted stream datagram is {} bytes", + packet.len() + ); + } + #[test] fn queued_large_write_flushes_in_window_sized_chunks_after_open() { let mut mux = StreamMux::new(TransportConfig {