Skip to content

Commit f8ebaf8

Browse files
authored
Release 4.8.2 (#663)
- [FIX] Reject HTTP messages with multiple conflicting content-length fields. - [FIX] Use ls-qpack v2.6.5 to pick up a fix for a latent use-after-free. - [IMPROVEMENT] Handle unexpected stream readv/writev args correctly. - [DOCS] Update docs about the now-defunct push promises.
1 parent 97c0681 commit f8ebaf8

11 files changed

Lines changed: 422 additions & 198 deletions

File tree

CHANGELOG

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
2026-06-28
2+
- 4.8.2
3+
- [FIX] Reject HTTP messages with multiple conflicting content-length
4+
fields.
5+
- [FIX] Use ls-qpack v2.6.5 to pick up a fix for a latent use-after-free.
6+
- [IMPROVEMENT] Handle unexpected stream readv/writev args correctly.
7+
- [DOCS] Update docs about the now-defunct push promises.
8+
19
2026-06-20
210
- 4.8.1
311
- [FIX] Send controller: bytes-scheduled underflow (issue #652).

docs/apiref.rst

Lines changed: 30 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -420,19 +420,9 @@ settings structure:
420420

421421
.. member:: int es_support_push
422422

423-
Setting this value to 0 means that
424-
425-
For client:
426-
427-
1. we send a SETTINGS frame to indicate that we do not support server
428-
push; and
429-
2. all incoming pushed streams get reset immediately.
430-
431-
(For maximum effect, set es_max_streams_in to 0.)
432-
433-
For server:
434-
435-
1. :func:`lsquic_conn_push_stream()` will return -1.
423+
Server push is not supported. This setting is retained for API
424+
compatibility. :func:`lsquic_conn_is_push_enabled()` returns false and
425+
:func:`lsquic_conn_push_stream()` returns 1.
436426

437427
.. member:: int es_support_tcid0
438428

@@ -1009,7 +999,7 @@ out of date. Please check your :file:`lsquic.h` for actual values.*
1009999

10101000
.. macro:: LSQUIC_DF_SUPPORT_PUSH
10111001

1012-
Push promises are supported by default.
1002+
Server push is not supported.
10131003

10141004
.. macro:: LSQUIC_DF_SUPPORT_TCID0
10151005

@@ -1868,7 +1858,8 @@ fields yourself. In that case, the header set must be "read" from the stream vi
18681858
:param stream: Stream with which the header set is associated. May be set
18691859
to NULL in server mode.
18701860
:param is_push_promise: Boolean value indicating whether this header set is
1871-
for a push promise.
1861+
for a push promise. Server push is not supported;
1862+
this parameter is retained for API compatibility.
18721863
:return: Pointer to user-defined header set object.
18731864

18741865
Create a new header set. This object is (and must be) fetched from a
@@ -1946,46 +1937,52 @@ fields yourself. In that case, the header set must be "read" from the stream vi
19461937
Push Promises
19471938
-------------
19481939

1940+
Server push is not supported. The following functions remain in the API for
1941+
compatibility.
1942+
19491943
.. function:: int lsquic_conn_push_stream (lsquic_conn_t *conn, void *hdr_set, lsquic_stream_t *stream, const lsquic_http_headers_t *headers)
19501944

19511945
:return:
19521946

1953-
- 0: Stream pushed successfully.
1954-
- 1: Stream push failed because it is disabled or because we hit
1955-
stream limit or connection is going away.
1956-
- -1: Stream push failed because of an internal error.
1957-
1958-
A server may push a stream. This call creates a new stream in reference
1959-
to stream ``stream``. It will behave as if the client made a request: it will
1960-
trigger ``on_new_stream()`` event and it can be used as a regular client-initiated stream.
1947+
- 1: Stream push failed because server push is not supported.
19611948

1962-
``hdr_set`` must be set. It is passed as-is to :func:`lsquic_stream_get_hset()`.
1949+
This function is retained for API compatibility.
19631950

19641951
.. function:: int lsquic_conn_is_push_enabled (lsquic_conn_t *conn)
19651952

1966-
:return: Boolean value indicating whether push promises are enabled.
1953+
:return: 0.
19671954

1968-
Only makes sense in server mode: the client cannot push a stream and this
1969-
function always returns false in client mode.
1955+
This function is retained for API compatibility.
19701956

19711957
.. function:: int lsquic_stream_is_pushed (const lsquic_stream_t *stream)
19721958

1973-
:return: Boolean value indicating whether this is a pushed stream.
1959+
:return: Boolean value indicating whether this is a legacy pushed stream.
1960+
1961+
This function is retained for API compatibility. Current LSQUIC versions
1962+
do not create pushed streams.
19741963

19751964
.. function:: int lsquic_stream_refuse_push (lsquic_stream_t *stream)
19761965

1977-
Refuse pushed stream. Call it from ``on_new_stream()``. No need to
1978-
call :func:`lsquic_stream_close()` after this. ``on_close()`` will be called.
1966+
Refuse a legacy pushed stream.
1967+
1968+
This function is retained for API compatibility. Current LSQUIC versions
1969+
do not create pushed streams.
19791970

19801971
.. function:: int lsquic_stream_push_info (const lsquic_stream_t *stream, lsquic_stream_id_t *ref_stream_id, void **hdr_set)
19811972

1982-
Get information associated with pushed stream
1973+
Get information associated with a legacy pushed stream.
19831974

1984-
:param ref_stream_id: Stream ID in response to which push promise was sent.
1985-
:param hdr_set: Header set. This object was passed to or generated by :func:`lsquic_conn_push_stream()`.
1975+
:param ref_stream_id: Stream ID in response to which a push promise would
1976+
have been sent.
1977+
:param hdr_set: Header set. In legacy push-enabled versions, this object
1978+
was passed to or generated by
1979+
:func:`lsquic_conn_push_stream()`.
19861980

19871981
:return: 0 on success and -1 if this is not a pushed stream.
19881982

1983+
This function is retained for API compatibility. Current LSQUIC versions
1984+
do not create pushed streams.
1985+
19891986
Stream Priorities
19901987
-----------------
19911988

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
# The short X.Y version
2727
version = u'4.8'
2828
# The full version, including alpha/beta/rc tags
29-
release = u'4.8.1'
29+
release = u'4.8.2'
3030

3131

3232
# -- General configuration ---------------------------------------------------

docs/index.rst

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ LSQUIC supports nearly all QUIC and HTTP/3 features, including
3333
- Spin bits (allowing network observer to calculate a connection's RTT)
3434
- Path migration
3535
- NAT rebinding
36-
- Push promises
3736
- TLS Key updates
3837
- Extensions:
3938

docs/internals.rst

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -720,10 +720,6 @@ internally:
720720

721721
- QPACK decoder stream
722722

723-
In addition, HTTP/3 push promises use unidirectional streams. In the
724-
code, we make a unidirectional stream simply by closing one end in the
725-
constructor.
726-
727723
All of the use cases above are handled by the single module,
728724
lsquic_stream. The differences in behavior -- gQUIC vs IETF QUIC, HTTP
729725
vs non-HTTP -- are handled either by explicit conditionals or via
@@ -752,7 +748,7 @@ size of 2\ :sup:`14` - 1 bytes. You will find literal ``2`` or ``3`` values
752748
in code that deals with writing HQ frames.
753749

754750
If the HQ frame's size is known in advance (SHF_FIXED_SIZE) -- which is
755-
the case for HEADERS and PUSH_PROMISE frames -- then the HQ header
751+
the case for HEADERS frames -- then the HQ header
756752
contents are written immediately. Otherwise, ``shf_frame_ptr`` points to
757753
the bytes in the packet where the HQ header was written, to be filled in
758754
later.
@@ -1054,24 +1050,17 @@ This is done to minimize the goodput overhead incurred by the DATA frame header.
10541050

10551051
.. image:: stream-http3-framing.png
10561052

1057-
There are a couple of things that do not fit into this model:
1058-
1059-
1. The HEADERS frame is fixed size [1]_. It is generated separately
1060-
(written by QPACK encoder into a buffer on the stack) and later
1061-
copied into the stream. (See the ``send_headers_ietf`` function.) It
1062-
can happen that the whole buffer cannot be written. In that case,
1063-
a rather complicated dance of buffering the unwritten HEADERS
1064-
frame bytes is performed. Here, the "on stream write" callback is
1065-
replaced with an internal callback (see the ``select_on_write``
1066-
function) and user interaction is prohibited until the whole of
1067-
the HEADERS frame is written to the stream.
1068-
1069-
2. Push promise streams are even weirder. In addition to the HEADERS
1070-
handling above, the push promise stream must begin with a
1071-
variable-integer Push ID. To make this fit into the framed stream
1072-
model, the code makes up the concept of a "phantom" HTTP/3 frame.
1073-
This type of frame's header is not written. This allows us to
1074-
treat the Push ID as the payload of a regular HTTP/3 frame.
1053+
There is one thing that does not fit into this model:
1054+
1055+
The HEADERS frame is fixed size [1]_. It is generated separately
1056+
(written by QPACK encoder into a buffer on the stack) and later
1057+
copied into the stream. (See the ``send_headers_ietf`` function.) It
1058+
can happen that the whole buffer cannot be written. In that case,
1059+
a rather complicated dance of buffering the unwritten HEADERS
1060+
frame bytes is performed. Here, the "on stream write" callback is
1061+
replaced with an internal callback (see the ``select_on_write``
1062+
function) and user interaction is prohibited until the whole of
1063+
the HEADERS frame is written to the stream.
10751064

10761065
The framing code has had its share of bugs. Because of that, there is a
10771066
dedicated unit test program just for the framing code,
@@ -1675,8 +1664,8 @@ fc_last_stream_id
16751664
ID of the last created stream.
16761665

16771666
Used to assign ID to streams created by this side of the connection.
1678-
Clients create odd-numbered streams, while servers initiate
1679-
even-numbered streams (push promises).
1667+
Clients create odd-numbered streams. The server-created, even-numbered
1668+
stream path was used by the now-removed push-promise support.
16801669

16811670
fc_max_peer_stream_id
16821671
---------------------
@@ -2408,7 +2397,8 @@ stored; they are not in the ``ifc_pub.all_streams`` hash.
24082397
ifc_u.ser
24092398
---------
24102399

2411-
The server-specific state is only about push promises.
2400+
The server-specific state tracks MAX_PUSH_ID for push-related HTTP/3
2401+
error handling. LSQUIC does not implement server push.
24122402

24132403
ifc_idle_to
24142404
-----------

include/lsquic.h

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ extern "C" {
2727

2828
#define LSQUIC_MAJOR_VERSION 4
2929
#define LSQUIC_MINOR_VERSION 8
30-
#define LSQUIC_PATCH_VERSION 1
30+
#define LSQUIC_PATCH_VERSION 2
3131

3232
#define LSQUIC_QUOTE(x) #x
3333
#define LSQUIC_SVAL(v) LSQUIC_QUOTE(v)
@@ -1771,25 +1771,18 @@ void *
17711771
lsquic_stream_get_hset (lsquic_stream_t *);
17721772

17731773
/**
1774-
* A server may push a stream. This call creates a new stream in reference
1775-
* to stream `s'. It will behave as if the client made a request: it will
1776-
* trigger on_new_stream() event and it can be used as a regular client-
1777-
* initiated stream.
1774+
* Server push is not supported. This function is retained for API
1775+
* compatibility.
17781776
*
1779-
* `hdr_set' must be set. It is passed as-is to @lsquic_stream_get_hset.
1780-
*
1781-
* @retval 0 Stream pushed successfully.
1782-
* @retval 1 Stream push failed because it is disabled or because we hit
1783-
* stream limit or connection is going away.
1784-
* @retval -1 Stream push failed because of an internal error.
1777+
* @retval 1 Stream push failed because server push is not supported.
17851778
*/
17861779
int
17871780
lsquic_conn_push_stream (lsquic_conn_t *c, void *hdr_set, lsquic_stream_t *s,
17881781
const lsquic_http_headers_t *headers);
17891782

17901783
/**
1791-
* Only makes sense in server mode: the client cannot push a stream and this
1792-
* function always returns false in client mode.
1784+
* Server push is not supported. This function is retained for API
1785+
* compatibility and always returns false.
17931786
*/
17941787
int
17951788
lsquic_conn_is_push_enabled (lsquic_conn_t *);
@@ -1832,7 +1825,10 @@ lsquic_stream_get_ctx (const lsquic_stream_t *s);
18321825
void
18331826
lsquic_stream_set_ctx (lsquic_stream_t *stream, lsquic_stream_ctx_t *ctx);
18341827

1835-
/** Returns true if this is a pushed stream */
1828+
/**
1829+
* Retained for API compatibility with removed server push support. Current
1830+
* LSQUIC versions do not create pushed streams.
1831+
*/
18361832
int
18371833
lsquic_stream_is_pushed (const lsquic_stream_t *s);
18381834

@@ -1844,22 +1840,21 @@ int
18441840
lsquic_stream_is_rejected (const lsquic_stream_t *s);
18451841

18461842
/**
1847-
* Refuse pushed stream. Call it from @ref on_new_stream.
1848-
*
1849-
* No need to call lsquic_stream_close() after this. on_close will be called.
1843+
* Retained for API compatibility with removed server push support. Current
1844+
* LSQUIC versions do not create pushed streams.
18501845
*
1851-
* @see lsquic_stream_is_pushed
1846+
* @see lsquic_stream_is_pushed.
18521847
*/
18531848
int
18541849
lsquic_stream_refuse_push (lsquic_stream_t *s);
18551850

18561851
/**
1857-
* Get information associated with pushed stream:
1852+
* Retained for API compatibility with removed server push support. Current
1853+
* LSQUIC versions do not create pushed streams.
18581854
*
1859-
* @param ref_stream_id Stream ID in response to which push promise was
1860-
* sent.
1861-
* @param hdr_set Header set. This object was passed to or generated
1862-
* by @ref lsquic_conn_push_stream().
1855+
* @param ref_stream_id Legacy output parameter for stream ID in response
1856+
* to which a push promise would have been sent.
1857+
* @param hdr_set Legacy output parameter for the push header set.
18631858
*
18641859
* @retval 0 Success.
18651860
* @retval -1 This is not a pushed stream.

0 commit comments

Comments
 (0)