Release 4.0.2

This commit is contained in:
George Wang 2023-12-19 22:48:06 -05:00
parent b81a3fb15f
commit a18ccca39e
20 changed files with 116 additions and 78 deletions

View file

@ -1,3 +1,10 @@
2023-12-19
- 4.0.2
- More strict RFC compliance.
- Minimize packet generated when send STREAM_BLOCKED frame
- Fix memory management bugs.
- Fix memory leak in unit tests.
2023-05-14 2023-05-14
- 4.0.1 - 4.0.1
- Fix send_ctl bug. - Fix send_ctl bug.

View file

@ -272,7 +272,8 @@ ENDIF()
SET(LIBS lsquic ${BORINGSSL_LIB_ssl} ${BORINGSSL_LIB_crypto} ${ZLIB_LIB} ${LIBS}) SET(LIBS lsquic ${BORINGSSL_LIB_ssl} ${BORINGSSL_LIB_crypto} ${ZLIB_LIB} ${LIBS})
IF (LSQUIC_BIN) IF (LSQUIC_BIN)
FIND_PATH(EVENT_INCLUDE_DIR NAMES event2/event.h) FIND_PATH(EVENT_INCLUDE_DIR NAMES event2/event.h
PATHS ${PROJECT_SOURCE_DIR}/../third-party/include)
IF (EVENT_INCLUDE_DIR) IF (EVENT_INCLUDE_DIR)
INCLUDE_DIRECTORIES(${EVENT_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${EVENT_INCLUDE_DIR})
ELSE() ELSE()
@ -285,7 +286,8 @@ IF (LSQUIC_BIN)
IF (CMAKE_SYSTEM_NAME STREQUAL Windows) IF (CMAKE_SYSTEM_NAME STREQUAL Windows)
FIND_LIBRARY(EVENT_LIB event) FIND_LIBRARY(EVENT_LIB event)
ELSE() ELSE()
FIND_LIBRARY(EVENT_LIB libevent${LIB_SUFFIX}) FIND_LIBRARY(EVENT_LIB libevent${LIB_SUFFIX}
PATHS ${PROJECT_SOURCE_DIR}/../third-party/lib)
IF(NOT EVENT_LIB) IF(NOT EVENT_LIB)
FIND_LIBRARY(EVENT_LIB libevent.so) FIND_LIBRARY(EVENT_LIB libevent.so)
ENDIF() ENDIF()

View file

@ -348,7 +348,10 @@ http_client_on_conn_closed (lsquic_conn_t *conn)
if (conn_h->client_ctx->hcc_flags & HCC_ABORT_ON_INCOMPLETE) if (conn_h->client_ctx->hcc_flags & HCC_ABORT_ON_INCOMPLETE)
{ {
if (!(conn_h->client_ctx->hcc_flags & HCC_SEEN_FIN)) if (!(conn_h->client_ctx->hcc_flags & HCC_SEEN_FIN))
abort(); {
LSQ_INFO("abort incomplete connection");
exit(1);
}
} }
--conn_h->client_ctx->hcc_n_open_conns; --conn_h->client_ctx->hcc_n_open_conns;

View file

@ -26,7 +26,7 @@ author = u'LiteSpeed Technologies'
# The short X.Y version # The short X.Y version
version = u'4.0' version = u'4.0'
# The full version, including alpha/beta/rc tags # The full version, including alpha/beta/rc tags
release = u'4.0.1' release = u'4.0.2'
# -- General configuration --------------------------------------------------- # -- General configuration ---------------------------------------------------

View file

@ -27,7 +27,7 @@ extern "C" {
#define LSQUIC_MAJOR_VERSION 4 #define LSQUIC_MAJOR_VERSION 4
#define LSQUIC_MINOR_VERSION 0 #define LSQUIC_MINOR_VERSION 0
#define LSQUIC_PATCH_VERSION 1 #define LSQUIC_PATCH_VERSION 2
/** /**
* Engine flags: * Engine flags:

@ -1 +1 @@
Subproject commit 19863c2ed8bf28d648213460093d1991def4e643 Subproject commit 521792711f2839f05565fd3dd617708cfb5b80ee

View file

@ -438,7 +438,8 @@ hash_di_insert_frame (struct data_in *data_in,
ins = lsquic_data_in_hash_insert_data_frame(data_in, data_frame, ins = lsquic_data_in_hash_insert_data_frame(data_in, data_frame,
read_offset); read_offset);
assert(ins != INS_FRAME_OVERLAP); assert(ins != INS_FRAME_OVERLAP);
/* NOTE: other cases are handled by caller */ /* NOTE: Only release packet and frame for INS_FRAME_OK,
* other cases are handled by caller */
if (ins == INS_FRAME_OK) if (ins == INS_FRAME_OK)
{ {
lsquic_packet_in_put(hdi->hdi_conn_pub->mm, new_frame->packet_in); lsquic_packet_in_put(hdi->hdi_conn_pub->mm, new_frame->packet_in);

View file

@ -3232,6 +3232,7 @@ lsquic_engine_packet_in (lsquic_engine_t *engine,
* by PI_OWN_DATA flag. * by PI_OWN_DATA flag.
*/ */
packet_in->pi_data = (unsigned char *) packet_in_data; packet_in->pi_data = (unsigned char *) packet_in_data;
packet_in->pi_pkt_size = packet_in_size;
if (0 != parse_packet_in_begin(packet_in, packet_end - packet_in_data, if (0 != parse_packet_in_begin(packet_in, packet_end - packet_in_data,
engine->flags & ENG_SERVER, engine->flags & ENG_SERVER,
engine->pub.enp_settings.es_scid_len, &ppstate)) engine->pub.enp_settings.es_scid_len, &ppstate))

View file

@ -2491,46 +2491,6 @@ generate_max_stream_data_frame (struct ietf_full_conn *conn,
} }
/* Return true if generated, false otherwise */
static int
generate_stream_blocked_frame (struct ietf_full_conn *conn,
struct lsquic_stream *stream)
{
struct lsquic_packet_out *packet_out;
unsigned need;
uint64_t off;
int sz;
off = lsquic_stream_combined_send_off(stream);
need = conn->ifc_conn.cn_pf->pf_stream_blocked_frame_size(stream->id, off);
packet_out = get_writeable_packet(conn, need);
if (!packet_out)
return 0;
sz = conn->ifc_conn.cn_pf->pf_gen_stream_blocked_frame(
packet_out->po_data + packet_out->po_data_sz,
lsquic_packet_out_avail(packet_out), stream->id, off);
if (sz < 0)
{
ABORT_ERROR("Generating STREAM_BLOCKED frame failed");
return 0;
}
LSQ_DEBUG("generated %d-byte STREAM_BLOCKED "
"frame; stream_id: %"PRIu64"; offset: %"PRIu64, sz, stream->id, off);
EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "generated %d-byte STREAM_BLOCKED "
"frame; stream_id: %"PRIu64"; offset: %"PRIu64, sz, stream->id, off);
if (0 != lsquic_packet_out_add_frame(packet_out, conn->ifc_pub.mm, 0,
QUIC_FRAME_STREAM_BLOCKED, packet_out->po_data_sz, sz))
{
ABORT_ERROR("adding frame to packet failed: %d", errno);
return 0;
}
lsquic_send_ctl_incr_pack_sz(&conn->ifc_send_ctl, packet_out, sz);
packet_out->po_frame_types |= 1 << QUIC_FRAME_STREAM_BLOCKED;
lsquic_stream_blocked_frame_sent(stream);
return 1;
}
static int static int
generate_stop_sending_frame_by_id (struct ietf_full_conn *conn, generate_stop_sending_frame_by_id (struct ietf_full_conn *conn,
lsquic_stream_id_t stream_id, enum http_error_code error_code) lsquic_stream_id_t stream_id, enum http_error_code error_code)
@ -2918,7 +2878,7 @@ process_stream_ready_to_send (struct ietf_full_conn *conn,
if (stream->sm_qflags & SMQF_SEND_MAX_STREAM_DATA) if (stream->sm_qflags & SMQF_SEND_MAX_STREAM_DATA)
r &= generate_max_stream_data_frame(conn, stream); r &= generate_max_stream_data_frame(conn, stream);
if (stream->sm_qflags & SMQF_SEND_BLOCKED) if (stream->sm_qflags & SMQF_SEND_BLOCKED)
r &= generate_stream_blocked_frame(conn, stream); r &= lsquic_sendctl_gen_stream_blocked_frame(&conn->ifc_send_ctl, stream);
if (stream->sm_qflags & SMQF_SEND_RST) if (stream->sm_qflags & SMQF_SEND_RST)
r &= generate_rst_stream_frame(conn, stream); r &= generate_rst_stream_frame(conn, stream);
if (stream->sm_qflags & SMQF_SEND_STOP_SENDING) if (stream->sm_qflags & SMQF_SEND_STOP_SENDING)

View file

@ -734,7 +734,7 @@ ietf_mini_conn_ci_hsk_done (struct lsquic_conn *lconn,
{ {
case LSQ_HSK_OK: case LSQ_HSK_OK:
case LSQ_HSK_RESUMED_OK: case LSQ_HSK_RESUMED_OK:
conn->imc_flags |= IMC_HSK_OK; conn->imc_flags |= IMC_HSK_OK | IMC_IGNORE_INIT;
conn->imc_conn.cn_flags |= LSCONN_HANDSHAKE_DONE; conn->imc_conn.cn_flags |= LSCONN_HANDSHAKE_DONE;
LSQ_DEBUG("handshake OK"); LSQ_DEBUG("handshake OK");
break; break;
@ -1436,6 +1436,14 @@ imico_parse_regular_packet (struct ietf_mini_conn *conn,
p = packet_in->pi_data + packet_in->pi_header_sz; p = packet_in->pi_data + packet_in->pi_header_sz;
pend = packet_in->pi_data + packet_in->pi_data_sz; pend = packet_in->pi_data + packet_in->pi_data_sz;
if (p >= pend)
{
ietf_mini_conn_ci_abort_error(&conn->imc_conn, 0,
TEC_PROTOCOL_VIOLATION,
"packet %"PRIu64" has no frames",
packet_in->pi_packno);
return -1;
}
while (p < pend) while (p < pend)
{ {
len = imico_process_packet_frame(conn, packet_in, p, pend - p); len = imico_process_packet_frame(conn, packet_in, p, pend - p);
@ -1677,10 +1685,20 @@ ietf_mini_conn_ci_packet_in (struct lsquic_conn *lconn,
imico_maybe_validate_by_dcid(conn, &packet_in->pi_dcid); imico_maybe_validate_by_dcid(conn, &packet_in->pi_dcid);
pns = lsquic_hety2pns[ packet_in->pi_header_type ]; pns = lsquic_hety2pns[ packet_in->pi_header_type ];
if (pns == PNS_INIT && (conn->imc_flags & IMC_IGNORE_INIT)) if (pns == PNS_INIT)
{ {
LSQ_DEBUG("ignore init packet"); /* Don't bother decrypting */ if (conn->imc_flags & IMC_IGNORE_INIT)
return; {
LSQ_DEBUG("ignore init packet"); /* Don't bother decrypting */
return;
}
if (packet_in->pi_pkt_size
&& packet_in->pi_pkt_size < IQUIC_MIN_INIT_PACKET_SZ)
{
LSQ_DEBUG("ignore init packet smaller than minimum size required");
/* Don't bother decrypting */
return;
}
} }
dec_packin = lconn->cn_esf_c->esf_decrypt_packet(lconn->cn_enc_session, dec_packin = lconn->cn_esf_c->esf_decrypt_packet(lconn->cn_enc_session,
@ -1718,7 +1736,15 @@ ietf_mini_conn_ci_packet_in (struct lsquic_conn *lconn,
return; return;
} }
else if (pns == PNS_HSK) else if (pns == PNS_HSK)
{
if (!LSQUIC_CIDS_EQ(CN_SCID(&conn->imc_conn), &packet_in->pi_dcid))
{
ietf_mini_conn_ci_abort_error(lconn, 0, TEC_PROTOCOL_VIOLATION,
"protocol violation detected bad dcid for HSK pns");
return;
}
imico_peer_addr_validated(conn, "handshake PNS"); imico_peer_addr_validated(conn, "handshake PNS");
}
if (((conn->imc_flags >> IMCBIT_PNS_BIT_SHIFT) & 3) < pns) if (((conn->imc_flags >> IMCBIT_PNS_BIT_SHIFT) & 3) < pns)
{ {

View file

@ -364,6 +364,7 @@ maybe_shrink_packet_out_bufs (struct lsquic_mm *mm, unsigned idx)
#endif #endif
#if LSQUIC_USE_POOLS
/* If average maximum falls under 1/4 of all objects allocated, release /* If average maximum falls under 1/4 of all objects allocated, release
* half of the objects allocated. * half of the objects allocated.
*/ */
@ -398,6 +399,7 @@ maybe_shrink_packet_in_bufs (struct lsquic_mm *mm, unsigned idx)
} }
#endif #endif
} }
#endif
void void

View file

@ -148,28 +148,16 @@ lsquic_frame_types_to_str (char *buf, size_t bufsz, enum quic_ft_bit);
enum packno_bits enum packno_bits
{ {
PACKNO_BITS_0 = 0, PACKNO_BITS_0 = 0,
PACKNO_BITS_1 = 1,
PACKNO_BITS_2 = 2,
PACKNO_BITS_3 = 3,
};
/* GQUIC maps 0, 1, 2, 3 -> 1, 2, 4, 6 */
enum
{
GQUIC_PACKNO_LEN_1 = PACKNO_BITS_0, GQUIC_PACKNO_LEN_1 = PACKNO_BITS_0,
GQUIC_PACKNO_LEN_2 = PACKNO_BITS_1,
GQUIC_PACKNO_LEN_4 = PACKNO_BITS_2,
GQUIC_PACKNO_LEN_6 = PACKNO_BITS_3,
};
/* IQUIC maps 0, 1, 2, 3 -> 1, 2, 3, 4 (as of ID-17) */
enum
{
IQUIC_PACKNO_LEN_1 = PACKNO_BITS_0, IQUIC_PACKNO_LEN_1 = PACKNO_BITS_0,
PACKNO_BITS_1 = 1,
GQUIC_PACKNO_LEN_2 = PACKNO_BITS_1,
IQUIC_PACKNO_LEN_2 = PACKNO_BITS_1, IQUIC_PACKNO_LEN_2 = PACKNO_BITS_1,
PACKNO_BITS_2 = 2,
GQUIC_PACKNO_LEN_4 = PACKNO_BITS_2,
IQUIC_PACKNO_LEN_3 = PACKNO_BITS_2, IQUIC_PACKNO_LEN_3 = PACKNO_BITS_2,
PACKNO_BITS_3 = 3,
GQUIC_PACKNO_LEN_6 = PACKNO_BITS_3,
IQUIC_PACKNO_LEN_4 = PACKNO_BITS_3, IQUIC_PACKNO_LEN_4 = PACKNO_BITS_3,
}; };

View file

@ -93,6 +93,7 @@ typedef struct lsquic_packet_in
} pi_flags; } pi_flags;
/* pi_token and pi_token_size are set in Initial and Retry packets */ /* pi_token and pi_token_size are set in Initial and Retry packets */
unsigned short pi_token_size; /* Size of the token */ unsigned short pi_token_size; /* Size of the token */
unsigned short pi_pkt_size; /* Size of the whole packet */
unsigned char pi_token; /* Offset to token */ unsigned char pi_token; /* Offset to token */
/* pi_odcid and pi_odcid_len are only set in Retry packets for I-D < 25 */ /* pi_odcid and pi_odcid_len are only set in Retry packets for I-D < 25 */
unsigned char pi_odcid; /* Offset to Original DCID */ unsigned char pi_odcid; /* Offset to Original DCID */

View file

@ -2132,7 +2132,7 @@ lsquic_send_ctl_next_packet_to_send (struct lsquic_send_ctl *ctl,
else else
packet_out->po_lflags &= ~POL_LIMITED; packet_out->po_lflags &= ~POL_LIMITED;
if (UNLIKELY(!(ctl->sc_conn_pub->lconn->cn_flags & LSCONN_HANDSHAKE_DONE)) if (UNLIKELY(packet_out->po_header_type == HETY_INITIAL)
&& (!(ctl->sc_conn_pub->lconn->cn_flags & LSCONN_SERVER) && (!(ctl->sc_conn_pub->lconn->cn_flags & LSCONN_SERVER)
|| (packet_out->po_frame_types || (packet_out->po_frame_types
& IQUIC_FRAME_ACKABLE_MASK)) & IQUIC_FRAME_ACKABLE_MASK))
@ -2966,6 +2966,42 @@ lsquic_send_ctl_get_packet_for_stream (lsquic_send_ctl_t *ctl,
} }
/* Return true if generated, false otherwise */
int
lsquic_sendctl_gen_stream_blocked_frame (struct lsquic_send_ctl *ctl,
struct lsquic_stream *stream)
{
struct lsquic_packet_out *packet_out;
const struct parse_funcs *const pf = stream->conn_pub->lconn->cn_pf;
unsigned need;
uint64_t off;
int sz;
off = lsquic_stream_combined_send_off(stream);
need = pf->pf_stream_blocked_frame_size(stream->id, off);
packet_out = lsquic_send_ctl_get_packet_for_stream(ctl, need,
stream->conn_pub->path, stream);
if (!packet_out)
return 0;
sz = pf->pf_gen_stream_blocked_frame(
packet_out->po_data + packet_out->po_data_sz,
lsquic_packet_out_avail(packet_out), stream->id, off);
if (sz < 0)
return 0;
LSQ_DEBUG("generated %d-byte STREAM_BLOCKED "
"frame; stream_id: %"PRIu64"; offset: %"PRIu64, sz, stream->id, off);
EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "generated %d-byte STREAM_BLOCKED "
"frame; stream_id: %"PRIu64"; offset: %"PRIu64, sz, stream->id, off);
if (0 != lsquic_packet_out_add_frame(packet_out, &ctl->sc_enpub->enp_mm, 0,
QUIC_FRAME_STREAM_BLOCKED, packet_out->po_data_sz, sz))
return 0;
lsquic_send_ctl_incr_pack_sz(ctl, packet_out, sz);
packet_out->po_frame_types |= 1 << QUIC_FRAME_STREAM_BLOCKED;
lsquic_stream_blocked_frame_sent(stream);
return 1;
}
#ifdef NDEBUG #ifdef NDEBUG
static static
#elif __GNUC__ #elif __GNUC__
@ -3775,9 +3811,9 @@ lsquic_send_ctl_resize (struct lsquic_send_ctl *ctl)
size = lsquic_packet_out_total_sz(lconn, packet_out); size = lsquic_packet_out_total_sz(lconn, packet_out);
if (size > packet_out->po_path->np_pack_size) if (size > packet_out->po_path->np_pack_size)
{ {
send_ctl_resize_q(ctl, *q, packet_out->po_path);
path_ids |= 1 << packet_out->po_path->np_path_id; path_ids |= 1 << packet_out->po_path->np_path_id;
q_idxs |= 1 << (q - queues); q_idxs |= 1 << (q - queues);
send_ctl_resize_q(ctl, *q, packet_out->po_path);
goto redo_q; goto redo_q;
} }
} }

View file

@ -236,6 +236,10 @@ lsquic_send_ctl_get_packet_for_stream (lsquic_send_ctl_t *,
unsigned need_at_least, const struct network_path *, unsigned need_at_least, const struct network_path *,
const struct lsquic_stream *); const struct lsquic_stream *);
int
lsquic_sendctl_gen_stream_blocked_frame (struct lsquic_send_ctl *ctl,
struct lsquic_stream *stream);
struct lsquic_packet_out * struct lsquic_packet_out *
lsquic_send_ctl_get_packet_for_crypto (struct lsquic_send_ctl *ctl, lsquic_send_ctl_get_packet_for_crypto (struct lsquic_send_ctl *ctl,
unsigned need_at_least, enum packnum_space, const struct network_path *); unsigned need_at_least, enum packnum_space, const struct network_path *);

View file

@ -3695,10 +3695,15 @@ stream_write (lsquic_stream_t *stream, struct lsquic_reader *reader,
} }
while (nwritten < len while (nwritten < len
&& stream->sm_n_buffered < stream->sm_n_allocated); && stream->sm_n_buffered < stream->sm_n_allocated);
return nwritten;
} }
else else
return stream_write_to_packets(stream, reader, thresh, swo); nwritten = stream_write_to_packets(stream, reader, thresh, swo);
if ((stream->sm_qflags & SMQF_SEND_BLOCKED) &&
(stream->sm_bflags & SMBF_IETF))
{
lsquic_sendctl_gen_stream_blocked_frame(stream->conn_pub->send_ctl, stream);
}
return nwritten;
} }

@ -1 +1 @@
Subproject commit df068e6feec3268a32a1edbbec4a4636d200ee90 Subproject commit 32e96f10593c7cb8553cd8c9c12721100ae9e924

View file

@ -1134,8 +1134,9 @@ test_one_frt (const struct frame_reader_test *frt)
stream.conn_pub = &conn_pub; stream.conn_pub = &conn_pub;
conn_pub.lconn = &lconn; conn_pub.lconn = &lconn;
top:
lsquic_mm_init(&mm); lsquic_mm_init(&mm);
top:
lshpack_dec_init(&hdec); lshpack_dec_init(&hdec);
memset(&input, 0, sizeof(input)); memset(&input, 0, sizeof(input));
memcpy(input.in_buf, frt->frt_buf, frt->frt_bufsz); memcpy(input.in_buf, frt->frt_buf, frt->frt_bufsz);

View file

@ -376,7 +376,7 @@ init_test_objs (struct test_objs *tobjs, unsigned initial_conn_window,
tobjs->stream_if = &stream_if; tobjs->stream_if = &stream_if;
tobjs->stream_if_ctx = &test_ctx; tobjs->stream_if_ctx = &test_ctx;
tobjs->ctor_flags = stream_ctor_flags; tobjs->ctor_flags = stream_ctor_flags;
if ((1 << tobjs->lconn.cn_version) & LSQUIC_IETF_VERSIONS) //if ((1 << tobjs->lconn.cn_version) & LSQUIC_IETF_VERSIONS)
{ {
lsquic_qeh_init(&tobjs->qeh, &tobjs->lconn); lsquic_qeh_init(&tobjs->qeh, &tobjs->lconn);
s = lsquic_qeh_settings(&tobjs->qeh, 0, 0, 0, 0); s = lsquic_qeh_settings(&tobjs->qeh, 0, 0, 0, 0);
@ -395,7 +395,7 @@ deinit_test_objs (struct test_objs *tobjs)
lsquic_send_ctl_cleanup(&tobjs->send_ctl); lsquic_send_ctl_cleanup(&tobjs->send_ctl);
lsquic_malo_destroy(tobjs->conn_pub.packet_out_malo); lsquic_malo_destroy(tobjs->conn_pub.packet_out_malo);
lsquic_mm_cleanup(&tobjs->eng_pub.enp_mm); lsquic_mm_cleanup(&tobjs->eng_pub.enp_mm);
if ((1 << tobjs->lconn.cn_version) & LSQUIC_IETF_VERSIONS) //if ((1 << tobjs->lconn.cn_version) & LSQUIC_IETF_VERSIONS)
lsquic_qeh_cleanup(&tobjs->qeh); lsquic_qeh_cleanup(&tobjs->qeh);
} }

View file

@ -35,6 +35,7 @@ main (int argc, char **argv)
printf("\n"); printf("\n");
lsquic_tg_destroy(tg); lsquic_tg_destroy(tg);
lsquic_stock_shared_hash_destroy(enpub.enp_shi_ctx);
return 0; return 0;
} }