Release 2.10.0

- [FEATURE] QUIC and HTTP/3 Internet Draft 25 support.
- [API] Drop support for ID-23.
- [BUGFIX] Set key phase bit on outgoing packets correctly.
- Code cleanup.
This commit is contained in:
Dmitri Tikhonov 2020-01-28 09:35:09 -05:00
parent fb96f4dd43
commit 9fc120419d
51 changed files with 8220 additions and 258 deletions

View File

@ -1,3 +1,10 @@
2020-01-28
- 2.10.0
- [FEATURE] QUIC and HTTP/3 Internet Draft 25 support.
- [API] Drop support for ID-23.
- [BUGFIX] Set key phase bit on outgoing packets correctly.
- Code cleanup.
2020-01-20
- 2.9.0
- [API] Drop support for Q039.

View File

@ -15,7 +15,7 @@ and OpenLiteSpeed. We think it is free of major problems. Nevertheless, do
not hesitate to report bugs back to us. Even better, send us fixes and
improvements!
Currently supported QUIC versions are Q043, Q046, Q050, ID-23, and ID-24.
Currently supported QUIC versions are Q043, Q046, Q050, ID-24, and ID-25.
Support for newer versions will be added soon after they are released.
Documentation

View File

@ -24,7 +24,7 @@ extern "C" {
#endif
#define LSQUIC_MAJOR_VERSION 2
#define LSQUIC_MINOR_VERSION 9
#define LSQUIC_MINOR_VERSION 10
#define LSQUIC_PATCH_VERSION 0
/**
@ -133,16 +133,16 @@ enum lsquic_version
#define LSQUIC_EXPERIMENTAL_Q098 0
#endif
/**
* IETF QUIC Draft-23
*/
LSQVER_ID23,
/**
* IETF QUIC Draft-24
*/
LSQVER_ID24,
/**
* IETF QUIC Draft-25
*/
LSQVER_ID25,
/**
* Special version to trigger version negotiation.
* [draft-ietf-quic-transport-11], Section 3.
@ -153,7 +153,7 @@ enum lsquic_version
};
/**
* We currently support versions 43, 46, 50, and IETF Draft-23 and Draft-24
* We currently support versions 43, 46, 50, and Draft-24
* @see lsquic_version
*/
#define LSQUIC_SUPPORTED_VERSIONS ((1 << N_LSQVER) - 1)
@ -170,10 +170,10 @@ enum lsquic_version
#define LSQUIC_GQUIC_HEADER_VERSIONS (1 << LSQVER_043)
#define LSQUIC_IETF_VERSIONS ((1 << LSQVER_ID23) | (1 << LSQVER_ID24) \
#define LSQUIC_IETF_VERSIONS ((1 << LSQVER_ID24) | (1 << LSQVER_ID25) \
| (1 << LSQVER_VERNEG))
#define LSQUIC_IETF_DRAFT_VERSIONS ((1 << LSQVER_ID23) | (1 << LSQVER_ID24) \
#define LSQUIC_IETF_DRAFT_VERSIONS ((1 << LSQVER_ID24) | (1 << LSQVER_ID25) \
| (1 << LSQVER_VERNEG))
enum lsquic_hsk_status

View File

@ -26,6 +26,7 @@ SET(lsquic_STAT_SRCS
lsquic_frame_reader.c
lsquic_frame_writer.c
lsquic_full_conn.c
lsquic_full_conn_id24.c
lsquic_full_conn_ietf.c
lsquic_global.c
lsquic_handshake.c

View File

@ -31,6 +31,7 @@ liblsquic_a_SOURCES = ls-qpack/lsqpack.c \
lsquic_frame_reader.c \
lsquic_frame_writer.c \
lsquic_full_conn.c \
lsquic_full_conn_id24.c \
lsquic_full_conn_ietf.c \
lsquic_global.c \
lsquic_handshake.c \

View File

@ -48,6 +48,7 @@ const char *const lsquic_alid2str[] =
[AL_PATH_CHAL_0] = "PATH_CHAL_0",
[AL_PATH_CHAL_1] = "PATH_CHAL_1",
[AL_SESS_TICKET] = "SESS_TICKET",
[AL_BLOCKED_KA] = "BLOCKED_KA",
};

View File

@ -36,6 +36,7 @@ enum alarm_id {
AL_PATH_CHAL_0 = AL_PATH_CHAL,
AL_PATH_CHAL_1,
AL_SESS_TICKET,
AL_BLOCKED_KA, /* Blocked Keep-Alive */
MAX_LSQUIC_ALARMS
};
@ -55,6 +56,7 @@ enum alarm_id_bit {
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,
ALBIT_BLOCKED_KA = 1 << AL_BLOCKED_KA,
};

View File

@ -164,14 +164,8 @@ set_startup_values (struct lsquic_bbr *bbr)
static void
lsquic_bbr_init (void *cong_ctl, const struct lsquic_conn_public *conn_pub,
enum quic_ft_bit retx_frames)
init_bbr (struct lsquic_bbr *bbr)
{
struct lsquic_bbr *const bbr = cong_ctl;
bbr->bbr_conn_pub = conn_pub;
lsquic_bw_sampler_init(&bbr->bbr_bw_sampler, conn_pub->lconn, retx_frames);
bbr->bbr_rtt_stats = &conn_pub->rtt_stats;
bbr->bbr_mode = BBR_MODE_STARTUP;
bbr->bbr_round_count = 0;
minmax_init(&bbr->bbr_max_bandwidth, 10);
@ -203,13 +197,36 @@ lsquic_bbr_init (void *cong_ctl, const struct lsquic_conn_public *conn_pub,
bbr->bbr_flags &= ~BBR_FLAG_LAST_SAMPLE_APP_LIMITED;
bbr->bbr_flags &= ~BBR_FLAG_HAS_NON_APP_LIMITED;
bbr->bbr_flags &= ~BBR_FLAG_FLEXIBLE_APP_LIMITED;
set_startup_values(bbr);
}
static void
lsquic_bbr_init (void *cong_ctl, const struct lsquic_conn_public *conn_pub,
enum quic_ft_bit retx_frames)
{
struct lsquic_bbr *const bbr = cong_ctl;
bbr->bbr_conn_pub = conn_pub;
lsquic_bw_sampler_init(&bbr->bbr_bw_sampler, conn_pub->lconn, retx_frames);
bbr->bbr_rtt_stats = &conn_pub->rtt_stats;
init_bbr(bbr);
LSQ_DEBUG("initialized");
}
static void
lsquic_bbr_reinit (void *cong_ctl)
{
struct lsquic_bbr *const bbr = cong_ctl;
init_bbr(bbr);
LSQ_DEBUG("re-initialized");
}
static lsquic_time_t
get_min_rtt (const struct lsquic_bbr *bbr)
{
@ -1060,6 +1077,7 @@ const struct cong_ctl_if lsquic_cong_bbr_if =
.cci_pacing_rate = lsquic_bbr_pacing_rate,
.cci_loss = lsquic_bbr_loss,
.cci_lost = lsquic_bbr_lost,
.cci_reinit = lsquic_bbr_reinit,
.cci_timeout = lsquic_bbr_timeout,
.cci_sent = lsquic_bbr_sent,
.cci_was_quiet = lsquic_bbr_was_quiet,

View File

@ -23,6 +23,9 @@ struct cong_ctl_if
(*cci_init) (void *cong_ctl, const struct lsquic_conn_public *,
enum quic_ft_bit);
void
(*cci_reinit) (void *cong_ctl);
void
(*cci_ack) (void *cong_ctl, struct lsquic_packet_out *, unsigned packet_sz,
lsquic_time_t now, int app_limited);

View File

@ -137,6 +137,16 @@ lsquic_cubic_init (void *cong_ctl, const struct lsquic_conn_public *conn_pub,
}
static void
lsquic_cubic_reinit (void *cong_ctl)
{
struct lsquic_cubic *const cubic = cong_ctl;
cubic_reset(cubic);
cubic->cu_ssthresh = 10000 * TCP_MSS; /* Emulate "unbounded" slow start */
LSQ_DEBUG("re-initialized");
}
#define LOG_CWND(c) do { \
if (LSQ_LOG_ENABLED(LSQ_LOG_INFO)) { \
lsquic_time_t now = lsquic_time_now(); \
@ -278,6 +288,7 @@ const struct cong_ctl_if lsquic_cong_cubic_if =
.cci_init = lsquic_cubic_init,
.cci_pacing_rate = lsquic_cubic_pacing_rate,
.cci_loss = lsquic_cubic_loss,
.cci_reinit = lsquic_cubic_reinit,
.cci_timeout = lsquic_cubic_timeout,
.cci_was_quiet = lsquic_cubic_was_quiet,
};

View File

@ -295,7 +295,7 @@ struct enc_session_funcs_iquic
const char *);
void
(*esfi_1rtt_acked)(enc_session_t *);
(*esfi_handshake_confirmed)(enc_session_t *);
};
extern
@ -321,8 +321,8 @@ struct enc_session_funcs_gquic lsquic_enc_session_gquic_gquic_1;
extern const struct enc_session_funcs_iquic lsquic_enc_session_iquic_ietf_v1;
#define select_esf_common_by_ver(ver) ( \
ver == LSQVER_ID23 ? &lsquic_enc_session_common_ietf_v1 : \
ver == LSQVER_ID24 ? &lsquic_enc_session_common_ietf_v1 : \
ver == LSQVER_ID25 ? &lsquic_enc_session_common_ietf_v1 : \
ver == LSQVER_VERNEG ? &lsquic_enc_session_common_ietf_v1 : \
ver == LSQVER_050 ? &lsquic_enc_session_common_gquic_2 : \
&lsquic_enc_session_common_gquic_1 )

View File

@ -74,8 +74,8 @@ static const struct alpn_map {
const unsigned char *alpn;
} s_alpns[] = {
{ LSQVER_ID24, (unsigned char *) "\x05h3-24", },
{ LSQVER_ID23, (unsigned char *) "\x05h3-23", },
{ LSQVER_VERNEG, (unsigned char *) "\x05h3-24", },
{ LSQVER_ID25, (unsigned char *) "\x05h3-25", },
{ LSQVER_VERNEG, (unsigned char *) "\x05h3-25", },
};
struct enc_sess_iquic;
@ -235,7 +235,7 @@ struct enc_sess_iquic
ESI_HAVE_PEER_TP = 1 << 7,
ESI_ALPN_CHECKED = 1 << 8,
ESI_CACHED_INFO = 1 << 9,
ESI_1RTT_ACKED = 1 << 10,
ESI_HSK_CONFIRMED= 1 << 10,
ESI_WANT_TICKET = 1 << 11,
ESI_RECV_QL_BITS = 1 << 12,
ESI_SEND_QL_BITS = 1 << 13,
@ -533,12 +533,16 @@ gen_trans_params (struct enc_sess_iquic *enc_sess, unsigned char *buf,
= settings->es_init_max_streams_bidi;
params.tp_ack_delay_exponent
= TP_DEF_ACK_DELAY_EXP;
params.tp_idle_timeout = settings->es_idle_timeout * 1000;
params.tp_max_idle_timeout = settings->es_idle_timeout * 1000;
params.tp_max_ack_delay = TP_DEF_MAX_ACK_DELAY;
params.tp_max_packet_size = 1370 /* XXX: based on socket */;
params.tp_active_connection_id_limit = MAX_IETF_CONN_DCIDS
params.tp_active_connection_id_limit = MAX_IETF_CONN_DCIDS;
if (enc_sess->esi_conn->cn_version == LSQVER_ID24)
{
params.tp_active_connection_id_limit = params.tp_active_connection_id_limit
- 1 /* One slot is used by peer's SCID */
- !!(params.tp_flags & (TRAPA_PREFADDR_IPv4|TRAPA_PREFADDR_IPv6));
}
if (!settings->es_allow_migration)
params.tp_disable_active_migration = 1;
if (settings->es_ql_bits == -1)
@ -1828,10 +1832,7 @@ static struct ku_label
select_ku_label (const struct enc_sess_iquic *enc_sess)
{
if (enc_sess->esi_conn->cn_version == LSQVER_ID23)
return (struct ku_label) { "traffic upd", 11, };
else
return (struct ku_label) { "quic ku", 7, };
return (struct ku_label) { "quic ku", 7, };
}
@ -2226,14 +2227,14 @@ iquic_esfi_reset_dcid (enc_session_t *enc_session_p,
static void
iquic_esfi_1rtt_acked (enc_session_t *sess)
iquic_esfi_handshake_confirmed (enc_session_t *sess)
{
struct enc_sess_iquic *enc_sess = (struct enc_sess_iquic *) sess;
if (!(enc_sess->esi_flags & ESI_1RTT_ACKED))
if (!(enc_sess->esi_flags & ESI_HSK_CONFIRMED))
{
LSQ_DEBUG("1RTT packet has been acked");
enc_sess->esi_flags |= ESI_1RTT_ACKED;
LSQ_DEBUG("handshake has been confirmed");
enc_sess->esi_flags |= ESI_HSK_CONFIRMED;
maybe_drop_SSL(enc_sess);
}
}
@ -2254,7 +2255,8 @@ const struct enc_session_funcs_iquic lsquic_enc_session_iquic_ietf_v1 =
.esfi_set_streams = iquic_esfi_set_streams,
.esfi_create_server = iquic_esfi_create_server,
.esfi_shake_stream = iquic_esfi_shake_stream,
.esfi_1rtt_acked = iquic_esfi_1rtt_acked,
.esfi_handshake_confirmed
= iquic_esfi_handshake_confirmed,
};
@ -2310,8 +2312,8 @@ maybe_drop_SSL (struct enc_sess_iquic *enc_sess)
* in which case we can close it, or (unlikely) they are buffered in the
* frab list.
*/
if ((enc_sess->esi_flags & (ESI_1RTT_ACKED|ESI_HANDSHAKE_OK))
== (ESI_1RTT_ACKED|ESI_HANDSHAKE_OK)
if ((enc_sess->esi_flags & (ESI_HSK_CONFIRMED|ESI_HANDSHAKE_OK))
== (ESI_HSK_CONFIRMED|ESI_HANDSHAKE_OK)
&& enc_sess->esi_ssl
&& lsquic_frab_list_empty(&enc_sess->esi_frals[ENC_LEV_FORW]))
{

View File

@ -77,6 +77,7 @@
#include "lsquic_parse_common.h"
#include "lsquic_handshake.h"
#include "lsquic_crand.h"
#include "lsquic_ietf.h"
#define LSQUIC_LOGGER_MODULE LSQLM_ENGINE
#include "lsquic_logger.h"
@ -259,6 +260,7 @@ struct lsquic_engine
int last_tick_diff;
#endif
struct crand crand;
EVP_AEAD_CTX retry_aead_ctx;
};
@ -625,6 +627,14 @@ lsquic_engine_new (unsigned flags,
#if LSQUIC_CONN_STATS
engine->stats_fh = api->ea_stats_fh;
#endif
if (1 != EVP_AEAD_CTX_init(&engine->retry_aead_ctx, EVP_aead_aes_128_gcm(),
IETF_RETRY_KEY_BUF, IETF_RETRY_KEY_SZ, 16, NULL))
{
LSQ_ERROR("could not initialize retry AEAD ctx");
lsquic_engine_destroy(engine);
return NULL;
}
engine->pub.enp_retry_aead_ctx = &engine->retry_aead_ctx;
LSQ_INFO("instantiated engine");
return engine;
@ -878,7 +888,12 @@ new_full_conn_server (lsquic_engine_t *engine, lsquic_conn_t *mini_conn,
flags = engine->flags & (ENG_SERVER|ENG_HTTP);
if (mini_conn->cn_flags & LSCONN_IETF)
ctor = lsquic_ietf_full_conn_server_new;
{
if (mini_conn->cn_version == LSQVER_ID24)
ctor = lsquic_id24_full_conn_server_new;
else
ctor = lsquic_ietf_full_conn_server_new;
}
else
ctor = lsquic_gquic_full_conn_server_new;
@ -1434,6 +1449,8 @@ lsquic_engine_destroy (lsquic_engine_t *engine)
#if LSQUIC_COUNT_ENGINE_CALLS
LSQ_NOTICE("number of calls into the engine: %lu", engine->n_engine_calls);
#endif
if (engine->pub.enp_retry_aead_ctx)
EVP_AEAD_CTX_cleanup(engine->pub.enp_retry_aead_ctx);
free(engine);
}
@ -1533,9 +1550,16 @@ lsquic_engine_connect (lsquic_engine_t *engine, enum lsquic_version version,
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);
{
if (version == LSQVER_ID24)
conn = lsquic_id24_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_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, versions,
flags, hostname, max_packet_size, is_ipv4,
@ -2577,7 +2601,11 @@ process_connections (lsquic_engine_t *engine, conn_iter_f next_conn,
engine_incref_conn(conn, LSCONN_ATTQ);
}
else
assert(0);
/* In all other cases, the idle timeout would make the next
* tick time non-zero:
*/
assert((conn->cn_flags & LSCONN_IETF)
&& engine->pub.enp_settings.es_idle_timeout == 0);
}
}

View File

@ -17,6 +17,7 @@ struct lsquic_hash;
struct lsquic_stream_if;
struct ssl_ctx_st;
struct crand;
struct evp_aead_ctx_st;
enum warning_type
{
@ -62,6 +63,7 @@ struct lsquic_engine_public {
unsigned char enp_ver_tags_buf[ sizeof(lsquic_ver_tag_t) * N_LSQVER ];
unsigned enp_ver_tags_len;
struct crand *enp_crand;
struct evp_aead_ctx_st *enp_retry_aead_ctx;
};
/* Put connection onto the Tickable Queue if it is not already on it. If

View File

@ -21,6 +21,14 @@ lsquic_ietf_full_conn_client_new (struct lsquic_engine_public *,
const unsigned char *zero_rtt, size_t,
const unsigned char *token, size_t);
struct lsquic_conn *
lsquic_id24_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,
const unsigned char *token, size_t);
typedef struct lsquic_conn *
(*server_conn_ctor_f) (struct lsquic_engine_public *,
unsigned flags /* Only FC_SERVER and FC_HTTP */,
@ -36,6 +44,11 @@ lsquic_ietf_full_conn_server_new (struct lsquic_engine_public *,
unsigned flags /* Only FC_SERVER and FC_HTTP */,
struct lsquic_conn *mini_conn);
struct lsquic_conn *
lsquic_id24_full_conn_server_new (struct lsquic_engine_public *,
unsigned flags /* Only FC_SERVER and FC_HTTP */,
struct lsquic_conn *mini_conn);
struct dcid_elem
{
/* This is never both in the hash and on the retirement list */

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,7 @@
#include <string.h>
#include <sys/queue.h>
#include <openssl/aead.h>
#include <openssl/rand.h>
#include "fiu-local.h"
@ -129,6 +130,7 @@ enum ifull_conn_flags
IFC_FIRST_TICK = 1 << 24,
IFC_IGNORE_HSK = 1 << 25,
IFC_PROC_CRYPTO = 1 << 26,
IFC_MIGRA = 1 << 27,
};
@ -353,12 +355,10 @@ struct ietf_full_conn
unsigned char ifc_cur_path_id; /* Indexes ifc_paths */
unsigned char ifc_used_paths; /* Bitmask */
unsigned char ifc_mig_path_id;
unsigned char ifc_original_cids;
/* ifc_active_cids_limit is the maximum number of CIDs at any one time this
* endpoint is allowed to issue to peer. If the TP value exceeds cn_n_cces,
* it is reduced to it. ifc_active_cids_count tracks how many CIDs have
* been issued. It is decremented each time a CID is retired. Both are
* only applicable to CIDs issued via NEW_CONNECTION_ID frame.
* been issued. It is decremented each time a CID is retired.
*/
unsigned char ifc_active_cids_limit;
unsigned char ifc_active_cids_count;
@ -388,9 +388,6 @@ struct ietf_full_conn
} ifser_flags;
} ser;
} ifc_u;
/* XXX This is 16 bytes per connection, which is expensive. Perhaps move
* these to enpub (add a new IETF-specific section)?
*/
lsquic_time_t ifc_idle_to;
lsquic_time_t ifc_ping_period;
uint64_t ifc_last_max_data_off_sent;
@ -564,6 +561,45 @@ path_chal_1_alarm_expired (enum alarm_id al_id, void *ctx,
}
/* Sending DATA_BLOCKED and STREAM_DATA_BLOCKED frames is a way to elicit
* incoming packets from peer when it is too slow to read data. This is
* recommended by [draft-ietf-quic-transport-25] Section 4.1.
*
* If we are still in the blocked state, we schedule a blocked frame to
* be sent.
*/
static void
blocked_ka_alarm_expired (enum alarm_id al_id, void *ctx,
lsquic_time_t expiry, lsquic_time_t now)
{
struct ietf_full_conn *const conn = (struct ietf_full_conn *) ctx;
struct lsquic_stream *stream;
struct lsquic_hash_elem *el;
if (lsquic_conn_cap_avail(&conn->ifc_pub.conn_cap) == 0)
{
LSQ_DEBUG("set SEND_BLOCKED flag on connection");
conn->ifc_conn.cn_flags |= LSCONN_SEND_BLOCKED;
return;
}
for (el = lsquic_hash_first(conn->ifc_pub.all_streams); el;
el = lsquic_hash_next(conn->ifc_pub.all_streams))
{
stream = lsquic_hashelem_getdata(el);
if (lsquic_stream_is_blocked(stream))
{
if (!(stream->sm_qflags & SMQF_SENDING_FLAGS))
TAILQ_INSERT_TAIL(&conn->ifc_pub.sending_streams, stream,
next_send_stream);
stream->sm_qflags |= SMQF_SEND_BLOCKED;
LSQ_DEBUG("set SEND_BLOCKED flag on stream %"PRIu64, stream->id);
return;
}
}
}
static int
migra_is_on (const struct ietf_full_conn *conn)
{
@ -612,6 +648,53 @@ ping_alarm_expired (enum alarm_id al_id, void *ctx, lsquic_time_t expiry,
static void
retire_cid (struct ietf_full_conn *, struct conn_cid_elem *, lsquic_time_t);
static void
log_scids (const struct ietf_full_conn *conn)
{
const struct lsquic_conn *const lconn = &conn->ifc_conn;
const struct conn_cid_elem *cce;
char flags[5];
unsigned idx;
int fi;
LSQ_DEBUG("Log SCID array: (n_cces %hhu; mask: 0x%hhX; "
"active: %hhu; limit: %hhu)",
conn->ifc_conn.cn_n_cces, conn->ifc_conn.cn_cces_mask,
conn->ifc_active_cids_count, conn->ifc_active_cids_limit);
for (cce = lconn->cn_cces; cce < END_OF_CCES(lconn); ++cce)
{
idx = cce - lconn->cn_cces;
fi = 0;
if (cce->cce_flags & CCE_PORT) flags[fi++] = 'p';
if (cce->cce_flags & CCE_REG) flags[fi++] = 'r';
if (cce->cce_flags & CCE_SEQNO) flags[fi++] = 's';
if (cce->cce_flags & CCE_USED) flags[fi++] = 'u';
flags[fi] = '\0';
if (lconn->cn_cces_mask & (1 << idx))
{
if (cce->cce_flags & CCE_PORT)
LSQ_DEBUG( " %u: flags %-4s; port %hu", idx, flags,
cce->cce_port);
else if (cce->cce_flags & CCE_SEQNO)
LSQ_DEBUGC(" %u: flags %-4s; seqno: %u; %"CID_FMT, idx,
flags, cce->cce_seqno, CID_BITS(&cce->cce_cid));
else
LSQ_DEBUGC(" %u: flags %-4s; %"CID_FMT, idx, flags,
CID_BITS(&cce->cce_cid));
}
else
LSQ_DEBUG( " %u: flags %-4s; <empty>", idx, flags);
}
}
#define LOG_SCIDS(conn_) do { \
if (LSQ_LOG_ENABLED(LSQ_LOG_DEBUG)) \
log_scids(conn_); \
} while (0)
static void
ret_cids_alarm_expired (enum alarm_id al_id, void *ctx, lsquic_time_t expiry,
lsquic_time_t now)
@ -626,14 +709,14 @@ ret_cids_alarm_expired (enum alarm_id al_id, void *ctx, lsquic_time_t expiry,
for (cce = lconn->cn_cces; cce < END_OF_CCES(lconn); ++cce)
{
idx = cce - lconn->cn_cces;
if (conn->ifc_original_cids & (1 << idx))
if ((lconn->cn_cces_mask & (1 << idx))
&& (cce->cce_flags & (CCE_SEQNO|CCE_PORT)) == 0)
{
assert(lconn->cn_cces_mask & (1 << idx));
conn->ifc_original_cids &= ~(1 << idx);
LSQ_DEBUG("retiring original CID at index %u", idx);
retire_cid(conn, cce, now);
}
}
LOG_SCIDS(conn);
}
@ -875,6 +958,7 @@ ietf_full_conn_add_scid (struct ietf_full_conn *conn,
cce->cce_seqno = conn->ifc_scid_seqno++;
cce->cce_flags |= CCE_SEQNO | flags;
lconn->cn_cces_mask |= 1 << (cce - lconn->cn_cces);
++conn->ifc_active_cids_count;
if (enpub->enp_settings.es_scid_iss_rate)
{
min_timestamp = &conn->ifc_scid_timestamp[0];
@ -923,6 +1007,7 @@ ietf_full_conn_init (struct ietf_full_conn *conn,
lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_CID_THROT, cid_throt_alarm_expired, conn);
lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_PATH_CHAL_0, path_chal_0_alarm_expired, conn);
lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_PATH_CHAL_1, path_chal_1_alarm_expired, conn);
lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_BLOCKED_KA, blocked_ka_alarm_expired, conn);
lsquic_rechist_init(&conn->ifc_rechist[PNS_INIT], &conn->ifc_conn, 1);
lsquic_rechist_init(&conn->ifc_rechist[PNS_HSK], &conn->ifc_conn, 1);
lsquic_rechist_init(&conn->ifc_rechist[PNS_APP], &conn->ifc_conn, 1);
@ -949,8 +1034,6 @@ ietf_full_conn_init (struct ietf_full_conn *conn,
conn->ifc_paths[1].cop_path.np_path_id = 1;
#define valid_stream_id(v) ((v) <= VINT_MAX_VALUE)
conn->ifc_max_req_id = VINT_MAX_VALUE + 1;
conn->ifc_idle_to = enpub->enp_settings.es_idle_timeout * 1000 * 1000;
conn->ifc_ping_period = enpub->enp_settings.es_ping_period * 1000 * 1000;
conn->ifc_ping_unretx_thresh = 20;
return 0;
}
@ -1035,7 +1118,8 @@ lsquic_ietf_full_conn_client_new (struct lsquic_engine_public *enpub,
if (conn->ifc_settings->es_handshake_to)
lsquic_alarmset_set(&conn->ifc_alset, AL_HANDSHAKE,
lsquic_time_now() + conn->ifc_settings->es_handshake_to);
lsquic_alarmset_set(&conn->ifc_alset, AL_IDLE, now + conn->ifc_idle_to);
if (conn->ifc_idle_to)
lsquic_alarmset_set(&conn->ifc_alset, AL_IDLE, now + conn->ifc_idle_to);
if (enpub->enp_settings.es_support_push && CLIENT_PUSH_SUPPORT)
{
conn->ifc_u.cli.ifcli_flags |= IFCLI_PUSH_ENABLED;
@ -1134,10 +1218,9 @@ lsquic_ietf_full_conn_server_new (struct lsquic_engine_public *enpub,
if (cce->cce_seqno > conn->ifc_scid_seqno)
conn->ifc_scid_seqno = cce->cce_seqno;
conn->ifc_conn.cn_cces[i].cce_seqno = cce->cce_seqno;
conn->ifc_scid_timestamp[i] = now;
++conn->ifc_active_cids_count;
}
else
conn->ifc_original_cids |= 1 << i;
conn->ifc_scid_timestamp[i] = now;
}
++conn->ifc_scid_seqno;
@ -1265,14 +1348,10 @@ lsquic_ietf_full_conn_server_new (struct lsquic_engine_public *enpub,
conn->ifc_incoming_ecn = imc->imc_incoming_ecn;
conn->ifc_pub.rtt_stats = imc->imc_rtt_stats;
if (conn->ifc_original_cids)
{
lsquic_time_t now = lsquic_time_now();
lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_RET_CIDS,
ret_cids_alarm_expired, conn);
lsquic_alarmset_set(&conn->ifc_alset, AL_RET_CIDS,
now + RET_CID_TIMEOUT);
}
lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_RET_CIDS,
ret_cids_alarm_expired, conn);
lsquic_alarmset_set(&conn->ifc_alset, AL_RET_CIDS,
now + RET_CID_TIMEOUT);
conn->ifc_last_live_update = now;
@ -1285,7 +1364,8 @@ lsquic_ietf_full_conn_server_new (struct lsquic_engine_public *enpub,
if (0 != handshake_ok(&conn->ifc_conn))
goto err3;
lsquic_alarmset_set(&conn->ifc_alset, AL_IDLE,
if (conn->ifc_idle_to)
lsquic_alarmset_set(&conn->ifc_alset, AL_IDLE,
imc->imc_created + conn->ifc_idle_to);
while ((packet_in = TAILQ_FIRST(&imc->imc_app_packets)))
{
@ -1504,7 +1584,16 @@ generate_max_data_frame (struct ietf_full_conn *conn)
static int
can_issue_cids (const struct ietf_full_conn *conn)
{
return conn->ifc_active_cids_count < conn->ifc_active_cids_limit;
int can;
can = ((1 << conn->ifc_conn.cn_n_cces) - 1
!= conn->ifc_conn.cn_cces_mask)
&& conn->ifc_active_cids_count < conn->ifc_active_cids_limit;
LSQ_DEBUG("can issue CIDs: %d (n_cces %hhu; mask: 0x%hhX; "
"active: %hhu; limit: %hhu)",
can, conn->ifc_conn.cn_n_cces, conn->ifc_conn.cn_cces_mask,
conn->ifc_active_cids_count, conn->ifc_active_cids_limit);
return can;
}
@ -1556,10 +1645,8 @@ generate_new_cid_frame (struct ietf_full_conn *conn, lsquic_time_t now)
conn->ifc_conn.cn_pf, packet_out->po_data + packet_out->po_data_sz, w);
packet_out->po_frame_types |= QUIC_FTBIT_NEW_CONNECTION_ID;
lsquic_send_ctl_incr_pack_sz(&conn->ifc_send_ctl, packet_out, w);
++conn->ifc_active_cids_count;
if ((1 << conn->ifc_conn.cn_n_cces) - 1 == conn->ifc_conn.cn_cces_mask
|| !can_issue_cids(conn))
if (!can_issue_cids(conn))
{
conn->ifc_send_flags &= ~SF_SEND_NEW_CID;
LSQ_DEBUG("All %u SCID slots have been assigned",
@ -1574,7 +1661,9 @@ static void
maybe_get_rate_available_scid_slot (struct ietf_full_conn *conn,
lsquic_time_t now)
{
unsigned i, active_cid;
const struct lsquic_conn *const lconn = &conn->ifc_conn;
const struct conn_cid_elem *cce;
unsigned active_cid;
lsquic_time_t total_elapsed, elapsed_thresh, period, wait_time;
if (!conn->ifc_enpub->enp_settings.es_scid_iss_rate)
@ -1587,12 +1676,18 @@ maybe_get_rate_available_scid_slot (struct ietf_full_conn *conn,
period = (60 * 1000000) / conn->ifc_enpub->enp_settings.es_scid_iss_rate;
active_cid = 0;
total_elapsed = 0;
for (i = 0; i < MAX_SCID; i++)
for (cce = lconn->cn_cces; cce < END_OF_CCES(lconn); ++cce)
{
if (conn->ifc_original_cids & (1 << i))
continue;
active_cid += 1;
total_elapsed += (now - conn->ifc_scid_timestamp[i]);
if ((cce->cce_flags & (CCE_SEQNO|CCE_PORT)) == CCE_SEQNO)
{
active_cid += 1;
/* When server is promoted, the timestamp may be larger than the
* first tick time.
*/
if (now > conn->ifc_scid_timestamp[cce - lconn->cn_cces])
total_elapsed +=
now - conn->ifc_scid_timestamp[cce - lconn->cn_cces];
}
}
elapsed_thresh = ((active_cid * (active_cid + 1)) / 2) * period;
/* compare total elapsed ns to elapsed ns threshold */
@ -1623,6 +1718,7 @@ generate_new_cid_frames (struct ietf_full_conn *conn, lsquic_time_t now)
maybe_get_rate_available_scid_slot(conn, now);
}
while (conn->ifc_send_flags & SF_SEND_NEW_CID);
LOG_SCIDS(conn);
}
@ -2306,6 +2402,25 @@ retire_dcid (struct ietf_full_conn *conn, struct dcid_elem **dce)
}
static void
retire_seqno (struct ietf_full_conn *conn, unsigned seqno)
{
struct dcid_elem *dce;
dce = lsquic_malo_get(conn->ifc_pub.mm->malo.dcid_elem);
if (dce)
{
memset(dce, 0, sizeof(*dce));
dce->de_seqno = seqno;
TAILQ_INSERT_TAIL(&conn->ifc_to_retire, dce, de_next_to_ret);
LSQ_DEBUG("prepare to retire DCID seqno %"PRIu32, seqno);
conn->ifc_send_flags |= SF_SEND_RETIRE_CID;
}
else
LSQ_INFO("%s: cannot allocate dce", __func__);
}
/* This function exists for testing purposes.
*
* The user can switch DCIDs and request that the old DCID is retired.
@ -2785,7 +2900,42 @@ handshake_ok (struct lsquic_conn *lconn)
= params->tp_init_max_stream_data_bidi_remote;
conn->ifc_cfg.ack_exp = params->tp_ack_delay_exponent;
/* TODO: idle timeout, packet size */
switch ((!!conn->ifc_settings->es_idle_timeout << 1)
| !!params->tp_max_idle_timeout)
{
case (0 << 1) | 0:
LSQ_DEBUG("neither side specified max idle time out, turn it off");
break;
case (0 << 1) | 1:
LSQ_DEBUG("peer specified max idle timeout of %"PRIu64" ms (vs ours "
"of zero): use it", params->tp_max_idle_timeout);
conn->ifc_idle_to = params->tp_max_idle_timeout * 1000;
break;
case (1 << 1) | 0:
LSQ_DEBUG("peer did not specify max idle timeout, while ours is "
"%u ms: use it", conn->ifc_settings->es_idle_timeout * 1000);
conn->ifc_idle_to = conn->ifc_settings->es_idle_timeout * 1000000;
break;
default:/* (1 << 1) | 1 */
LSQ_DEBUG("our max idle timeout is %u ms, peer's is %"PRIu64" ms; "
"use minimum value of %"PRIu64" ms",
conn->ifc_settings->es_idle_timeout * 1000,
params->tp_max_idle_timeout,
MIN(conn->ifc_settings->es_idle_timeout * 1000,
params->tp_max_idle_timeout));
conn->ifc_idle_to = 1000 * MIN(conn->ifc_settings->es_idle_timeout
* 1000, params->tp_max_idle_timeout);
break;
}
if (conn->ifc_idle_to >= 2000000
&& conn->ifc_enpub->enp_settings.es_ping_period)
conn->ifc_ping_period = conn->ifc_idle_to / 2;
else
conn->ifc_ping_period = 0;
LSQ_DEBUG("PING period is set to %"PRIu64" usec", conn->ifc_ping_period);
/* TODO: packet size */
dce = get_new_dce(conn);
if (!dce)
@ -2878,9 +3028,7 @@ handshake_ok (struct lsquic_conn *lconn)
conn->ifc_active_cids_limit = params->tp_active_connection_id_limit;
conn->ifc_first_active_cid_seqno = conn->ifc_scid_seqno;
if ((1 << conn->ifc_conn.cn_n_cces) - 1 != conn->ifc_conn.cn_cces_mask
&& can_issue_cids(conn)
&& CN_SCID(&conn->ifc_conn)->len != 0)
if (can_issue_cids(conn) && CN_SCID(&conn->ifc_conn)->len != 0)
conn->ifc_send_flags |= SF_SEND_NEW_CID;
maybe_create_delayed_streams(conn);
@ -3297,6 +3445,11 @@ ietf_full_conn_ci_is_tickable (struct lsquic_conn *lconn)
LSQ_DEBUG("tickable: send flags: 0x%X", conn->ifc_send_flags);
goto check_can_send;
}
if (conn->ifc_conn.cn_flags & LSCONN_SEND_BLOCKED)
{
LSQ_DEBUG("tickable: send DATA_BLOCKED frame");
goto check_can_send;
}
if (conn->ifc_conn.cn_flags & LSCONN_HANDSHAKE_DONE ?
lsquic_send_ctl_has_buffered(&conn->ifc_send_ctl) :
lsquic_send_ctl_has_buffered_high(&conn->ifc_send_ctl))
@ -3819,6 +3972,22 @@ process_padding_frame (struct ietf_full_conn *conn,
}
static void
handshake_confirmed (struct ietf_full_conn *conn)
{
ignore_hsk(conn);
/* Even in ID-25, we wait for 1-RTT ACK on the server before dropping keys.
*/
conn->ifc_conn.cn_esf.i->esfi_handshake_confirmed(
conn->ifc_conn.cn_enc_session);
if (!(conn->ifc_flags & (IFC_SERVER|IFC_MIGRA)))
{
conn->ifc_flags |= IFC_MIGRA; /* Perform migration just once */
maybe_start_migration(conn);
}
}
static int
process_ack (struct ietf_full_conn *conn, struct ack_info *acki,
lsquic_time_t received, lsquic_time_t now)
@ -3841,11 +4010,7 @@ process_ack (struct ietf_full_conn *conn, struct ack_info *acki,
{
if (!(conn->ifc_flags & IFC_IGNORE_INIT))
ignore_init(conn);
ignore_hsk(conn);
conn->ifc_conn.cn_esf.i->esfi_1rtt_acked(
conn->ifc_conn.cn_enc_session);
if (!(conn->ifc_flags & IFC_SERVER))
maybe_start_migration(conn);
handshake_confirmed(conn);
}
return 0;
}
@ -4329,6 +4494,8 @@ process_crypto_frame (struct ietf_full_conn *conn,
stream_frame);
if (parsed_len < 0) {
lsquic_malo_put(stream_frame);
ABORT_QUIETLY(0, TEC_FRAME_ENCODING_ERROR,
"cannot decode CRYPTO frame");
return 0;
}
enc_level = lsquic_packet_in_enc_level(packet_in);
@ -4409,6 +4576,8 @@ process_stream_frame (struct ietf_full_conn *conn,
stream_frame);
if (parsed_len < 0) {
lsquic_malo_put(stream_frame);
ABORT_QUIETLY(0, TEC_FRAME_ENCODING_ERROR,
"cannot decode STREAM frame");
return 0;
}
EV_LOG_STREAM_FRAME_IN(LSQUIC_LOG_CONN_ID, stream_frame);
@ -4774,30 +4943,6 @@ retire_dcids_prior_to (struct ietf_full_conn *conn, unsigned retire_prior_to)
}
/* We need to be able to allocate a DCE slot to begin migration or to retire
* the DCID in transport parameters.
*/
static int
must_reserve_one_dce_slot (struct ietf_full_conn *conn)
{
struct lsquic_conn *const lconn = &conn->ifc_conn;
const struct transport_params *params;
if (conn->ifc_flags & IFC_SERVER)
return 0;
if (lsquic_send_ctl_1rtt_acked(&conn->ifc_send_ctl))
return 0;
params = lconn->cn_esf.i->esfi_get_peer_transport_params(
lconn->cn_enc_session);
if (params) /* Just in case */
return !!(params->tp_flags & (TRAPA_PREFADDR_IPv4|TRAPA_PREFADDR_IPv6));
else
return 0;
}
static unsigned
process_new_connection_id_frame (struct ietf_full_conn *conn,
struct lsquic_packet_in *packet_in, const unsigned char *p, size_t len)
@ -4837,6 +4982,13 @@ process_new_connection_id_frame (struct ietf_full_conn *conn,
return 0;
}
if (seqno < conn->ifc_last_retire_prior_to)
{
retire_seqno(conn, seqno);
action_str = "Ignored (seqno smaller than last retire_prior_to";
goto end;
}
if (retire_prior_to > conn->ifc_last_retire_prior_to)
{
conn->ifc_last_retire_prior_to = retire_prior_to;
@ -4888,35 +5040,28 @@ process_new_connection_id_frame (struct ietf_full_conn *conn,
else if (!dce)
dce = el;
if (dce)
if (!dce)
{
if (must_reserve_one_dce_slot(conn))
{
for (el = dce + 1; el < DCES_END(conn) && *el; ++el)
;
if (el == DCES_END(conn))
{
action_str = "Ignored (last slot reserved for migration)";
goto end;
}
}
*dce = lsquic_malo_get(conn->ifc_pub.mm->malo.dcid_elem);
if (*dce)
{
memset(*dce, 0, sizeof(**dce));
(*dce)->de_seqno = seqno;
(*dce)->de_cid = cid;
memcpy((*dce)->de_srst, token, sizeof((*dce)->de_srst));
(*dce)->de_flags |= DE_SRST;
action_str = "Saved";
if (update_cur_dcid)
*CUR_DCID(conn) = cid;
}
else
action_str = "Ignored (alloc failure)";
ABORT_QUIETLY(0, TEC_CONNECTION_ID_LIMIT_ERROR,
"NEW_CONNECTION_ID: received connection ID that is going over the "
"limit of %u CIDs", MAX_IETF_CONN_DCIDS);
return 0;
}
*dce = lsquic_malo_get(conn->ifc_pub.mm->malo.dcid_elem);
if (*dce)
{
memset(*dce, 0, sizeof(**dce));
(*dce)->de_seqno = seqno;
(*dce)->de_cid = cid;
memcpy((*dce)->de_srst, token, sizeof((*dce)->de_srst));
(*dce)->de_flags |= DE_SRST;
action_str = "Saved";
if (update_cur_dcid)
*CUR_DCID(conn) = cid;
}
else
action_str = "Ignored (no slots available)";
action_str = "Ignored (alloc failure)";
end:
LSQ_DEBUGC("Got new connection ID from peer: seq=%"PRIu64"; "
@ -4935,11 +5080,12 @@ retire_cid (struct ietf_full_conn *conn, struct conn_cid_elem *cce,
CID_BITS(&cce->cce_cid), cce->cce_seqno,
(cce->cce_flags & CCE_SEQNO) ? "" : "original");
if (cce->cce_flags & CCE_SEQNO)
--conn->ifc_active_cids_count;
lsquic_engine_retire_cid(conn->ifc_enpub, lconn, cce - lconn->cn_cces, now);
memset(cce, 0, sizeof(*cce));
if (((1 << conn->ifc_conn.cn_n_cces) - 1 != conn->ifc_conn.cn_cces_mask)
&& can_issue_cids(conn)
if (can_issue_cids(conn)
&& !(lsquic_alarmset_is_set(&conn->ifc_alset, AL_CID_THROT)))
maybe_get_rate_available_scid_slot(conn, now);
}
@ -4954,11 +5100,11 @@ process_retire_connection_id_frame (struct ietf_full_conn *conn,
uint64_t seqno;
int parsed_len;
/* [draft-ietf-quic-transport-20] Section 19.16
/* [draft-ietf-quic-transport-25] Section 19.16
*
* - Peer cannot retire zero-lenth CID. (MUST treat as PROTOCOL_VIOLATION)
* - Peer cannot retire CID with sequence number that has not been
* allocated yet. (MAY treat as PROTOCOL_VIOLATION)
* allocated yet. (MUST treat as PROTOCOL_VIOLATION)
* - Peer cannot retire CID that matches the DCID in packet.
* (MAY treat as PROTOCOL_VIOLATION)
*/
@ -5002,6 +5148,7 @@ process_retire_connection_id_frame (struct ietf_full_conn *conn,
}
else
LSQ_DEBUG("cannot retire CID seqno=%"PRIu64": not found", seqno);
LOG_SCIDS(conn);
return parsed_len;
}
@ -5120,7 +5267,7 @@ static unsigned
process_blocked_frame (struct ietf_full_conn *conn,
struct lsquic_packet_in *packet_in, const unsigned char *p, size_t len)
{
uint64_t peer_off, last_off;
uint64_t peer_off;
int parsed_len;
parsed_len = conn->ifc_conn.cn_pf->pf_parse_blocked_frame(p, len,
@ -5132,25 +5279,43 @@ process_blocked_frame (struct ietf_full_conn *conn,
peer_off);
LSQ_DEBUG("received BLOCKED frame: offset %"PRIu64, peer_off);
if (conn->ifc_last_max_data_off_sent)
last_off = conn->ifc_last_max_data_off_sent;
else
last_off = lsquic_cfcw_get_max_recv_off(&conn->ifc_pub.cfcw);
/* Same logic as in lsquic_stream_peer_blocked() */
if (peer_off > last_off && !(conn->ifc_send_flags & SF_SEND_MAX_DATA))
if (peer_off > conn->ifc_last_max_data_off_sent
&& !(conn->ifc_send_flags & SF_SEND_MAX_DATA))
{
conn->ifc_send_flags |= SF_SEND_MAX_DATA;
LSQ_DEBUG("marked to send MAX_DATA frame");
}
else if (conn->ifc_send_flags & SF_SEND_MAX_DATA)
LSQ_DEBUG("MAX_STREAM_DATA frame is already scheduled");
else if (conn->ifc_last_max_data_off_sent)
LSQ_DEBUG("MAX_DATA(%"PRIu64") has already been either "
"packetized or sent", conn->ifc_last_max_data_off_sent);
else
LSQ_INFO("Peer should have received transport param limit "
"of %"PRIu64"; odd", last_off);
LSQ_DEBUG("MAX_DATA(%"PRIu64") has already been either "
"packetized or sent to peer", conn->ifc_last_max_data_off_sent);
return parsed_len;
}
static unsigned
process_handshake_done_frame (struct ietf_full_conn *conn,
struct lsquic_packet_in *packet_in, const unsigned char *p, size_t len)
{
int parsed_len;
parsed_len = conn->ifc_conn.cn_pf->pf_parse_handshake_done_frame(p, len);
if (parsed_len < 0)
return 0;
EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "HANDSHAKE_DONE frame in");
LSQ_DEBUG("received HANDSHAKE_DONE frame");
if (conn->ifc_flags & IFC_SERVER)
{
ABORT_QUIETLY(0, TEC_PROTOCOL_VIOLATION,
"Client cannot send HANDSHAKE_DONE frame");
return 0;
}
handshake_confirmed(conn);
return parsed_len;
}
@ -5182,6 +5347,7 @@ static process_frame_f const process_frames[N_QUIC_FRAMES] =
[QUIC_FRAME_RETIRE_CONNECTION_ID] = process_retire_connection_id_frame,
[QUIC_FRAME_STREAM] = process_stream_frame,
[QUIC_FRAME_CRYPTO] = process_crypto_frame,
[QUIC_FRAME_HANDSHAKE_DONE] = process_handshake_done_frame,
};
@ -5332,6 +5498,7 @@ on_new_or_unconfirmed_path (struct ietf_full_conn *conn,
path->cop_cce_idx = cce - lconn->cn_cces;
cce->cce_flags |= CCE_USED;
LOG_SCIDS(conn);
}
@ -5435,6 +5602,49 @@ maybe_queue_opp_ack (struct ietf_full_conn *conn)
}
static int
verify_retry_packet (struct ietf_full_conn *conn,
const struct lsquic_packet_in *packet_in)
{
unsigned char *pseudo_packet;
size_t out_len, ad_len;
int verified;
if (1 + CUR_DCID(conn)->len + packet_in->pi_data_sz > 0x1000)
{
/* Cover the theoretical possibility that we cannot fit the pseudo-
* packet and 16-byte decrypted output into 4 KB:
*/
LSQ_INFO("%s: Retry packet is too long: %hu bytes", __func__,
packet_in->pi_data_sz);
return -1;
}
pseudo_packet = lsquic_mm_get_4k(conn->ifc_pub.mm);
if (!pseudo_packet)
{
LSQ_INFO("%s: cannot allocate memory", __func__);
return -1;
}
pseudo_packet[0] = CUR_DCID(conn)->len;
memcpy(pseudo_packet + 1, CUR_DCID(conn)->idbuf, CUR_DCID(conn)->len);
memcpy(pseudo_packet + 1 + CUR_DCID(conn)->len, packet_in->pi_data,
packet_in->pi_data_sz);
out_len = 0;
ad_len = 1 + CUR_DCID(conn)->len + packet_in->pi_data_sz - 16;
verified = 1 == EVP_AEAD_CTX_open(conn->ifc_enpub->enp_retry_aead_ctx,
pseudo_packet + ad_len, &out_len, out_len,
IETF_RETRY_NONCE_BUF, IETF_RETRY_NONCE_SZ,
pseudo_packet + ad_len, 16, pseudo_packet, ad_len)
&& out_len == 0;
lsquic_mm_put_4k(conn->ifc_pub.mm, pseudo_packet);
return verified ? 0 : -1;
}
static int
process_retry_packet (struct ietf_full_conn *conn,
struct lsquic_packet_in *packet_in)
@ -5467,14 +5677,8 @@ process_retry_packet (struct ietf_full_conn *conn,
return 0;
}
if (!(CUR_DCID(conn)->len == packet_in->pi_odcid_len
&& 0 == memcmp(CUR_DCID(conn)->idbuf,
packet_in->pi_data + packet_in->pi_odcid,
packet_in->pi_odcid_len)))
{
LSQ_DEBUG("retry packet's ODCID does not match the original: ignore");
if (0 != verify_retry_packet(conn, packet_in))
return 0;
}
if (0 != lsquic_send_ctl_retry(&conn->ifc_send_ctl,
packet_in->pi_data + packet_in->pi_token,
@ -5560,6 +5764,7 @@ on_dcid_change (struct ietf_full_conn *conn, const lsquic_cid_t *dcid_in)
cce->cce_flags |= CCE_USED;
lconn->cn_cur_cce_idx = cce - lconn->cn_cces;
LSQ_DEBUGC("%s: set SCID to %"CID_FMT, __func__, CID_BITS(CN_SCID(lconn)));
LOG_SCIDS(conn);
/* Reset spin bit, see [draft-ietf-quic-transport-20] Section 17.3.1 */
conn->ifc_spin_bit = 0;
@ -5928,7 +6133,8 @@ ietf_full_conn_ci_packet_in (struct lsquic_conn *lconn,
{
struct ietf_full_conn *conn = (struct ietf_full_conn *) lconn;
lsquic_alarmset_set(&conn->ifc_alset, AL_IDLE,
if (conn->ifc_idle_to)
lsquic_alarmset_set(&conn->ifc_alset, AL_IDLE,
packet_in->pi_received + conn->ifc_idle_to);
if (0 == (conn->ifc_flags & IFC_IMMEDIATE_CLOSE_FLAGS))
if (0 != conn->ifc_process_incoming_packet(conn, packet_in))
@ -5989,6 +6195,12 @@ ietf_full_conn_ci_packet_sent (struct lsquic_conn *lconn,
ABORT_ERROR("sent packet failed: %s", strerror(errno));
++conn->ifc_ecn_counts_out[ lsquic_packet_out_pns(packet_out) ]
[ lsquic_packet_out_ecn(packet_out) ];
/* Set blocked keep-alive for a [1,8] seconds */
if (packet_out->po_frame_types
& (QUIC_FTBIT_BLOCKED|QUIC_FTBIT_STREAM_BLOCKED))
lsquic_alarmset_set(&conn->ifc_alset, AL_BLOCKED_KA,
packet_out->po_sent + (1 + (7 & lsquic_crand_get_nybble(
conn->ifc_enpub->enp_crand))) * 1000000);
}

View File

@ -69,7 +69,6 @@ enum http_error_code
HEC_REQUEST_REJECTED = 0x10B,
HEC_REQUEST_CANCELLED = 0x10C,
HEC_REQUEST_INCOMPLETE = 0x10D,
HEC_EARLY_RESPONSE = 0x10E,
HEC_CONNECT_ERROR = 0x10F,
HEC_VERSION_FALLBACK = 0x110,
HEC_QPACK_DECOMPRESSION_FAILED = 0x200,

View File

@ -4,7 +4,7 @@
/* Things specific to the IETF version of QUIC that do not fit anywhere else */
/* [draft-ietf-quic-transport-18] Section 22.3 */
/* [draft-ietf-quic-transport-25] Section 22.4 */
enum trans_error_code
{
TEC_NO_ERROR = 0x0,
@ -16,12 +16,21 @@ enum trans_error_code
TEC_FINAL_SIZE_ERROR = 0x6,
TEC_FRAME_ENCODING_ERROR = 0x7,
TEC_TRANSPORT_PARAMETER_ERROR = 0x8,
TEC_VERSION_NEGOTIATION_ERROR = 0x9,
TEC_CONNECTION_ID_LIMIT_ERROR = 0x9,
TEC_PROTOCOL_VIOLATION = 0xA,
TEC_INVALID_TOKEN = 0xB,
TEC_CRYPTO_BUFFER_EXCEEDED = 0xD,
};
/* Must be at least two */
#define MAX_IETF_CONN_DCIDS 8
/* [draft-ietf-quic-tls-25] Section 5.8 */
#define IETF_RETRY_KEY_BUF ((unsigned char *) \
"\x4d\x32\xec\xdb\x2a\x21\x33\xc8\x41\xe4\x04\x3d\xf2\x7d\x44\x30")
#define IETF_RETRY_KEY_SZ 16
#define IETF_RETRY_NONCE_BUF ((unsigned char *) \
"\x4d\x16\x11\xd0\x55\x13\xa5\x52\xc5\x87\xd5\x75")
#define IETF_RETRY_NONCE_SZ 12
#endif

View File

@ -760,7 +760,10 @@ imico_process_crypto_frame (IMICO_PROC_FRAME_ARGS)
parsed_len = conn->imc_conn.cn_pf->pf_parse_crypto_frame(p, len,
&stream_frame);
if (parsed_len < 0)
{
conn->imc_flags |= IMC_PARSE_FAILED;
return 0;
}
enc_level = lsquic_packet_in_enc_level(packet_in);
EV_LOG_CRYPTO_FRAME_IN(LSQUIC_LOG_CONN_ID, &stream_frame, enc_level);
@ -903,7 +906,10 @@ imico_process_ack_frame (IMICO_PROC_FRAME_ARGS)
parsed_len = conn->imc_conn.cn_pf->pf_parse_ack_frame(p, len, acki,
ack_exp);
if (parsed_len < 0)
{
conn->imc_flags |= IMC_PARSE_FAILED;
return 0;
}
pns = lsquic_hety2pns[ packet_in->pi_header_type ];
acked = 0;
@ -996,7 +1002,10 @@ imico_process_connection_close_frame (IMICO_PROC_FRAME_ARGS)
parsed_len = conn->imc_conn.cn_pf->pf_parse_connect_close_frame(p, len,
&app_error, &error_code, &reason_len, &reason_off);
if (parsed_len < 0)
{
conn->imc_flags |= IMC_PARSE_FAILED;
return 0;
}
EV_LOG_CONNECTION_CLOSE_FRAME_IN(LSQUIC_LOG_CONN_ID, error_code,
(int) reason_len, (const char *) p + reason_off);
LSQ_INFO("Received CONNECTION_CLOSE frame (%s-level code: %"PRIu64"; "
@ -1039,6 +1048,7 @@ static unsigned (*const imico_process_frames[N_QUIC_FRAMES])
[QUIC_FRAME_PATH_RESPONSE] = imico_process_invalid_frame,
/* STREAM frame can only come in the App PNS and we delay those packets: */
[QUIC_FRAME_STREAM] = imico_process_invalid_frame,
[QUIC_FRAME_HANDSHAKE_DONE] = imico_process_invalid_frame,
};
@ -1540,6 +1550,13 @@ imico_generate_conn_close (struct ietf_mini_conn *conn)
reason = "handshake failed";
rlen = 16;
}
else if (conn->imc_flags & IMC_PARSE_FAILED)
{
is_app = 0;
error_code = TEC_FRAME_ENCODING_ERROR;
reason = "cannot decode frame";
rlen = 19;
}
else
{
is_app = 0;
@ -1605,6 +1622,34 @@ imico_generate_conn_close (struct ietf_mini_conn *conn)
}
static int
imico_generate_handshake_done (struct ietf_mini_conn *conn)
{
struct lsquic_packet_out *packet_out;
unsigned need;
int sz;
need = conn->imc_conn.cn_pf->pf_handshake_done_frame_size();
packet_out = imico_get_packet_out(conn, HETY_NOT_SET, need);
if (!packet_out)
return -1;
sz = conn->imc_conn.cn_pf->pf_gen_handshake_done_frame(
packet_out->po_data + packet_out->po_data_sz,
lsquic_packet_out_avail(packet_out));
if (sz < 0)
{
LSQ_WARN("could not generate HANDSHAKE_DONE frame");
return -1;
}
packet_out->po_frame_types |= 1 << QUIC_FRAME_HANDSHAKE_DONE;
packet_out->po_data_sz += sz;
LSQ_DEBUG("generated HANDSHAKE_DONE frame");
return 0;
}
static enum tick_st
ietf_mini_conn_ci_tick (struct lsquic_conn *lconn, lsquic_time_t now)
{
@ -1633,12 +1678,18 @@ ietf_mini_conn_ci_tick (struct lsquic_conn *lconn, lsquic_time_t now)
if (conn->imc_flags & IMC_ERROR)
{
close_on_error:
if (!(conn->imc_flags & IMC_CLOSE_RECVD))
imico_generate_conn_close(conn);
tick |= TICK_CLOSE;
}
else if (conn->imc_flags & IMC_HSK_OK)
{
if (conn->imc_conn.cn_version > LSQVER_ID24
&& 0 != imico_generate_handshake_done(conn))
goto close_on_error;
tick |= TICK_PROMOTE;
}
if (imico_have_packets_to_send(conn, now))
tick |= TICK_SEND;

View File

@ -55,6 +55,7 @@ struct ietf_mini_conn
IMC_ADDR_VALIDATED = 1 << 17,
IMC_HSK_PACKET_SENT = 1 << 18,
IMC_CLOSE_RECVD = 1 << 19,
IMC_PARSE_FAILED = 1 << 20,
} imc_flags;
struct mini_crypto_stream imc_streams[N_ENC_LEVS];
void *imc_stream_ps[N_ENC_LEVS];

View File

@ -33,6 +33,7 @@ enum quic_frame_type
QUIC_FRAME_CRYPTO, /* B */
QUIC_FRAME_RETIRE_CONNECTION_ID,/* I */
QUIC_FRAME_NEW_TOKEN, /* I */
QUIC_FRAME_HANDSHAKE_DONE, /* I */
N_QUIC_FRAMES
};
@ -60,6 +61,7 @@ enum quic_ft_bit {
QUIC_FTBIT_CRYPTO = 1 << QUIC_FRAME_CRYPTO,
QUIC_FTBIT_NEW_TOKEN = 1 << QUIC_FRAME_NEW_TOKEN,
QUIC_FTBIT_RETIRE_CONNECTION_ID = 1 << QUIC_FRAME_RETIRE_CONNECTION_ID,
QUIC_FTBIT_HANDSHAKE_DONE = 1 << QUIC_FRAME_HANDSHAKE_DONE,
};
static const char * const frame_type_2_str[N_QUIC_FRAMES] = {
@ -86,6 +88,7 @@ static const char * const frame_type_2_str[N_QUIC_FRAMES] = {
[QUIC_FRAME_CRYPTO] = "QUIC_FRAME_CRYPTO",
[QUIC_FRAME_NEW_TOKEN] = "QUIC_FRAME_NEW_TOKEN",
[QUIC_FRAME_RETIRE_CONNECTION_ID] = "QUIC_FRAME_RETIRE_CONNECTION_ID",
[QUIC_FRAME_HANDSHAKE_DONE] = "QUIC_FRAME_HANDSHAKE_DONE",
};
#define QUIC_FRAME_PRELEN (sizeof("QUIC_FRAME_"))
@ -120,6 +123,7 @@ static const char * const frame_type_2_str[N_QUIC_FRAMES] = {
QUIC_FRAME_SLEN(QUIC_FRAME_RETIRE_CONNECTION_ID) \
+ 1 + \
QUIC_FRAME_SLEN(QUIC_FRAME_NEW_TOKEN) + 1 + \
QUIC_FRAME_SLEN(QUIC_FRAME_HANDSHAKE_DONE) + 1 + \
0
@ -207,6 +211,7 @@ extern const char *const lsquic_pns2str[];
| QUIC_FTBIT_PATH_RESPONSE \
| QUIC_FTBIT_RETIRE_CONNECTION_ID \
| QUIC_FTBIT_NEW_TOKEN \
| QUIC_FTBIT_HANDSHAKE_DONE \
| QUIC_FTBIT_CRYPTO )
/* [draft-ietf-quic-transport-24] Section 1.2 */

View File

@ -91,7 +91,7 @@ typedef struct lsquic_packet_in
/* pi_token and pi_token_size are set in Initial and Retry packets */
unsigned short pi_token_size; /* Size of the token */
unsigned char pi_token; /* Offset to token */
/* pi_odcid and pi_odcid_len are only set in Retry packets */
/* 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_len; /* Size of ODCID */
unsigned char pi_scid_off; /* Offset to SCID */

View File

@ -139,7 +139,7 @@ typedef struct lsquic_packet_out
POL_ELBIT_0 = 1 << 1, /* EL bits encode the crypto level. */
POL_ELBIT_1 = 1 << 2,
#define POKP_SHIFT 3
POL_KEY_PHASE= 1 << 3, /* Used for logging */
POL_KEY_PHASE= 1 << 3,
#define POECN_SHIFT 4
POL_ECNBIT_0 = 1 << 4,
POL_ECNBIT_1 = 1 << 5,
@ -210,8 +210,6 @@ typedef struct lsquic_packet_out
(p)->po_flags |= ((b) & 1) << POSPIN_SHIFT; \
} while (0)
#define lsquic_packet_out_key_phase(p) 0 /* TODO */
#define lsquic_po_header_length(lconn, po_flags, dcid_len) ( \
lconn->cn_pf->pf_packout_max_header_size(lconn, po_flags, dcid_len))

View File

@ -295,12 +295,19 @@ struct parse_funcs
(*pf_path_resp_frame_size) (void);
int
(*pf_gen_path_resp_frame) (unsigned char *, size_t, uint64_t resp);
int
(*pf_gen_handshake_done_frame) (unsigned char *buf, size_t buf_len);
int
(*pf_parse_handshake_done_frame) (const unsigned char *buf, size_t buf_len);
unsigned
(*pf_handshake_done_frame_size) (void);
};
extern const struct parse_funcs lsquic_parse_funcs_gquic_Q043;
extern const struct parse_funcs lsquic_parse_funcs_gquic_Q046;
extern const struct parse_funcs lsquic_parse_funcs_gquic_Q050;
extern const struct parse_funcs lsquic_parse_funcs_ietf_id24;
extern const struct parse_funcs lsquic_parse_funcs_ietf_v1;
#define select_pf_by_ver(ver) ( \
@ -310,6 +317,8 @@ extern const struct parse_funcs lsquic_parse_funcs_ietf_v1;
&lsquic_parse_funcs_gquic_Q046 : \
(1 << (ver)) & ((1 << LSQVER_050)|LSQUIC_EXPERIMENTAL_Q098) ? \
&lsquic_parse_funcs_gquic_Q050 : \
(1 << (ver)) & (1 << LSQVER_ID24) ? \
&lsquic_parse_funcs_ietf_id24 : \
&lsquic_parse_funcs_ietf_v1)
/* This function is gQUIC-version independent */

View File

@ -289,6 +289,36 @@ gquic_Q046_packno_info (const struct lsquic_conn *lconn,
}
/* No simple PRST for Q046 */
static ssize_t
gquic_Q046_generate_simple_prst (const lsquic_cid_t *cidp, unsigned char *buf,
size_t buf_sz)
{
return -1;
}
static unsigned
gquic_Q046_handshake_done_frame_size (void)
{
return 0;
}
static int
gquic_Q046_gen_handshake_done_frame (unsigned char *buf, size_t buf_len)
{
return -1;
}
static int
gquic_Q046_parse_handshake_done_frame (const unsigned char *buf, size_t buf_len)
{
return -1;
}
const struct parse_funcs lsquic_parse_funcs_gquic_Q046 =
{
.pf_gen_reg_pkt_header = gquic_Q046_gen_reg_pkt_header,
@ -317,7 +347,7 @@ const struct parse_funcs lsquic_parse_funcs_gquic_Q046 =
.pf_write_float_time16 = gquic_be_write_float_time16,
.pf_read_float_time16 = gquic_be_read_float_time16,
#endif
.pf_generate_simple_prst = lsquic_generate_iquic_reset,
.pf_generate_simple_prst = gquic_Q046_generate_simple_prst,
.pf_parse_frame_type = lsquic_parse_frame_type_gquic_Q035_thru_Q046,
.pf_turn_on_fin = lsquic_turn_on_fin_Q035_thru_Q046,
.pf_packout_size = gquic_Q046_packout_size,
@ -327,4 +357,7 @@ const struct parse_funcs lsquic_parse_funcs_gquic_Q046 =
.pf_gen_crypto_frame = gquic_Q046_gen_crypto_frame,
.pf_parse_crypto_frame = gquic_Q046_parse_crypto_frame,
.pf_packno_info = gquic_Q046_packno_info,
.pf_gen_handshake_done_frame = gquic_Q046_gen_handshake_done_frame,
.pf_parse_handshake_done_frame = gquic_Q046_parse_handshake_done_frame,
.pf_handshake_done_frame_size = gquic_Q046_handshake_done_frame_size,
};

View File

@ -825,6 +825,36 @@ gquic_Q050_calc_crypto_frame_header_sz (uint64_t offset, unsigned data_sz)
}
/* No simple PRST for Q050 */
static ssize_t
gquic_Q050_generate_simple_prst (const lsquic_cid_t *cidp, unsigned char *buf,
size_t buf_sz)
{
return -1;
}
static unsigned
gquic_Q050_handshake_done_frame_size (void)
{
return 0;
}
static int
gquic_Q050_gen_handshake_done_frame (unsigned char *buf, size_t buf_len)
{
return -1;
}
static int
gquic_Q050_parse_handshake_done_frame (const unsigned char *buf, size_t buf_len)
{
return -1;
}
const struct parse_funcs lsquic_parse_funcs_gquic_Q050 =
{
.pf_gen_reg_pkt_header = gquic_Q050_gen_reg_pkt_header,
@ -853,7 +883,7 @@ const struct parse_funcs lsquic_parse_funcs_gquic_Q050 =
.pf_write_float_time16 = gquic_be_write_float_time16,
.pf_read_float_time16 = gquic_be_read_float_time16,
#endif
.pf_generate_simple_prst = lsquic_generate_iquic_reset,
.pf_generate_simple_prst = gquic_Q050_generate_simple_prst,
.pf_parse_frame_type = gquic_Q050_parse_frame_type,
.pf_turn_on_fin = lsquic_turn_on_fin_Q035_thru_Q046,
.pf_packout_size = gquic_Q050_packout_size,
@ -864,4 +894,7 @@ const struct parse_funcs lsquic_parse_funcs_gquic_Q050 =
.pf_parse_crypto_frame = gquic_Q050_parse_crypto_frame,
.pf_packno_info = gquic_Q050_packno_info,
.pf_calc_crypto_frame_header_sz = gquic_Q050_calc_crypto_frame_header_sz,
.pf_gen_handshake_done_frame = gquic_Q050_gen_handshake_done_frame,
.pf_parse_handshake_done_frame = gquic_Q050_parse_handshake_done_frame,
.pf_handshake_done_frame_size = gquic_Q050_handshake_done_frame_size,
};

View File

@ -217,7 +217,7 @@ lsquic_cid_from_packet (const unsigned char *buf, size_t bufsz,
}
/* See [draft-ietf-quic-tls-19], Section 4 */
/* See [draft-ietf-quic-transport-25], Section 12.4 (Table 3) */
const enum quic_ft_bit lsquic_legal_frames_by_level[N_ENC_LEVS] =
{
[ENC_LEV_CLEAR] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
@ -230,7 +230,7 @@ const enum quic_ft_bit lsquic_legal_frames_by_level[N_ENC_LEVS] =
| QUIC_FTBIT_STREAMS_BLOCKED
| QUIC_FTBIT_NEW_CONNECTION_ID | QUIC_FTBIT_STOP_SENDING
| QUIC_FTBIT_PATH_CHALLENGE | QUIC_FTBIT_PATH_RESPONSE
| QUIC_FTBIT_RETIRE_CONNECTION_ID | QUIC_FTBIT_NEW_TOKEN,
| QUIC_FTBIT_RETIRE_CONNECTION_ID,
[ENC_LEV_INIT] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
| QUIC_FTBIT_ACK| QUIC_FTBIT_CONNECTION_CLOSE,
[ENC_LEV_FORW] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
@ -242,5 +242,6 @@ const enum quic_ft_bit lsquic_legal_frames_by_level[N_ENC_LEVS] =
| QUIC_FTBIT_STREAMS_BLOCKED
| QUIC_FTBIT_NEW_CONNECTION_ID | QUIC_FTBIT_STOP_SENDING
| QUIC_FTBIT_PATH_CHALLENGE | QUIC_FTBIT_PATH_RESPONSE
| QUIC_FTBIT_HANDSHAKE_DONE
| QUIC_FTBIT_RETIRE_CONNECTION_ID | QUIC_FTBIT_NEW_TOKEN,
};

View File

@ -69,9 +69,6 @@ lsquic_iquic_gen_retry_pkt (unsigned char *buf, size_t bufsz,
const struct lsquic_engine_public *, const lsquic_cid_t *scid,
const lsquic_cid_t *dcid, enum lsquic_version, const struct sockaddr *,
uint8_t random_nybble);
ssize_t
lsquic_generate_iquic_reset (const lsquic_cid_t *, unsigned char *buf,
size_t buf_sz);
#define GQUIC_RESET_SZ 33
ssize_t

View File

@ -1010,6 +1010,27 @@ gquic_be_packno_info (const struct lsquic_conn *lconn,
}
static unsigned
gquic_Q043_handshake_done_frame_size (void)
{
return 0;
}
static int
gquic_Q043_gen_handshake_done_frame (unsigned char *buf, size_t buf_len)
{
return -1;
}
static int
gquic_Q043_parse_handshake_done_frame (const unsigned char *buf, size_t buf_len)
{
return -1;
}
const struct parse_funcs lsquic_parse_funcs_gquic_Q043 =
{
.pf_gen_reg_pkt_header = gquic_be_gen_reg_pkt_header,
@ -1049,4 +1070,7 @@ const struct parse_funcs lsquic_parse_funcs_gquic_Q043 =
.pf_gen_crypto_frame = gquic_be_gen_crypto_frame,
.pf_parse_crypto_frame = gquic_be_parse_crypto_frame,
.pf_packno_info = gquic_be_packno_info,
.pf_gen_handshake_done_frame = gquic_Q043_gen_handshake_done_frame,
.pf_parse_handshake_done_frame = gquic_Q043_parse_handshake_done_frame,
.pf_handshake_done_frame_size = gquic_Q043_handshake_done_frame_size,
};

View File

@ -266,7 +266,7 @@ gen_short_pkt_header (const struct lsquic_conn *lconn,
| (lsquic_packet_out_spin_bit(packet_out) << 5)
| (lsquic_packet_out_square_bit(packet_out) << 4)
| (lsquic_packet_out_loss_bit(packet_out) << 3)
| (lsquic_packet_out_key_phase(packet_out) << 2)
| (lsquic_packet_out_kp(packet_out) << 2)
| packno_bits
;
@ -529,6 +529,10 @@ ietf_v1_parse_stream_frame (const unsigned char *buf, size_t rem_packet_sz,
else
data_sz = pend - p;
/* Largest offset cannot exceed this value and we MUST detect this error */
if (VINT_MAX_VALUE - offset < data_sz)
return -1;
stream_frame->stream_id = stream_id;
stream_frame->data_frame.df_fin = type & 0x1;
stream_frame->data_frame.df_offset = offset;
@ -567,6 +571,10 @@ lsquic_ietf_v1_parse_crypto_frame (const unsigned char *buf,
p += r;
CHECK_SPACE(data_sz, p, pend);
/* Largest offset cannot exceed this value and we MUST detect this error */
if (VINT_MAX_VALUE - offset < data_sz)
return -1;
stream_frame->stream_id = ~0ULL; /* Unset */
stream_frame->data_frame.df_fin = 0;
stream_frame->data_frame.df_offset = offset;
@ -1096,6 +1104,273 @@ ietf_v1_parse_frame_type (unsigned char byte)
}
static enum quic_frame_type
ietf_id24_parse_frame_type (unsigned char byte)
{
/* This one does not have QUIC_FRAME_HANDSHAKE_DONE */
static const enum quic_frame_type byte2type[0x100] =
{
[0x00] = QUIC_FRAME_PADDING,
[0x01] = QUIC_FRAME_PING,
[0x02] = QUIC_FRAME_ACK,
[0x03] = QUIC_FRAME_ACK,
[0x04] = QUIC_FRAME_RST_STREAM,
[0x05] = QUIC_FRAME_STOP_SENDING,
[0x06] = QUIC_FRAME_CRYPTO,
[0x07] = QUIC_FRAME_NEW_TOKEN,
[0x08] = QUIC_FRAME_STREAM,
[0x09] = QUIC_FRAME_STREAM,
[0x0A] = QUIC_FRAME_STREAM,
[0x0B] = QUIC_FRAME_STREAM,
[0x0C] = QUIC_FRAME_STREAM,
[0x0D] = QUIC_FRAME_STREAM,
[0x0E] = QUIC_FRAME_STREAM,
[0x0F] = QUIC_FRAME_STREAM,
[0x10] = QUIC_FRAME_MAX_DATA,
[0x11] = QUIC_FRAME_MAX_STREAM_DATA,
[0x12] = QUIC_FRAME_MAX_STREAMS,
[0x13] = QUIC_FRAME_MAX_STREAMS,
[0x14] = QUIC_FRAME_BLOCKED,
[0x15] = QUIC_FRAME_STREAM_BLOCKED,
[0x16] = QUIC_FRAME_STREAMS_BLOCKED,
[0x17] = QUIC_FRAME_STREAMS_BLOCKED,
[0x18] = QUIC_FRAME_NEW_CONNECTION_ID,
[0x19] = QUIC_FRAME_RETIRE_CONNECTION_ID,
[0x1A] = QUIC_FRAME_PATH_CHALLENGE,
[0x1B] = QUIC_FRAME_PATH_RESPONSE,
[0x1C] = QUIC_FRAME_CONNECTION_CLOSE,
[0x1D] = QUIC_FRAME_CONNECTION_CLOSE,
[0x1E] = QUIC_FRAME_INVALID,
[0x1F] = QUIC_FRAME_INVALID,
[0x20] = QUIC_FRAME_INVALID,
[0x21] = QUIC_FRAME_INVALID,
[0x22] = QUIC_FRAME_INVALID,
[0x23] = QUIC_FRAME_INVALID,
[0x24] = QUIC_FRAME_INVALID,
[0x25] = QUIC_FRAME_INVALID,
[0x26] = QUIC_FRAME_INVALID,
[0x27] = QUIC_FRAME_INVALID,
[0x28] = QUIC_FRAME_INVALID,
[0x29] = QUIC_FRAME_INVALID,
[0x2A] = QUIC_FRAME_INVALID,
[0x2B] = QUIC_FRAME_INVALID,
[0x2C] = QUIC_FRAME_INVALID,
[0x2D] = QUIC_FRAME_INVALID,
[0x2E] = QUIC_FRAME_INVALID,
[0x2F] = QUIC_FRAME_INVALID,
[0x30] = QUIC_FRAME_INVALID,
[0x31] = QUIC_FRAME_INVALID,
[0x32] = QUIC_FRAME_INVALID,
[0x33] = QUIC_FRAME_INVALID,
[0x34] = QUIC_FRAME_INVALID,
[0x35] = QUIC_FRAME_INVALID,
[0x36] = QUIC_FRAME_INVALID,
[0x37] = QUIC_FRAME_INVALID,
[0x38] = QUIC_FRAME_INVALID,
[0x39] = QUIC_FRAME_INVALID,
[0x3A] = QUIC_FRAME_INVALID,
[0x3B] = QUIC_FRAME_INVALID,
[0x3C] = QUIC_FRAME_INVALID,
[0x3D] = QUIC_FRAME_INVALID,
[0x3E] = QUIC_FRAME_INVALID,
[0x3F] = QUIC_FRAME_INVALID,
[0x40] = QUIC_FRAME_INVALID,
[0x41] = QUIC_FRAME_INVALID,
[0x42] = QUIC_FRAME_INVALID,
[0x43] = QUIC_FRAME_INVALID,
[0x44] = QUIC_FRAME_INVALID,
[0x45] = QUIC_FRAME_INVALID,
[0x46] = QUIC_FRAME_INVALID,
[0x47] = QUIC_FRAME_INVALID,
[0x48] = QUIC_FRAME_INVALID,
[0x49] = QUIC_FRAME_INVALID,
[0x4A] = QUIC_FRAME_INVALID,
[0x4B] = QUIC_FRAME_INVALID,
[0x4C] = QUIC_FRAME_INVALID,
[0x4D] = QUIC_FRAME_INVALID,
[0x4E] = QUIC_FRAME_INVALID,
[0x4F] = QUIC_FRAME_INVALID,
[0x50] = QUIC_FRAME_INVALID,
[0x51] = QUIC_FRAME_INVALID,
[0x52] = QUIC_FRAME_INVALID,
[0x53] = QUIC_FRAME_INVALID,
[0x54] = QUIC_FRAME_INVALID,
[0x55] = QUIC_FRAME_INVALID,
[0x56] = QUIC_FRAME_INVALID,
[0x57] = QUIC_FRAME_INVALID,
[0x58] = QUIC_FRAME_INVALID,
[0x59] = QUIC_FRAME_INVALID,
[0x5A] = QUIC_FRAME_INVALID,
[0x5B] = QUIC_FRAME_INVALID,
[0x5C] = QUIC_FRAME_INVALID,
[0x5D] = QUIC_FRAME_INVALID,
[0x5E] = QUIC_FRAME_INVALID,
[0x5F] = QUIC_FRAME_INVALID,
[0x60] = QUIC_FRAME_INVALID,
[0x61] = QUIC_FRAME_INVALID,
[0x62] = QUIC_FRAME_INVALID,
[0x63] = QUIC_FRAME_INVALID,
[0x64] = QUIC_FRAME_INVALID,
[0x65] = QUIC_FRAME_INVALID,
[0x66] = QUIC_FRAME_INVALID,
[0x67] = QUIC_FRAME_INVALID,
[0x68] = QUIC_FRAME_INVALID,
[0x69] = QUIC_FRAME_INVALID,
[0x6A] = QUIC_FRAME_INVALID,
[0x6B] = QUIC_FRAME_INVALID,
[0x6C] = QUIC_FRAME_INVALID,
[0x6D] = QUIC_FRAME_INVALID,
[0x6E] = QUIC_FRAME_INVALID,
[0x6F] = QUIC_FRAME_INVALID,
[0x70] = QUIC_FRAME_INVALID,
[0x71] = QUIC_FRAME_INVALID,
[0x72] = QUIC_FRAME_INVALID,
[0x73] = QUIC_FRAME_INVALID,
[0x74] = QUIC_FRAME_INVALID,
[0x75] = QUIC_FRAME_INVALID,
[0x76] = QUIC_FRAME_INVALID,
[0x77] = QUIC_FRAME_INVALID,
[0x78] = QUIC_FRAME_INVALID,
[0x79] = QUIC_FRAME_INVALID,
[0x7A] = QUIC_FRAME_INVALID,
[0x7B] = QUIC_FRAME_INVALID,
[0x7C] = QUIC_FRAME_INVALID,
[0x7D] = QUIC_FRAME_INVALID,
[0x7E] = QUIC_FRAME_INVALID,
[0x7F] = QUIC_FRAME_INVALID,
[0x80] = QUIC_FRAME_INVALID,
[0x81] = QUIC_FRAME_INVALID,
[0x82] = QUIC_FRAME_INVALID,
[0x83] = QUIC_FRAME_INVALID,
[0x84] = QUIC_FRAME_INVALID,
[0x85] = QUIC_FRAME_INVALID,
[0x86] = QUIC_FRAME_INVALID,
[0x87] = QUIC_FRAME_INVALID,
[0x88] = QUIC_FRAME_INVALID,
[0x89] = QUIC_FRAME_INVALID,
[0x8A] = QUIC_FRAME_INVALID,
[0x8B] = QUIC_FRAME_INVALID,
[0x8C] = QUIC_FRAME_INVALID,
[0x8D] = QUIC_FRAME_INVALID,
[0x8E] = QUIC_FRAME_INVALID,
[0x8F] = QUIC_FRAME_INVALID,
[0x90] = QUIC_FRAME_INVALID,
[0x91] = QUIC_FRAME_INVALID,
[0x92] = QUIC_FRAME_INVALID,
[0x93] = QUIC_FRAME_INVALID,
[0x94] = QUIC_FRAME_INVALID,
[0x95] = QUIC_FRAME_INVALID,
[0x96] = QUIC_FRAME_INVALID,
[0x97] = QUIC_FRAME_INVALID,
[0x98] = QUIC_FRAME_INVALID,
[0x99] = QUIC_FRAME_INVALID,
[0x9A] = QUIC_FRAME_INVALID,
[0x9B] = QUIC_FRAME_INVALID,
[0x9C] = QUIC_FRAME_INVALID,
[0x9D] = QUIC_FRAME_INVALID,
[0x9E] = QUIC_FRAME_INVALID,
[0x9F] = QUIC_FRAME_INVALID,
[0xA0] = QUIC_FRAME_INVALID,
[0xA1] = QUIC_FRAME_INVALID,
[0xA2] = QUIC_FRAME_INVALID,
[0xA3] = QUIC_FRAME_INVALID,
[0xA4] = QUIC_FRAME_INVALID,
[0xA5] = QUIC_FRAME_INVALID,
[0xA6] = QUIC_FRAME_INVALID,
[0xA7] = QUIC_FRAME_INVALID,
[0xA8] = QUIC_FRAME_INVALID,
[0xA9] = QUIC_FRAME_INVALID,
[0xAA] = QUIC_FRAME_INVALID,
[0xAB] = QUIC_FRAME_INVALID,
[0xAC] = QUIC_FRAME_INVALID,
[0xAD] = QUIC_FRAME_INVALID,
[0xAE] = QUIC_FRAME_INVALID,
[0xAF] = QUIC_FRAME_INVALID,
[0xB0] = QUIC_FRAME_INVALID,
[0xB1] = QUIC_FRAME_INVALID,
[0xB2] = QUIC_FRAME_INVALID,
[0xB3] = QUIC_FRAME_INVALID,
[0xB4] = QUIC_FRAME_INVALID,
[0xB5] = QUIC_FRAME_INVALID,
[0xB6] = QUIC_FRAME_INVALID,
[0xB7] = QUIC_FRAME_INVALID,
[0xB8] = QUIC_FRAME_INVALID,
[0xB9] = QUIC_FRAME_INVALID,
[0xBA] = QUIC_FRAME_INVALID,
[0xBB] = QUIC_FRAME_INVALID,
[0xBC] = QUIC_FRAME_INVALID,
[0xBD] = QUIC_FRAME_INVALID,
[0xBE] = QUIC_FRAME_INVALID,
[0xBF] = QUIC_FRAME_INVALID,
[0xC0] = QUIC_FRAME_INVALID,
[0xC1] = QUIC_FRAME_INVALID,
[0xC2] = QUIC_FRAME_INVALID,
[0xC3] = QUIC_FRAME_INVALID,
[0xC4] = QUIC_FRAME_INVALID,
[0xC5] = QUIC_FRAME_INVALID,
[0xC6] = QUIC_FRAME_INVALID,
[0xC7] = QUIC_FRAME_INVALID,
[0xC8] = QUIC_FRAME_INVALID,
[0xC9] = QUIC_FRAME_INVALID,
[0xCA] = QUIC_FRAME_INVALID,
[0xCB] = QUIC_FRAME_INVALID,
[0xCC] = QUIC_FRAME_INVALID,
[0xCD] = QUIC_FRAME_INVALID,
[0xCE] = QUIC_FRAME_INVALID,
[0xCF] = QUIC_FRAME_INVALID,
[0xD0] = QUIC_FRAME_INVALID,
[0xD1] = QUIC_FRAME_INVALID,
[0xD2] = QUIC_FRAME_INVALID,
[0xD3] = QUIC_FRAME_INVALID,
[0xD4] = QUIC_FRAME_INVALID,
[0xD5] = QUIC_FRAME_INVALID,
[0xD6] = QUIC_FRAME_INVALID,
[0xD7] = QUIC_FRAME_INVALID,
[0xD8] = QUIC_FRAME_INVALID,
[0xD9] = QUIC_FRAME_INVALID,
[0xDA] = QUIC_FRAME_INVALID,
[0xDB] = QUIC_FRAME_INVALID,
[0xDC] = QUIC_FRAME_INVALID,
[0xDD] = QUIC_FRAME_INVALID,
[0xDE] = QUIC_FRAME_INVALID,
[0xDF] = QUIC_FRAME_INVALID,
[0xE0] = QUIC_FRAME_INVALID,
[0xE1] = QUIC_FRAME_INVALID,
[0xE2] = QUIC_FRAME_INVALID,
[0xE3] = QUIC_FRAME_INVALID,
[0xE4] = QUIC_FRAME_INVALID,
[0xE5] = QUIC_FRAME_INVALID,
[0xE6] = QUIC_FRAME_INVALID,
[0xE7] = QUIC_FRAME_INVALID,
[0xE8] = QUIC_FRAME_INVALID,
[0xE9] = QUIC_FRAME_INVALID,
[0xEA] = QUIC_FRAME_INVALID,
[0xEB] = QUIC_FRAME_INVALID,
[0xEC] = QUIC_FRAME_INVALID,
[0xED] = QUIC_FRAME_INVALID,
[0xEE] = QUIC_FRAME_INVALID,
[0xEF] = QUIC_FRAME_INVALID,
[0xF0] = QUIC_FRAME_INVALID,
[0xF1] = QUIC_FRAME_INVALID,
[0xF2] = QUIC_FRAME_INVALID,
[0xF3] = QUIC_FRAME_INVALID,
[0xF4] = QUIC_FRAME_INVALID,
[0xF5] = QUIC_FRAME_INVALID,
[0xF6] = QUIC_FRAME_INVALID,
[0xF7] = QUIC_FRAME_INVALID,
[0xF8] = QUIC_FRAME_INVALID,
[0xF9] = QUIC_FRAME_INVALID,
[0xFA] = QUIC_FRAME_INVALID,
[0xFB] = QUIC_FRAME_INVALID,
[0xFC] = QUIC_FRAME_INVALID,
[0xFD] = QUIC_FRAME_INVALID,
[0xFE] = QUIC_FRAME_INVALID,
[0xFF] = QUIC_FRAME_INVALID,
};
return byte2type[byte];
}
static unsigned
ietf_v1_path_chal_frame_size (void)
{
@ -1695,14 +1970,32 @@ lsquic_ietf_v1_parse_packet_in_long_begin (struct lsquic_packet_in *packet_in,
case HETY_RETRY:
if (p >= end)
return -1;
odcil = *p++;
if (p + odcil > end || odcil > MAX_CID_LEN)
return -1;
packet_in->pi_odcid_len = odcil;
packet_in->pi_odcid = p - packet_in->pi_data;
p += odcil;
packet_in->pi_token = p - packet_in->pi_data;
packet_in->pi_token_size = end - p;
if (LSQVER_ID24 == lsquic_tag2ver(tag))
{
odcil = *p++;
if (p + odcil > end || odcil > MAX_CID_LEN)
return -1;
packet_in->pi_odcid_len = odcil;
packet_in->pi_odcid = p - packet_in->pi_data;
p += odcil;
packet_in->pi_token = p - packet_in->pi_data;
packet_in->pi_token_size = end - p;
}
else
{
if (p
/* [draft-ietf-quic-transport-25] Section 17.2.5 says that "a
* client MUST discard a Retry packet with a zero-length Retry
* Token field." We might as well do it here.
*/
+ 1
/* Integrity tag length: */
+ 16 > end)
return -1;
packet_in->pi_token = p - packet_in->pi_data;
packet_in->pi_token_size = end - p - 16;
/* Tag validation happens later */
}
p = end;
length = end - packet_in->pi_data;
state->pps_p = NULL;
@ -1937,6 +2230,117 @@ lsquic_ietf_v1_gen_ver_nego_pkt (unsigned char *buf, size_t bufsz,
}
static int
ietf_v1_gen_handshake_done_frame (unsigned char *buf, size_t buf_len)
{
if (buf_len > 0)
{
*buf = 0x1E;
return 1;
}
else
return -1;
}
static int
ietf_v1_parse_handshake_done_frame (const unsigned char *buf, size_t buf_len)
{
assert(buf[0] == 0x1E);
assert(buf_len > 0);
return 1;
}
static unsigned
ietf_v1_handshake_done_frame_size (void)
{
return 1;
}
static int
ietf_id24_gen_handshake_done_frame (unsigned char *buf, size_t buf_len)
{
/* ID-24 does not have HANDSHAKE_DONE frame */
return -1;
}
static int
ietf_id24_parse_handshake_done_frame (const unsigned char *buf, size_t buf_len)
{
/* ID-24 does not have HANDSHAKE_DONE frame */
return -1;
}
const struct parse_funcs lsquic_parse_funcs_ietf_id24 =
{
.pf_gen_reg_pkt_header = ietf_v1_gen_reg_pkt_header,
.pf_parse_packet_in_finish = ietf_v1_parse_packet_in_finish,
.pf_gen_stream_frame = ietf_v1_gen_stream_frame,
.pf_calc_stream_frame_header_sz = ietf_v1_calc_stream_frame_header_sz,
.pf_parse_stream_frame = ietf_v1_parse_stream_frame,
.pf_parse_ack_frame = ietf_v1_parse_ack_frame,
.pf_gen_ack_frame = ietf_v1_gen_ack_frame,
.pf_gen_blocked_frame = ietf_v1_gen_blocked_frame,
.pf_parse_blocked_frame = ietf_v1_parse_blocked_frame,
.pf_blocked_frame_size = ietf_v1_blocked_frame_size,
.pf_rst_frame_size = ietf_v1_rst_frame_size,
.pf_gen_rst_frame = ietf_v1_gen_rst_frame,
.pf_parse_rst_frame = ietf_v1_parse_rst_frame,
.pf_connect_close_frame_size = ietf_v1_connect_close_frame_size,
.pf_gen_connect_close_frame = ietf_v1_gen_connect_close_frame,
.pf_parse_connect_close_frame = ietf_v1_parse_connect_close_frame,
.pf_gen_ping_frame = ietf_v1_gen_ping_frame,
.pf_parse_frame_type = ietf_id24_parse_frame_type,
.pf_turn_on_fin = ietf_v1_turn_on_fin,
.pf_packout_size = ietf_v1_packout_size,
.pf_packout_max_header_size = ietf_v1_packout_max_header_size,
.pf_path_chal_frame_size = ietf_v1_path_chal_frame_size,
.pf_parse_path_chal_frame = ietf_v1_parse_path_chal_frame,
.pf_gen_path_chal_frame = ietf_v1_gen_path_chal_frame,
.pf_path_resp_frame_size = ietf_v1_path_resp_frame_size,
.pf_gen_path_resp_frame = ietf_v1_gen_path_resp_frame,
.pf_parse_path_resp_frame = ietf_v1_parse_path_resp_frame,
.pf_calc_packno_bits = ietf_v1_calc_packno_bits,
.pf_packno_bits2len = ietf_v1_packno_bits2len,
.pf_packno_info = ietf_v1_packno_info,
.pf_gen_crypto_frame = ietf_v1_gen_crypto_frame,
.pf_parse_crypto_frame = ietf_v1_parse_crypto_frame,
.pf_calc_crypto_frame_header_sz = ietf_v1_calc_crypto_frame_header_sz,
.pf_parse_max_data = ietf_v1_parse_max_data,
.pf_gen_max_data_frame = ietf_v1_gen_max_data_frame,
.pf_max_data_frame_size = ietf_v1_max_data_frame_size,
.pf_parse_new_conn_id = ietf_v1_parse_new_conn_id,
.pf_gen_stream_blocked_frame = ietf_v1_gen_stream_blocked_frame,
.pf_parse_stream_blocked_frame = ietf_v1_parse_stream_blocked_frame,
.pf_stream_blocked_frame_size = ietf_v1_stream_blocked_frame_size,
.pf_gen_max_stream_data_frame = ietf_v1_gen_max_stream_data_frame,
.pf_parse_max_stream_data_frame = ietf_v1_parse_max_stream_data_frame,
.pf_max_stream_data_frame_size = ietf_v1_max_stream_data_frame_size,
.pf_parse_stop_sending_frame = ietf_v1_parse_stop_sending_frame,
.pf_gen_stop_sending_frame = ietf_v1_gen_stop_sending_frame,
.pf_stop_sending_frame_size = ietf_v1_stop_sending_frame_size,
.pf_parse_new_token_frame = ietf_v1_parse_new_token_frame,
.pf_new_connection_id_frame_size = ietf_v1_new_connection_id_frame_size,
.pf_gen_new_connection_id_frame = ietf_v1_gen_new_connection_id_frame,
.pf_new_token_frame_size = ietf_v1_new_token_frame_size,
.pf_gen_new_token_frame = ietf_v1_gen_new_token_frame,
.pf_parse_retire_cid_frame = ietf_v1_parse_retire_cid_frame,
.pf_gen_retire_cid_frame = ietf_v1_gen_retire_cid_frame,
.pf_retire_cid_frame_size = ietf_v1_retire_cid_frame_size,
.pf_gen_streams_blocked_frame = ietf_v1_gen_streams_blocked_frame,
.pf_parse_streams_blocked_frame = ietf_v1_parse_streams_blocked_frame,
.pf_streams_blocked_frame_size = ietf_v1_streams_blocked_frame_size,
.pf_gen_max_streams_frame = ietf_v1_gen_max_streams_frame,
.pf_parse_max_streams_frame = ietf_v1_parse_max_streams_frame,
.pf_max_streams_frame_size = ietf_v1_max_streams_frame_size,
.pf_gen_handshake_done_frame = ietf_id24_gen_handshake_done_frame,
.pf_parse_handshake_done_frame = ietf_id24_parse_handshake_done_frame,
.pf_handshake_done_frame_size = ietf_v1_handshake_done_frame_size,
};
const struct parse_funcs lsquic_parse_funcs_ietf_v1 =
@ -2001,4 +2405,7 @@ const struct parse_funcs lsquic_parse_funcs_ietf_v1 =
.pf_gen_max_streams_frame = ietf_v1_gen_max_streams_frame,
.pf_parse_max_streams_frame = ietf_v1_parse_max_streams_frame,
.pf_max_streams_frame_size = ietf_v1_max_streams_frame_size,
.pf_gen_handshake_done_frame = ietf_v1_gen_handshake_done_frame,
.pf_parse_handshake_done_frame = ietf_v1_parse_handshake_done_frame,
.pf_handshake_done_frame_size = ietf_v1_handshake_done_frame_size,
};

View File

@ -28,6 +28,7 @@
#include "lsquic.h"
#include "lsquic_mm.h"
#include "lsquic_engine_public.h"
#include "lsquic_ietf.h"
/* [draft-ietf-quic-transport-17] Section-17.2 */
@ -194,35 +195,6 @@ lsquic_Q046_parse_packet_in_short_begin (lsquic_packet_in_t *packet_in,
}
/* TODO: this only works Q044? XXX */
ssize_t
lsquic_generate_iquic_reset (const lsquic_cid_t *cidp, unsigned char *buf,
size_t buf_sz)
{
size_t need;
uint64_t id;
need = 1 /* Type */ + 20 /* Random bytes */ + 16 /* Reset token */;
if (buf_sz < need)
return -1;
*buf = 0x30;
(void) RAND_pseudo_bytes(buf + 1, 20);
/* XXX code duplication here and lsquic_generate_reset_token(). Which
* should call which: parse function the crypto functions or the other
* way around?
*/
/* TODO test this */
memcpy(&id, cidp->idbuf, GQUIC_CID_LEN);
#if __BYTE_ORDER == __LITTLE_ENDIAN
id = bswap_64(id);
#endif
memcpy(buf + 21, &id, sizeof(id));
memset(buf + 21 + sizeof(id), 0, SRST_LENGTH - sizeof(id));
return need;
}
/* This is a bare-bones version of lsquic_Q046_parse_packet_in_long_begin()
*/
int
@ -300,7 +272,7 @@ const enum quic_frame_type lsquic_iquic_byte2type[0x100] =
[0x1B] = QUIC_FRAME_PATH_RESPONSE,
[0x1C] = QUIC_FRAME_CONNECTION_CLOSE,
[0x1D] = QUIC_FRAME_CONNECTION_CLOSE,
[0x1E] = QUIC_FRAME_INVALID,
[0x1E] = QUIC_FRAME_HANDSHAKE_DONE,
[0x1F] = QUIC_FRAME_INVALID,
[0x20] = QUIC_FRAME_INVALID,
[0x21] = QUIC_FRAME_INVALID,

View File

@ -2909,6 +2909,10 @@ lsquic_send_ctl_repath (struct lsquic_send_ctl *ctl, struct network_path *old,
}
LSQ_DEBUG("repathed %u packet%.*s", count, count != 1, "s");
memset(&ctl->sc_conn_pub->rtt_stats, 0,
sizeof(ctl->sc_conn_pub->rtt_stats));
ctl->sc_ci->cci_reinit(CGP(ctl));
}

View File

@ -610,4 +610,7 @@ lsquic_stream_header_is_trailer (const struct lsquic_stream *);
int
lsquic_stream_verify_len (struct lsquic_stream *, unsigned long long);
#define lsquic_stream_is_blocked(stream_) ((stream_)->blocked_off && \
(stream_)->blocked_off == (stream_)->max_send_off)
#endif

View File

@ -137,8 +137,8 @@ get_or_generate_state (struct lsquic_engine_public *enpub, time_t now,
sizeof(TOKGEN_SHM_MAGIC_TOP) - 1);
if (getenv("LSQUIC_NULL_TOKGEN"))
{
memset(&srst_ikm, 0, sizeof(srst_ikm));
LSQ_NOTICE("using NULL tokgen");
memset(&srst_ikm, 0, sizeof(srst_ikm));
}
else
{

View File

@ -36,7 +36,7 @@ static const uint64_t def_vals[MAX_TPI + 1] =
[TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL] = TP_DEF_INIT_MAX_STREAM_DATA_BIDI_LOCAL,
[TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE] = TP_DEF_INIT_MAX_STREAM_DATA_BIDI_REMOTE,
[TPI_INIT_MAX_STREAM_DATA_UNI] = TP_DEF_INIT_MAX_STREAM_DATA_UNI,
[TPI_IDLE_TIMEOUT] = TP_DEF_IDLE_TIMEOUT,
[TPI_MAX_IDLE_TIMEOUT] = TP_DEF_MAX_IDLE_TIMEOUT,
[TPI_MAX_ACK_DELAY] = TP_DEF_MAX_ACK_DELAY,
[TPI_ACTIVE_CONNECTION_ID_LIMIT] = TP_DEF_ACTIVE_CONNECTION_ID_LIMIT,
};
@ -52,7 +52,7 @@ static const uint64_t max_vals[MAX_TPI + 1] =
[TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL] = VINT_MAX_VALUE,
[TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE] = VINT_MAX_VALUE,
[TPI_INIT_MAX_STREAM_DATA_UNI] = VINT_MAX_VALUE,
[TPI_IDLE_TIMEOUT] = VINT_MAX_VALUE,
[TPI_MAX_IDLE_TIMEOUT] = VINT_MAX_VALUE,
[TPI_MAX_ACK_DELAY] = TP_MAX_MAX_ACK_DELAY,
[TPI_ACTIVE_CONNECTION_ID_LIMIT] = VINT_MAX_VALUE,
};
@ -73,7 +73,7 @@ static const unsigned tpi2idx[MAX_TPI + 1] =
[TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL] = TP_OFF(init_max_stream_data_bidi_local),
[TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE] = TP_OFF(init_max_stream_data_bidi_remote),
[TPI_INIT_MAX_STREAM_DATA_UNI] = TP_OFF(init_max_stream_data_uni),
[TPI_IDLE_TIMEOUT] = TP_OFF(idle_timeout),
[TPI_MAX_IDLE_TIMEOUT] = TP_OFF(max_idle_timeout),
[TPI_MAX_ACK_DELAY] = TP_OFF(max_ack_delay),
[TPI_ACTIVE_CONNECTION_ID_LIMIT] = TP_OFF(active_connection_id_limit),
};
@ -533,7 +533,7 @@ lsquic_tp_to_str (const struct transport_params *params, char *buf, size_t sz)
WRITE_ONE_PARAM(init_max_stream_data_bidi_remote, "%"PRIu64);
WRITE_ONE_PARAM(init_max_stream_data_uni, "%"PRIu64);
WRITE_ONE_PARAM(init_max_data, "%"PRIu64);
WRITE_ONE_PARAM(idle_timeout, "%"PRIu64);
WRITE_ONE_PARAM(max_idle_timeout, "%"PRIu64);
WRITE_ONE_PARAM(init_max_streams_bidi, "%"PRIu64);
WRITE_ONE_PARAM(init_max_streams_uni, "%"PRIu64);
WRITE_ONE_PARAM(max_packet_size, "%"PRIu64);

View File

@ -10,7 +10,7 @@
enum transport_param_id
{
TPI_ORIGINAL_CONNECTION_ID = 0,
TPI_IDLE_TIMEOUT = 1,
TPI_MAX_IDLE_TIMEOUT = 1,
TPI_STATELESS_RESET_TOKEN = 2,
TPI_MAX_PACKET_SIZE = 3,
TPI_INIT_MAX_DATA = 4,
@ -36,7 +36,7 @@ enum transport_param_id
|(1 << TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL) \
|(1 << TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE) \
|(1 << TPI_INIT_MAX_STREAM_DATA_UNI) \
|(1 << TPI_IDLE_TIMEOUT) \
|(1 << TPI_MAX_IDLE_TIMEOUT) \
|(1 << TPI_MAX_ACK_DELAY) \
|(1 << TPI_ACK_DELAY_EXPONENT) \
|(1 << TPI_ACTIVE_CONNECTION_ID_LIMIT) \
@ -74,7 +74,7 @@ struct transport_params
uint64_t init_max_stream_data_bidi_remote;
uint64_t init_max_stream_data_uni;
uint64_t init_max_data;
uint64_t idle_timeout;
uint64_t max_idle_timeout;
uint64_t init_max_streams_bidi;
uint64_t init_max_streams_uni;
uint64_t max_packet_size;
@ -88,7 +88,7 @@ struct transport_params
#define tp_init_max_stream_data_bidi_remote tp_numerics_u.s.init_max_stream_data_bidi_remote
#define tp_init_max_stream_data_uni tp_numerics_u.s.init_max_stream_data_uni
#define tp_init_max_data tp_numerics_u.s.init_max_data
#define tp_idle_timeout tp_numerics_u.s.idle_timeout
#define tp_max_idle_timeout tp_numerics_u.s.max_idle_timeout
#define tp_init_max_streams_bidi tp_numerics_u.s.init_max_streams_bidi
#define tp_init_max_streams_uni tp_numerics_u.s.init_max_streams_uni
#define tp_max_packet_size tp_numerics_u.s.max_packet_size
@ -119,16 +119,16 @@ struct transport_params
#define TP_DEF_INIT_MAX_STREAM_DATA_BIDI_LOCAL 0
#define TP_DEF_INIT_MAX_STREAM_DATA_BIDI_REMOTE 0
#define TP_DEF_INIT_MAX_STREAM_DATA_UNI 0
#define TP_DEF_IDLE_TIMEOUT 0
#define TP_DEF_MAX_IDLE_TIMEOUT 0
#define TP_DEF_MAX_ACK_DELAY 25
#define TP_DEF_ACTIVE_CONNECTION_ID_LIMIT 0
#define TP_DEF_ACTIVE_CONNECTION_ID_LIMIT 2
/* [draft-ietf-quic-transport-18], Section 18.1 */
#define TP_MAX_MAX_ACK_DELAY ((1u << 14) - 1)
#define TP_DEFAULT_VALUES \
.tp_active_connection_id_limit = TP_DEF_ACTIVE_CONNECTION_ID_LIMIT, \
.tp_idle_timeout = TP_DEF_IDLE_TIMEOUT, \
.tp_max_idle_timeout = TP_DEF_MAX_IDLE_TIMEOUT, \
.tp_max_ack_delay = TP_DEF_MAX_ACK_DELAY, \
.tp_max_packet_size = TP_DEF_MAX_PACKET_SIZE, \
.tp_ack_delay_exponent = TP_DEF_ACK_DELAY_EXP, \

View File

@ -14,8 +14,8 @@ static const unsigned char version_tags[N_LSQVER][4] =
#if LSQUIC_USE_Q098
[LSQVER_098] = { 'Q', '0', '9', '8', },
#endif
[LSQVER_ID23] = { 0xFF, 0, 0, 23, },
[LSQVER_ID24] = { 0xFF, 0, 0, 24, },
[LSQVER_ID25] = { 0xFF, 0, 0, 25, },
[LSQVER_VERNEG] = { 0xFA, 0xFA, 0xFA, 0xFA, },
};
@ -52,8 +52,8 @@ const char *const lsquic_ver2str[N_LSQVER] = {
#if LSQUIC_USE_Q098
[LSQVER_098] = "Q098",
#endif
[LSQVER_ID23] = "FF000017",
[LSQVER_ID24] = "FF000018",
[LSQVER_ID25] = "FF000019",
[LSQVER_VERNEG] = "FAFAFAFA",
};

View File

@ -706,6 +706,7 @@ http_client_on_read (lsquic_stream_t *stream, lsquic_stream_ctx_t *st_h)
s_stat_downloaded_bytes > client_ctx->hcc_retire_cid_after_nbytes)
{
lsquic_conn_retire_cid(lsquic_stream_conn(stream));
client_ctx->hcc_retire_cid_after_nbytes = 0;
break;
}
if (!g_header_bypass && !(st_h->sh_flags & PROCESSED_HEADERS))
@ -850,6 +851,7 @@ usage (const char *prog)
" -T FILE Print stats to FILE. If FILE is -, print stats to stdout.\n"
" -q FILE QIF mode: issue requests from the QIF file and validate\n"
" server responses.\n"
" -e TOKEN Hexadecimal string representing resume token.\n"
, prog);
}

View File

@ -127,7 +127,7 @@ prog_print_common_options (const struct prog *prog, FILE *out)
" If no -s option is given, 0.0.0.0:12345 address\n"
" is used.\n"
#if LSQUIC_DONTFRAG_SUPPORTED
" -D Set `do not fragment' flag on outgoing UDP packets\n"
" -D Do not set `do not fragment' flag on outgoing UDP packets\n"
#endif
" -z BYTES Maximum size of outgoing UDP packets. The default is 1370\n"
" bytes for IPv4 socket and 1350 bytes for IPv6 socket\n"
@ -226,7 +226,7 @@ prog_set_opt (struct prog *prog, int opt, const char *arg)
struct service_port *sport = TAILQ_LAST(prog->prog_sports, sport_head);
if (!sport)
sport = &prog->prog_dummy_sport;
sport->sp_flags |= SPORT_DONT_FRAGMENT;
sport->sp_flags |= SPORT_FRAGMENT_OK;
}
return 0;
#endif

View File

@ -21,7 +21,7 @@ static int
select_alpn (SSL *ssl, const unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen, void *arg)
{
const unsigned char alpn[] = "\x5h3-23\x5h3-24";
const unsigned char alpn[] = "\x5h3-24\x5h3-25";
int r;
r = SSL_select_next_proto((unsigned char **) out, outlen, in, inlen,

View File

@ -922,7 +922,7 @@ sport_init_server (struct service_port *sport, struct lsquic_engine *engine,
#endif
#if LSQUIC_DONTFRAG_SUPPORTED
if (sport->sp_flags & SPORT_DONT_FRAGMENT)
if (!(sport->sp_flags & SPORT_FRAGMENT_OK))
{
if (AF_INET == sa_local->sa_family)
{
@ -1110,7 +1110,7 @@ sport_init_client (struct service_port *sport, struct lsquic_engine *engine,
#endif
#if LSQUIC_DONTFRAG_SUPPORTED
if (sport->sp_flags & SPORT_DONT_FRAGMENT)
if (!(sport->sp_flags & SPORT_FRAGMENT_OK))
{
if (AF_INET == sa_local->sa_family)
{
@ -1811,6 +1811,11 @@ set_engine_option (struct lsquic_engine_settings *settings,
settings->es_idle_conn_to = atoi(val);
return 0;
}
if (0 == strncmp(name, "idle_timeout", 12))
{
settings->es_idle_timeout = atoi(val);
return 0;
}
if (0 == strncmp(name, "silent_close", 12))
{
settings->es_silent_close = atoi(val);

View File

@ -23,7 +23,7 @@ struct reader_ctx;
enum sport_flags
{
#if LSQUIC_DONTFRAG_SUPPORTED
SPORT_DONT_FRAGMENT = (1 << 0),
SPORT_FRAGMENT_OK = (1 << 0),
#endif
SPORT_SET_SNDBUF = (1 << 1), /* SO_SNDBUF */
SPORT_SET_RCVBUF = (1 << 2), /* SO_RCVBUF */

View File

@ -179,7 +179,7 @@ run_test (const struct test *test)
size_t sz;
unsigned char buf[0x1000];
pf = select_pf_by_ver(LSQVER_ID23);
pf = select_pf_by_ver(LSQVER_ID24);
if (!test->skip_gen)
{
rechist.acki = &test->acki;

View File

@ -33,7 +33,7 @@ struct test {
static const struct test tests[] = {
{ .lineno = __LINE__,
.pf = select_pf_by_ver(LSQVER_ID23),
.pf = select_pf_by_ver(LSQVER_ID24),
.offset = 0,
.data_sz = 10,
.data = "0123456789",
@ -49,7 +49,7 @@ static const struct test tests[] = {
},
{ .lineno = __LINE__,
.pf = select_pf_by_ver(LSQVER_ID23),
.pf = select_pf_by_ver(LSQVER_ID24),
.offset = 500,
.data_sz = 10,
.data = "0123456789",

View File

@ -56,7 +56,7 @@
#include "lsquic_hq.h"
#include "lsquic_data_in_if.h"
static const struct parse_funcs *g_pf = select_pf_by_ver(LSQVER_ID23);
static const struct parse_funcs *g_pf = select_pf_by_ver(LSQVER_ID24);
struct test_ctl_settings
{
@ -297,7 +297,7 @@ init_test_objs (struct test_objs *tobjs, unsigned initial_conn_window,
memset(tobjs, 0, sizeof(*tobjs));
LSCONN_INITIALIZE(&tobjs->lconn);
tobjs->lconn.cn_pf = g_pf;
tobjs->lconn.cn_version = LSQVER_ID23;
tobjs->lconn.cn_version = LSQVER_ID24;
tobjs->lconn.cn_esf_c = &lsquic_enc_session_common_ietf_v1;
network_path.np_pack_size = packet_sz;
tobjs->lconn.cn_if = &our_conn_if;

View File

@ -158,8 +158,8 @@ init_test_objs (struct test_objs *tobjs, unsigned initial_conn_window,
int s;
memset(tobjs, 0, sizeof(*tobjs));
LSCONN_INITIALIZE(&tobjs->lconn);
tobjs->lconn.cn_pf = select_pf_by_ver(LSQVER_ID23);
tobjs->lconn.cn_version = LSQVER_ID23;
tobjs->lconn.cn_pf = select_pf_by_ver(LSQVER_ID24);
tobjs->lconn.cn_version = LSQVER_ID24;
tobjs->lconn.cn_esf_c = &lsquic_enc_session_common_ietf_v1;
network_path.np_pack_size = IQUIC_MAX_IPv4_PACKET_SZ;
tobjs->lconn.cn_if = &our_conn_if;

View File

@ -325,7 +325,7 @@ init_test_objs (struct test_objs *tobjs, unsigned initial_conn_window,
LSCONN_INITIALIZE(&tobjs->lconn);
tobjs->lconn.cn_pf = pf ? pf : g_pf;
tobjs->lconn.cn_version = tobjs->lconn.cn_pf == &lsquic_parse_funcs_ietf_v1 ?
LSQVER_ID23 : LSQVER_043;
LSQVER_ID24 : LSQVER_043;
tobjs->lconn.cn_esf_c = &lsquic_enc_session_common_gquic_1;
network_path.np_pack_size = 1370;
tobjs->lconn.cn_if = &our_conn_if;
@ -2200,7 +2200,7 @@ test_changing_pack_size (void)
enum lsquic_version versions_to_test[3] =
{
LSQVER_046,
LSQVER_ID23,
LSQVER_ID24,
};
for (i = 0; i < 3; i++)
@ -3130,7 +3130,7 @@ main (int argc, char **argv)
/* Redo some tests using crypto streams and frames */
g_use_crypto_ctor = 1;
g_pf = select_pf_by_ver(LSQVER_ID23);
g_pf = select_pf_by_ver(LSQVER_ID24);
main_test_packetization();
return 0;

View File

@ -279,7 +279,7 @@ static const struct test tests[] = {
*/
{ .lineno = __LINE__,
.pf = select_pf_by_ver(LSQVER_ID23),
.pf = select_pf_by_ver(LSQVER_ID24),
.fin = { 0, 1, },
.offset = 0x0807060504030201UL,
.stream_id = 0x210,
@ -299,7 +299,7 @@ static const struct test tests[] = {
},
{ .lineno = __LINE__,
.pf = select_pf_by_ver(LSQVER_ID23),
.pf = select_pf_by_ver(LSQVER_ID24),
.fin = { 0, 0, },
.offset = 0,
.stream_id = 0x210,
@ -318,7 +318,7 @@ static const struct test tests[] = {
},
{ .lineno = __LINE__,
.pf = select_pf_by_ver(LSQVER_ID23),
.pf = select_pf_by_ver(LSQVER_ID24),
.fin = { 0, 0, },
.offset = 0,
.stream_id = 0x21,
@ -336,7 +336,7 @@ static const struct test tests[] = {
},
{ .lineno = __LINE__,
.pf = select_pf_by_ver(LSQVER_ID23),
.pf = select_pf_by_ver(LSQVER_ID24),
.fin = { 0, 0, },
.offset = 0x0807060504030201UL,
.stream_id = 0x210,
@ -356,7 +356,7 @@ static const struct test tests[] = {
},
{ .lineno = __LINE__,
.pf = select_pf_by_ver(LSQVER_ID23),
.pf = select_pf_by_ver(LSQVER_ID24),
.fin = { 1, 0, },
.offset = 0x0807060504030201UL,
.stream_id = 0x210,
@ -374,7 +374,7 @@ static const struct test tests[] = {
},
{ .lineno = __LINE__,
.pf = select_pf_by_ver(LSQVER_ID23),
.pf = select_pf_by_ver(LSQVER_ID24),
.fin = { 1, 0, },
.offset = 0x0807060504030201UL,
.stream_id = 0x210,

View File

@ -243,7 +243,7 @@ static const struct test tests[] = {
{ "Balls to the wall: every possible bit is set",
__LINE__,
select_pf_by_ver(LSQVER_ID23),
select_pf_by_ver(LSQVER_ID24),
/* TYPE OFF DLEN FIN */
{ 0x10 | 1<<2 | 1<<1 | 1<<0,
0x41, 0x23, /* Stream ID */
@ -262,7 +262,7 @@ static const struct test tests[] = {
{ "Balls to the wall #2: every possible bit is set except FIN",
__LINE__,
select_pf_by_ver(LSQVER_ID23),
select_pf_by_ver(LSQVER_ID24),
/* TYPE OFF DLEN FIN */
{ 0x10 | 1<<2 | 1<<1 | 0<<0,
0x81, 0x23, 0x00, 0xE4, /* Stream ID */
@ -281,7 +281,7 @@ static const struct test tests[] = {
{ "Data length is zero",
__LINE__,
select_pf_by_ver(LSQVER_ID23),
select_pf_by_ver(LSQVER_ID24),
/* TYPE OFF DLEN FIN */
{ 0x10 | 1<<2 | 0<<1 | 0<<0,
0x81, 0x23, 0x00, 0xE4, /* Stream ID */
@ -299,7 +299,7 @@ static const struct test tests[] = {
{ "Sanity check: what happens when data length is zero #1",
__LINE__,
select_pf_by_ver(LSQVER_ID23),
select_pf_by_ver(LSQVER_ID24),
/* TYPE OFF DLEN FIN */
{ 0x10 | 1<<2 | 1<<1 | 0<<0,
0x81, 0x23, 0x00, 0xE4, /* Stream ID */
@ -318,7 +318,7 @@ static const struct test tests[] = {
{ "Sanity check: what happens when data length is zero #2",
__LINE__,
select_pf_by_ver(LSQVER_ID23),
select_pf_by_ver(LSQVER_ID24),
/* TYPE OFF DLEN FIN */
{ 0x10 | 1<<2 | 1<<1 | 0<<0,
0x81, 0x23, 0x00, 0xE4, /* Stream ID */
@ -337,7 +337,7 @@ static const struct test tests[] = {
{ "Sanity check: what happens when data length is zero #3",
__LINE__,
select_pf_by_ver(LSQVER_ID23),
select_pf_by_ver(LSQVER_ID24),
/* TYPE OFF DLEN FIN */
{ 0x10 | 0<<2 | 1<<1 | 0<<0,
0x81, 0x23, 0x00, 0xE4, /* Stream ID */
@ -355,7 +355,7 @@ static const struct test tests[] = {
{ "Sanity check: what happens when data length is zero #3",
__LINE__,
select_pf_by_ver(LSQVER_ID23),
select_pf_by_ver(LSQVER_ID24),
/* TYPE OFF DLEN FIN */
{ 0x10 | 1<<2 | 1<<1 | 1<<0,
0x81, 0x23, 0x00, 0xE4, /* Stream ID */
@ -374,7 +374,7 @@ static const struct test tests[] = {
{ "Check data bounds #1",
__LINE__,
select_pf_by_ver(LSQVER_ID23),
select_pf_by_ver(LSQVER_ID24),
/* TYPE OFF DLEN FIN */
{ 0x10 | 1<<2 | 1<<1 | 1<<0,
0x81, 0x23, 0x00, 0xE4, /* Stream ID */
@ -393,7 +393,7 @@ static const struct test tests[] = {
{ "Check data bounds #2",
__LINE__,
select_pf_by_ver(LSQVER_ID23),
select_pf_by_ver(LSQVER_ID24),
/* TYPE OFF DLEN FIN */
{ 0x10 | 1<<2 | 1<<1 | 1<<0,
0x81, 0x23, 0x00, 0xE4, /* Stream ID */

View File

@ -56,7 +56,7 @@ static const struct trapa_test tests[] =
.tp_flags = 0,
.tp_init_max_stream_data_bidi_local = 0x12348877,
.tp_init_max_data = 0xAABB,
.tp_idle_timeout = 10 * 1000,
.tp_max_idle_timeout = 10 * 1000,
.tp_max_ack_delay = TP_DEF_MAX_ACK_DELAY,
.tp_active_connection_id_limit = 7,
},