⚔️ 0.29.3
- Fixed unbounded
PathEventqueue growth when an authenticated peer sends valid packets from rapidly changing source ports. Path events are now bounded by the configured path capacity. - Hardened HTTP/3 frame parsing against memory exhaustion by enforcing payload limits as soon as frame lengths are known, allocating frame buffers incrementally, and skipping unknown frame payloads without buffering them.
- Fixed HTTP/3 field-section size enforcement to include the 32-byte per-field overhead required by RFC 9114, preventing the configured limit from being bypassed with many small fields.
Highlights:
h3::Config::new()now advertises and enforces a defaultSETTINGS_MAX_FIELD_SECTION_SIZEof 32 KiB. Applications that accept larger field sections must configure a higher limit withh3::Config::set_max_field_section_size().- Added
h3::Config::set_max_priority_update_size()to configure the maximumPRIORITY_UPDATEframe payload size. The default is 256 bytes. - Connection and stream receive flow-control windows now always start at their configured initial maximum data values instead of being clamped to smaller defaults. The related Rust and C configuration setters are deprecated no-ops.
- Fixed destination connection ID retirement when connection IDs arrive out of sequence, including associated path retirement bookkeeping.
- Fixed PTO backoff arithmetic overflow on connections with prolonged packet loss.
Full changelog at 0.29.2...0.29.3
🛡️ 0.29.2
- Fixed a use-after-free in
quiche_connection_id_iter_next(), which is part of quiche's C FFI API. The iterator previously returned a pointer to a cloned connection ID whose backing storage was dropped before the caller could read it. It now returns pointers to connection IDs owned by the iterator. - Fixed a use-after-free in
quiche_conn_retired_scid_next(), which is also part of the C FFI API. The function previously returned a pointer to a retired source connection ID whose backing storage was dropped before the caller could read it. It has been replaced byquiche_conn_retired_scid_iter(), which drains retired source connection IDs into an iterator before exposing them to callers.
The C FFI API is disabled by default via the ffi feature. The normal Rust API is not affected by these issues.
Breaking changes:
- The C API function
quiche_conn_retired_scid_next()was removed and replaced withquiche_conn_retired_scid_iter()to avoid returning pointers to temporary memory. Applications usingquiche_conn_retired_scid_next()should callquiche_conn_retired_scid_iter(conn), iterate withquiche_connection_id_iter_next(), and release the iterator withquiche_connection_id_iter_free().
Highlights:
- Fixed stream send-buffer accounting so congestion controller app-limited detection and
Stats::tx_buffered_statetrack the actual bytes buffered in stream send buffers. This avoids buffered byte-count drift across retransmissions, ACKs, and stream shutdown/reset paths.
Full changelog at 0.29.1...0.29.2
🩹 0.29.1
Highlights:
- Added
Connection::stream_closed()to query whether a stream is fully closed. - Fixed bandwidth arithmetic overflow in recovery and pacing calculations at high bandwidth or over long time periods.
- Fixed PTO retransmission bookkeeping so consecutive PTOs do not duplicate pending lost frames, while preserving overflow protection.
- Increased the PTO backoff cap to allow longer exponential backoff before hitting the cap.
- Fixed HTTP/3 stream cleanup when the local send side finishes before the receive side, avoiding stream state leaks.
- Late
PRIORITY_UPDATEframes for closed streams are now ignored instead of recreating HTTP/3 stream state. - Other bug fixes and performance improvements.
Full changelog at 0.29.0...0.29.1
🧱 0.29.0
Breaking Changes:
- Removed the
opensslandboringssl-vendoredfeatures, as well as the vendored BoringSSL source. The default TLS backend is nowboringssl-boring-crate. - The minimum supported Rust version was raised to 1.88.
Connection::stream_send_zc()no longer takes thelenargument. Callers now pass the stream ID, buffer, and FIN flag.Stats,PathStats, andh3::Statsare now marked#[non_exhaustive], so downstream code should not construct or exhaustively match them.
Highlights:
- Added
Stats::amplification_limited_countto count sends blocked by the anti-amplification limit. - Added
PathStats::dgram_lostto track lost DATAGRAM frames per path. - Added the C API
quiche_config_set_use_initial_max_data_as_flow_control_win(). - Hardened HTTP/3 request-stream frame processing, rejected unsupported push streams on both endpoints, and fixed varint parsing for
PRIORITY_UPDATEandPUSH_PROMISE. - Fixed PTO and loss-detection overflow cases that could cause panics or tight timeout loops.
- Made C FFI
*_free(NULL)calls safe, and fixed a source connection ID accounting underflow during connection ID rotation. Config::set_ack_delay_exponent()now clamps values to RFC 9000's maximum, exposed asMAX_ACK_DELAY_EXPONENT.- Other bug fixes and performance improvements.
Full changelog at 0.28.0...0.29.0
🔁 0.27.0 / 0.28.0
0.27.0 release has been yanked and should not be used. The 0.28.0 release is the non-yanked replacement and contains the same quiche crate changes, with only the crate version changed from 0.27.0 to 0.28.0.
Breaking Changes:
- The zero-copy buffer APIs changed.
BufFactorynow includes DATAGRAM buffer support, anddgram_send_vec()/dgram_recv_vec()were replaced byConnection::dgram_send_buf()andConnection::dgram_recv_buf(). Statsand the Cquiche_statsstructure gained counters for receivedSTREAMS_BLOCKEDframes.- qlog output was updated to newer qlog drafts. Applications consuming qlog output may need parser updates for renamed HTTP/3 event types, changed time precision, ACK range serialization, wall-clock reference time, and related schema changes.
Highlights:
- Added
bytes::BufMutreceive APIs viaConnection::stream_recv_buf()andh3::Connection::recv_body_buf(). - Added
Config::set_use_initial_max_data_as_flow_control_win()to use the advertised initial max data as the initial flow-control window, avoiding pathologicalMAX_DATAandMAX_STREAM_DATAupdate behavior with large windows. - Added the CUBIC idle-restart fix, enabled by default, with
Config::set_enable_cubic_idle_restart_fix()and related handshake and C API controls. - Added optional
STREAMS_BLOCKEDsignaling viaConfig::set_enable_send_streams_blocked(). - Updated qlog output to include PTO information and align with newer QUIC and HTTP/3 qlog drafts.
- Other bug fixes and performance improvements.
Full changelog at 0.26.1...0.28.0
🩹 0.26.1
Highlights:
- Fixed CUBIC congestion control during application-limited periods, avoiding cases where small-cwnd packet trains could keep a connection stuck in recovery or at the minimum congestion window after loss.
Full changelog at 0.26.0...0.26.1
🪪 0.26.0
Breaking Changes:
- Added
Error::InvalidDcidInitializationfor invalid custom client destination connection ID initialization, so exhaustive matches onErrorneed to be updated.
Highlights:
- Added the
custom-client-dcidfeature, withconnect_with_dcid()andconnect_with_dcid_and_buffer_factory(), for clients that need to provide the initial destination connection ID. Applications using this feature must satisfy RFC 9000 requirements for destination connection ID unpredictability and length. - Added C API support for custom client destination connection IDs via
quiche_conn_new_with_tls_and_client_dcid()when thecustom-client-dcidfeature is enabled. - Fixed retransmission of lost flow-control credit updates, including
MAX_DATA,MAX_STREAM_DATA, andMAX_STREAMS_*frames. - Fixed stream-cancellation retransmission so lost
RESET_STREAMframes are retransmitted even after stream collection, andSTOP_SENDINGframes are retransmitted only while useful. - Improved stream-limit behavior for long-lived connections by sending
MAX_STREAMSupdates when available stream credit drops to half of the initial limit. - Gracefully handles DPLPMTUD probe errors instead of surfacing non-critical send failures.
- Added qlog loss metrics in
MetricsUpdated.ex_data, including lost packet and byte totals and deltas. - Other bug fixes and performance improvements.
Full changelog at 0.25.0...0.26.0
🎫 0.25.0
Breaking Changes:
Connection::set_discover_pmtu_in_handshake()now takes amax_probesargument.- The C API congestion control enum now exposes
QUICHE_CC_BBR2_GCONGESTIONinstead ofQUICHE_CC_BBRandQUICHE_CC_BBR2. Thebbrandbbr2string aliases still select the gcongestion BBR2 implementation. StartupExitReasongained aConservativeSlowStartRoundsvariant, so exhaustive matches need to be updated.
Highlights:
- Added
Config::set_pmtud_max_probes()so DPLPMTUD can tolerate multiple lost probes before treating a probe size as failed. - Added
accept_with_retry()andRetryConnectionIds, allowing servers to use a fresh connection source connection ID that is distinct from the Retry source connection ID. - Improved qlog congestion metrics with Cloudflare-specific delivery, send, and ACK rate values in
MetricsUpdated.ex_data. - Fixed in-handshake recovery and configuration overrides so they still apply after ACK-only packets in multi-packet handshakes.
- Other bug fixes and performance improvements.
Full changelog at 0.24.9...0.25.0
🗑️ 0.24.9
Highlights:
- Added
Connection::stream_discard()to discard received stream data without copying it into an application buffer. - Updated BBR2 default parameters to behave closer to
draft-ietf-ccwg-bbr-04, disabling older experiments that could hurt bandwidth estimates, high-loss behavior, and buffering. - Other bug fixes and performance improvements.
Full changelog at 0.24.8...0.24.9
🪢 0.24.8
Breaking Changes:
Connection::stream_capacity()now takes&mut self, so stopped streams can be collected after reportingError::StreamStopped.
Highlights:
- Fixed a race where
Error::StreamStoppedcould be lost if the peer ACKed aRESET_STREAMbefore the application handled writable streams. - Added
Connection::early_data_reason()to expose BoringSSL's early-data decision for logging and debugging 0-RTT behavior. - Fixed BBR2 RTT accounting and ProbeBW upward accounting to better match the BBR draft.
- Other bug fixes and performance improvements.
Full changelog at 0.24.7...0.24.8