dart_udx 2.0.3
dart_udx: ^2.0.3 copied to clipboard
A Dart implementation of UDX - reliable, multiplexed, and congestion-controlled streams over UDP
Changelog #
All notable changes to dart-udx will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
2.0.3 - 2026-02-22 #
Fixed #
- Control-only stream packets (WindowUpdate) no longer consume sequence numbers, preventing permanent receiver stalls when the Go UDX peer buffers out-of-order packets waiting for a gap that can never be filled
- Fixes 64KB+ payload echo timeouts and yamux keepalive-triggered connection kills
2.0.2 - 2026-02-22 #
Fixed #
- Control-only packets (ACKs, window updates) now bypass connection-level receive ordering, preventing sequence gaps when reordered ACKs advance
_nextExpectedSeqpast data packets - Fixes handshake failures over networks with packet reordering (mobile, satellite, congested links)
2.0.1 - 2026-02-17 #
Fixed #
- Stream-level flow control: send window updates when 25% of receive window consumed, preventing yamux mux stalls on long-lived streams
- Connection window exhaustion due to uninitialized CUBIC epoch
- Always use bidirectional stream type for incoming connections
Changed #
- Per-connection packet sequencing for QUIC RFC 9000 compliance
2.0.0 - 2026-01-03 #
Breaking Changes #
- Variable-Length Connection IDs: Connection IDs can now be 0-20 bytes (previously fixed at 8 bytes)
- Updated Packet Format: New packet header format includes version field and variable-length CID encoding
- Protocol Version: Bumped to v2 (0x00000002) to reflect breaking changes
Added - Phase 1: Packet Format Foundation #
-
Variable-Length Connection IDs: Support for 0-20 byte CIDs per QUIC spec
ConnectionId.minCidLengthandConnectionId.maxCidLengthconstantsConnectionId.random(length)factory with configurable length- Updated
UDXPacketserialization to handle variable-length CIDs
-
Version Negotiation: Full version negotiation support
UdxVersionclass with v1/v2 supportVersionNegotiationPacketfor incompatible version handling- Automatic VERSION_NEGOTIATION response for unsupported versions
-
CONNECTION_CLOSE Frame: Graceful connection termination
ConnectionCloseFramewith error code, frame type, and reason phraseUdxErrorCodeconstants for standard error codesUDPSocket.closeWithError()method for sending CONNECTION_CLOSE- Automatic handling of incoming CONNECTION_CLOSE frames
-
STATELESS_RESET Mechanism: Connection state recovery
StatelessResetTokenclass with HMAC-SHA256 generationStatelessResetPacketfor stateless connection terminationUDXMultiplexer.sendStatelessReset()method- Automatic detection and handling of stateless reset packets
Added - Phase 2: Stream Management #
-
Unidirectional Streams: Half-duplex stream support
StreamTypeenum: bidirectional, unidirectionalLocal, unidirectionalRemoteStreamIdHelperfor QUIC-style stream ID encoding- Automatic stream type detection from stream ID
- Write operation validation based on stream directionality
-
STOP_SENDING Frame: Receiver-initiated stream termination
StopSendingFramefor signaling unwanted dataUDXStream.stopReceiving()method- Automatic handling of incoming STOP_SENDING frames
-
BLOCKED Frames: Flow control signaling
DataBlockedFramefor connection-level blockingStreamDataBlockedFramefor stream-level blocking- Automatic BLOCKED frame transmission when flow control limits are hit
- Events for applications to respond to blocking
-
Stream Priorities: Priority-based stream scheduling
UDXStream.priorityproperty (0-255, lower = higher priority)UDXStream.setPriority()method- Infrastructure for future priority-based packet scheduling
Added - Phase 3: Security Enhancements #
-
Anti-Amplification Limits: DDoS protection per RFC 9000
- 3x amplification factor enforcement
- Packet queueing when amplification limit is reached
- Address validation after receiving sufficient data
UDPSocket._onAddressValidated()for flushing queued packets
-
CID Rotation Frames: Connection ID management
NewConnectionIdFramefor providing new CIDsRetireConnectionIdFramefor CID retirement- Infrastructure for future active CID rotation
Added - Phase 4: Performance Enhancements #
-
ECN Support: Explicit Congestion Notification infrastructure
- Optional ECN count fields in
AckFrame(ect0Count, ect1Count, ceCount) CongestionController.processEcnFeedback()placeholder- Ready for future OS-level ECN integration
- Optional ECN count fields in
-
RTT Estimation Improvements: RFC 9002 compliance
maxAckDelayconstant (25ms per RFC 9002)- ACK delay capping in
_updateRtt()method - More accurate RTT measurements
Added - Phase 5: Code Quality #
-
Configurable Logging: Structured logging system
UdxLoggingclass with debug, info, warn, error levelsUdxLoggertypedef for custom logger functions- Verbose and info flags for log level control
- Replacement of direct print statements
-
Constants Extraction: Centralized configuration
constants.dartwith all transport parameters- Error codes, timeouts, and limits
- Improved code maintainability
Changed #
UDXPacketnow includesversionfield (default:UDXPacket.currentVersion)UDXStreamconstructor now accepts optionalstreamTypeparameterUDPSocket.handleIncomingDatagram()is now async to support CONNECTION_CLOSE handling- Sequence number handling for non-reliable frames (ACKs, STOP_SENDING, etc.) reuses last sent sequence
Fixed #
- Sequence number desynchronization bug (documented in SEQUENCE_NUMBER_DESYNC_FIX.md)
- Linter warnings for unused variables and redundant null checks
Migration Guide #
For v1 → v2 Migration:
-
Packet Format: No action required if using default 8-byte CIDs. Variable-length CIDs are opt-in.
-
Version Negotiation: Clients will automatically handle VERSION_NEGOTIATION. Listen for
versionNegotiationevents if needed:socket.on('versionNegotiation', (event) { print('Server doesn\'t support our version: ${event['clientVersion']}'); }); -
Graceful Shutdown: Replace
socket.close()withsocket.closeWithError()for explicit error codes:await socket.closeWithError(UdxErrorCode.noError, 'Normal close'); -
Unidirectional Streams: Specify stream type when creating:
final stream = await UDXStream.createOutgoing( udx, socket, localId, remoteId, host, port, streamType: StreamType.unidirectionalLocal, ); -
Logging: Enable logging for debugging:
UdxLogging.setDefaultLogger(); UdxLogging.verbose = true;
Notes #
- Full CID rotation implementation requires additional state management (future enhancement)
- ECN processing awaits OS-level integration (infrastructure in place)
- Stream priority scheduling is partially implemented (priorities settable, scheduling to be enhanced)
0.3.1 Previous Version #
Previous changes not documented in this changelog.