mirror of
https://gitea.invidious.io/iv-org/litespeed-quic.git
synced 2024-08-15 00:53:43 +00:00
Release 2.5.0
- [API] lsquic_engine_connect() can now be passed QUIC version to use. - [OPTIMIZATION] Queue opportunistic ACKs if there is data to be sent. - [BUGFIX] Don't evict streams from priority iterator if there is only one queue. - [OPTIMIZATION, BUGFIX] Several other optimizations and bug fixes. - Use ls-qpack v0.10.7.
This commit is contained in:
parent
34e9ac5f5d
commit
a0e1aeeee0
34 changed files with 327 additions and 108 deletions
|
@ -1,3 +1,12 @@
|
|||
2019-10-31
|
||||
- 2.5.0
|
||||
- [API] lsquic_engine_connect() can now be passed QUIC version to use.
|
||||
- [OPTIMIZATION] Queue opportunistic ACKs if there is data to be sent.
|
||||
- [BUGFIX] Don't evict streams from priority iterator if there is
|
||||
only one queue.
|
||||
- [OPTIMIZATION, BUGFIX] Several other optimizations and bug fixes.
|
||||
- Use ls-qpack v0.10.7.
|
||||
|
||||
2019-10-24
|
||||
- 2.4.10
|
||||
- [BUGFIX] IETF QUIC server: fix uninitialized variable use.
|
||||
|
|
|
@ -22,7 +22,9 @@ MESSAGE(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
|
|||
|
||||
OPTION(LSQUIC_FIU "Use Fault Injection in Userspace (FIU)" OFF)
|
||||
|
||||
SET(MY_CMAKE_FLAGS "-DLSQUIC_DEBUG_NEXT_ADV_TICK=1")
|
||||
IF (NOT "$ENV{EXTRA_CFLAGS}" MATCHES "-DLSQUIC_DEBUG_NEXT_ADV_TICK")
|
||||
SET(MY_CMAKE_FLAGS "-DLSQUIC_DEBUG_NEXT_ADV_TICK=1")
|
||||
ENDIF()
|
||||
|
||||
IF (NOT MSVC)
|
||||
|
||||
|
|
|
@ -24,8 +24,8 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#define LSQUIC_MAJOR_VERSION 2
|
||||
#define LSQUIC_MINOR_VERSION 4
|
||||
#define LSQUIC_PATCH_VERSION 10
|
||||
#define LSQUIC_MINOR_VERSION 5
|
||||
#define LSQUIC_PATCH_VERSION 0
|
||||
|
||||
/**
|
||||
* Engine flags:
|
||||
|
@ -1026,11 +1026,16 @@ lsquic_engine_new (unsigned lsquic_engine_flags,
|
|||
|
||||
/**
|
||||
* Create a client connection to peer identified by `peer_ctx'.
|
||||
*
|
||||
* To let the engine specify QUIC version, use N_LSQVER. If zero-rtt info
|
||||
* is supplied, version is picked from there instead.
|
||||
*
|
||||
* If `max_packet_size' is set to zero, it is inferred based on `peer_sa':
|
||||
* 1350 for IPv6 and 1370 for IPv4.
|
||||
*/
|
||||
lsquic_conn_t *
|
||||
lsquic_engine_connect (lsquic_engine_t *, const struct sockaddr *local_sa,
|
||||
lsquic_engine_connect (lsquic_engine_t *, enum lsquic_version,
|
||||
const struct sockaddr *local_sa,
|
||||
const struct sockaddr *peer_sa,
|
||||
void *peer_ctx, lsquic_conn_ctx_t *conn_ctx,
|
||||
const char *hostname, unsigned short max_packet_size,
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 1786126dc6e104fdfa7b7c45611b2d7c870a0e55
|
||||
Subproject commit 9ace654b3aac2cf16f76fbcf52d3170278f60141
|
|
@ -52,7 +52,6 @@ enum alarm_id_bit {
|
|||
ALBIT_IDLE = 1 << AL_IDLE,
|
||||
ALBIT_RET_CIDS = 1 << AL_RET_CIDS,
|
||||
ALBIT_CID_THROT = 1 << AL_CID_THROT,
|
||||
ALBIT_PATH_CHAL = 1 << AL_PATH_CHAL,
|
||||
ALBIT_PATH_CHAL_0 = 1 << AL_PATH_CHAL_0,
|
||||
ALBIT_PATH_CHAL_1 = 1 << AL_PATH_CHAL_1,
|
||||
ALBIT_SESS_TICKET = 1 << AL_SESS_TICKET,
|
||||
|
|
|
@ -30,5 +30,5 @@ lsquic_zero_rtt_version (const unsigned char *buf, size_t bufsz)
|
|||
return lsquic_tag2ver(tag);
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
return N_LSQVER;
|
||||
}
|
||||
|
|
|
@ -1462,7 +1462,8 @@ add_conn_to_hash (struct lsquic_engine *engine, struct lsquic_conn *conn,
|
|||
|
||||
|
||||
lsquic_conn_t *
|
||||
lsquic_engine_connect (lsquic_engine_t *engine, const struct sockaddr *local_sa,
|
||||
lsquic_engine_connect (lsquic_engine_t *engine, enum lsquic_version version,
|
||||
const struct sockaddr *local_sa,
|
||||
const struct sockaddr *peer_sa,
|
||||
void *peer_ctx, lsquic_conn_ctx_t *conn_ctx,
|
||||
const char *hostname, unsigned short max_packet_size,
|
||||
|
@ -1470,7 +1471,7 @@ lsquic_engine_connect (lsquic_engine_t *engine, const struct sockaddr *local_sa,
|
|||
const unsigned char *token, size_t token_sz)
|
||||
{
|
||||
lsquic_conn_t *conn;
|
||||
unsigned flags;
|
||||
unsigned flags, versions;
|
||||
int is_ipv4;
|
||||
|
||||
ENGINE_IN(engine);
|
||||
|
@ -1492,13 +1493,31 @@ lsquic_engine_connect (lsquic_engine_t *engine, const struct sockaddr *local_sa,
|
|||
return NULL;
|
||||
flags = engine->flags & (ENG_SERVER|ENG_HTTP);
|
||||
is_ipv4 = peer_sa->sa_family == AF_INET;
|
||||
if (engine->pub.enp_settings.es_versions & LSQUIC_IETF_VERSIONS)
|
||||
conn = lsquic_ietf_full_conn_client_new(&engine->pub,
|
||||
if (zero_rtt && zero_rtt_len)
|
||||
{
|
||||
version = lsquic_zero_rtt_version(zero_rtt, zero_rtt_len);
|
||||
if (version >= N_LSQVER)
|
||||
{
|
||||
LSQ_INFO("zero-rtt version is bad, won't use");
|
||||
zero_rtt = NULL;
|
||||
zero_rtt_len = 0;
|
||||
}
|
||||
}
|
||||
if (version >= N_LSQVER)
|
||||
{
|
||||
if (version > N_LSQVER)
|
||||
LSQ_WARN("invalid version specified, engine will pick");
|
||||
versions = engine->pub.enp_settings.es_versions;
|
||||
}
|
||||
else
|
||||
versions = 1u << version;
|
||||
if (versions & LSQUIC_IETF_VERSIONS)
|
||||
conn = lsquic_ietf_full_conn_client_new(&engine->pub, versions,
|
||||
flags, hostname, max_packet_size,
|
||||
is_ipv4, zero_rtt, zero_rtt_len, token, token_sz);
|
||||
else
|
||||
conn = lsquic_gquic_full_conn_client_new(&engine->pub, flags,
|
||||
hostname, max_packet_size, is_ipv4,
|
||||
versions, hostname, max_packet_size, is_ipv4,
|
||||
zero_rtt, zero_rtt_len);
|
||||
if (!conn)
|
||||
goto err;
|
||||
|
@ -1558,13 +1577,12 @@ refflags2str (enum lsquic_conn_flags flags, char s[6])
|
|||
static void
|
||||
engine_incref_conn (lsquic_conn_t *conn, enum lsquic_conn_flags flag)
|
||||
{
|
||||
const lsquic_cid_t *cid;
|
||||
char str[2][7];
|
||||
assert(flag & CONN_REF_FLAGS);
|
||||
assert(!(conn->cn_flags & flag));
|
||||
conn->cn_flags |= flag;
|
||||
cid = lsquic_conn_log_cid(conn);
|
||||
LSQ_DEBUGC("incref conn %"CID_FMT", '%s' -> '%s'", CID_BITS(cid),
|
||||
LSQ_DEBUGC("incref conn %"CID_FMT", '%s' -> '%s'",
|
||||
CID_BITS(lsquic_conn_log_cid(conn)),
|
||||
(refflags2str(conn->cn_flags & ~flag, str[0]), str[0]),
|
||||
(refflags2str(conn->cn_flags, str[1]), str[1]));
|
||||
}
|
||||
|
@ -1574,7 +1592,6 @@ static lsquic_conn_t *
|
|||
engine_decref_conn (lsquic_engine_t *engine, lsquic_conn_t *conn,
|
||||
enum lsquic_conn_flags flags)
|
||||
{
|
||||
const lsquic_cid_t *cid;
|
||||
char str[2][7];
|
||||
lsquic_time_t now;
|
||||
assert(flags & CONN_REF_FLAGS);
|
||||
|
@ -1584,8 +1601,8 @@ engine_decref_conn (lsquic_engine_t *engine, lsquic_conn_t *conn,
|
|||
assert(0 == (conn->cn_flags & LSCONN_HASHED));
|
||||
#endif
|
||||
conn->cn_flags &= ~flags;
|
||||
cid = lsquic_conn_log_cid(conn);
|
||||
LSQ_DEBUGC("decref conn %"CID_FMT", '%s' -> '%s'", CID_BITS(cid),
|
||||
LSQ_DEBUGC("decref conn %"CID_FMT", '%s' -> '%s'",
|
||||
CID_BITS(lsquic_conn_log_cid(conn)),
|
||||
(refflags2str(conn->cn_flags | flags, str[0]), str[0]),
|
||||
(refflags2str(conn->cn_flags, str[1]), str[1]));
|
||||
if (0 == (conn->cn_flags & CONN_REF_FLAGS))
|
||||
|
@ -2128,7 +2145,6 @@ send_packets_out (struct lsquic_engine *engine,
|
|||
struct conns_tailq *ticked_conns,
|
||||
struct conns_stailq *closed_conns)
|
||||
{
|
||||
const lsquic_cid_t *cid;
|
||||
unsigned n, w, n_sent, n_batches_sent;
|
||||
lsquic_packet_out_t *packet_out;
|
||||
struct lsquic_packet_out **packet;
|
||||
|
@ -2148,14 +2164,13 @@ send_packets_out (struct lsquic_engine *engine,
|
|||
|
||||
while ((conn = coi_next(&conns_iter)))
|
||||
{
|
||||
cid = lsquic_conn_log_cid(conn);
|
||||
packet_out = conn->cn_if->ci_next_packet_to_send(conn, 0);
|
||||
if (!packet_out) {
|
||||
/* Evanescent connection always has a packet to send: */
|
||||
assert(!(conn->cn_flags & LSCONN_EVANESCENT));
|
||||
LSQ_DEBUGC("batched all outgoing packets for %s conn %"CID_FMT,
|
||||
(conn->cn_flags & LSCONN_MINI ? "mini" :
|
||||
"full"), CID_BITS(cid));
|
||||
(conn->cn_flags & LSCONN_MINI ? "mini" : "full"),
|
||||
CID_BITS(lsquic_conn_log_cid(conn)));
|
||||
coi_deactivate(&conns_iter, conn);
|
||||
continue;
|
||||
}
|
||||
|
@ -2174,7 +2189,7 @@ send_packets_out (struct lsquic_engine *engine,
|
|||
/* This is pretty bad: close connection immediately */
|
||||
conn->cn_if->ci_packet_not_sent(conn, packet_out);
|
||||
LSQ_INFOC("conn %"CID_FMT" has unsendable packets",
|
||||
CID_BITS(cid));
|
||||
CID_BITS(lsquic_conn_log_cid(conn)));
|
||||
if (!(conn->cn_flags & LSCONN_EVANESCENT))
|
||||
{
|
||||
if (!(conn->cn_flags & LSCONN_CLOSING))
|
||||
|
@ -2207,7 +2222,7 @@ send_packets_out (struct lsquic_engine *engine,
|
|||
}
|
||||
}
|
||||
LSQ_DEBUGC("batched packet %"PRIu64" for connection %"CID_FMT,
|
||||
packet_out->po_packno, CID_BITS(cid));
|
||||
packet_out->po_packno, CID_BITS(lsquic_conn_log_cid(conn)));
|
||||
if (packet_out->po_flags & PO_ENCRYPTED)
|
||||
{
|
||||
iov->iov_base = packet_out->po_enc_data;
|
||||
|
@ -2597,7 +2612,6 @@ lsquic_engine_earliest_adv_tick (lsquic_engine_t *engine, int *diff)
|
|||
lsquic_time_t now, next_time;
|
||||
#if LSQUIC_DEBUG_NEXT_ADV_TICK
|
||||
const struct lsquic_conn *conn;
|
||||
const lsquic_cid_t *cid;
|
||||
const enum lsq_log_level L = LSQ_LOG_DEBUG; /* Easy toggle */
|
||||
#endif
|
||||
|
||||
|
@ -2608,11 +2622,11 @@ lsquic_engine_earliest_adv_tick (lsquic_engine_t *engine, int *diff)
|
|||
{
|
||||
#if LSQUIC_DEBUG_NEXT_ADV_TICK
|
||||
conn = lsquic_mh_peek(&engine->conns_out);
|
||||
cid = lsquic_conn_log_cid(conn);
|
||||
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),
|
||||
lsquic_mh_count(&engine->conns_out) != 1, "s", CID_BITS(cid));
|
||||
lsquic_mh_count(&engine->conns_out) != 1, "s",
|
||||
CID_BITS(lsquic_conn_log_cid(conn)));
|
||||
#endif
|
||||
*diff = 0;
|
||||
return 1;
|
||||
|
@ -2631,11 +2645,11 @@ lsquic_engine_earliest_adv_tick (lsquic_engine_t *engine, int *diff)
|
|||
{
|
||||
#if LSQUIC_DEBUG_NEXT_ADV_TICK
|
||||
conn = lsquic_mh_peek(&engine->conns_tickable);
|
||||
cid = lsquic_conn_log_cid(conn);
|
||||
LSQ_LOGC(L, "next advisory tick is now: have %u tickable "
|
||||
"connection%.*s (%"CID_FMT" first)",
|
||||
lsquic_mh_count(&engine->conns_tickable),
|
||||
lsquic_mh_count(&engine->conns_tickable) != 1, "s", CID_BITS(cid));
|
||||
lsquic_mh_count(&engine->conns_tickable) != 1, "s",
|
||||
CID_BITS(lsquic_conn_log_cid(conn)));
|
||||
#endif
|
||||
*diff = 0;
|
||||
return 1;
|
||||
|
@ -2668,12 +2682,9 @@ 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)
|
||||
{
|
||||
cid = lsquic_conn_log_cid(next_attq->ae_conn);
|
||||
LSQ_LOGC(L, "next advisory tick is %d usec away: conn %"CID_FMT
|
||||
": %s", *diff, CID_BITS(cid),
|
||||
": %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
|
||||
|
|
|
@ -619,8 +619,6 @@ decode_and_pass_payload (struct lsquic_frame_reader *fr)
|
|||
LSQ_INFO("%s: stream error %u", __func__, err);
|
||||
if (hset)
|
||||
fr->fr_hsi_if->hsi_discard_header_set(hset);
|
||||
if (uh)
|
||||
free(uh);
|
||||
if (buf)
|
||||
lsquic_mm_put_16k(fr->fr_mm, buf);
|
||||
fr->fr_callbacks->frc_on_error(fr->fr_cb_ctx, fr_get_stream_id(fr), err);
|
||||
|
|
|
@ -219,6 +219,7 @@ struct full_conn
|
|||
struct short_ack_info fc_saved_ack_info;
|
||||
lsquic_time_t fc_saved_ack_received;
|
||||
struct network_path fc_path;
|
||||
unsigned fc_orig_versions; /* Client only */
|
||||
};
|
||||
|
||||
static const struct ver_neg server_ver_neg;
|
||||
|
@ -672,7 +673,7 @@ new_conn_common (lsquic_cid_t cid, struct lsquic_engine_public *enpub,
|
|||
|
||||
struct lsquic_conn *
|
||||
lsquic_gquic_full_conn_client_new (struct lsquic_engine_public *enpub,
|
||||
unsigned flags,
|
||||
unsigned versions, unsigned flags,
|
||||
const char *hostname, unsigned short max_packet_size,
|
||||
int is_ipv4,
|
||||
const unsigned char *zero_rtt, size_t zero_rtt_len)
|
||||
|
@ -682,12 +683,13 @@ lsquic_gquic_full_conn_client_new (struct lsquic_engine_public *enpub,
|
|||
lsquic_cid_t cid;
|
||||
const struct enc_session_funcs_gquic *esf_g;
|
||||
|
||||
version = highest_bit_set(enpub->enp_settings.es_versions);
|
||||
versions &= (~LSQUIC_IETF_VERSIONS & LSQUIC_SUPPORTED_VERSIONS);
|
||||
assert(versions);
|
||||
version = highest_bit_set(versions);
|
||||
if (zero_rtt)
|
||||
{
|
||||
zero_rtt_version = lsquic_zero_rtt_version(zero_rtt, zero_rtt_len);
|
||||
if (zero_rtt_version < N_LSQVER &&
|
||||
((1 << zero_rtt_version) & enpub->enp_settings.es_versions))
|
||||
if (zero_rtt_version < N_LSQVER && ((1 << zero_rtt_version) & versions))
|
||||
version = zero_rtt_version;
|
||||
}
|
||||
esf_g = select_esf_gquic_by_ver(version);
|
||||
|
@ -725,7 +727,8 @@ lsquic_gquic_full_conn_client_new (struct lsquic_engine_public *enpub,
|
|||
conn->fc_stream_ifs[STREAM_IF_HSK]
|
||||
.stream_if = &lsquic_client_hsk_stream_if;
|
||||
conn->fc_stream_ifs[STREAM_IF_HSK].stream_if_ctx = &conn->fc_hsk_ctx.client;
|
||||
init_ver_neg(conn, conn->fc_settings->es_versions, &version);
|
||||
conn->fc_orig_versions = versions;
|
||||
init_ver_neg(conn, versions, &version);
|
||||
if (conn->fc_settings->es_handshake_to)
|
||||
lsquic_alarmset_set(&conn->fc_alset, AL_HANDSHAKE,
|
||||
lsquic_time_now() + conn->fc_settings->es_handshake_to);
|
||||
|
@ -2510,6 +2513,7 @@ idle_alarm_expired (enum alarm_id al_id, void *ctx, lsquic_time_t expiry,
|
|||
{
|
||||
struct full_conn *conn = ctx;
|
||||
LSQ_DEBUG("connection timed out");
|
||||
EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "connection timed out");
|
||||
conn->fc_flags |= FC_TIMED_OUT;
|
||||
}
|
||||
|
||||
|
@ -4379,8 +4383,8 @@ lsquic_gquic_full_conn_srej (struct lsquic_conn *lconn)
|
|||
lconn->cn_esf.g->esf_reset_cid(lconn->cn_enc_session, &cce->cce_cid);
|
||||
|
||||
/* Reset version negotiation */
|
||||
version = highest_bit_set(conn->fc_settings->es_versions);
|
||||
init_ver_neg(conn, conn->fc_settings->es_versions, &version);
|
||||
version = highest_bit_set(conn->fc_orig_versions);
|
||||
init_ver_neg(conn, conn->fc_orig_versions, &version);
|
||||
|
||||
/* Reset receive history */
|
||||
lsquic_rechist_cleanup(&conn->fc_rechist);
|
||||
|
|
|
@ -7,6 +7,7 @@ struct lsquic_engine_public;
|
|||
|
||||
struct lsquic_conn *
|
||||
lsquic_gquic_full_conn_client_new (struct lsquic_engine_public *,
|
||||
unsigned versions,
|
||||
unsigned flags /* Only FC_SERVER and FC_HTTP */,
|
||||
const char *hostname, unsigned short max_packet_size,
|
||||
int is_ipv4,
|
||||
|
@ -14,6 +15,7 @@ lsquic_gquic_full_conn_client_new (struct lsquic_engine_public *,
|
|||
|
||||
struct lsquic_conn *
|
||||
lsquic_ietf_full_conn_client_new (struct lsquic_engine_public *,
|
||||
unsigned versions,
|
||||
unsigned flags /* Only FC_SERVER and FC_HTTP */,
|
||||
const char *hostname, unsigned short max_packet_size, int is_ipv4,
|
||||
const unsigned char *zero_rtt, size_t,
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
#include "lsquic_headers.h"
|
||||
|
||||
#define LSQUIC_LOGGER_MODULE LSQLM_CONN
|
||||
#define LSQUIC_LOG_CONN_ID lsquic_conn_log_cid(&conn->ifc_conn)
|
||||
#define LSQUIC_LOG_CONN_ID ietf_full_conn_ci_get_log_cid(&conn->ifc_conn)
|
||||
#include "lsquic_logger.h"
|
||||
|
||||
#define MAX_RETR_PACKETS_SINCE_LAST_ACK 2
|
||||
|
@ -421,6 +421,9 @@ ignore_hsk (struct ietf_full_conn *);
|
|||
static unsigned
|
||||
ietf_full_conn_ci_n_avail_streams (const struct lsquic_conn *);
|
||||
|
||||
static const lsquic_cid_t *
|
||||
ietf_full_conn_ci_get_log_cid (const struct lsquic_conn *);
|
||||
|
||||
|
||||
static unsigned
|
||||
highest_bit_set (unsigned sz)
|
||||
|
@ -480,6 +483,7 @@ idle_alarm_expired (enum alarm_id al_id, void *ctx, lsquic_time_t expiry,
|
|||
{
|
||||
struct ietf_full_conn *const conn = (struct ietf_full_conn *) ctx;
|
||||
LSQ_DEBUG("connection timed out");
|
||||
EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "connection timed out");
|
||||
conn->ifc_flags |= IFC_TIMED_OUT;
|
||||
}
|
||||
|
||||
|
@ -937,7 +941,7 @@ ietf_full_conn_init (struct ietf_full_conn *conn,
|
|||
|
||||
struct lsquic_conn *
|
||||
lsquic_ietf_full_conn_client_new (struct lsquic_engine_public *enpub,
|
||||
unsigned flags,
|
||||
unsigned versions, unsigned flags,
|
||||
const char *hostname, unsigned short max_packet_size, int is_ipv4,
|
||||
const unsigned char *zero_rtt, size_t zero_rtt_sz,
|
||||
const unsigned char *token, size_t token_sz)
|
||||
|
@ -946,7 +950,6 @@ lsquic_ietf_full_conn_client_new (struct lsquic_engine_public *enpub,
|
|||
struct ietf_full_conn *conn;
|
||||
enum lsquic_version ver, zero_rtt_version;
|
||||
lsquic_time_t now;
|
||||
unsigned versions;
|
||||
|
||||
conn = calloc(1, sizeof(*conn));
|
||||
if (!conn)
|
||||
|
@ -963,8 +966,8 @@ lsquic_ietf_full_conn_client_new (struct lsquic_engine_public *enpub,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
versions = enpub->enp_settings.es_versions & LSQUIC_IETF_VERSIONS;
|
||||
assert(versions);
|
||||
versions &= LSQUIC_IETF_VERSIONS;
|
||||
ver = highest_bit_set(versions);
|
||||
if (zero_rtt)
|
||||
{
|
||||
|
@ -1070,8 +1073,8 @@ lsquic_ietf_full_conn_client_new (struct lsquic_engine_public *enpub,
|
|||
lsquic_malo_create(sizeof(struct lsquic_packet_out));
|
||||
if (!conn->ifc_pub.packet_out_malo)
|
||||
{
|
||||
free(conn);
|
||||
lsquic_stream_destroy(conn->ifc_u.cli.crypto_streams[ENC_LEV_CLEAR]);
|
||||
free(conn);
|
||||
return NULL;
|
||||
}
|
||||
conn->ifc_flags |= IFC_PROC_CRYPTO;
|
||||
|
@ -2420,6 +2423,7 @@ ietf_full_conn_ci_destroy (struct lsquic_conn *lconn)
|
|||
lsquic_hash_destroy(conn->ifc_pub.u.ietf.promises);
|
||||
}
|
||||
lsquic_hash_destroy(conn->ifc_pub.all_streams);
|
||||
EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "full connection destroyed");
|
||||
free(conn->ifc_errmsg);
|
||||
free(conn);
|
||||
}
|
||||
|
@ -3133,6 +3137,7 @@ ietf_full_conn_ci_push_stream (struct lsquic_conn *lconn, void *hset,
|
|||
if (!uh)
|
||||
{
|
||||
LSQ_WARN("stream push: cannot allocate uh");
|
||||
free(promise);
|
||||
lsquic_mm_put_4k(conn->ifc_pub.mm, header_block_buf);
|
||||
if (own_hset)
|
||||
conn->ifc_enpub->enp_hsi_if->hsi_discard_header_set(hset);
|
||||
|
@ -5391,6 +5396,27 @@ try_queueing_ack (struct ietf_full_conn *conn, enum packnum_space pns,
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
maybe_queue_opp_ack (struct ietf_full_conn *conn)
|
||||
{
|
||||
if (/* If there is at least one ackable packet */
|
||||
conn->ifc_n_slack_akbl[PNS_APP] > 0
|
||||
/* ...and there are things to write */
|
||||
&& (!TAILQ_EMPTY(&conn->ifc_pub.write_streams) || conn->ifc_send_flags)
|
||||
/* ...and writing is possible */
|
||||
&& write_is_possible(conn))
|
||||
{
|
||||
lsquic_alarmset_unset(&conn->ifc_alset, AL_ACK_APP);
|
||||
lsquic_send_ctl_sanity_check(&conn->ifc_send_ctl);
|
||||
conn->ifc_flags |= IFC_ACK_QUED_APP;
|
||||
LSQ_DEBUG("%s ACK queued opportunistically", lsquic_pns2str[PNS_APP]);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
process_retry_packet (struct ietf_full_conn *conn,
|
||||
struct lsquic_packet_in *packet_in)
|
||||
|
@ -5750,8 +5776,7 @@ verneg_ok (const struct ietf_full_conn *conn)
|
|||
{
|
||||
enum lsquic_version ver;
|
||||
|
||||
ver = highest_bit_set(conn->ifc_enpub->enp_settings.es_versions
|
||||
& LSQUIC_IETF_VERSIONS);
|
||||
ver = highest_bit_set(conn->ifc_u.cli.ifcli_ver_neg.vn_supp);
|
||||
return (1 << ver) & LSQUIC_IETF_DRAFT_VERSIONS;
|
||||
}
|
||||
|
||||
|
@ -6005,7 +6030,8 @@ ietf_full_conn_ci_tick (struct lsquic_conn *lconn, lsquic_time_t now)
|
|||
have_delayed_packets =
|
||||
lsquic_send_ctl_maybe_squeeze_sched(&conn->ifc_send_ctl);
|
||||
|
||||
if (should_generate_ack(conn, IFC_ACK_QUEUED))
|
||||
if (should_generate_ack(conn, IFC_ACK_QUEUED) ||
|
||||
(!have_delayed_packets && maybe_queue_opp_ack(conn)))
|
||||
{
|
||||
if (have_delayed_packets)
|
||||
lsquic_send_ctl_reset_packnos(&conn->ifc_send_ctl);
|
||||
|
@ -6483,8 +6509,7 @@ ietf_full_conn_ci_record_addrs (struct lsquic_conn *lconn, void *peer_ctx,
|
|||
if (first_unvalidated || first_other)
|
||||
{
|
||||
victim = first_unvalidated ? first_unvalidated : first_other;
|
||||
record_to_path(&first_unvalidated->cop_path, peer_ctx, local_sa,
|
||||
peer_sa);
|
||||
record_to_path(&victim->cop_path, peer_ctx, local_sa, peer_sa);
|
||||
return victim - conn->ifc_paths;
|
||||
}
|
||||
|
||||
|
|
|
@ -2892,6 +2892,7 @@ gquic_decrypt_packet (enc_session_t *enc_session_p,
|
|||
return DECPI_NOMEM;
|
||||
}
|
||||
|
||||
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,
|
||||
|
|
|
@ -261,10 +261,10 @@ lsquic_logger_log3 (enum lsq_log_level log_level,
|
|||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
lb = vsnprintf(buf + len, max - len, fmt, ap);
|
||||
va_end(ap);
|
||||
if (FORMAT_PROBLEM(lb, len, max))
|
||||
goto end;
|
||||
len += lb;
|
||||
va_end(ap);
|
||||
lb = snprintf(buf + len, max - len, "\n");
|
||||
if (FORMAT_PROBLEM(lb, len, max))
|
||||
goto end;
|
||||
|
@ -303,10 +303,10 @@ lsquic_logger_log2 (enum lsq_log_level log_level,
|
|||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
lb = vsnprintf(buf + len, max - len, fmt, ap);
|
||||
va_end(ap);
|
||||
if (FORMAT_PROBLEM(lb, len, max))
|
||||
goto end;
|
||||
len += lb;
|
||||
va_end(ap);
|
||||
lb = snprintf(buf + len, max - len, "\n");
|
||||
if (FORMAT_PROBLEM(lb, len, max))
|
||||
goto end;
|
||||
|
@ -343,10 +343,10 @@ lsquic_logger_log1 (enum lsq_log_level log_level,
|
|||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
lb = vsnprintf(buf + len, max - len, fmt, ap);
|
||||
va_end(ap);
|
||||
if (FORMAT_PROBLEM(lb, len, max))
|
||||
goto end;
|
||||
len += lb;
|
||||
va_end(ap);
|
||||
lb = snprintf(buf + len, max - len, "\n");
|
||||
if (FORMAT_PROBLEM(lb, len, max))
|
||||
goto end;
|
||||
|
|
|
@ -58,10 +58,12 @@ lsquic_gquic_gen_ver_nego_pkt (unsigned char *buf, size_t bufsz,
|
|||
const lsquic_cid_t *cid, unsigned versions);
|
||||
int
|
||||
lsquic_Q046_gen_ver_nego_pkt (unsigned char *buf, size_t bufsz,
|
||||
const lsquic_cid_t *scid, const lsquic_cid_t *dcid, unsigned versions);
|
||||
const lsquic_cid_t *scid, const lsquic_cid_t *dcid, unsigned versions,
|
||||
uint8_t);
|
||||
int
|
||||
lsquic_ietf_v1_gen_ver_nego_pkt (unsigned char *buf, size_t bufsz,
|
||||
const lsquic_cid_t *scid, const lsquic_cid_t *dcid, unsigned versions);
|
||||
const lsquic_cid_t *scid, const lsquic_cid_t *dcid, unsigned versions,
|
||||
uint8_t);
|
||||
int
|
||||
lsquic_iquic_gen_retry_pkt (unsigned char *buf, size_t bufsz,
|
||||
const struct lsquic_engine_public *, const lsquic_cid_t *scid,
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include <inttypes.h>
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/queue.h>
|
||||
#ifndef WIN32
|
||||
|
@ -1835,7 +1834,8 @@ popcount (unsigned v)
|
|||
|
||||
int
|
||||
lsquic_ietf_v1_gen_ver_nego_pkt (unsigned char *buf, size_t bufsz,
|
||||
const lsquic_cid_t *scid, const lsquic_cid_t *dcid, unsigned versions)
|
||||
const lsquic_cid_t *scid, const lsquic_cid_t *dcid, unsigned versions,
|
||||
uint8_t rand)
|
||||
{
|
||||
size_t need;
|
||||
int r;
|
||||
|
@ -1846,7 +1846,7 @@ lsquic_ietf_v1_gen_ver_nego_pkt (unsigned char *buf, size_t bufsz,
|
|||
if (need > bufsz)
|
||||
return -1;
|
||||
|
||||
*buf++ = 0x80 | 0x40 | rand();
|
||||
*buf++ = 0x80 | 0x40 | (rand & 0xF);
|
||||
memset(buf, 0, 4);
|
||||
buf += 4;
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -549,7 +548,8 @@ popcount (unsigned v)
|
|||
|
||||
int
|
||||
lsquic_Q046_gen_ver_nego_pkt (unsigned char *buf, size_t bufsz,
|
||||
const lsquic_cid_t *scid, const lsquic_cid_t *dcid, unsigned versions)
|
||||
const lsquic_cid_t *scid, const lsquic_cid_t *dcid, unsigned versions,
|
||||
uint8_t rand)
|
||||
{
|
||||
unsigned slen, dlen;
|
||||
size_t need;
|
||||
|
@ -561,7 +561,7 @@ lsquic_Q046_gen_ver_nego_pkt (unsigned char *buf, size_t bufsz,
|
|||
if (need > bufsz)
|
||||
return -1;
|
||||
|
||||
*buf++ = 0x80 | 0x40 | rand();
|
||||
*buf++ = 0x80 | 0x40 | (rand & 0xF);
|
||||
memset(buf, 0, 4);
|
||||
buf += 4;
|
||||
|
||||
|
|
|
@ -103,9 +103,19 @@ struct pr_queue
|
|||
unsigned char prq_pubres_g_buf[GQUIC_RESET_SZ];
|
||||
unsigned char prq_verneg_g_buf[1 + GQUIC_CID_LEN
|
||||
+ N_LSQVER * 4];
|
||||
/* We generate random nybbles in batches */
|
||||
#define NYBBLE_COUNT_BITS 4
|
||||
#define NYBBLE_COUNT (1 << NYBBLE_COUNT_BITS)
|
||||
#define NYBBLE_MASK (NYBBLE_COUNT - 1)
|
||||
unsigned prq_rand_nybble_off;
|
||||
uint8_t prq_rand_nybble_buf[NYBBLE_COUNT * 2];
|
||||
};
|
||||
|
||||
|
||||
static uint8_t
|
||||
get_rand_byte (struct pr_queue *);
|
||||
|
||||
|
||||
static int
|
||||
comp_reqs (const void *s1, const void *s2, size_t n)
|
||||
{
|
||||
|
@ -196,6 +206,7 @@ prq_create (unsigned max_elems, unsigned max_conns,
|
|||
prq->prq_verneg_g_sz = verneg_g_sz;
|
||||
prq->prq_pubres_g_sz = (unsigned) prst_g_sz;
|
||||
prq->prq_enpub = enpub;
|
||||
prq->prq_rand_nybble_off = 0;
|
||||
|
||||
LSQ_INFO("initialized queue of size %d", max_elems);
|
||||
|
||||
|
@ -264,7 +275,7 @@ prq_new_req (struct pr_queue *prq, enum packet_req_type type,
|
|||
lsquic_ver_tag_t ver_tag;
|
||||
enum lsquic_version version;
|
||||
enum pr_flags flags;
|
||||
unsigned max, size;
|
||||
unsigned max, size, rand;
|
||||
|
||||
if (packet_in->pi_flags & PI_GQUIC)
|
||||
flags = PR_GQUIC;
|
||||
|
@ -292,7 +303,10 @@ prq_new_req (struct pr_queue *prq, enum packet_req_type type,
|
|||
/* Use a random stateless reset size */
|
||||
max = MIN(IQUIC_MAX_SRST_SIZE, packet_in->pi_data_sz - 1u);
|
||||
if (max > IQUIC_MIN_SRST_SIZE)
|
||||
size = IQUIC_MIN_SRST_SIZE + rand() % (max - IQUIC_MIN_SRST_SIZE);
|
||||
{
|
||||
rand = get_rand_byte(prq);
|
||||
size = IQUIC_MIN_SRST_SIZE + rand % (max - IQUIC_MIN_SRST_SIZE);
|
||||
}
|
||||
else
|
||||
size = IQUIC_MIN_SRST_SIZE;
|
||||
LSQ_DEBUGC("selected %u-byte reset size for CID %"CID_FMT
|
||||
|
@ -398,6 +412,31 @@ get_evconn (struct pr_queue *prq)
|
|||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
get_rand_nybble (struct pr_queue *prq)
|
||||
{
|
||||
uint8_t byte;
|
||||
|
||||
if (prq->prq_rand_nybble_off == 0)
|
||||
RAND_bytes(prq->prq_rand_nybble_buf, sizeof(prq->prq_rand_nybble_buf));
|
||||
|
||||
byte = prq->prq_rand_nybble_buf[prq->prq_rand_nybble_off / 2];
|
||||
if (prq->prq_rand_nybble_off & 1)
|
||||
byte >>= 4;
|
||||
else
|
||||
byte &= 0xF;
|
||||
prq->prq_rand_nybble_off = (prq->prq_rand_nybble_off + 1) & NYBBLE_MASK;
|
||||
return byte;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
get_rand_byte (struct pr_queue *prq)
|
||||
{
|
||||
return (get_rand_nybble(prq) << 4) | get_rand_nybble(prq);
|
||||
}
|
||||
|
||||
|
||||
struct lsquic_conn *
|
||||
prq_next_conn (struct pr_queue *prq)
|
||||
{
|
||||
|
@ -407,7 +446,7 @@ prq_next_conn (struct pr_queue *prq)
|
|||
struct packet_req *req;
|
||||
struct lsquic_packet_out *packet_out;
|
||||
int (*gen_verneg) (unsigned char *, size_t, const lsquic_cid_t *,
|
||||
const lsquic_cid_t *, unsigned);
|
||||
const lsquic_cid_t *, unsigned, uint8_t);
|
||||
int len;
|
||||
|
||||
lconn = TAILQ_FIRST(&prq->prq_returned_conns);
|
||||
|
@ -451,7 +490,8 @@ prq_next_conn (struct pr_queue *prq)
|
|||
gen_verneg = lsquic_ietf_v1_gen_ver_nego_pkt;
|
||||
len = gen_verneg(packet_out->po_data, max_bufsz(prq),
|
||||
/* Flip SCID/DCID here: */ &req->pr_dcid, &req->pr_scid,
|
||||
prq->prq_enpub->enp_settings.es_versions);
|
||||
prq->prq_enpub->enp_settings.es_versions,
|
||||
get_rand_nybble(prq));
|
||||
if (len > 0)
|
||||
packet_out->po_data_sz = len;
|
||||
else
|
||||
|
|
|
@ -410,6 +410,7 @@ qdh_supply_hset_to_stream (struct qpack_dec_hdl *qdh,
|
|||
}
|
||||
|
||||
lsqpack_dec_destroy_header_list(qlist);
|
||||
qlist = NULL;
|
||||
st = hset_if->hsi_process_header(hset, 0, 0, 0, 0, 0);
|
||||
if (st != LSQUIC_HDR_OK)
|
||||
goto err;
|
||||
|
@ -431,7 +432,8 @@ qdh_supply_hset_to_stream (struct qpack_dec_hdl *qdh,
|
|||
return 0;
|
||||
|
||||
err:
|
||||
lsqpack_dec_destroy_header_list(qlist);
|
||||
if (qlist)
|
||||
lsqpack_dec_destroy_header_list(qlist);
|
||||
hset_if->hsi_discard_header_set(hset);
|
||||
free(uh);
|
||||
return -1;
|
||||
|
|
|
@ -114,7 +114,7 @@ lsquic_qeh_settings (struct qpack_enc_hdl *qeh, unsigned max_table_size,
|
|||
}
|
||||
|
||||
enc_opts = LSQPACK_ENC_OPT_STAGE_2
|
||||
| server ? LSQPACK_ENC_OPT_SERVER : 0;
|
||||
| (server ? LSQPACK_ENC_OPT_SERVER : 0);
|
||||
qeh->qeh_tsu_sz = sizeof(qeh->qeh_tsu_buf);
|
||||
if (0 != lsqpack_enc_init(&qeh->qeh_encoder, (void *) qeh->qeh_conn,
|
||||
max_table_size, dyn_table_size, max_risked_streams, enc_opts,
|
||||
|
|
|
@ -99,7 +99,8 @@ lsquic_qlog_packet_rx (const lsquic_cid_t* cid,
|
|||
const unsigned char *packet_in_data,
|
||||
size_t packet_in_size)
|
||||
{
|
||||
int i, cur = 0, first = 0, ret = 0;
|
||||
int i, first, ret;
|
||||
unsigned cur;
|
||||
size_t raw_bytes_written;
|
||||
char data[QLOG_PACKET_RAW_SZ];
|
||||
char frame_list[QLOG_FRAME_LIST_MAX + 1];
|
||||
|
@ -107,11 +108,12 @@ lsquic_qlog_packet_rx (const lsquic_cid_t* cid,
|
|||
if (!packet_in || !packet_in_data)
|
||||
return;
|
||||
|
||||
frame_list[cur] = '\0';
|
||||
if (packet_in->pi_frame_types)
|
||||
{
|
||||
cur = sprintf(frame_list, "%s", QLOG_FRAME_LIST_PREFIX);
|
||||
for (i = 0; i < N_QUIC_FRAMES; i++)
|
||||
memcpy(frame_list, QLOG_FRAME_LIST_PREFIX,
|
||||
sizeof(QLOG_FRAME_LIST_PREFIX));
|
||||
cur = sizeof(QLOG_FRAME_LIST_PREFIX) - 1;
|
||||
for (i = 0, first = 0; i < N_QUIC_FRAMES; i++)
|
||||
if (packet_in->pi_frame_types & (1 << i))
|
||||
{
|
||||
ret = snprintf(frame_list + cur,
|
||||
|
@ -124,13 +126,16 @@ lsquic_qlog_packet_rx (const lsquic_cid_t* cid,
|
|||
QLOG_FRAME_DICT_PREFIX),
|
||||
QUIC_FRAME_NAME(i),
|
||||
QLOG_FRAME_DICT_SUFFIX);
|
||||
if ((unsigned)ret > QLOG_FRAME_LIST_MAX - cur)
|
||||
if (ret < 0 || (unsigned)ret > QLOG_FRAME_LIST_MAX - cur)
|
||||
break;
|
||||
cur += ret;
|
||||
}
|
||||
if ((unsigned)cur <= QLOG_FRAME_LIST_MAX)
|
||||
sprintf(frame_list + cur, "%s", QLOG_FRAME_LIST_SUFFIX);
|
||||
if (cur + sizeof(QLOG_FRAME_LIST_SUFFIX) <= QLOG_FRAME_LIST_MAX)
|
||||
memcpy(frame_list + cur, QLOG_FRAME_LIST_SUFFIX,
|
||||
sizeof(QLOG_FRAME_LIST_SUFFIX));
|
||||
}
|
||||
else
|
||||
frame_list[0] = '\0';
|
||||
|
||||
raw_bytes_written = lsquic_hex_encode(packet_in_data, packet_in_size,
|
||||
data, QLOG_PACKET_RAW_SZ);
|
||||
|
|
|
@ -2402,7 +2402,7 @@ split_buffered_packet (lsquic_send_ctl_t *ctl,
|
|||
|
||||
new_packet_out = send_ctl_allocate_packet(ctl, bits, 0,
|
||||
lsquic_packet_out_pns(packet_out), packet_out->po_path);
|
||||
if (!packet_out)
|
||||
if (!new_packet_out)
|
||||
return -1;
|
||||
|
||||
if (0 == lsquic_packet_out_split_in_two(&ctl->sc_enpub->enp_mm, packet_out,
|
||||
|
|
|
@ -46,6 +46,7 @@ add_stream_to_spi (struct stream_prio_iter *iter, lsquic_stream_t *stream)
|
|||
}
|
||||
TAILQ_INSERT_TAIL(&iter->spi_streams[ stream->sm_priority ],
|
||||
stream, next_prio_stream);
|
||||
++iter->spi_n_added;
|
||||
}
|
||||
|
||||
|
||||
|
@ -70,6 +71,7 @@ lsquic_spi_init (struct stream_prio_iter *iter, struct lsquic_stream *first,
|
|||
iter->spi_cur_prio = 0;
|
||||
iter->spi_prev_stream = NULL;
|
||||
iter->spi_next_stream = NULL;
|
||||
iter->spi_n_added = 0;
|
||||
|
||||
stream = first;
|
||||
count = 0;
|
||||
|
@ -302,12 +304,53 @@ have_non_critical_streams (const struct stream_prio_iter *iter)
|
|||
}
|
||||
|
||||
|
||||
#if __GNUC__
|
||||
# define popcount __builtin_popcountll
|
||||
#else
|
||||
static int
|
||||
popcount (unsigned long long v)
|
||||
{
|
||||
int count, i;
|
||||
for (i = 0, count = 0; i < sizeof(v) * 8; ++i)
|
||||
if (v & (1 << i))
|
||||
++count;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static int
|
||||
spi_has_more_than_one_queue (const struct stream_prio_iter *iter)
|
||||
{
|
||||
unsigned i;
|
||||
int count;
|
||||
|
||||
if (iter->spi_n_added < 2)
|
||||
return 0;
|
||||
|
||||
count = 0;
|
||||
for (i = 0; i < sizeof(iter->spi_set) / sizeof(iter->spi_set[0]); ++i)
|
||||
{
|
||||
count += popcount(iter->spi_set[i]);
|
||||
if (count > 1)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
spi_drop_high_or_non_high (struct stream_prio_iter *iter, int drop_high)
|
||||
{
|
||||
uint64_t new_set[ sizeof(iter->spi_set) / sizeof(iter->spi_set[0]) ];
|
||||
unsigned bit, set, n;
|
||||
|
||||
if (!spi_has_more_than_one_queue(iter))
|
||||
return;
|
||||
|
||||
memset(new_set, 0, sizeof(new_set));
|
||||
|
||||
find_and_set_lowest_priority(iter);
|
||||
|
|
|
@ -23,6 +23,7 @@ struct stream_prio_iter
|
|||
const char *spi_name; /* Used for logging */
|
||||
uint64_t spi_set[4]; /* 256 bits */
|
||||
enum stream_q_flags spi_onlist_mask;
|
||||
unsigned spi_n_added;
|
||||
unsigned char spi_cur_prio;
|
||||
unsigned char spi_prev_prio;
|
||||
struct lsquic_stream *spi_prev_stream,
|
||||
|
|
|
@ -677,11 +677,25 @@ lsquic_stream_call_on_close (lsquic_stream_t *stream)
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
stream_has_frame_at_read_offset (struct lsquic_stream *stream)
|
||||
{
|
||||
if (!((stream->stream_flags & STREAM_CACHED_FRAME)
|
||||
&& stream->read_offset == stream->sm_last_frame_off))
|
||||
{
|
||||
stream->sm_has_frame = stream->data_in->di_if->di_get_frame(
|
||||
stream->data_in, stream->read_offset) != NULL;
|
||||
stream->sm_last_frame_off = stream->read_offset;
|
||||
stream->stream_flags |= STREAM_CACHED_FRAME;
|
||||
}
|
||||
return stream->sm_has_frame;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
stream_readable_non_http (struct lsquic_stream *stream)
|
||||
{
|
||||
return stream->data_in->di_if->di_get_frame(stream->data_in,
|
||||
stream->read_offset) != NULL;
|
||||
return stream_has_frame_at_read_offset(stream);
|
||||
}
|
||||
|
||||
|
||||
|
@ -690,8 +704,7 @@ stream_readable_http_gquic (struct lsquic_stream *stream)
|
|||
{
|
||||
return (stream->stream_flags & STREAM_HAVE_UH)
|
||||
&& (stream->uh
|
||||
|| stream->data_in->di_if->di_get_frame(stream->data_in,
|
||||
stream->read_offset));
|
||||
|| stream_has_frame_at_read_offset(stream));
|
||||
}
|
||||
|
||||
|
||||
|
@ -708,8 +721,7 @@ stream_readable_http_ietf (struct lsquic_stream *stream)
|
|||
(stream->sm_sfi->sfi_readable(stream)
|
||||
&& (/* Running the filter may result in hitting FIN: */
|
||||
(stream->stream_flags & STREAM_FIN_REACHED)
|
||||
|| stream->data_in->di_if->di_get_frame(stream->data_in,
|
||||
stream->read_offset)));
|
||||
|| stream_has_frame_at_read_offset(stream)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -940,6 +952,7 @@ lsquic_stream_frame_in (lsquic_stream_t *stream, stream_frame_t *frame)
|
|||
end_ok:
|
||||
if (free_frame)
|
||||
lsquic_malo_put(frame);
|
||||
stream->stream_flags &= ~STREAM_CACHED_FRAME;
|
||||
return rv;
|
||||
}
|
||||
else if (INS_FRAME_DUP == ins_frame)
|
||||
|
@ -977,6 +990,7 @@ drop_frames_in (lsquic_stream_t *stream)
|
|||
* dropped.
|
||||
*/
|
||||
stream->data_in = data_in_error_new();
|
||||
stream->stream_flags &= ~STREAM_CACHED_FRAME;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1462,7 +1476,7 @@ readv_f (void *ctx_p, const unsigned char *buf, size_t len, int fin)
|
|||
if (ctx->iov < ctx->end)
|
||||
ctx->p = ctx->iov->iov_base;
|
||||
else
|
||||
ctx->p = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2584,7 +2598,9 @@ frame_hq_gen_read (void *ctx, void *begin_buf, size_t len, int *fin)
|
|||
rem = (1 << 14) - 1;
|
||||
shf = stream_activate_hq_frame(stream,
|
||||
stream->sm_payload, HQFT_DATA, 0, rem);
|
||||
if (!shf)
|
||||
if (shf)
|
||||
goto insert;
|
||||
else
|
||||
{
|
||||
/* TODO: abort connection? Handle failure somehow */
|
||||
break;
|
||||
|
@ -2593,10 +2609,10 @@ frame_hq_gen_read (void *ctx, void *begin_buf, size_t len, int *fin)
|
|||
else
|
||||
break;
|
||||
}
|
||||
avail = stream->sm_n_buffered + stream->sm_write_avail(stream);
|
||||
if (shf->shf_off == stream->sm_payload
|
||||
&& !(shf->shf_flags & SHF_WRITTEN))
|
||||
{
|
||||
insert:
|
||||
frame_sz = stream_hq_frame_size(shf);
|
||||
if (frame_sz > (uintptr_t) (end - p))
|
||||
{
|
||||
|
@ -2634,6 +2650,7 @@ frame_hq_gen_read (void *ctx, void *begin_buf, size_t len, int *fin)
|
|||
}
|
||||
else
|
||||
{
|
||||
avail = stream->sm_n_buffered + stream->sm_write_avail(stream);
|
||||
len = stream_hq_frame_end(shf) - stream->sm_payload;
|
||||
assert(len);
|
||||
if (len > (unsigned) (end - p))
|
||||
|
|
|
@ -194,7 +194,7 @@ enum stream_flags {
|
|||
STREAM_FIN_REACHED = 1 << 7, /* User read data up to FIN */
|
||||
STREAM_FINISHED = 1 << 8, /* Stream is finished */
|
||||
STREAM_ONCLOSE_DONE = 1 << 9, /* on_close has been called */
|
||||
STREAM_UNUSED10 = 1 << 10, /* Unused */
|
||||
STREAM_CACHED_FRAME = 1 << 10, /* If set, sm_has_frame can be used */
|
||||
STREAM_HEADERS_SENT = 1 << 11,
|
||||
STREAM_HAVE_UH = 1 << 12, /* Have uncompressed headers */
|
||||
STREAM_ENCODER_DEP = 1 << 13, /* Encoder dependency: flush (IETF only) */
|
||||
|
@ -310,6 +310,8 @@ struct lsquic_stream
|
|||
/* Push promises sent on this stream */
|
||||
SLIST_HEAD(, push_promise) sm_promises;
|
||||
|
||||
uint64_t sm_last_frame_off;
|
||||
|
||||
/* How much data there is in sm_header_block and how much of it has been
|
||||
* sent:
|
||||
*/
|
||||
|
@ -327,6 +329,7 @@ struct lsquic_stream
|
|||
SSHS_HBLOCK_SENDING,/* Sending header block data */
|
||||
} sm_send_headers_state:8;
|
||||
signed char sm_saved_want_write;
|
||||
signed char sm_has_frame;
|
||||
|
||||
unsigned char sm_dup_push_off;
|
||||
unsigned char sm_dup_push_len;
|
||||
|
|
|
@ -1168,6 +1168,8 @@ interop_server_hset_add_header (void *hset_p, unsigned name_idx,
|
|||
req->qif_str[req->qif_sz + name_len + 1 + value_len] = '\n';
|
||||
req->qif_sz += name_len + value_len + 2;
|
||||
}
|
||||
else
|
||||
return LSQUIC_HDR_OK;
|
||||
|
||||
if (5 == name_len && 0 == strncmp(name, ":path", 5))
|
||||
{
|
||||
|
|
|
@ -368,7 +368,7 @@ prog_connect (struct prog *prog, unsigned char *zero_rtt, size_t zero_rtt_len)
|
|||
struct service_port *sport;
|
||||
|
||||
sport = TAILQ_FIRST(prog->prog_sports);
|
||||
if (NULL == lsquic_engine_connect(prog->prog_engine,
|
||||
if (NULL == lsquic_engine_connect(prog->prog_engine, N_LSQVER,
|
||||
(struct sockaddr *) &sport->sp_local_addr,
|
||||
(struct sockaddr *) &sport->sas, sport, NULL,
|
||||
prog->prog_hostname ? prog->prog_hostname : sport->host,
|
||||
|
|
|
@ -117,8 +117,6 @@ load_cert (struct lsquic_hash *certs, const char *optarg)
|
|||
|
||||
end:
|
||||
free(sni);
|
||||
if (f)
|
||||
fclose(f);
|
||||
if (rv != 0)
|
||||
{ /* Error: free cert and its components */
|
||||
if (cert)
|
||||
|
|
|
@ -1592,15 +1592,14 @@ send_packets_one_by_one (const struct lsquic_out_spec *specs, unsigned count)
|
|||
|
||||
if (n > 0)
|
||||
return n;
|
||||
else if (s < 0)
|
||||
else
|
||||
{
|
||||
assert(s < 0);
|
||||
#if LSQUIC_RANDOM_SEND_FAILURE
|
||||
random_send_failure:
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -32,6 +32,21 @@ alarm_cb (enum alarm_id al_id, void *ctx, lsquic_time_t expiry,
|
|||
}
|
||||
|
||||
|
||||
#if __GNUC__
|
||||
# define popcount __builtin_popcount
|
||||
#else
|
||||
static int
|
||||
popcount (unsigned v)
|
||||
{
|
||||
int count, i;
|
||||
for (i = 0, count = 0; i < sizeof(v) * 8; ++i)
|
||||
if (v & (1 << i))
|
||||
++count;
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
|
@ -83,5 +98,32 @@ main (void)
|
|||
assert(4 == global_ctx.n_calls);
|
||||
assert(20 == global_ctx.last_expiry);
|
||||
|
||||
unsigned t = 1;
|
||||
for (i = 1; i < (1u << MAX_LSQUIC_ALARMS); ++i)
|
||||
{
|
||||
alset.as_armed_set = 0; /* Unset all */
|
||||
unsigned const count = popcount(i);
|
||||
unsigned const min_n = i % count;
|
||||
unsigned const min_t = t++;
|
||||
unsigned j, n, ids[2];
|
||||
for (j = 0, n = 0; j < MAX_LSQUIC_ALARMS; ++j)
|
||||
{
|
||||
if ((1u << j) & i)
|
||||
{
|
||||
if (n == min_n)
|
||||
{
|
||||
ids[0] = j;
|
||||
lsquic_alarmset_set(&alset, j, min_t);
|
||||
}
|
||||
else
|
||||
lsquic_alarmset_set(&alset, j, t++);
|
||||
++n;
|
||||
}
|
||||
}
|
||||
lsquic_time_t found_min_t = lsquic_alarmset_mintime(&alset, &ids[1]);
|
||||
assert(min_t == found_min_t);
|
||||
assert(ids[0] == ids[1]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -690,7 +690,7 @@ test_frame_header_split (unsigned n_packets)
|
|||
|
||||
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 */
|
||||
|
|
|
@ -147,7 +147,7 @@ main (int argc, char **argv)
|
|||
cid.idbuf[2] = i;
|
||||
puel = lsquic_purga_contains(purga, &cid);
|
||||
assert(puel && PUTY_CONN_DELETED == puel->puel_type);
|
||||
~i == puel->puel_time;
|
||||
assert(~i == puel->puel_time);
|
||||
}
|
||||
|
||||
++cid.idbuf[1];
|
||||
|
|
|
@ -152,25 +152,31 @@ test_different_priorities (int *priority)
|
|||
struct stream_info
|
||||
{
|
||||
uint32_t stream_id;
|
||||
enum stream_b_flags bflags;
|
||||
unsigned char prio;
|
||||
};
|
||||
|
||||
|
||||
const struct stream_info infos1[] = {
|
||||
{ LSQUIC_GQUIC_STREAM_HANDSHAKE, 0, },
|
||||
{ LSQUIC_GQUIC_STREAM_HEADERS, 0, },
|
||||
{ 5, 0, },
|
||||
{ 7, 1, },
|
||||
{ 127, 200, },
|
||||
{ LSQUIC_GQUIC_STREAM_HANDSHAKE, SMBF_CRITICAL, 0, },
|
||||
{ LSQUIC_GQUIC_STREAM_HEADERS, SMBF_CRITICAL, 0, },
|
||||
{ 5, 0, 0, },
|
||||
{ 7, 0, 1, },
|
||||
{ 127, 0, 200, },
|
||||
};
|
||||
|
||||
|
||||
const struct stream_info infos2[] = {
|
||||
{ LSQUIC_GQUIC_STREAM_HANDSHAKE, 0, },
|
||||
{ LSQUIC_GQUIC_STREAM_HEADERS, 0, },
|
||||
{ 5, 4, },
|
||||
{ 7, 1, },
|
||||
{ 127, 200, },
|
||||
{ LSQUIC_GQUIC_STREAM_HANDSHAKE, SMBF_CRITICAL, 0, },
|
||||
{ LSQUIC_GQUIC_STREAM_HEADERS, SMBF_CRITICAL, 0, },
|
||||
{ 5, 0, 4, },
|
||||
{ 7, 0, 1, },
|
||||
{ 127, 0, 200, },
|
||||
};
|
||||
|
||||
|
||||
const struct stream_info infos3[] = {
|
||||
{ 0, 0, 0, },
|
||||
};
|
||||
|
||||
|
||||
|
@ -185,6 +191,7 @@ struct drop_test
|
|||
static const struct drop_test drop_tests[] = {
|
||||
{ infos1, 5, 0x7, },
|
||||
{ infos2, 5, 0x3, },
|
||||
{ infos3, 1, 0x0, },
|
||||
};
|
||||
|
||||
|
||||
|
@ -203,7 +210,7 @@ test_drop (const struct drop_test *test)
|
|||
{
|
||||
stream_arr[n].sm_priority = test->infos[n].prio;
|
||||
stream_arr[n].id = test->infos[n].stream_id;
|
||||
stream_arr[n].sm_bflags = SMBF_USE_HEADERS;
|
||||
stream_arr[n].sm_bflags = SMBF_USE_HEADERS | test->infos[n].bflags;
|
||||
}
|
||||
|
||||
for (drop_high = 0; drop_high < 2; ++drop_high)
|
||||
|
@ -227,7 +234,9 @@ test_drop (const struct drop_test *test)
|
|||
stream = lsquic_spi_next(&spi))
|
||||
seen_mask |= 1 << (stream - stream_arr);
|
||||
|
||||
if (drop_high)
|
||||
if (test->n_infos == 1)
|
||||
assert(seen_mask == (1u << test->infos[0].stream_id));
|
||||
else if (drop_high)
|
||||
assert((((1 << test->n_infos) - 1) & ~test->high_streams) == seen_mask);
|
||||
else
|
||||
assert(test->high_streams == seen_mask);
|
||||
|
|
|
@ -144,7 +144,7 @@ run_gvnt (int i)
|
|||
/* XXX this is never executed, as there is no test case for this */
|
||||
scid = (lsquic_cid_t) { .len = 0, };
|
||||
len = lsquic_Q046_gen_ver_nego_pkt(out, gvnt->gvnt_bufsz, &dcid,
|
||||
&scid, gvnt->gvnt_versions);
|
||||
&scid, gvnt->gvnt_versions, ((unsigned char) rand()) & 0xF);
|
||||
}
|
||||
assert(("Packet length is correct", len == gvnt->gvnt_len));
|
||||
|
||||
|
|
Loading…
Reference in a new issue