mirror of
https://gitea.invidious.io/iv-org/litespeed-quic.git
synced 2024-08-15 00:53:43 +00:00
Release 2.6.3
- [BUGFIX] Close DATA frames with empty payload correctly.
This commit is contained in:
parent
767cf6112c
commit
2f7aa65884
8 changed files with 136 additions and 37 deletions
|
@ -1,3 +1,7 @@
|
||||||
|
2019-11-12
|
||||||
|
- 2.6.3
|
||||||
|
- [BUGFIX] Close DATA frames with empty payload correctly.
|
||||||
|
|
||||||
2019-11-11
|
2019-11-11
|
||||||
- 2.6.2
|
- 2.6.2
|
||||||
- [BUGFIX] SCID!=ODCID rule applies to Retry packets, not regular
|
- [BUGFIX] SCID!=ODCID rule applies to Retry packets, not regular
|
||||||
|
|
|
@ -25,7 +25,7 @@ extern "C" {
|
||||||
|
|
||||||
#define LSQUIC_MAJOR_VERSION 2
|
#define LSQUIC_MAJOR_VERSION 2
|
||||||
#define LSQUIC_MINOR_VERSION 6
|
#define LSQUIC_MINOR_VERSION 6
|
||||||
#define LSQUIC_PATCH_VERSION 2
|
#define LSQUIC_PATCH_VERSION 3
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Engine flags:
|
* Engine flags:
|
||||||
|
|
|
@ -99,9 +99,6 @@ struct enc_session_funcs_common
|
||||||
int
|
int
|
||||||
(*esf_alg_keysize) (enc_session_t *);
|
(*esf_alg_keysize) (enc_session_t *);
|
||||||
|
|
||||||
const char *
|
|
||||||
(*esf_get_sni) (enc_session_t *);
|
|
||||||
|
|
||||||
enum enc_packout
|
enum enc_packout
|
||||||
(*esf_encrypt_packet) (enc_session_t *, const struct lsquic_engine_public *,
|
(*esf_encrypt_packet) (enc_session_t *, const struct lsquic_engine_public *,
|
||||||
struct lsquic_conn *, struct lsquic_packet_out *);
|
struct lsquic_conn *, struct lsquic_packet_out *);
|
||||||
|
|
|
@ -1013,8 +1013,8 @@ iquic_lookup_cert (SSL *ssl, void *arg)
|
||||||
#endif
|
#endif
|
||||||
if (!server_name)
|
if (!server_name)
|
||||||
{
|
{
|
||||||
LSQ_DEBUG("cert lookup: server name is not set, error");
|
LSQ_DEBUG("cert lookup: server name is not set, skip");
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
path = enc_sess->esi_conn->cn_if->ci_get_path(enc_sess->esi_conn, NULL);
|
path = enc_sess->esi_conn->cn_if->ci_get_path(enc_sess->esi_conn, NULL);
|
||||||
|
@ -2048,15 +2048,6 @@ iquic_esf_decrypt_packet (enc_session_t *enc_session_p,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
iquic_esf_get_sni (enc_session_t *enc_session_p)
|
|
||||||
{
|
|
||||||
struct enc_sess_iquic *const enc_sess = enc_session_p;
|
|
||||||
|
|
||||||
return SSL_get_servername(enc_sess->esi_ssl, TLSEXT_NAMETYPE_host_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
iquic_esf_global_init (int flags)
|
iquic_esf_global_init (int flags)
|
||||||
{
|
{
|
||||||
|
@ -2240,7 +2231,6 @@ const struct enc_session_funcs_common lsquic_enc_session_common_ietf_v1 =
|
||||||
.esf_tag_len = IQUIC_TAG_LEN,
|
.esf_tag_len = IQUIC_TAG_LEN,
|
||||||
.esf_get_server_cert_chain
|
.esf_get_server_cert_chain
|
||||||
= iquic_esf_get_server_cert_chain,
|
= iquic_esf_get_server_cert_chain,
|
||||||
.esf_get_sni = iquic_esf_get_sni,
|
|
||||||
.esf_cipher = iquic_esf_cipher,
|
.esf_cipher = iquic_esf_cipher,
|
||||||
.esf_keysize = iquic_esf_keysize,
|
.esf_keysize = iquic_esf_keysize,
|
||||||
.esf_alg_keysize = iquic_esf_alg_keysize,
|
.esf_alg_keysize = iquic_esf_alg_keysize,
|
||||||
|
|
|
@ -5464,6 +5464,11 @@ process_retry_packet (struct ietf_full_conn *conn,
|
||||||
|
|
||||||
if (conn->ifc_flags & (IFC_SERVER|IFC_RETRIED))
|
if (conn->ifc_flags & (IFC_SERVER|IFC_RETRIED))
|
||||||
{
|
{
|
||||||
|
/* [draft-ietf-quic-transport-24] Section 17.2.5:
|
||||||
|
" After the client has received and processed an Initial or Retry
|
||||||
|
" packet from the server, it MUST discard any subsequent Retry
|
||||||
|
" packets that it receives.
|
||||||
|
*/
|
||||||
LSQ_DEBUG("ignore Retry packet");
|
LSQ_DEBUG("ignore Retry packet");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3281,13 +3281,6 @@ set_handshake_completed (struct lsquic_enc_session *enc_session)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const char *
|
|
||||||
lsquic_enc_session_get_sni (enc_session_t *enc_session_p)
|
|
||||||
{
|
|
||||||
struct lsquic_enc_session *const enc_session = enc_session_p;
|
|
||||||
return lsquic_str_cstr(&enc_session->hs_ctx.sni);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
static uint8_t
|
static uint8_t
|
||||||
|
@ -3631,7 +3624,6 @@ struct enc_session_funcs_common lsquic_enc_session_common_gquic_1 =
|
||||||
.esf_cipher = lsquic_enc_session_cipher,
|
.esf_cipher = lsquic_enc_session_cipher,
|
||||||
.esf_keysize = lsquic_enc_session_keysize,
|
.esf_keysize = lsquic_enc_session_keysize,
|
||||||
.esf_alg_keysize = lsquic_enc_session_alg_keysize,
|
.esf_alg_keysize = lsquic_enc_session_alg_keysize,
|
||||||
.esf_get_sni = lsquic_enc_session_get_sni,
|
|
||||||
.esf_encrypt_packet = gquic_encrypt_packet,
|
.esf_encrypt_packet = gquic_encrypt_packet,
|
||||||
.esf_decrypt_packet = gquic_decrypt_packet,
|
.esf_decrypt_packet = gquic_decrypt_packet,
|
||||||
.esf_tag_len = GQUIC_PACKET_HASH_SZ,
|
.esf_tag_len = GQUIC_PACKET_HASH_SZ,
|
||||||
|
|
|
@ -2536,7 +2536,6 @@ open_hq_frame (struct lsquic_stream *stream)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Returns index of the new frame */
|
|
||||||
static struct stream_hq_frame *
|
static struct stream_hq_frame *
|
||||||
stream_activate_hq_frame (struct lsquic_stream *stream, uint64_t off,
|
stream_activate_hq_frame (struct lsquic_stream *stream, uint64_t off,
|
||||||
enum hq_frame_type frame_type, enum shf_flags flags, size_t size)
|
enum hq_frame_type frame_type, enum shf_flags flags, size_t size)
|
||||||
|
@ -2915,7 +2914,7 @@ maybe_close_varsize_hq_frame (struct lsquic_stream *stream)
|
||||||
|
|
||||||
bits = (shf->shf_flags & SHF_TWO_BYTES) > 0;
|
bits = (shf->shf_flags & SHF_TWO_BYTES) > 0;
|
||||||
size = stream->sm_payload + stream->sm_n_buffered - shf->shf_off;
|
size = stream->sm_payload + stream->sm_n_buffered - shf->shf_off;
|
||||||
if (size && size <= VINT_MAX_B(bits) && shf->shf_frame_ptr)
|
if (size <= VINT_MAX_B(bits) && shf->shf_frame_ptr)
|
||||||
{
|
{
|
||||||
if (0 == stream->sm_n_buffered)
|
if (0 == stream->sm_n_buffered)
|
||||||
LSQ_DEBUG("close HQ frame type 0x%X of size %"PRIu64,
|
LSQ_DEBUG("close HQ frame type 0x%X of size %"PRIu64,
|
||||||
|
@ -2935,23 +2934,18 @@ maybe_close_varsize_hq_frame (struct lsquic_stream *stream)
|
||||||
}
|
}
|
||||||
else if (!shf->shf_frame_ptr)
|
else if (!shf->shf_frame_ptr)
|
||||||
{
|
{
|
||||||
LSQ_WARN("dangling HTTP/3 frame");
|
LSQ_ERROR("dangling HTTP/3 frame, on stream %"PRIu64, stream->id);
|
||||||
stream->conn_pub->lconn->cn_if->ci_internal_error(
|
stream->conn_pub->lconn->cn_if->ci_internal_error(
|
||||||
stream->conn_pub->lconn, "dangling HTTP/3 frame on stream %"PRIu64,
|
stream->conn_pub->lconn, "dangling HTTP/3 frame");
|
||||||
stream->id);
|
|
||||||
stream_hq_frame_put(stream, shf);
|
|
||||||
}
|
|
||||||
else if (!size)
|
|
||||||
{
|
|
||||||
LSQ_WARN("discard zero-sized HQ frame type 0x%X (off: %"PRIu64")",
|
|
||||||
shf->shf_frame_type, shf->shf_off);
|
|
||||||
stream_hq_frame_put(stream, shf);
|
stream_hq_frame_put(stream, shf);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(stream->sm_n_buffered);
|
assert(stream->sm_n_buffered);
|
||||||
LSQ_ERROR("cannot close frame of size %"PRIu64" -- too large", size);
|
LSQ_ERROR("cannot close frame of size %"PRIu64" on stream %"PRIu64
|
||||||
/* TODO: abort connection */
|
" -- too large", size, stream->id);
|
||||||
|
stream->conn_pub->lconn->cn_if->ci_internal_error(
|
||||||
|
stream->conn_pub->lconn, "HTTP/3 frame too large");
|
||||||
stream_hq_frame_put(stream, shf);
|
stream_hq_frame_put(stream, shf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -755,6 +755,122 @@ test_frame_header_split (unsigned n_packets)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_zero_size_frame (void)
|
||||||
|
{
|
||||||
|
struct test_objs tobjs;
|
||||||
|
struct lsquic_stream *stream;
|
||||||
|
ssize_t w;
|
||||||
|
size_t nw;
|
||||||
|
int fin, s;
|
||||||
|
unsigned char *buf_in, *buf_out;
|
||||||
|
const unsigned wsize = 7000;
|
||||||
|
const size_t buf_in_sz = wsize, buf_out_sz = 0x500000;
|
||||||
|
|
||||||
|
struct lsquic_http_header header = {
|
||||||
|
.name = { ":method", 7, },
|
||||||
|
.value = { "GET", 3, },
|
||||||
|
};
|
||||||
|
struct lsquic_http_headers headers = { 1, &header, };
|
||||||
|
|
||||||
|
buf_in = malloc(buf_in_sz);
|
||||||
|
buf_out = malloc(buf_out_sz);
|
||||||
|
assert(buf_in && buf_out);
|
||||||
|
|
||||||
|
struct packetization_test_stream_ctx packet_stream_ctx =
|
||||||
|
{
|
||||||
|
.buf = buf_in,
|
||||||
|
.off = 0,
|
||||||
|
.len = buf_in_sz,
|
||||||
|
.write_size = wsize,
|
||||||
|
.flush_after_each_write = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
init_buf(buf_in, buf_in_sz);
|
||||||
|
|
||||||
|
init_test_ctl_settings(&g_ctl_settings);
|
||||||
|
g_ctl_settings.tcs_schedule_stream_packets_immediately = 1;
|
||||||
|
|
||||||
|
stream_ctor_flags |= SCF_IETF;
|
||||||
|
init_test_objs(&tobjs, 0x1000, buf_out_sz, 1252);
|
||||||
|
tobjs.stream_if_ctx = &packet_stream_ctx;
|
||||||
|
tobjs.ctor_flags |= SCF_HTTP|SCF_IETF;
|
||||||
|
|
||||||
|
g_ctl_settings.tcs_can_send = 1;
|
||||||
|
tobjs.stream_if = &packetization_inside_once_stream_if;
|
||||||
|
tobjs.ctor_flags |= SCF_DISP_RW_ONCE;
|
||||||
|
|
||||||
|
struct lsquic_packet_out *const packet_out
|
||||||
|
= lsquic_send_ctl_new_packet_out(&tobjs.send_ctl, 0, PNS_APP, &network_path);
|
||||||
|
assert(packet_out);
|
||||||
|
const size_t pad_size = packet_out->po_n_alloc
|
||||||
|
- 2 /* STREAM header */
|
||||||
|
- 5 /* 3-byte HEADERS frame */
|
||||||
|
- 3;
|
||||||
|
packet_out->po_data_sz = pad_size;
|
||||||
|
lsquic_send_ctl_scheduled_one(&tobjs.send_ctl, packet_out);
|
||||||
|
|
||||||
|
stream = new_stream(&tobjs, 0, buf_out_sz);
|
||||||
|
|
||||||
|
s = lsquic_stream_send_headers(stream, &headers, 0);
|
||||||
|
assert(0 == s);
|
||||||
|
|
||||||
|
w = lsquic_stream_write(stream, buf_in, buf_in_sz);
|
||||||
|
assert(w >= 0);
|
||||||
|
lsquic_stream_flush(stream);
|
||||||
|
|
||||||
|
g_ctl_settings.tcs_can_send++;
|
||||||
|
w = lsquic_stream_write(stream, buf_in, buf_in_sz);
|
||||||
|
assert(w >= 0);
|
||||||
|
lsquic_stream_flush(stream);
|
||||||
|
|
||||||
|
/* Verify written data: */
|
||||||
|
nw = read_from_scheduled_packets(&tobjs.send_ctl, 0, buf_out, buf_out_sz,
|
||||||
|
0, &fin, 1);
|
||||||
|
{ /* Remove framing and verify contents */
|
||||||
|
const unsigned char *src;
|
||||||
|
unsigned char *dst;
|
||||||
|
uint64_t sz;
|
||||||
|
unsigned frame_type;
|
||||||
|
int s;
|
||||||
|
|
||||||
|
src = buf_out;
|
||||||
|
dst = buf_out;
|
||||||
|
while (src < buf_out + nw)
|
||||||
|
{
|
||||||
|
frame_type = *src++;
|
||||||
|
s = vint_read(src, buf_out + buf_out_sz, &sz);
|
||||||
|
assert(s > 0);
|
||||||
|
assert(sz < (1 << 14));
|
||||||
|
src += s;
|
||||||
|
if (src == buf_out + s + 1)
|
||||||
|
{
|
||||||
|
/* Ignore headers */
|
||||||
|
assert(frame_type == HQFT_HEADERS);
|
||||||
|
src += sz;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(frame_type == HQFT_DATA);
|
||||||
|
if (src + sz > buf_out + nw) /* Chopped DATA frame (last) */
|
||||||
|
sz = buf_out + nw - src;
|
||||||
|
memmove(dst, src, sz);
|
||||||
|
dst += sz;
|
||||||
|
src += sz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(0 == memcmp(buf_in, buf_out, (uintptr_t) dst - (uintptr_t) buf_out));
|
||||||
|
}
|
||||||
|
|
||||||
|
lsquic_stream_destroy(stream);
|
||||||
|
deinit_test_objs(&tobjs);
|
||||||
|
free(buf_in);
|
||||||
|
free(buf_out);
|
||||||
|
|
||||||
|
stream_ctor_flags &= ~SCF_IETF;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
|
@ -781,6 +897,7 @@ main (int argc, char **argv)
|
||||||
main_test_hq_framing();
|
main_test_hq_framing();
|
||||||
test_frame_header_split(1);
|
test_frame_header_split(1);
|
||||||
test_frame_header_split(2);
|
test_frame_header_split(2);
|
||||||
|
test_zero_size_frame();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue