Skip to content

Commit 292abba

Browse files
author
Dmitri Tikhonov
committed
Release 2.26.2
- [BUGFIX] Do not drop incoming data when STOP_SENDING is received. - [BUGFIX] Receipt of STOP_SENDING should not cause read-reset. - [BUGFIX] Allow stream writes after receiving RESET. - [BUGFIX] Typo in stream: ANDing enum with wrong flag. - [BUGFIX] Reset elision: do not use zero as special stream ID value, for zero is a valid stream ID in IETF QUIC. - [API] Add optional on_conncloseframe_received() callback. - Use zero error code in RESET stream sent in response to STOP_SENDING.
1 parent efa7f95 commit 292abba

File tree

11 files changed

+163
-31
lines changed

11 files changed

+163
-31
lines changed

CHANGELOG

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
2020-12-23
2+
- 2.26.2
3+
- [BUGFIX] Do not drop incoming data when STOP_SENDING is received.
4+
- [BUGFIX] Receipt of STOP_SENDING should not cause read-reset.
5+
- [BUGFIX] Allow stream writes after receiving RESET.
6+
- [BUGFIX] Typo in stream: ANDing enum with wrong flag.
7+
- [BUGFIX] Reset elision: do not use zero as special stream ID value,
8+
for zero is a valid stream ID in IETF QUIC.
9+
- [API] Add optional on_conncloseframe_received() callback.
10+
- Use zero error code in RESET stream sent in response to STOP_SENDING.
11+
112
2020-12-17
213
- 2.26.1
314
- [BUGFIX] Migration corner cases: drop or pad over path challenge

CONTRIBUTORS.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ to the LiteSpeed QUIC and HTTP/3 Library:
1313
- Victor Stewart -- Generate SCIDs API (connection ID steering)
1414
- Aaron France -- Shared library support and Lisp bindings
1515
- Suma Subbarao -- Use callback to supply client's SSL_CTX
16+
- Paul Sheer -- Callback on arrival of CONNECTION_CLOSE frame
1617

1718
Thank you!
1819

docs/apiref.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1294,7 +1294,7 @@ the engine to communicate with the user code:
12941294
signals the user to stop reading, writing, or both.
12951295

12961296
Note that resets differ in gQUIC and IETF QUIC. In gQUIC, `how` is
1297-
always 2; in IETF QUIC, `how` is either 0 or 1 because on can reset
1297+
always 2; in IETF QUIC, `how` is either 0 or 1 because one can reset
12981298
just one direction in IETF QUIC.
12991299

13001300
This callback is optional. The reset error can still be collected

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'2.26'
2828
# The full version, including alpha/beta/rc tags
29-
release = u'2.26.1'
29+
release = u'2.26.2'
3030

3131

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

include/lsquic.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ extern "C" {
2525

2626
#define LSQUIC_MAJOR_VERSION 2
2727
#define LSQUIC_MINOR_VERSION 26
28-
#define LSQUIC_PATCH_VERSION 1
28+
#define LSQUIC_PATCH_VERSION 2
2929

3030
/**
3131
* Engine flags:
@@ -217,7 +217,7 @@ struct lsquic_stream_if {
217217
* signals the user to stop reading, writing, or both.
218218
*
219219
* Note that resets differ in gQUIC and IETF QUIC. In gQUIC, `how' is
220-
* always 2; in IETF QUIC, `how' is either 0 or 1 because on can reset
220+
* always 2; in IETF QUIC, `how' is either 0 or 1 because one can reset
221221
* just one direction in IETF QUIC.
222222
*/
223223
void (*on_reset) (lsquic_stream_t *s, lsquic_stream_ctx_t *h, int how);

src/liblsquic/lsquic_packet_out.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ lsquic_packet_out_destroy (lsquic_packet_out_t *packet_out,
297297
}
298298

299299

300-
/* If `stream_id' is zero, stream frames from all reset streams are elided.
300+
/* If `stream_id' is UINT64_MAX, stream frames from all reset streams are elided.
301301
* Otherwise, elision is limited to the specified stream.
302302
*/
303303
unsigned
@@ -320,16 +320,16 @@ lsquic_packet_out_elide_reset_stream_frames (lsquic_packet_out_t *packet_out,
320320
{
321321
++n_stream_frames;
322322

323-
if (stream_id)
323+
if (stream_id != UINT64_MAX)
324324
{
325325
victim = frec->fe_stream->id == stream_id;
326326
if (victim)
327327
{
328-
assert(lsquic_stream_is_reset(frec->fe_stream));
328+
assert(lsquic_stream_is_write_reset(frec->fe_stream));
329329
}
330330
}
331331
else
332-
victim = lsquic_stream_is_reset(frec->fe_stream);
332+
victim = lsquic_stream_is_write_reset(frec->fe_stream);
333333

334334
if (victim)
335335
{

src/liblsquic/lsquic_send_ctl.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1430,7 +1430,8 @@ send_ctl_next_lost (lsquic_send_ctl_t *ctl)
14301430
{
14311431
if (0 == (lost_packet->po_flags & PO_MINI))
14321432
{
1433-
lsquic_packet_out_elide_reset_stream_frames(lost_packet, 0);
1433+
lsquic_packet_out_elide_reset_stream_frames(lost_packet,
1434+
UINT64_MAX);
14341435
if (lost_packet->po_regen_sz >= lost_packet->po_data_sz)
14351436
{
14361437
LSQ_DEBUG("Dropping packet %"PRIu64" from lost queue",

src/liblsquic/lsquic_stream.c

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,17 @@ stream_readable_discard (struct lsquic_stream *stream)
872872
}
873873

874874

875+
static int
876+
stream_is_read_reset (const struct lsquic_stream *stream)
877+
{
878+
if (stream->sm_bflags & SMBF_IETF)
879+
return stream->stream_flags & STREAM_RST_RECVD;
880+
else
881+
return (stream->stream_flags & (STREAM_RST_RECVD|STREAM_RST_SENT))
882+
|| (stream->sm_qflags & SMQF_SEND_RST);
883+
}
884+
885+
875886
int
876887
lsquic_stream_readable (struct lsquic_stream *stream)
877888
{
@@ -885,13 +896,27 @@ lsquic_stream_readable (struct lsquic_stream *stream)
885896
* lsquic_stream_read() will return -1 (we want the user to be
886897
* able to collect the error).
887898
*/
888-
|| lsquic_stream_is_reset(stream)
899+
|| stream_is_read_reset(stream)
889900
/* Type-dependent readability check: */
890901
|| stream->sm_readable(stream);
891902
;
892903
}
893904

894905

906+
/* Return true if write end of the stream has been reset.
907+
* Note that the logic for gQUIC is the same for write and read resets.
908+
*/
909+
int
910+
lsquic_stream_is_write_reset (const struct lsquic_stream *stream)
911+
{
912+
if (stream->sm_bflags & SMBF_IETF)
913+
return stream->stream_flags & STREAM_SS_RECVD;
914+
else
915+
return (stream->stream_flags & (STREAM_RST_RECVD|STREAM_RST_SENT))
916+
|| (stream->sm_qflags & SMQF_SEND_RST);
917+
}
918+
919+
895920
static int
896921
stream_writeable (struct lsquic_stream *stream)
897922
{
@@ -901,7 +926,7 @@ stream_writeable (struct lsquic_stream *stream)
901926
* lsquic_stream_write() will return -1 (we want the user to be
902927
* able to collect the error).
903928
*/
904-
lsquic_stream_is_reset(stream)
929+
lsquic_stream_is_write_reset(stream)
905930
/* - Data can be written to stream: */
906931
|| lsquic_stream_write_avail(stream)
907932
;
@@ -1294,13 +1319,12 @@ lsquic_stream_stop_sending_in (struct lsquic_stream *stream,
12941319
maybe_conn_to_tickable_if_writeable(stream, 0);
12951320

12961321
lsquic_sfcw_consume_rem(&stream->fc);
1297-
drop_frames_in(stream);
12981322
drop_buffered_data(stream);
12991323
maybe_elide_stream_frames(stream);
13001324

13011325
if (!(stream->stream_flags & (STREAM_RST_SENT|STREAM_FIN_SENT))
13021326
&& !(stream->sm_qflags & SMQF_SEND_RST))
1303-
lsquic_stream_reset_ext(stream, error_code, 0);
1327+
lsquic_stream_reset_ext(stream, 0, 0);
13041328

13051329
maybe_finish_stream(stream);
13061330
maybe_schedule_call_on_close(stream);
@@ -1628,7 +1652,7 @@ lsquic_stream_readf (struct lsquic_stream *stream,
16281652

16291653
SM_HISTORY_APPEND(stream, SHE_USER_READ);
16301654

1631-
if (lsquic_stream_is_reset(stream))
1655+
if (stream_is_read_reset(stream))
16321656
{
16331657
if (stream->stream_flags & STREAM_RST_RECVD)
16341658
stream->stream_flags |= STREAM_RST_READ;
@@ -1816,7 +1840,7 @@ stream_shutdown_write (lsquic_stream_t *stream)
18161840
&& !(stream->stream_flags & (STREAM_FIN_SENT|STREAM_RST_SENT))
18171841
&& !stream_is_incoming_unidir(stream)
18181842
/* In gQUIC, receiving a RESET means "stop sending" */
1819-
&& !(!(stream->sm_qflags & SMBF_IETF)
1843+
&& !(!(stream->sm_bflags & SMBF_IETF)
18201844
&& (stream->stream_flags & STREAM_RST_RECVD)))
18211845
{
18221846
if ((stream->sm_bflags & SMBF_USE_HEADERS)
@@ -2530,7 +2554,7 @@ lsquic_stream_flush_threshold (const struct lsquic_stream *stream,
25302554
return -1; \
25312555
} \
25322556
} \
2533-
if (lsquic_stream_is_reset(stream)) \
2557+
if (lsquic_stream_is_write_reset(stream)) \
25342558
{ \
25352559
LSQ_INFO("Attempt to write to stream after it had been reset"); \
25362560
errno = ECONNRESET; \
@@ -4600,7 +4624,7 @@ lsquic_stream_get_hset (struct lsquic_stream *stream)
46004624
{
46014625
void *hset;
46024626

4603-
if (lsquic_stream_is_reset(stream))
4627+
if (stream_is_read_reset(stream))
46044628
{
46054629
LSQ_INFO("%s: stream is reset, no headers returned", __func__);
46064630
errno = ECONNRESET;

src/liblsquic/lsquic_stream.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -429,16 +429,15 @@ lsquic_stream_call_on_new (lsquic_stream_t *);
429429
void
430430
lsquic_stream_destroy (lsquic_stream_t *);
431431

432-
/* Any of these flags will cause user-facing read and write and
433-
* shutdown calls to return an error. They also make the stream
434-
* both readable and writeable, as we want the user to collect
435-
* the error.
436-
*/
432+
/* True if either read or write side of the stream has been reset */
437433
#define lsquic_stream_is_reset(stream) \
438434
(((stream)->stream_flags & \
439435
(STREAM_RST_RECVD|STREAM_RST_SENT|STREAM_SS_RECVD)) \
440436
|| ((stream)->sm_qflags & SMQF_SEND_RST))
441437

438+
int
439+
lsquic_stream_is_write_reset (const struct lsquic_stream *);
440+
442441
/* Data that from the network gets inserted into the stream using
443442
* lsquic_stream_frame_in() function. Returns 0 on success, -1 on
444443
* failure. The latter may be caused by flow control violation or

tests/test_elision.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ elide_single_stream_frame (void)
124124

125125
streams[0].stream_flags |= STREAM_RST_SENT;
126126

127-
lsquic_packet_out_elide_reset_stream_frames(packet_out, 0);
127+
lsquic_packet_out_elide_reset_stream_frames(packet_out, UINT64_MAX);
128128
assert(0 == streams[0].n_unacked);
129129
assert(0 == packet_out->po_frame_types);
130130
assert(!lsquic_pofi_first(&pofi, packet_out));
@@ -193,7 +193,7 @@ shrink_packet_post_elision (void)
193193

194194
streams[0].stream_flags |= STREAM_RST_SENT;
195195

196-
lsquic_packet_out_elide_reset_stream_frames(packet_out, 0);
196+
lsquic_packet_out_elide_reset_stream_frames(packet_out, UINT64_MAX);
197197
assert(0 == streams[0].n_unacked);
198198

199199
assert(QUIC_FTBIT_STREAM == packet_out->po_frame_types);
@@ -364,7 +364,7 @@ elide_three_stream_frames (int chop_regen)
364364

365365
if (chop_regen)
366366
lsquic_packet_out_chop_regen(packet_out);
367-
lsquic_packet_out_elide_reset_stream_frames(packet_out, 0);
367+
lsquic_packet_out_elide_reset_stream_frames(packet_out, UINT64_MAX);
368368

369369
assert(ref_out->po_data_sz == packet_out->po_data_sz + (chop_regen ? 5 : 0));
370370
assert(ref_out->po_regen_sz == packet_out->po_regen_sz + (chop_regen ? 5 : 0));

0 commit comments

Comments
 (0)