mirror of
https://gitea.invidious.io/iv-org/litespeed-quic.git
synced 2024-08-15 00:53:43 +00:00
Release 2.30.0
- [FEATURE] Added support for sending/receiving multiple headers to address the case related to "100 continue" header handling. - [BUGFIX] Addressed high CPU usage for a GOAWAY connection before sending CONNECTION_CLOSE. - [BUGFIX] Addressed SIGFPE due to zero pacing rate. (ISSUE #254). - [BUGFIX] Fixed a minor issue related to multi-paths.
This commit is contained in:
parent
ab69788e51
commit
293df8d66b
16 changed files with 815 additions and 125 deletions
|
@ -15,7 +15,7 @@ struct adaptive_cc
|
|||
struct lsquic_cubic acc_cubic;
|
||||
struct lsquic_bbr acc_bbr;
|
||||
enum {
|
||||
ACC_CUBIC, /* If set, use Cubic; otherwise, use BBR */
|
||||
ACC_CUBIC = 1, /* If set, use Cubic; otherwise, use BBR */
|
||||
} acc_flags;
|
||||
};
|
||||
|
||||
|
|
|
@ -45,6 +45,8 @@ const char *const lsquic_alid2str[] =
|
|||
[AL_CID_THROT] = "CID_THROT",
|
||||
[AL_PATH_CHAL_0] = "PATH_CHAL_0",
|
||||
[AL_PATH_CHAL_1] = "PATH_CHAL_1",
|
||||
[AL_PATH_CHAL_2] = "PATH_CHAL_2",
|
||||
[AL_PATH_CHAL_3] = "PATH_CHAL_3",
|
||||
[AL_SESS_TICKET] = "SESS_TICKET",
|
||||
[AL_BLOCKED_KA] = "BLOCKED_KA",
|
||||
[AL_MTU_PROBE] = "MTU_PROBE",
|
||||
|
|
|
@ -704,6 +704,7 @@ wipe_path (struct ietf_full_conn *conn, unsigned path_id)
|
|||
memset(&conn->ifc_paths[path_id], 0, sizeof(conn->ifc_paths[0]));
|
||||
conn->ifc_paths[path_id].cop_path.np_path_id = path_id;
|
||||
conn->ifc_paths[path_id].cop_path.np_peer_ctx = peer_ctx;
|
||||
conn->ifc_used_paths &= ~(1 << path_id);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2755,6 +2756,20 @@ have_bidi_streams (const struct ietf_full_conn *conn)
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
conn_ok_to_close (const struct ietf_full_conn *conn)
|
||||
{
|
||||
assert(conn->ifc_flags & IFC_CLOSING);
|
||||
return !(conn->ifc_flags & IFC_SERVER)
|
||||
|| (conn->ifc_flags & IFC_RECV_CLOSE)
|
||||
|| (
|
||||
!lsquic_send_ctl_have_outgoing_stream_frames(&conn->ifc_send_ctl)
|
||||
&& !have_bidi_streams(conn)
|
||||
&& lsquic_send_ctl_have_unacked_stream_frames(
|
||||
&conn->ifc_send_ctl) == 0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
maybe_close_conn (struct ietf_full_conn *conn)
|
||||
{
|
||||
|
@ -2763,8 +2778,13 @@ maybe_close_conn (struct ietf_full_conn *conn)
|
|||
&& !have_bidi_streams(conn))
|
||||
{
|
||||
conn->ifc_flags |= IFC_CLOSING|IFC_GOAWAY_CLOSE;
|
||||
conn->ifc_send_flags |= SF_SEND_CONN_CLOSE;
|
||||
LSQ_DEBUG("closing connection: GOAWAY sent and no responses remain");
|
||||
LSQ_DEBUG("maybe_close_conn: GOAWAY sent and no responses remain");
|
||||
if (conn_ok_to_close(conn))
|
||||
{
|
||||
conn->ifc_send_flags |= SF_SEND_CONN_CLOSE;
|
||||
LSQ_DEBUG("maybe_close_conn: ok to close: "
|
||||
"schedule to send CONNECTION_CLOSE");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2920,7 +2940,12 @@ ietf_full_conn_ci_close (struct lsquic_conn *lconn)
|
|||
lsquic_stream_maybe_reset(stream, 0, 1);
|
||||
}
|
||||
conn->ifc_flags |= IFC_CLOSING;
|
||||
conn->ifc_send_flags |= SF_SEND_CONN_CLOSE;
|
||||
if (conn_ok_to_close(conn))
|
||||
{
|
||||
conn->ifc_send_flags |= SF_SEND_CONN_CLOSE;
|
||||
LSQ_DEBUG("ietf_full_conn_ci_close: ok to close: "
|
||||
"schedule to send CONNECTION_CLOSE");
|
||||
}
|
||||
lsquic_engine_add_conn_to_tickable(conn->ifc_enpub, lconn);
|
||||
}
|
||||
}
|
||||
|
@ -3204,7 +3229,8 @@ ietf_full_conn_ci_going_away (struct lsquic_conn *lconn)
|
|||
{
|
||||
if (!(conn->ifc_flags & (IFC_CLOSING|IFC_GOING_AWAY)))
|
||||
{
|
||||
LSQ_INFO("connection marked as going away");
|
||||
LSQ_INFO("connection marked as going away, last stream: %ld",
|
||||
conn->ifc_max_req_id);
|
||||
conn->ifc_flags |= IFC_GOING_AWAY;
|
||||
const lsquic_stream_id_t stream_id = conn->ifc_max_req_id + N_SITS;
|
||||
if (valid_stream_id(stream_id))
|
||||
|
@ -4340,20 +4366,6 @@ process_streams_write_events (struct ietf_full_conn *conn, int high_prio)
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
conn_ok_to_close (const struct ietf_full_conn *conn)
|
||||
{
|
||||
assert(conn->ifc_flags & IFC_CLOSING);
|
||||
return !(conn->ifc_flags & IFC_SERVER)
|
||||
|| (conn->ifc_flags & IFC_RECV_CLOSE)
|
||||
|| (
|
||||
!lsquic_send_ctl_have_outgoing_stream_frames(&conn->ifc_send_ctl)
|
||||
&& !have_bidi_streams(conn)
|
||||
&& lsquic_send_ctl_have_unacked_stream_frames(
|
||||
&conn->ifc_send_ctl) == 0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
generate_connection_close_packet (struct ietf_full_conn *conn)
|
||||
{
|
||||
|
@ -8325,7 +8337,9 @@ ietf_full_conn_ci_tick (struct lsquic_conn *lconn, lsquic_time_t now)
|
|||
lsquic_send_ctl_maybe_app_limited(&conn->ifc_send_ctl, CUR_NPATH(conn));
|
||||
|
||||
end_write:
|
||||
if ((conn->ifc_flags & IFC_CLOSING) && conn_ok_to_close(conn))
|
||||
if ((conn->ifc_flags & IFC_CLOSING)
|
||||
&& ((conn->ifc_send_flags & SF_SEND_CONN_CLOSE)
|
||||
|| conn_ok_to_close(conn)))
|
||||
{
|
||||
LSQ_DEBUG("connection is OK to close");
|
||||
conn->ifc_flags |= IFC_TICK_CLOSE;
|
||||
|
|
|
@ -133,6 +133,7 @@ typedef struct hs_ctx_st
|
|||
HSET_SCID = (1 << 2),
|
||||
HSET_IRTT = (1 << 3),
|
||||
HSET_SRST = (1 << 4),
|
||||
HSET_XLCT = (1 << 5), /* xlct is set */
|
||||
} set;
|
||||
enum {
|
||||
HOPT_NSTP = (1 << 0), /* NSTP option present in COPT */
|
||||
|
@ -283,6 +284,7 @@ struct lsquic_enc_session
|
|||
SSL_CTX * ssl_ctx;
|
||||
struct lsquic_engine_public *enpub;
|
||||
struct lsquic_str * cert_ptr; /* pointer to the leaf cert of the server, not real copy */
|
||||
uint64_t cert_hash;
|
||||
struct lsquic_str chlo; /* real copy of CHLO message */
|
||||
struct lsquic_str sstk;
|
||||
struct lsquic_str ssno;
|
||||
|
@ -310,6 +312,7 @@ typedef struct compress_cert_hash_item_st
|
|||
typedef struct cert_item_st
|
||||
{
|
||||
struct lsquic_str* crt;
|
||||
uint64_t hash; /* Hash of `crt' */
|
||||
struct lsquic_hash_elem hash_el;
|
||||
unsigned char key[0];
|
||||
} cert_item_t;
|
||||
|
@ -535,6 +538,8 @@ insert_cert (struct lsquic_engine_public *enpub, const unsigned char *key,
|
|||
|
||||
item->crt = crt_copy;
|
||||
memcpy(item->key, key, key_sz);
|
||||
item->hash = lsquic_fnv1a_64((const uint8_t *)lsquic_str_buf(crt),
|
||||
lsquic_str_len(crt));
|
||||
el = lsquic_hash_insert(enpub->enp_server_certs, item->key, key_sz,
|
||||
item, &item->hash_el);
|
||||
if (el)
|
||||
|
@ -1267,6 +1272,13 @@ static int parse_hs_data (struct lsquic_enc_session *enc_session, uint32_t tag,
|
|||
break;
|
||||
|
||||
case QTAG_XLCT:
|
||||
if (len != sizeof(hs_ctx->xlct))
|
||||
{
|
||||
LSQ_INFO("Unexpected size of XLCT: %u instead of %zu bytes",
|
||||
len, sizeof(hs_ctx->xlct));
|
||||
return -1;
|
||||
}
|
||||
hs_ctx->set |= HSET_XLCT;
|
||||
hs_ctx->xlct = get_tag_value_i64(val, len);
|
||||
break;
|
||||
|
||||
|
@ -1664,7 +1676,6 @@ determine_rtts (struct lsquic_enc_session *enc_session,
|
|||
{
|
||||
hs_ctx_t *const hs_ctx = &enc_session->hs_ctx;
|
||||
enum hsk_failure_reason hfr;
|
||||
uint64_t hash = 0;
|
||||
|
||||
if (!(hs_ctx->set & HSET_SCID))
|
||||
{
|
||||
|
@ -1701,12 +1712,9 @@ determine_rtts (struct lsquic_enc_session *enc_session,
|
|||
goto fail_1rtt;
|
||||
}
|
||||
|
||||
if (hs_ctx->xlct)
|
||||
if (hs_ctx->set & HSET_XLCT)
|
||||
{
|
||||
hash = lsquic_fnv1a_64((const uint8_t *)lsquic_str_buf(enc_session->cert_ptr),
|
||||
lsquic_str_len(enc_session->cert_ptr));
|
||||
|
||||
if (hash != hs_ctx->xlct)
|
||||
if (enc_session->cert_hash != hs_ctx->xlct)
|
||||
{
|
||||
/* The expected leaf certificate hash could not be validated. */
|
||||
hs_ctx->rrej = HFR_INVALID_EXPECTED_LEAF_CERTIFICATE;
|
||||
|
@ -2297,6 +2305,7 @@ get_sni_SSL_CTX(struct lsquic_enc_session *enc_session, lsquic_lookup_cert_f cb,
|
|||
}
|
||||
}
|
||||
enc_session->cert_ptr = item->crt;
|
||||
enc_session->cert_hash = item->hash;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2310,6 +2319,9 @@ get_sni_SSL_CTX(struct lsquic_enc_session *enc_session, lsquic_lookup_cert_f cb,
|
|||
if (!enc_session->cert_ptr)
|
||||
return GET_SNI_ERR;
|
||||
enc_session->es_flags |= ES_FREE_CERT_PTR;
|
||||
enc_session->cert_hash = lsquic_fnv1a_64(
|
||||
(const uint8_t *) lsquic_str_buf(enc_session->cert_ptr),
|
||||
lsquic_str_len(enc_session->cert_ptr));
|
||||
}
|
||||
}
|
||||
return GET_SNI_OK;
|
||||
|
|
|
@ -36,6 +36,8 @@ struct uncompressed_headers
|
|||
UH_H1H = (1 << 2), /* uh_hset points to http1x_headers */
|
||||
} uh_flags:8;
|
||||
void *uh_hset;
|
||||
struct uncompressed_headers
|
||||
*uh_next;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -36,7 +36,6 @@ struct lsquic_mm {
|
|||
struct malo *frame_rec_arr; /* For struct frame_rec_arr */
|
||||
struct malo *mini_conn; /* For struct mini_conn */
|
||||
struct malo *mini_conn_ietf;/* For struct ietf_mini_conn */
|
||||
struct malo *retry_conn; /* For struct retry_conn */
|
||||
struct malo *packet_in; /* For struct lsquic_packet_in */
|
||||
struct malo *packet_out; /* For struct lsquic_packet_out */
|
||||
struct malo *dcid_elem; /* For struct dcid_elem */
|
||||
|
|
|
@ -641,7 +641,7 @@ qdh_header_read_results (struct qpack_dec_hdl *qdh,
|
|||
|
||||
if (rhs == LQRHS_DONE)
|
||||
{
|
||||
if (!lsquic_stream_header_is_trailer(stream))
|
||||
if (1) //!lsquic_stream_header_is_trailer(stream))
|
||||
{
|
||||
if (stream->sm_hblock_ctx->ctx.ppc_flags
|
||||
& (PPC_INC_SET|PPC_URG_SET))
|
||||
|
|
|
@ -546,6 +546,8 @@ send_ctl_transfer_time (void *ctx)
|
|||
|
||||
in_recovery = send_ctl_in_recovery(ctl);
|
||||
pacing_rate = ctl->sc_ci->cci_pacing_rate(CGP(ctl), in_recovery);
|
||||
if (!pacing_rate)
|
||||
pacing_rate = 1;
|
||||
tx_time = (uint64_t) SC_PACK_SIZE(ctl) * 1000000 / pacing_rate;
|
||||
return tx_time;
|
||||
}
|
||||
|
@ -3788,6 +3790,8 @@ lsquic_send_ctl_can_send_probe (const struct lsquic_send_ctl *ctl,
|
|||
if (n_out + path->np_pack_size >= cwnd)
|
||||
return 0;
|
||||
pacing_rate = ctl->sc_ci->cci_pacing_rate(CGP(ctl), 0);
|
||||
if (!pacing_rate)
|
||||
pacing_rate = 1;
|
||||
tx_time = (uint64_t) path->np_pack_size * 1000000 / pacing_rate;
|
||||
return lsquic_pacer_can_schedule_probe(&ctl->sc_pacer,
|
||||
ctl->sc_n_scheduled + ctl->sc_n_in_flight_all, tx_time);
|
||||
|
|
|
@ -623,15 +623,13 @@ lsquic_stream_drop_hset_ref (struct lsquic_stream *stream)
|
|||
|
||||
|
||||
static void
|
||||
destroy_uh (struct lsquic_stream *stream)
|
||||
destroy_uh (struct uncompressed_headers *uh, const struct lsquic_hset_if *hsi_if)
|
||||
{
|
||||
if (stream->uh)
|
||||
if (uh)
|
||||
{
|
||||
if (stream->uh->uh_hset)
|
||||
stream->conn_pub->enpub->enp_hsi_if
|
||||
->hsi_discard_header_set(stream->uh->uh_hset);
|
||||
free(stream->uh);
|
||||
stream->uh = NULL;
|
||||
if (uh->uh_hset)
|
||||
hsi_if->hsi_discard_header_set(uh->uh_hset);
|
||||
free(uh);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -641,6 +639,7 @@ lsquic_stream_destroy (lsquic_stream_t *stream)
|
|||
{
|
||||
struct push_promise *promise;
|
||||
struct stream_hq_frame *shf;
|
||||
struct uncompressed_headers *uh;
|
||||
|
||||
stream->stream_flags |= STREAM_U_WRITE_DONE|STREAM_U_READ_DONE;
|
||||
if ((stream->stream_flags & (STREAM_ONNEW_DONE|STREAM_ONCLOSE_DONE)) ==
|
||||
|
@ -687,7 +686,12 @@ lsquic_stream_destroy (lsquic_stream_t *stream)
|
|||
}
|
||||
while ((shf = STAILQ_FIRST(&stream->sm_hq_frames)))
|
||||
stream_hq_frame_put(stream, shf);
|
||||
destroy_uh(stream);
|
||||
while(stream->uh)
|
||||
{
|
||||
uh = stream->uh;
|
||||
stream->uh = uh->uh_next;
|
||||
destroy_uh(uh, stream->conn_pub->enpub->enp_hsi_if);
|
||||
}
|
||||
free(stream->sm_buf);
|
||||
free(stream->sm_header_block);
|
||||
LSQ_DEBUG("destroyed stream");
|
||||
|
@ -1443,7 +1447,8 @@ static size_t
|
|||
read_uh (struct lsquic_stream *stream,
|
||||
size_t (*readf)(void *, const unsigned char *, size_t, int), void *ctx)
|
||||
{
|
||||
struct http1x_headers *const h1h = stream->uh->uh_hset;
|
||||
struct uncompressed_headers *uh = stream->uh;
|
||||
struct http1x_headers *const h1h = uh->uh_hset;
|
||||
size_t nread;
|
||||
|
||||
nread = readf(ctx, (unsigned char *) h1h->h1h_buf + h1h->h1h_off,
|
||||
|
@ -1452,8 +1457,10 @@ read_uh (struct lsquic_stream *stream,
|
|||
h1h->h1h_off += nread;
|
||||
if (h1h->h1h_off == h1h->h1h_size)
|
||||
{
|
||||
LSQ_DEBUG("read all uncompressed headers");
|
||||
destroy_uh(stream);
|
||||
stream->uh = uh->uh_next;
|
||||
LSQ_DEBUG("read all uncompressed headers from uh: %p, next uh: %p",
|
||||
uh, stream->uh);
|
||||
destroy_uh(uh, stream->conn_pub->enpub->enp_hsi_if);
|
||||
if (stream->stream_flags & STREAM_HEAD_IN_FIN)
|
||||
{
|
||||
stream->stream_flags |= STREAM_FIN_REACHED;
|
||||
|
@ -4186,7 +4193,7 @@ lsquic_stream_send_headers (lsquic_stream_t *stream,
|
|||
const lsquic_http_headers_t *headers, int eos)
|
||||
{
|
||||
if ((stream->sm_bflags & SMBF_USE_HEADERS)
|
||||
&& !(stream->stream_flags & (STREAM_HEADERS_SENT|STREAM_U_WRITE_DONE)))
|
||||
&& !(stream->stream_flags & (STREAM_U_WRITE_DONE)))
|
||||
{
|
||||
if (stream->sm_bflags & SMBF_IETF)
|
||||
return send_headers_ietf(stream, headers, eos);
|
||||
|
@ -4411,15 +4418,19 @@ static int
|
|||
stream_uh_in_gquic (struct lsquic_stream *stream,
|
||||
struct uncompressed_headers *uh)
|
||||
{
|
||||
if ((stream->sm_bflags & SMBF_USE_HEADERS)
|
||||
&& !(stream->stream_flags & STREAM_HAVE_UH))
|
||||
struct uncompressed_headers **next;
|
||||
if ((stream->sm_bflags & SMBF_USE_HEADERS))
|
||||
{
|
||||
SM_HISTORY_APPEND(stream, SHE_HEADERS_IN);
|
||||
LSQ_DEBUG("received uncompressed headers");
|
||||
stream->stream_flags |= STREAM_HAVE_UH;
|
||||
if (uh->uh_flags & UH_FIN)
|
||||
stream->stream_flags |= STREAM_FIN_RECVD|STREAM_HEAD_IN_FIN;
|
||||
stream->uh = uh;
|
||||
next = &stream->uh;
|
||||
while(*next)
|
||||
next = &(*next)->uh_next;
|
||||
*next = uh;
|
||||
assert(uh->uh_next == NULL);
|
||||
if (uh->uh_oth_stream_id == 0)
|
||||
{
|
||||
if (uh->uh_weight)
|
||||
|
@ -4443,9 +4454,10 @@ stream_uh_in_ietf (struct lsquic_stream *stream,
|
|||
struct uncompressed_headers *uh)
|
||||
{
|
||||
int push_promise;
|
||||
struct uncompressed_headers **next;
|
||||
|
||||
push_promise = lsquic_stream_header_is_pp(stream);
|
||||
if (!(stream->stream_flags & STREAM_HAVE_UH) && !push_promise)
|
||||
if (!push_promise)
|
||||
{
|
||||
SM_HISTORY_APPEND(stream, SHE_HEADERS_IN);
|
||||
LSQ_DEBUG("received uncompressed headers");
|
||||
|
@ -4460,7 +4472,11 @@ stream_uh_in_ietf (struct lsquic_stream *stream,
|
|||
&& lsquic_stream_is_pushed(stream));
|
||||
stream->stream_flags |= STREAM_FIN_RECVD|STREAM_HEAD_IN_FIN;
|
||||
}
|
||||
stream->uh = uh;
|
||||
next = &stream->uh;
|
||||
while(*next)
|
||||
next = &(*next)->uh_next;
|
||||
*next = uh;
|
||||
assert(uh->uh_next == NULL);
|
||||
if (uh->uh_oth_stream_id == 0)
|
||||
{
|
||||
if (uh->uh_weight)
|
||||
|
@ -4652,6 +4668,7 @@ void *
|
|||
lsquic_stream_get_hset (struct lsquic_stream *stream)
|
||||
{
|
||||
void *hset;
|
||||
struct uncompressed_headers *uh;
|
||||
|
||||
if (stream_is_read_reset(stream))
|
||||
{
|
||||
|
@ -4676,9 +4693,14 @@ lsquic_stream_get_hset (struct lsquic_stream *stream)
|
|||
|
||||
hset = stream->uh->uh_hset;
|
||||
stream->uh->uh_hset = NULL;
|
||||
destroy_uh(stream);
|
||||
|
||||
uh = stream->uh;
|
||||
stream->uh = uh->uh_next;
|
||||
free(uh);
|
||||
|
||||
if (stream->stream_flags & STREAM_HEAD_IN_FIN)
|
||||
{
|
||||
|
||||
stream->stream_flags |= STREAM_FIN_REACHED;
|
||||
SM_HISTORY_APPEND(stream, SHE_REACH_FIN);
|
||||
}
|
||||
|
@ -4706,31 +4728,21 @@ static int
|
|||
update_type_hist_and_check (const struct lsquic_stream *stream,
|
||||
struct hq_filter *filter)
|
||||
{
|
||||
/* 3-bit codes: */
|
||||
enum {
|
||||
CODE_UNSET,
|
||||
CODE_HEADER, /* H Header */
|
||||
CODE_DATA, /* D Data */
|
||||
CODE_PLUS, /* + Plus: meaning previous frame repeats */
|
||||
};
|
||||
static const unsigned valid_seqs[] = {
|
||||
/* Ordered by expected frequency */
|
||||
0123, /* HD+ */
|
||||
012, /* HD */
|
||||
01, /* H */
|
||||
013, /* H+ */ /* Really HH, but we don't record it like this */
|
||||
01231, /* HD+H */
|
||||
0121, /* HDH */
|
||||
};
|
||||
unsigned code, i;
|
||||
|
||||
switch (filter->hqfi_type)
|
||||
{
|
||||
case HQFT_HEADERS:
|
||||
code = CODE_HEADER;
|
||||
if (filter->hqfi_flags & HQFI_FLAG_TRAILER)
|
||||
return -1;
|
||||
if (filter->hqfi_flags & HQFI_FLAG_DATA)
|
||||
filter->hqfi_flags |= HQFI_FLAG_TRAILER;
|
||||
else
|
||||
filter->hqfi_flags |= HQFI_FLAG_HEADER;
|
||||
break;
|
||||
case HQFT_DATA:
|
||||
code = CODE_DATA;
|
||||
if ((filter->hqfi_flags & (HQFI_FLAG_HEADER
|
||||
| HQFI_FLAG_TRAILER)) != HQFI_FLAG_HEADER)
|
||||
return -1;
|
||||
filter->hqfi_flags |= HQFI_FLAG_DATA;
|
||||
break;
|
||||
case HQFT_PUSH_PROMISE:
|
||||
/* [draft-ietf-quic-http-24], Section 7 */
|
||||
|
@ -4768,31 +4780,7 @@ update_type_hist_and_check (const struct lsquic_stream *stream,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (filter->hqfi_hist_idx >= MAX_HQFI_ENTRIES)
|
||||
return -1;
|
||||
|
||||
if (filter->hqfi_hist_idx && (filter->hqfi_hist_buf & 7) == code)
|
||||
{
|
||||
filter->hqfi_hist_buf <<= 3;
|
||||
filter->hqfi_hist_buf |= CODE_PLUS;
|
||||
filter->hqfi_hist_idx++;
|
||||
}
|
||||
else if (filter->hqfi_hist_idx > 1
|
||||
&& ((filter->hqfi_hist_buf >> 3) & 7) == code
|
||||
&& (filter->hqfi_hist_buf & 7) == CODE_PLUS)
|
||||
/* Keep it at plus, do nothing */;
|
||||
else
|
||||
{
|
||||
filter->hqfi_hist_buf <<= 3;
|
||||
filter->hqfi_hist_buf |= code;
|
||||
filter->hqfi_hist_idx++;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(valid_seqs) / sizeof(valid_seqs[0]); ++i)
|
||||
if (filter->hqfi_hist_buf == valid_seqs[i])
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -4860,8 +4848,7 @@ hq_read (void *ctx, const unsigned char *buf, size_t sz, int fin)
|
|||
{
|
||||
lconn = stream->conn_pub->lconn;
|
||||
filter->hqfi_flags |= HQFI_FLAG_ERROR;
|
||||
LSQ_INFO("unexpected HTTP/3 frame sequence: %o",
|
||||
filter->hqfi_hist_buf);
|
||||
LSQ_INFO("unexpected HTTP/3 frame sequence");
|
||||
lconn->cn_if->ci_abort_error(lconn, 1, HEC_FRAME_UNEXPECTED,
|
||||
"unexpected HTTP/3 frame sequence on stream %"PRIu64,
|
||||
stream->id);
|
||||
|
|
|
@ -109,6 +109,9 @@ struct hq_filter
|
|||
HQFI_FLAG_ERROR = 1 << 1,
|
||||
HQFI_FLAG_BEGIN = 1 << 2,
|
||||
HQFI_FLAG_BLOCKED = 1 << 3,
|
||||
HQFI_FLAG_HEADER = 1 << 4,
|
||||
HQFI_FLAG_DATA = 1 << 5,
|
||||
HQFI_FLAG_TRAILER = 1 << 6,
|
||||
} hqfi_flags:8;
|
||||
enum {
|
||||
HQFI_STATE_FRAME_HEADER_BEGIN,
|
||||
|
@ -117,9 +120,6 @@ struct hq_filter
|
|||
HQFI_STATE_PUSH_ID_BEGIN,
|
||||
HQFI_STATE_PUSH_ID_CONTINUE,
|
||||
} hqfi_state:8;
|
||||
unsigned char hqfi_hist_idx;
|
||||
#define MAX_HQFI_ENTRIES (sizeof(unsigned) * 8 / 3)
|
||||
unsigned hqfi_hist_buf;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue