Release 2.7.2

- [BUGFIX] Send controller: update scheduled bytes when DCID length
  changes (IETF client).
- [BUGFIX] Drop alarm check from sanity test.  It no longer works now
  that we use loss chains.
- [PORTABILITY] Fix build on Alpine Linux.
- [PORTABILITY] Fix build using XCode.
- Client initial DCID length: use RAND_bytes() instead of rand(3).
- Add unit tests for connection min heap.
- [DEBUG] Log CID in gQUIC handshake module
- [DEBUG] Turn on extra checks for IETF client send controller.
- [DEBUG] Dedup next advisory tick messages when reason is IDLE timer.
- [DEBUG] QPACK decoder handler: log header error code.
This commit is contained in:
Dmitri Tikhonov 2019-12-11 09:38:58 -05:00
parent d6937ddce0
commit a137764bf2
22 changed files with 369 additions and 76 deletions

View File

@ -1,3 +1,18 @@
2019-12-11
- 2.7.2
- [BUGFIX] Send controller: update scheduled bytes when DCID length
changes (IETF client).
- [BUGFIX] Drop alarm check from sanity test. It no longer works now
that we use loss chains.
- [PORTABILITY] Fix build on Alpine Linux.
- [PORTABILITY] Fix build using XCode.
- Client initial DCID length: use RAND_bytes() instead of rand(3).
- Add unit tests for connection min heap.
- [DEBUG] Log CID in gQUIC handshake module
- [DEBUG] Turn on extra checks for IETF client send controller.
- [DEBUG] Dedup next advisory tick messages when reason is IDLE timer.
- [DEBUG] QPACK decoder handler: log header error code.
2019-12-05
- 2.7.1
- [BUGFIX] client: don't call ignore_init() in middle of batch send.

View File

@ -7,6 +7,8 @@ to the LiteSpeed Client Library:
- Alexis La Goutte -- Travis-CI integration
- Bernhard Jaeger -- DNS Resolution
- Zhang Chi -- libevent build fix on Darwin
- Omar Roth -- Alpine Linux build and Crystal language bindings
- initlife (?) -- XCode build
Thank you!

View File

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

View File

@ -3,7 +3,6 @@
#include <inttypes.h>
#include <string.h>
#include <sys/queue.h>
#include <stdlib.h>
#include <openssl/rand.h>
@ -238,8 +237,12 @@ void
lsquic_generate_cid (lsquic_cid_t *cid, size_t len)
{
if (!len)
{
/* If not set, generate ID between 8 and MAX_CID_LEN bytes in length */
len = 8 + rand() % (MAX_CID_LEN - 7);
RAND_bytes((uint8_t *) &len, sizeof(len));
len %= MAX_CID_LEN - 7;
len += 8;
}
RAND_bytes(cid->idbuf, len);
cid->len = len;
}

View File

@ -99,6 +99,9 @@ struct enc_session_funcs_common
int
(*esf_alg_keysize) (enc_session_t *);
/* Need to pass lconn in encrypt and decrypt methods because enc_session
* is allowed to be NULL for gQUIC.
*/
enum enc_packout
(*esf_encrypt_packet) (enc_session_t *, const struct lsquic_engine_public *,
struct lsquic_conn *, struct lsquic_packet_out *);
@ -119,6 +122,9 @@ struct enc_session_funcs_common
int
(*esf_is_zero_rtt_enabled) (enc_session_t *);
void
(*esf_set_conn) (enc_session_t *, struct lsquic_conn *);
unsigned
esf_tag_len;
};
@ -147,7 +153,8 @@ struct enc_session_funcs_gquic
/* Create server session */
enc_session_t *
(*esf_create_server) (lsquic_cid_t cid, const struct lsquic_engine_public *);
(*esf_create_server) (struct lsquic_conn *,
lsquic_cid_t cid, const struct lsquic_engine_public *);
/* out_len should have init value as the max length of out */
enum handshake_error
@ -208,7 +215,8 @@ struct enc_session_funcs_gquic
/* Create client session */
enc_session_t *
(*esf_create_client) (const char *domain, lsquic_cid_t cid,
(*esf_create_client) (struct lsquic_conn *, const char *domain,
lsquic_cid_t cid,
const struct lsquic_engine_public *,
const unsigned char *, size_t);
@ -229,7 +237,6 @@ struct enc_session_funcs_gquic
* call it after the "handshake is done" callback is called.
*/
void (*esf_maybe_dispatch_zero_rtt) (enc_session_t *,
struct lsquic_conn *conn,
void (*cb)(struct lsquic_conn *, const unsigned char *, size_t));
void (*esf_reset_cid) (enc_session_t *, const lsquic_cid_t *);
@ -279,9 +286,6 @@ struct enc_session_funcs_iquic
int
(*esfi_init_server) (enc_session_t *);
void
(*esfi_set_conn) (enc_session_t *, struct lsquic_conn *);
void
(*esfi_set_streams) (enc_session_t *, void *(crypto_streams)[4],
const struct crypto_stream_if *);

View File

@ -1064,7 +1064,7 @@ iquic_lookup_cert (SSL *ssl, void *arg)
static void
iquic_esfi_set_conn (enc_session_t *enc_session_p, struct lsquic_conn *lconn)
iquic_esf_set_conn (enc_session_t *enc_session_p, struct lsquic_conn *lconn)
{
struct enc_sess_iquic *const enc_sess = enc_session_p;
enc_sess->esi_conn = lconn;
@ -1657,10 +1657,11 @@ static const enum enc_level pns2enc_level[] =
static enum enc_packout
iquic_esf_encrypt_packet (enc_session_t *enc_session_p,
const struct lsquic_engine_public *enpub, struct lsquic_conn *lconn,
const struct lsquic_engine_public *enpub, struct lsquic_conn *lconn_UNUSED,
struct lsquic_packet_out *packet_out)
{
struct enc_sess_iquic *const enc_sess = enc_session_p;
struct lsquic_conn *const lconn = enc_sess->esi_conn;
unsigned char *dst;
const struct crypto_ctx_pair *pair;
const struct crypto_ctx *crypto_ctx;
@ -1676,8 +1677,6 @@ iquic_esf_encrypt_packet (enc_session_t *enc_session_p,
enum packnum_space pns;
char errbuf[ERR_ERROR_STRING_BUF_LEN];
assert(lconn == enc_sess->esi_conn);
if (packet_out->po_flags & PO_MINI)
{
/* XXX TODO Don't rely on PO_MINI, generalize this logic */
@ -2232,7 +2231,6 @@ const struct enc_session_funcs_iquic lsquic_enc_session_iquic_ietf_v1 =
= iquic_esfi_get_peer_transport_params,
.esfi_reset_dcid = iquic_esfi_reset_dcid,
.esfi_init_server = iquic_esfi_init_server,
.esfi_set_conn = iquic_esfi_set_conn,
.esfi_set_streams = iquic_esfi_set_streams,
.esfi_create_server = iquic_esfi_create_server,
.esfi_shake_stream = iquic_esfi_shake_stream,
@ -2253,6 +2251,7 @@ const struct enc_session_funcs_common lsquic_enc_session_common_ietf_v1 =
.esf_keysize = iquic_esf_keysize,
.esf_alg_keysize = iquic_esf_alg_keysize,
.esf_is_zero_rtt_enabled = iquic_esf_zero_rtt_enabled,
.esf_set_conn = iquic_esf_set_conn,
};

View File

@ -84,6 +84,10 @@
#define LSQUIC_DEBUG_NEXT_ADV_TICK 1
#endif
#if LSQUIC_DEBUG_NEXT_ADV_TICK
#include "lsquic_alarmset.h"
#endif
#define MIN(a, b) ((a) < (b) ? (a) : (b))
/* The batch of outgoing packets grows and shrinks dynamically */
@ -248,6 +252,9 @@ struct lsquic_engine
#if LSQUIC_COUNT_ENGINE_CALLS
unsigned long n_engine_calls;
#endif
#if LSQUIC_DEBUG_NEXT_ADV_TICK
uintptr_t last_logged_idle_conn;
#endif
};
@ -2543,9 +2550,6 @@ process_connections (lsquic_engine_t *engine, conn_iter_f next_conn,
(void) engine_decref_conn(engine, conn, LSCONN_CLOSING);
}
/* TODO Heapification can be optimized by switching to the Floyd method:
* https://en.wikipedia.org/wiki/Binary_heap#Building_a_heap
*/
while ((conn = TAILQ_FIRST(&ticked_conns)))
{
TAILQ_REMOVE(&ticked_conns, conn, cn_next_ticked);
@ -2553,6 +2557,7 @@ process_connections (lsquic_engine_t *engine, conn_iter_f next_conn,
if (!(conn->cn_flags & LSCONN_TICKABLE)
&& conn->cn_if->ci_is_tickable(conn))
{
/* Floyd heapification is not faster, don't bother. */
lsquic_mh_insert(&engine->conns_tickable, conn, conn->cn_last_ticked);
engine_incref_conn(conn, LSCONN_TICKABLE);
}
@ -2709,6 +2714,7 @@ lsquic_engine_earliest_adv_tick (lsquic_engine_t *engine, int *diff)
{
#if LSQUIC_DEBUG_NEXT_ADV_TICK
conn = lsquic_mh_peek(&engine->conns_out);
engine->last_logged_idle_conn = 0;
LSQ_LOGC(L, "next advisory tick is now: went past deadline last time "
"and have %u outgoing connection%.*s (%"CID_FMT" first)",
lsquic_mh_count(&engine->conns_out),
@ -2722,6 +2728,7 @@ lsquic_engine_earliest_adv_tick (lsquic_engine_t *engine, int *diff)
if (engine->pr_queue && prq_have_pending(engine->pr_queue))
{
#if LSQUIC_DEBUG_NEXT_ADV_TICK
engine->last_logged_idle_conn = 0;
LSQ_LOG(L, "next advisory tick is now: have pending PRQ elements");
#endif
*diff = 0;
@ -2732,6 +2739,7 @@ lsquic_engine_earliest_adv_tick (lsquic_engine_t *engine, int *diff)
{
#if LSQUIC_DEBUG_NEXT_ADV_TICK
conn = lsquic_mh_peek(&engine->conns_tickable);
engine->last_logged_idle_conn = 0;
LSQ_LOGC(L, "next advisory tick is now: have %u tickable "
"connection%.*s (%"CID_FMT" first)",
lsquic_mh_count(&engine->conns_tickable),
@ -2769,9 +2777,21 @@ lsquic_engine_earliest_adv_tick (lsquic_engine_t *engine, int *diff)
*diff = (int) ((int64_t) next_time - (int64_t) now);
#if LSQUIC_DEBUG_NEXT_ADV_TICK
if (next_attq)
LSQ_LOGC(L, "next advisory tick is %d usec away: conn %"CID_FMT
": %s", *diff, CID_BITS(lsquic_conn_log_cid(next_attq->ae_conn)),
lsquic_attq_why2str(next_attq->ae_why));
{
/* Deduplicate consecutive log messages about IDLE timer for the
* same connection.
*/
if (!((unsigned) next_attq->ae_why == (unsigned) (N_AEWS + AL_IDLE)
&& (uintptr_t) next_attq->ae_conn
== engine->last_logged_idle_conn))
{
if ((unsigned) next_attq->ae_why == (unsigned) (N_AEWS + AL_IDLE))
engine->last_logged_idle_conn = (uintptr_t) next_attq->ae_conn;
LSQ_LOGC(L, "next advisory tick is %d usec away: conn %"CID_FMT
": %s", *diff, CID_BITS(lsquic_conn_log_cid(next_attq->ae_conn)),
lsquic_attq_why2str(next_attq->ae_why));
}
}
else
LSQ_LOG(L, "next advisory tick is %d usec away: resume sending", *diff);
#endif

View File

@ -708,8 +708,8 @@ lsquic_gquic_full_conn_client_new (struct lsquic_engine_public *enpub,
conn->fc_conn.cn_esf_c = select_esf_common_by_ver(version);
conn->fc_conn.cn_esf.g = esf_g;
conn->fc_conn.cn_enc_session =
conn->fc_conn.cn_esf.g->esf_create_client(hostname, cid, conn->fc_enpub,
zero_rtt, zero_rtt_len);
conn->fc_conn.cn_esf.g->esf_create_client(&conn->fc_conn, hostname,
cid, conn->fc_enpub, zero_rtt, zero_rtt_len);
if (!conn->fc_conn.cn_enc_session)
{
LSQ_WARN("could not create enc session: %s", strerror(errno));
@ -818,6 +818,8 @@ lsquic_gquic_full_conn_server_new (struct lsquic_engine_public *enpub,
assert(lconn_full->cn_enc_session == NULL);
lconn_full->cn_enc_session = lconn_mini->cn_enc_session;
lconn_mini->cn_enc_session = NULL;
lconn_full->cn_esf_c->esf_set_conn(lconn_full->cn_enc_session,
&conn->fc_conn);
lsquic_send_ctl_verneg_done(&conn->fc_send_ctl);
conn->fc_send_ctl.sc_cur_packno = mc->mc_cur_packno;
@ -3640,7 +3642,7 @@ full_conn_ci_hsk_done (lsquic_conn_t *lconn, enum lsquic_hsk_status status)
{
if (conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_zero_rtt_info)
conn->fc_conn.cn_esf.g->esf_maybe_dispatch_zero_rtt(
conn->fc_conn.cn_enc_session, &conn->fc_conn,
conn->fc_conn.cn_enc_session,
conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_zero_rtt_info);
if (conn->fc_n_delayed_streams)
create_delayed_streams(conn);

View File

@ -1209,7 +1209,7 @@ lsquic_ietf_full_conn_server_new (struct lsquic_engine_public *enpub,
conn->ifc_conn.cn_enc_session = mini_conn->cn_enc_session;
mini_conn->cn_enc_session = NULL;
conn->ifc_conn.cn_esf.i->esfi_set_conn(conn->ifc_conn.cn_enc_session,
conn->ifc_conn.cn_esf_c->esf_set_conn(conn->ifc_conn.cn_enc_session,
&conn->ifc_conn);
conn->ifc_process_incoming_packet = process_incoming_packet_fast;
@ -5672,6 +5672,21 @@ sockaddr_eq (const struct sockaddr *a, const struct sockaddr *b)
}
static void
record_dcid (struct ietf_full_conn *conn,
const struct lsquic_packet_in *packet_in)
{
unsigned orig_cid_len;
orig_cid_len = CUR_DCID(conn)->len;
conn->ifc_flags |= IFC_DCID_SET;
lsquic_scid_from_packet_in(packet_in, CUR_DCID(conn));
LSQ_DEBUGC("set DCID to %"CID_FMT, CID_BITS(CUR_DCID(conn)));
lsquic_send_ctl_cidlen_change(&conn->ifc_send_ctl, orig_cid_len,
CUR_DCID(conn)->len);
}
static int
process_regular_packet (struct ietf_full_conn *conn,
struct lsquic_packet_in *packet_in)
@ -5732,8 +5747,8 @@ process_regular_packet (struct ietf_full_conn *conn,
if (0 == (packet_in->pi_flags & PI_DECRYPTED))
{
dec_packin = conn->ifc_conn.cn_esf_c->esf_decrypt_packet(
conn->ifc_conn.cn_enc_session, conn->ifc_enpub,
&conn->ifc_conn, packet_in);
conn->ifc_conn.cn_enc_session, conn->ifc_enpub,
&conn->ifc_conn, packet_in);
switch (dec_packin)
{
case DECPI_BADCRYPT:
@ -5784,12 +5799,7 @@ process_regular_packet (struct ietf_full_conn *conn,
case REC_ST_OK:
if (!(conn->ifc_flags & (IFC_SERVER|IFC_DCID_SET))
&& (packet_in->pi_scid_len))
{
conn->ifc_flags |= IFC_DCID_SET;
lsquic_scid_from_packet_in(packet_in, CUR_DCID(conn));
LSQ_DEBUGC("set DCID to %"CID_FMT,
CID_BITS(CUR_DCID(conn)));
}
record_dcid(conn, packet_in);
saved_path_id = conn->ifc_cur_path_id;
parse_regular_packet(conn, packet_in);
if (saved_path_id == conn->ifc_cur_path_id)

View File

@ -56,8 +56,19 @@
#define MAX_SPUBS_LENGTH 32
#define LSQUIC_LOGGER_MODULE LSQLM_HANDSHAKE
#define LSQUIC_LOG_CONN_ID lsquic_conn_log_cid( \
enc_session && enc_session->es_conn ? enc_session->es_conn : \
lconn && lconn != &dummy_lsquic_conn ? lconn : \
&dummy_lsquic_conn)
#include "lsquic_logger.h"
/* enc_session may be NULL when encrypt and decrypt packet functions are
* called. This is a workaround.
*/
static struct conn_cid_elem dummy_cce;
static const struct lsquic_conn dummy_lsquic_conn = { .cn_cces = &dummy_cce, };
static const struct lsquic_conn *const lconn = &dummy_lsquic_conn;
enum handshake_state
{
HSK_CHLO_REJ = 0,
@ -200,6 +211,7 @@ struct lsquic_zero_rtt_storage
struct lsquic_enc_session
{
struct lsquic_conn *es_conn;
enum handshake_state hsk_state;
enum {
ES_SERVER = 1 << 0,
@ -674,8 +686,8 @@ lsquic_enc_session_deserialize_zero_rtt(
static enc_session_t *
lsquic_enc_session_create_client (const char *domain, lsquic_cid_t cid,
const struct lsquic_engine_public *enpub,
lsquic_enc_session_create_client (struct lsquic_conn *lconn, const char *domain,
lsquic_cid_t cid, const struct lsquic_engine_public *enpub,
const unsigned char *zero_rtt, size_t zero_rtt_len)
{
lsquic_session_cache_info_t *info;
@ -734,6 +746,7 @@ lsquic_enc_session_create_client (const char *domain, lsquic_cid_t cid,
break;
}
}
enc_session->es_conn = lconn;
enc_session->enpub = enpub;
enc_session->cid = cid;
enc_session->info = info;
@ -745,7 +758,7 @@ lsquic_enc_session_create_client (const char *domain, lsquic_cid_t cid,
/* Server side: Session_cache_entry can be saved for 0rtt */
static enc_session_t *
lsquic_enc_session_create_server (lsquic_cid_t cid,
lsquic_enc_session_create_server (struct lsquic_conn *lconn, lsquic_cid_t cid,
const struct lsquic_engine_public *enpub)
{
fiu_return_on("handshake/new_enc_session", NULL);
@ -756,6 +769,7 @@ lsquic_enc_session_create_server (lsquic_cid_t cid,
if (!enc_session)
return NULL;
enc_session->es_conn = lconn;
enc_session->enpub = enpub;
enc_session->cid = cid;
enc_session->es_flags |= ES_SERVER;
@ -1575,7 +1589,8 @@ determine_rtts (struct lsquic_enc_session *enc_session,
static int
config_has_correct_size (const void *data, unsigned shm_len)
config_has_correct_size (const struct lsquic_enc_session *enc_session,
const void *data, unsigned shm_len)
{
/* EVP_AEAD_CTX from boringssl after-18d9f28f0df9f95570. */
struct new_evp_aead_ctx_st {
@ -1620,7 +1635,8 @@ config_has_correct_size (const void *data, unsigned shm_len)
static lsquic_server_config_t *
get_valid_scfg (const struct lsquic_engine_public *enpub)
get_valid_scfg (const struct lsquic_enc_session *enc_session,
const struct lsquic_engine_public *enpub)
{
#define SERVER_SCFG_KEY "SERVER_SCFG"
#define SERVER_SCFG_KEY_SIZE (sizeof(SERVER_SCFG_KEY) - 1)
@ -1644,7 +1660,7 @@ get_valid_scfg (const struct lsquic_engine_public *enpub)
&scfg_ptr, &real_len);
if (ret == 1)
{
if (config_has_correct_size(scfg_ptr, real_len) &&
if (config_has_correct_size(enc_session, scfg_ptr, real_len) &&
(s_server_config.lsc_scfg = scfg_ptr,
s_server_config.lsc_scfg->info.expy > (uint64_t)t))
{
@ -2621,7 +2637,8 @@ gen_stk (lsquic_server_config_t *server_config, const struct sockaddr *ip_addr,
static
#endif
enum hsk_failure_reason
verify_stk0 (lsquic_server_config_t *server_config,
verify_stk0 (const struct lsquic_enc_session *enc_session,
lsquic_server_config_t *server_config,
const struct sockaddr *ip_addr, uint64_t tm, lsquic_str_t *stk,
unsigned secs_since_stk_generated)
{
@ -2701,7 +2718,8 @@ verify_stk (enc_session_t *enc_session_p,
return HFR_SRC_ADDR_TOKEN_INVALID;
}
else
return verify_stk0(enc_session->server_config, ip_addr, tm, stk, 0);
return verify_stk0(enc_session, enc_session->server_config, ip_addr,
tm, stk, 0);
}
@ -2850,14 +2868,13 @@ lsquic_enc_session_have_key_gt_one (enc_session_t *enc_session_p)
* buffer correspond to the header and the payload of incoming QUIC packet.
*/
static enum enc_level
lsquic_enc_session_decrypt (enc_session_t *enc_session_p,
lsquic_enc_session_decrypt (struct lsquic_enc_session *enc_session,
enum lsquic_version version,
uint8_t path_id, uint64_t pack_num,
unsigned char *buf, size_t *header_len, size_t data_len,
unsigned char *diversification_nonce,
unsigned char *buf_out, size_t max_out_len, size_t *out_len)
{
struct lsquic_enc_session *const enc_session = enc_session_p;
/* Client: got SHLO which should have diversification_nonce */
if (diversification_nonce && enc_session && enc_session->have_key == 1)
{
@ -2882,6 +2899,7 @@ gquic_decrypt_packet (enc_session_t *enc_session_p,
const struct lsquic_conn *lconn,
struct lsquic_packet_in *packet_in)
{
struct lsquic_enc_session *const enc_session = enc_session_p;
size_t header_len, data_len;
enum enc_level enc_level;
size_t out_len = 0;
@ -2895,7 +2913,7 @@ gquic_decrypt_packet (enc_session_t *enc_session_p,
assert(packet_in->pi_data);
header_len = packet_in->pi_header_sz;
data_len = packet_in->pi_data_sz - packet_in->pi_header_sz;
enc_level = lsquic_enc_session_decrypt(enc_session_p,
enc_level = lsquic_enc_session_decrypt(enc_session,
lconn->cn_version, 0,
packet_in->pi_packno, packet_in->pi_data,
&header_len, data_len,
@ -3030,7 +3048,7 @@ lsquic_enc_session_handle_chlo(enc_session_t *enc_session_p,
const struct lsquic_shared_hash_if *const shi = enpub->enp_shi;
void *const shi_ctx = enpub->enp_shi_ctx;
server_config = get_valid_scfg(enpub);
server_config = get_valid_scfg(enc_session, enpub);
if (!server_config)
return HS_ERROR;
assert(server_config->lsc_scfg);
@ -3493,10 +3511,10 @@ lsquic_enc_session_get_server_cert_chain (enc_session_t *enc_session_p)
static void
maybe_dispatch_zero_rtt (enc_session_t *enc_session_p,
struct lsquic_conn *lconn,
void (*cb)(struct lsquic_conn *, const unsigned char *, size_t))
{
struct lsquic_enc_session *const enc_session = enc_session_p;
struct lsquic_conn *const lconn = enc_session->es_conn;
void *buf;
size_t sz;
int i;
@ -3570,6 +3588,8 @@ gquic_encrypt_packet (enc_session_t *enc_session_p,
unsigned char *buf;
int ipv6;
assert(!enc_session || lconn == enc_session->es_conn);
bufsz = lconn->cn_pf->pf_packout_size(lconn, packet_out);
if (bufsz > USHRT_MAX)
return ENCPA_BADCRYPT; /* To cause connection to close */
@ -3614,6 +3634,15 @@ gquic_encrypt_packet (enc_session_t *enc_session_p,
}
static void
gquic_esf_set_conn (enc_session_t *enc_session_p, struct lsquic_conn *lconn)
{
struct lsquic_enc_session *const enc_session = enc_session_p;
enc_session->es_conn = lconn;
LSQ_DEBUG("updated conn reference");
}
#ifdef NDEBUG
const
#endif
@ -3631,6 +3660,7 @@ struct enc_session_funcs_common lsquic_enc_session_common_gquic_1 =
.esf_verify_reset_token = lsquic_enc_session_verify_reset_token,
.esf_did_zero_rtt_succeed = lsquic_enc_session_did_zero_rtt_succeed,
.esf_is_zero_rtt_enabled = lsquic_enc_session_is_zero_rtt_enabled,
.esf_set_conn = gquic_esf_set_conn,
};

View File

@ -12,6 +12,7 @@ struct sockaddr;
struct lsquic_str;
struct lsquic_packet_in;
struct lsquic_cid;
struct lsquic_enc_session;
/* client side, certs and hashs
*/
@ -28,7 +29,8 @@ typedef struct cert_hash_item_st
void gen_stk(struct lsquic_server_config *, const struct sockaddr *ip_addr, uint64_t tm,
unsigned char stk_out[STK_LENGTH]);
enum hsk_failure_reason
verify_stk0(struct lsquic_server_config *, const struct sockaddr *ip_addr, uint64_t tm,
verify_stk0(const struct lsquic_enc_session *,
struct lsquic_server_config *, const struct sockaddr *ip_addr, uint64_t tm,
struct lsquic_str *stk,
unsigned secs_since_stk_generated);
enum hsk_failure_reason

View File

@ -82,7 +82,6 @@ enum lsq_log_level lsq_log_levels[N_LSQUIC_LOGGER_MODULES] = {
[LSQLM_DI] = LSQ_LOG_WARN,
[LSQLM_PRQ] = LSQ_LOG_WARN,
[LSQLM_PACER] = LSQ_LOG_WARN,
[LSQLM_MIN_HEAP] = LSQ_LOG_WARN,
[LSQLM_HTTP1X] = LSQ_LOG_WARN,
[LSQLM_QLOG] = LSQ_LOG_WARN,
[LSQLM_TRAPA] = LSQ_LOG_WARN,
@ -125,7 +124,6 @@ const char *const lsqlm_to_str[N_LSQUIC_LOGGER_MODULES] = {
[LSQLM_DI] = "di",
[LSQLM_PRQ] = "prq",
[LSQLM_PACER] = "pacer",
[LSQLM_MIN_HEAP] = "min-heap",
[LSQLM_HTTP1X] = "http1x",
[LSQLM_QLOG] = "qlog",
[LSQLM_TRAPA] = "trapa",

View File

@ -73,7 +73,6 @@ enum lsquic_logger_module {
LSQLM_DI,
LSQLM_PRQ,
LSQLM_PACER,
LSQLM_MIN_HEAP,
LSQLM_HTTP1X,
LSQLM_QLOG,
LSQLM_TRAPA,

View File

@ -4,16 +4,10 @@
*/
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include "lsquic_min_heap.h"
#define LSQUIC_LOGGER_MODULE LSQLM_MIN_HEAP
#include "lsquic_types.h"
#include "lsquic_logger.h"
#define MHE_PARENT(i) ((i - 1) / 2)
#define MHE_LCHILD(i) (2 * i + 1)
#define MHE_RCHILD(i) (2 * i + 2)
static void

View File

@ -35,4 +35,8 @@ lsquic_mh_pop (struct min_heap *);
#define lsquic_mh_nalloc(heap) (+(heap)->mh_nalloc)
#define MHE_PARENT(i) ((i - 1) / 2)
#define MHE_LCHILD(i) (2 * i + 1)
#define MHE_RCHILD(i) (2 * i + 2)
#endif

View File

@ -1005,8 +1005,8 @@ continue_handshake (struct mini_conn *mc)
if (!mc->mc_conn.cn_enc_session)
{
mc->mc_conn.cn_enc_session =
mc->mc_conn.cn_esf.g->esf_create_server(mc->mc_conn.cn_cid,
mc->mc_enpub);
mc->mc_conn.cn_esf.g->esf_create_server(&mc->mc_conn,
mc->mc_conn.cn_cid, mc->mc_enpub);
if (!mc->mc_conn.cn_enc_session)
{
LSQ_WARN("cannot create new enc session");

View File

@ -1154,7 +1154,7 @@ ietf_mini_conn_ci_packet_in (struct lsquic_conn *lconn,
}
dec_packin = lconn->cn_esf_c->esf_decrypt_packet(lconn->cn_enc_session,
conn->imc_enpub, lconn, packet_in);
conn->imc_enpub, &conn->imc_conn, packet_in);
if (dec_packin != DECPI_OK)
{
/* TODO: handle reordering perhaps? */

View File

@ -408,7 +408,10 @@ qdh_supply_hset_to_stream (struct qpack_dec_hdl *qdh,
header->qh_name, header->qh_name_len,
header->qh_value, header->qh_value_len);
if (st != LSQUIC_HDR_OK)
{
LSQ_INFO("header process returned non-OK code %u", (unsigned) st);
goto err;
}
}
lsqpack_dec_destroy_header_list(qlist);

View File

@ -347,6 +347,13 @@ lsquic_send_ctl_init (lsquic_send_ctl_t *ctl, struct lsquic_alarmset *alset,
TAILQ_INIT(&ctl->sc_buffered_packets[i].bpq_packets);
ctl->sc_max_packno_bits = PACKNO_BITS_2; /* Safe value before verneg */
ctl->sc_cached_bpt.stream_id = UINT64_MAX;
#if LSQUIC_EXTRA_CHECKS
ctl->sc_flags |= SC_SANITY_CHECK;
#else
if ((ctl->sc_conn_pub->lconn->cn_flags & (LSCONN_IETF|LSCONN_SERVER))
== LSCONN_IETF)
ctl->sc_flags |= SC_SANITY_CHECK;
#endif
}
@ -1404,9 +1411,8 @@ lsquic_send_ctl_expire_all (lsquic_send_ctl_t *ctl)
}
#if LSQUIC_EXTRA_CHECKS
void
lsquic_send_ctl_sanity_check (const lsquic_send_ctl_t *ctl)
lsquic_send_ctl_do_sanity_check (const struct lsquic_send_ctl *ctl)
{
const struct lsquic_packet_out *packet_out;
lsquic_packno_t prev_packno;
@ -1414,15 +1420,6 @@ lsquic_send_ctl_sanity_check (const lsquic_send_ctl_t *ctl)
unsigned count, bytes;
enum packnum_space pns;
assert(!send_ctl_first_unacked_retx_packet(ctl, PNS_APP) ||
lsquic_alarmset_is_set(ctl->sc_alset, AL_RETX_APP));
if (lsquic_alarmset_is_set(ctl->sc_alset, AL_RETX_APP))
{
assert(send_ctl_first_unacked_retx_packet(ctl, PNS_APP));
assert(lsquic_time_now()
< ctl->sc_alset->as_expiry[AL_RETX_APP] + MAX_RTO_DELAY);
}
count = 0, bytes = 0;
for (pns = PNS_INIT; pns <= PNS_APP; ++pns)
{
@ -1456,7 +1453,6 @@ lsquic_send_ctl_sanity_check (const lsquic_send_ctl_t *ctl)
assert(count == ctl->sc_n_scheduled);
assert(bytes == ctl->sc_bytes_scheduled);
}
#endif
void
@ -2814,3 +2810,42 @@ lsquic_send_ctl_return_enc_data (struct lsquic_send_ctl *ctl)
if (packet_out->po_flags & PO_ENCRYPTED)
send_ctl_return_enc_data(ctl, packet_out);
}
/* When client updated DCID based on the first packet returned by the server,
* we must update the number of bytes scheduled if the DCID length changed
* because this length is used to calculate packet size.
*/
void
lsquic_send_ctl_cidlen_change (struct lsquic_send_ctl *ctl,
unsigned orig_cid_len, unsigned new_cid_len)
{
unsigned diff;
assert(!(ctl->sc_conn_pub->lconn->cn_flags & LSCONN_SERVER));
if (ctl->sc_n_scheduled)
{
ctl->sc_flags |= SC_CIDLEN;
ctl->sc_cidlen = (signed char) new_cid_len - (signed char) orig_cid_len;
if (new_cid_len > orig_cid_len)
{
diff = new_cid_len - orig_cid_len;
diff *= ctl->sc_n_scheduled;
ctl->sc_bytes_scheduled += diff;
LSQ_DEBUG("increased bytes scheduled by %u bytes to %u",
diff, ctl->sc_bytes_scheduled);
}
else if (new_cid_len < orig_cid_len)
{
diff = orig_cid_len - new_cid_len;
diff *= ctl->sc_n_scheduled;
ctl->sc_bytes_scheduled -= diff;
LSQ_DEBUG("decreased bytes scheduled by %u bytes to %u",
diff, ctl->sc_bytes_scheduled);
}
else
LSQ_DEBUG("DCID length did not change");
}
else
LSQ_DEBUG("no scheduled packets at the time of DCID change");
}

View File

@ -45,6 +45,8 @@ enum send_ctl_flags {
SC_APP_LIMITED = 1 << 12,
SC_ECN = 1 << 13,
SC_QL_BITS = 1 << 14,
SC_SANITY_CHECK = 1 << 15,
SC_CIDLEN = 1 << 16, /* sc_cidlen is set */
};
typedef struct lsquic_send_ctl {
@ -127,6 +129,7 @@ typedef struct lsquic_send_ctl {
lsquic_packno_t sc_cur_rt_end;
unsigned sc_loss_count; /* Used to set loss bit */
unsigned sc_square_count;/* Used to set square bit */
signed char sc_cidlen; /* For debug purposes */
} lsquic_send_ctl_t;
void
@ -172,12 +175,13 @@ lsquic_send_ctl_expire_all (lsquic_send_ctl_t *ctl);
#define lsquic_send_ctl_largest_ack2ed(ctl, pns) \
(+(ctl)->sc_largest_ack2ed[pns])
#if LSQUIC_EXTRA_CHECKS
void
lsquic_send_ctl_sanity_check (const lsquic_send_ctl_t *ctl);
#else
# define lsquic_send_ctl_sanity_check(ctl)
#endif
lsquic_send_ctl_do_sanity_check (const struct lsquic_send_ctl *ctl);
#define lsquic_send_ctl_sanity_check(ctl) do { \
if ((ctl)->sc_flags & SC_SANITY_CHECK) \
lsquic_send_ctl_do_sanity_check(ctl); \
} while (0)
int
lsquic_send_ctl_have_outgoing_stream_frames (const lsquic_send_ctl_t *);
@ -364,4 +368,8 @@ lsquic_send_ctl_maybe_app_limited (struct lsquic_send_ctl *,
(ctl)->sc_flags |= SC_QL_BITS; \
} while (0)
void
lsquic_send_ctl_cidlen_change (struct lsquic_send_ctl *,
unsigned orig_cid_len, unsigned new_cid_len);
#endif

View File

@ -99,6 +99,9 @@ TARGET_LINK_LIBRARIES(graph_cubic ${LIBS})
ADD_EXECUTABLE(mini_parse mini_parse.c ${ADDL_SOURCES})
TARGET_LINK_LIBRARIES(mini_parse ${LIBS})
ADD_EXECUTABLE(test_min_heap test_min_heap.c ../../src/liblsquic/lsquic_min_heap.c)
ADD_TEST(min_heap test_min_heap)
ADD_EXECUTABLE(test_malo_pooled test_malo.c ../../src/liblsquic/lsquic_malo.c)
SET_TARGET_PROPERTIES(test_malo_pooled
PROPERTIES COMPILE_FLAGS "${CMAKE_C_FLAGS} -DLSQUIC_USE_POOLS=1")

View File

@ -0,0 +1,162 @@
/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc. See LICENSE. */
/* Test min heap or benchmark heap creation */
/* Floyd mechanism has been removed. It's not faster. */
#define FLOYD 0
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "lsquic_min_heap.h"
static void
verify_min_heap (const struct min_heap *heap)
{
unsigned i;
for (i = 0; i < heap->mh_nelem; ++i)
{
if (MHE_LCHILD(i) < heap->mh_nelem)
assert(heap->mh_elems[i].mhe_val <=
heap->mh_elems[MHE_LCHILD(i)].mhe_val);
if (MHE_RCHILD(i) < heap->mh_nelem)
assert(heap->mh_elems[i].mhe_val <=
heap->mh_elems[MHE_RCHILD(i)].mhe_val);
}
}
#define MAX_ELEMS 1000
static void
test_min_heap (void)
{
struct min_heap heap;
uint64_t i, prev_val;
void *p;
struct min_heap_elem els[MAX_ELEMS];
heap.mh_elems = els;
heap.mh_nalloc = MAX_ELEMS;
heap.mh_nelem = 0;
for (i = 0; i < MAX_ELEMS; ++i)
lsquic_mh_insert(&heap, (void *) i, i);
verify_min_heap(&heap);
for (i = 0; i < MAX_ELEMS; ++i)
{
p = lsquic_mh_pop(&heap);
if (i)
assert((uintptr_t) p >= prev_val);
prev_val = (uintptr_t) p;
}
heap.mh_nelem = 0;
for (i = MAX_ELEMS; i > 0; --i)
lsquic_mh_insert(&heap, (void *) i, i);
verify_min_heap(&heap);
for (i = 0; i < MAX_ELEMS; ++i)
{
p = lsquic_mh_pop(&heap);
if (i)
assert((uintptr_t) p >= prev_val);
prev_val = (uintptr_t) p;
}
heap.mh_nelem = 0;
#if FLOYD
/* Now use Floyd method */
heap.mh_nelem = 0;
for (i = 0; i < MAX_ELEMS; ++i)
lsquic_mh_push(&heap, NULL, i);
lsquic_mh_heapify(&heap);
verify_min_heap(&heap);
heap.mh_nelem = 0;
for (i = MAX_ELEMS; i > 0; --i)
lsquic_mh_push(&heap, NULL, i);
lsquic_mh_heapify(&heap);
verify_min_heap(&heap);
#endif
}
int
main (int argc, char **argv)
{
if (argc == 1)
{
test_min_heap();
return 0;
}
if (argc != 4)
{
fprintf(stderr, "usage: %s nelems iters method\n"
" method is 0: insert; 1: floyd\n", argv[0]);
return 1;
}
unsigned i, j, n_iters, nelems;
struct min_heap_elem *els;
unsigned *vals;
struct min_heap heap;
nelems = atoi(argv[1]);
n_iters = atoi(argv[2]);
#if FLOYD
const int floyd = atoi(argv[3]);
#endif
vals = malloc(sizeof(vals[0]) * nelems);
assert(vals);
for (i = 0; i < nelems; ++i)
vals[i] = rand();
els = malloc(sizeof(els[0]) * nelems);
assert(els);
heap.mh_elems = els;
heap.mh_nalloc = nelems;
heap.mh_nelem = 0;
#if FLOYD
if (floyd)
{
for (i = 0; i < nelems; ++i)
lsquic_mh_push(&heap, NULL, vals[i]);
lsquic_mh_heapify(&heap);
}
else
#endif
for (i = 0; i < nelems; ++i)
lsquic_mh_insert(&heap, NULL, vals[i]);
verify_min_heap(&heap);
#if FLOYD
if (floyd)
{
for (j = 0; j < n_iters; ++j)
{
heap.mh_nelem = 0;
for (i = 0; i < nelems; ++i)
lsquic_mh_push(&heap, NULL, vals[i]);
lsquic_mh_heapify(&heap);
}
}
else
#endif
{
for (j = 0; j < n_iters; ++j)
{
heap.mh_nelem = 0;
for (i = 0; i < nelems; ++i)
lsquic_mh_insert(&heap, NULL, vals[i]);
}
}
free(els);
free(vals);
return 0;
}