mirror of
https://gitea.invidious.io/iv-org/litespeed-quic.git
synced 2024-08-15 00:53:43 +00:00
Release 1.14.0
- [API Change] Disable packet sending if full batch cannot be sent If lsquic_packets_out_f() cannot send the whole batch, disable packet sending until lsquic_engine_send_unsent_packets() is called. - [BUGFIX] Handle case when STREAM frame does not fit. - [BUGFIX] Always allow incoming STREAM frames to overlap. Peers may send overlapping STREAM frames even if using versions older than Q043. - Custom header set fixes: - set "FIN reached" flag when custom header with FIN flag is claimed; - do not return custom header set for a reset stream.
This commit is contained in:
parent
3b55e6ae0a
commit
14e3680d6b
19 changed files with 187 additions and 70 deletions
|
@ -51,7 +51,7 @@ SET(lsquic_STAT_SRCS
|
|||
lsquic_xxhash.c
|
||||
lsquic_buf.c
|
||||
lsquic_min_heap.c
|
||||
lshpack.c
|
||||
../lshpack/lshpack.c
|
||||
lsquic_parse_Q044.c
|
||||
lsquic_http1x_if.c
|
||||
)
|
||||
|
|
|
@ -977,13 +977,17 @@ send_batch (lsquic_engine_t *engine, struct conns_out_iter *conns_iter,
|
|||
batch->packets[i]->po_sent = now;
|
||||
n_sent = engine->packets_out(engine->packets_out_ctx, batch->outs,
|
||||
n_to_send);
|
||||
if (n_sent < (int) n_to_send)
|
||||
{
|
||||
engine->pub.enp_flags &= ~ENPUB_CAN_SEND;
|
||||
LSQ_DEBUG("cannot send packets");
|
||||
EV_LOG_GENERIC_EVENT("cannot send packets");
|
||||
}
|
||||
if (n_sent >= 0)
|
||||
LSQ_DEBUG("packets out returned %d (out of %u)", n_sent, n_to_send);
|
||||
else
|
||||
{
|
||||
engine->pub.enp_flags &= ~ENPUB_CAN_SEND;
|
||||
LSQ_DEBUG("packets out returned an error: %s", strerror(errno));
|
||||
EV_LOG_GENERIC_EVENT("cannot send packets");
|
||||
n_sent = 0;
|
||||
}
|
||||
if (n_sent > 0)
|
||||
|
|
|
@ -913,9 +913,6 @@ new_stream_ext (struct full_conn *conn, uint32_t stream_id, int if_idx,
|
|||
{
|
||||
struct lsquic_stream *stream;
|
||||
|
||||
if (conn->fc_conn.cn_version >= LSQVER_043)
|
||||
stream_ctor_flags |= SCF_ALLOW_OVERLAP;
|
||||
|
||||
stream = lsquic_stream_new_ext(stream_id, &conn->fc_pub,
|
||||
conn->fc_stream_ifs[if_idx].stream_if,
|
||||
conn->fc_stream_ifs[if_idx].stream_if_ctx, conn->fc_settings->es_sfcw,
|
||||
|
|
|
@ -73,7 +73,12 @@ struct parse_funcs
|
|||
struct packin_parse_state *);
|
||||
enum QUIC_FRAME_TYPE
|
||||
(*pf_parse_frame_type) (unsigned char);
|
||||
/* Return used buffer length */
|
||||
/* Return used buffer length or a negative value if there was not enough
|
||||
* room to write the stream frame. In the latter case, the negative of
|
||||
* the negative return value is the number of bytes required. The
|
||||
* exception is -1, which is a generic error code, as we always need
|
||||
* more than 1 byte to write a STREAM frame.
|
||||
*/
|
||||
int
|
||||
(*pf_gen_stream_frame) (unsigned char *buf, size_t bufsz,
|
||||
uint32_t stream_id, uint64_t offset,
|
||||
|
|
|
@ -117,7 +117,7 @@ gen_long_pkt_header (const struct lsquic_conn *lconn,
|
|||
p += 4;
|
||||
|
||||
|
||||
assert(need = p - buf);
|
||||
assert(need == (unsigned int)(p - buf));
|
||||
return p - buf;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,4 +21,13 @@ int
|
|||
lsquic_iquic_parse_packet_in_begin (struct lsquic_packet_in *,
|
||||
size_t length, int is_server, struct packin_parse_state *);
|
||||
|
||||
/* Instead of just -1 like CHECK_SPACE(), this macro returns the number
|
||||
* of bytes needed.
|
||||
*/
|
||||
#define CHECK_STREAM_SPACE(need, pstart, pend) do { \
|
||||
if ((intptr_t) (need) > ((pend) - (pstart))) { \
|
||||
return -((int) (need)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -222,7 +222,7 @@ gquic_be_gen_stream_frame (unsigned char *buf, size_t buf_len, uint32_t stream_i
|
|||
dlen = (size < n_avail) << 1;
|
||||
n_avail -= dlen;
|
||||
|
||||
CHECK_SPACE(1 + olen + slen + dlen +
|
||||
CHECK_STREAM_SPACE(1 + olen + slen + dlen +
|
||||
+ 1 /* We need to write at least 1 byte */, buf, buf + buf_len);
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
|
@ -255,7 +255,7 @@ gquic_be_gen_stream_frame (unsigned char *buf, size_t buf_len, uint32_t stream_i
|
|||
else
|
||||
{
|
||||
dlen = 2;
|
||||
CHECK_SPACE(1 + slen + olen + 2, buf, buf + buf_len);
|
||||
CHECK_STREAM_SPACE(1 + slen + olen + 2, buf, buf + buf_len);
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
stream_id = bswap_32(stream_id);
|
||||
#endif
|
||||
|
|
|
@ -217,7 +217,7 @@ gquic_le_gen_stream_frame (unsigned char *buf, size_t buf_len, uint32_t stream_i
|
|||
dlen = (size < n_avail) << 1;
|
||||
n_avail -= dlen;
|
||||
|
||||
CHECK_SPACE(1 + olen + slen + dlen +
|
||||
CHECK_STREAM_SPACE(1 + olen + slen + dlen +
|
||||
+ 1 /* We need to write at least 1 byte */, buf, buf + buf_len);
|
||||
|
||||
memcpy(p, &stream_id, slen);
|
||||
|
@ -238,7 +238,7 @@ gquic_le_gen_stream_frame (unsigned char *buf, size_t buf_len, uint32_t stream_i
|
|||
else
|
||||
{
|
||||
dlen = 2;
|
||||
CHECK_SPACE(1 + slen + olen + 2, buf, buf + buf_len);
|
||||
CHECK_STREAM_SPACE(1 + slen + olen + 2, buf, buf + buf_len);
|
||||
memcpy(p, &stream_id, slen);
|
||||
p += slen;
|
||||
memcpy(p, &offset, olen);
|
||||
|
|
|
@ -273,8 +273,6 @@ lsquic_stream_new_ext (uint32_t id, struct lsquic_conn_public *conn_pub,
|
|||
lsquic_stream_call_on_new(stream);
|
||||
if (ctor_flags & SCF_DISP_RW_ONCE)
|
||||
stream->stream_flags |= STREAM_RW_ONCE;
|
||||
if (ctor_flags & SCF_ALLOW_OVERLAP)
|
||||
stream->stream_flags |= STREAM_ALLOW_OVERLAP;
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
@ -559,17 +557,12 @@ lsquic_stream_frame_in (lsquic_stream_t *stream, stream_frame_t *frame)
|
|||
}
|
||||
else if (INS_FRAME_OVERLAP == ins_frame)
|
||||
{
|
||||
if (stream->stream_flags & STREAM_ALLOW_OVERLAP)
|
||||
{
|
||||
LSQ_DEBUG("overlap: switching DATA IN implementation");
|
||||
stream->data_in = stream->data_in->di_if->di_switch_impl(
|
||||
stream->data_in, stream->read_offset);
|
||||
if (stream->data_in)
|
||||
goto insert_frame;
|
||||
stream->data_in = data_in_error_new();
|
||||
}
|
||||
else
|
||||
LSQ_DEBUG("overlap not supported");
|
||||
LSQ_DEBUG("overlap: switching DATA IN implementation");
|
||||
stream->data_in = stream->data_in->di_if->di_switch_impl(
|
||||
stream->data_in, stream->read_offset);
|
||||
if (stream->data_in)
|
||||
goto insert_frame;
|
||||
stream->data_in = data_in_error_new();
|
||||
lsquic_packet_in_put(stream->conn_pub->mm, frame->packet_in);
|
||||
lsquic_malo_put(frame);
|
||||
return -1;
|
||||
|
@ -1573,6 +1566,7 @@ stream_write_to_packet (struct frame_gen_ctx *fg_ctx, const size_t size)
|
|||
stream->tosend_off);
|
||||
need_at_least = stream_header_sz + (size > 0);
|
||||
hsk = LSQUIC_STREAM_HANDSHAKE == stream->id;
|
||||
get_packet:
|
||||
packet_out = get_packet[hsk](send_ctl, need_at_least, stream);
|
||||
if (!packet_out)
|
||||
return SWTP_STOP;
|
||||
|
@ -1588,8 +1582,18 @@ stream_write_to_packet (struct frame_gen_ctx *fg_ctx, const size_t size)
|
|||
frame_gen_fin(fg_ctx), size, frame_gen_read, fg_ctx);
|
||||
if (len < 0)
|
||||
{
|
||||
LSQ_ERROR("could not generate stream frame");
|
||||
return SWTP_ERROR;
|
||||
if (-len > (int) need_at_least)
|
||||
{
|
||||
LSQ_DEBUG("need more room (%d bytes) than initially calculated "
|
||||
"%u bytes, will try again", -len, need_at_least);
|
||||
need_at_least = -len;
|
||||
goto get_packet;
|
||||
}
|
||||
else
|
||||
{
|
||||
LSQ_ERROR("could not generate stream frame");
|
||||
return SWTP_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
EV_LOG_GENERATED_STREAM_FRAME(LSQUIC_LOG_CONN_ID, pf,
|
||||
|
@ -2181,6 +2185,13 @@ lsquic_stream_get_hset (struct lsquic_stream *stream)
|
|||
{
|
||||
void *hset;
|
||||
|
||||
if (stream->stream_flags & STREAM_RST_FLAGS)
|
||||
{
|
||||
LSQ_INFO("%s: stream is reset, no headers returned", __func__);
|
||||
errno = ECONNRESET;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((stream->stream_flags & (STREAM_USE_HEADERS|STREAM_HAVE_UH))
|
||||
!= (STREAM_USE_HEADERS|STREAM_HAVE_UH))
|
||||
{
|
||||
|
@ -2204,6 +2215,11 @@ lsquic_stream_get_hset (struct lsquic_stream *stream)
|
|||
hset = stream->uh->uh_hset;
|
||||
stream->uh->uh_hset = NULL;
|
||||
destroy_uh(stream);
|
||||
if (stream->stream_flags & STREAM_HEAD_IN_FIN)
|
||||
{
|
||||
stream->stream_flags |= STREAM_FIN_REACHED;
|
||||
SM_HISTORY_APPEND(stream, SHE_REACH_FIN);
|
||||
}
|
||||
LSQ_DEBUG("return header set");
|
||||
return hset;
|
||||
}
|
||||
|
|
|
@ -62,7 +62,6 @@ struct lsquic_stream
|
|||
STREAM_ONNEW_DONE = (1 <<26), /* on_new_stream has been called */
|
||||
STREAM_AUTOSWITCH = (1 <<27),
|
||||
STREAM_RW_ONCE = (1 <<28), /* When set, read/write events are dispatched once per call */
|
||||
STREAM_ALLOW_OVERLAP= (1 <<29),
|
||||
} stream_flags;
|
||||
|
||||
/* There are more than one reason that a stream may be put onto
|
||||
|
@ -140,7 +139,6 @@ enum stream_ctor_flags
|
|||
* performance.
|
||||
*/
|
||||
SCF_DISP_RW_ONCE = (1 << 3),
|
||||
SCF_ALLOW_OVERLAP = (1 << 4), /* Allow STREAM frames to overlap */
|
||||
};
|
||||
|
||||
lsquic_stream_t *
|
||||
|
|
|
@ -36,7 +36,7 @@ SOFTWARE.
|
|||
#if LS_HPACK_EMIT_TEST_CODE
|
||||
#include "lshpack-test.h"
|
||||
#endif
|
||||
#include XXH_HEADER_NAME
|
||||
#include "lsquic_xxhash.h"
|
||||
|
||||
#define HPACK_STATIC_TABLE_SIZE 61
|
||||
#define INITIAL_DYNAMIC_TABLE_SIZE 4096
|
Loading…
Add table
Add a link
Reference in a new issue