Release 2.11.0

- [FEATURE] QUIC and HTTP/3 Internet Draft 27 support.
- [FEATURE] Add experimental delayed ACKs extension.
- Drop support for Internet Draft 24.
- Code cleanup.
This commit is contained in:
Dmitri Tikhonov 2020-02-24 12:02:57 -05:00
parent feca77f50d
commit bc520ef752
38 changed files with 626 additions and 7729 deletions

View File

@ -1,3 +1,10 @@
2020-02-24
- 2.11.0
- [FEATURE] QUIC and HTTP/3 Internet Draft 27 support.
- [FEATURE] Add experimental delayed ACKs extension.
- Drop support for Internet Draft 24.
- Code cleanup.
2020-02-14
- 2.10.6
- [BUGFIX] HTTP/3 framing: don't misinterpret rare occurence as error.

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-24, and ID-25.
Currently supported QUIC versions are Q043, Q046, Q050, ID-25, and ID-27.
Support for newer versions will be added soon after they are released.
Documentation

View File

@ -46,13 +46,13 @@ developed by the IETF. Both types are included in a single enum:
Google QUIC version Q050
.. member:: LSQVER_ID24
IETF QUIC version ID (Internet-Draft) 24
.. member:: LSQVER_ID25
IETF QUIC version ID 25
IETF QUIC version ID (Internet-Draft) 25
.. member:: LSQVER_ID27
IETF QUIC version ID 27
.. member:: N_LSQVER

View File

@ -24,9 +24,9 @@ copyright = u'2020, LiteSpeed Technologies'
author = u'LiteSpeed Technologies'
# The short X.Y version
version = u'2.10'
version = u'2.11'
# The full version, including alpha/beta/rc tags
release = u'2.10.6'
release = u'2.11.0'
# -- General configuration ---------------------------------------------------

View File

@ -19,7 +19,7 @@ Most of the code in this distribution has been used in our own products
-- `LiteSpeed Web Server`_, `LiteSpeed Web ADC`_, and OpenLiteSpeed_ --
since 2017.
Currently supported QUIC versions are Q043, Q046, Q050, ID-24, and ID-25.
Currently supported QUIC versions are Q043, Q046, Q050, ID-25, and ID-27.
Support for newer versions will be added soon after they are released.
LSQUIC is licensed under the `MIT License`_; see LICENSE in the source

View File

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

View File

@ -26,7 +26,6 @@ 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,7 +31,6 @@ 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

@ -40,8 +40,6 @@ const char *const lsquic_alid2str[] =
[AL_RETX_APP] = "RETX_APP",
[AL_PING] = "PING",
[AL_IDLE] = "IDLE",
[AL_ACK_INIT] = "ACK_INIT",
[AL_ACK_HSK] = "ACK_HSK",
[AL_ACK_APP] = "ACK_APP",
[AL_RET_CIDS] = "RET_CIDS",
[AL_CID_THROT] = "CID_THROT",

View File

@ -27,10 +27,7 @@ enum alarm_id {
AL_RETX_APP = AL_RETX_INIT + PNS_APP,
AL_PING,
AL_IDLE,
/* TODO: remove AL_ACK_INIT and AL_ACK_HSK when LSQVER_ID24 is removed */
AL_ACK_INIT,
AL_ACK_HSK = AL_ACK_INIT + PNS_HSK,
AL_ACK_APP = AL_ACK_INIT + PNS_APP,
AL_ACK_APP,
AL_RET_CIDS,
AL_CID_THROT,
AL_PATH_CHAL,
@ -48,8 +45,6 @@ enum alarm_id_bit {
ALBIT_RETX_HSK = 1 << AL_RETX_HSK,
ALBIT_RETX_APP = 1 << AL_RETX_APP,
ALBIT_ACK_APP = 1 << AL_ACK_APP,
ALBIT_ACK_INIT = 1 << AL_ACK_INIT,
ALBIT_ACK_HSK = 1 << AL_ACK_HSK,
ALBIT_PING = 1 << AL_PING,
ALBIT_IDLE = 1 << AL_IDLE,
ALBIT_RET_CIDS = 1 << AL_RET_CIDS,

View File

@ -328,8 +328,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_ID24 ? &lsquic_enc_session_common_ietf_v1 : \
ver == LSQVER_ID25 ? &lsquic_enc_session_common_ietf_v1 : \
ver == LSQVER_ID27 ? &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

@ -71,9 +71,9 @@ static const struct alpn_map {
enum lsquic_version version;
const unsigned char *alpn;
} s_alpns[] = {
{ LSQVER_ID24, (unsigned char *) "\x05h3-24", },
{ LSQVER_ID25, (unsigned char *) "\x05h3-25", },
{ LSQVER_VERNEG, (unsigned char *) "\x05h3-25", },
{ LSQVER_ID27, (unsigned char *) "\x05h3-27", },
{ LSQVER_VERNEG, (unsigned char *) "\x05h3-27", },
};
struct enc_sess_iquic;
@ -546,12 +546,6 @@ gen_trans_params (struct enc_sess_iquic *enc_sess, unsigned char *buf,
| (1 << TPI_MAX_PACKET_SIZE)
| (1 << TPI_ACTIVE_CONNECTION_ID_LIMIT)
;
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_set & (1 << TPI_PREFERRED_ADDRESS));
}
if (!settings->es_allow_migration)
params.tp_set |= 1 << TPI_DISABLE_ACTIVE_MIGRATION;
if (settings->es_ql_bits)
@ -565,7 +559,8 @@ gen_trans_params (struct enc_sess_iquic *enc_sess, unsigned char *buf,
params.tp_set |= 1 << TPI_MIN_ACK_DELAY;
}
len = lsquic_tp_encode(&params, enc_sess->esi_flags & ESI_SERVER, buf, bufsz);
len = (enc_sess->esi_conn->cn_version == LSQVER_ID25 ? lsquic_tp_encode_id25 :
lsquic_tp_encode)(&params, enc_sess->esi_flags & ESI_SERVER, buf, bufsz);
if (len >= 0)
LSQ_DEBUG("generated transport parameters buffer of %d bytes", len);
else
@ -1460,7 +1455,8 @@ get_peer_transport_params (struct enc_sess_iquic *enc_sess)
}
LSQ_DEBUG("have peer transport parameters (%zu bytes)", bufsz);
if (0 > lsquic_tp_decode(params_buf, bufsz,
if (0 > (enc_sess->esi_conn->cn_version == LSQVER_ID25
? lsquic_tp_decode_id25 : lsquic_tp_decode)(params_buf, bufsz,
!(enc_sess->esi_flags & ESI_SERVER),
trans_params))
{
@ -2674,7 +2670,8 @@ static void
chsk_ietf_on_close (struct lsquic_stream *stream, lsquic_stream_ctx_t *ctx)
{
struct enc_sess_iquic *const enc_sess = (struct enc_sess_iquic *) ctx;
LSQ_DEBUG("crypto stream level %u is closed",
if (enc_sess && enc_sess->esi_cryst_if)
LSQ_DEBUG("crypto stream level %u is closed",
(unsigned) enc_sess->esi_cryst_if->csi_enc_level(stream));
}

View File

@ -900,12 +900,7 @@ 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)
{
if (mini_conn->cn_version == LSQVER_ID24)
ctor = lsquic_id24_full_conn_server_new;
else
ctor = lsquic_ietf_full_conn_server_new;
}
ctor = lsquic_ietf_full_conn_server_new;
else
ctor = lsquic_gquic_full_conn_server_new;
@ -1562,16 +1557,9 @@ lsquic_engine_connect (lsquic_engine_t *engine, enum lsquic_version version,
else
versions = 1u << version;
if (versions & LSQUIC_IETF_VERSIONS)
{
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);
}
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,

View File

@ -21,14 +21,6 @@ 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 */,
@ -44,11 +36,6 @@ 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

@ -1341,8 +1341,7 @@ lsquic_ietf_full_conn_server_new (struct lsquic_engine_public *enpub,
assert(mini_conn->cn_flags & LSCONN_HANDSHAKE_DONE);
conn->ifc_conn.cn_flags |= LSCONN_HANDSHAKE_DONE;
if (mini_conn->cn_version > LSQVER_ID24
&& !(imc->imc_flags & IMC_HSK_DONE_SENT))
if (!(imc->imc_flags & IMC_HSK_DONE_SENT))
{
LSQ_DEBUG("HANDSHAKE_DONE not yet sent, will process CRYPTO frames");
conn->ifc_flags |= IFC_PROC_CRYPTO;
@ -1559,8 +1558,6 @@ generate_ack_frame_for_pns (struct ietf_full_conn *conn,
conn->ifc_n_slack_all = 0;
lsquic_alarmset_unset(&conn->ifc_alset, AL_ACK_APP);
}
else
assert(!lsquic_alarmset_is_set(&conn->ifc_alset, AL_ACK_INIT + pns));
lsquic_send_ctl_sanity_check(&conn->ifc_send_ctl);
LSQ_DEBUG("%s ACK state reset", lsquic_pns2str[pns]);
@ -3010,8 +3007,7 @@ handshake_ok (struct lsquic_conn *lconn)
conn->ifc_ping_period = 0;
LSQ_DEBUG("PING period is set to %"PRIu64" usec", conn->ifc_ping_period);
if (conn->ifc_conn.cn_version > LSQVER_ID24
&& conn->ifc_settings->es_delayed_acks
if (conn->ifc_settings->es_delayed_acks
&& (params->tp_set & (1 << TPI_MIN_ACK_DELAY)))
{
LSQ_DEBUG("delayed ACKs enabled");
@ -3265,11 +3261,11 @@ ietf_full_conn_ci_push_stream (struct lsquic_conn *lconn, void *hset,
return -1;
}
/* Generate header block. Using it, we will search for a duplicate push
* promise. If not found, it will be copied to a new push_promise object.
/* Generate header block in cheap 4K memory. It it will be copied to
* a new push_promise object.
*/
p = header_block_buf;
end = header_block_buf + 0x1000 - 1; /* Save one byte for key type */
end = header_block_buf + 0x1000;
pseudo_headers[0].name. iov_base = ":method";
pseudo_headers[0].name. iov_len = 7;
pseudo_headers[0].value.iov_base = "GET";
@ -3326,18 +3322,6 @@ ietf_full_conn_ci_push_stream (struct lsquic_conn *lconn, void *hset,
}
LSQ_DEBUG("generated push promise header block of %ld bytes",
(long) (p - header_block_buf));
*p++ = PPKT_CONTENT;
el = lsquic_hash_find(conn->ifc_pub.u.ietf.promises,
header_block_buf, p - header_block_buf);
if (el)
{
lsquic_mm_put_4k(conn->ifc_pub.mm, header_block_buf);
promise = lsquic_hashelem_getdata(el);
LSQ_DEBUG("found push promise %"PRIu64", will issue a duplicate",
promise->pp_id);
return lsquic_stream_duplicate_push(dep_stream, promise->pp_id);
}
own_hset = !hset;
if (!hset)
@ -3358,6 +3342,7 @@ ietf_full_conn_ci_push_stream (struct lsquic_conn *lconn, void *hset,
if (!hset)
{
LSQ_INFO("header set ctor failure");
lsquic_mm_put_4k(conn->ifc_pub.mm, header_block_buf);
return -1;
}
for (i = 0; i < n_header_sets; ++i)
@ -3439,13 +3424,12 @@ ietf_full_conn_ci_push_stream (struct lsquic_conn *lconn, void *hset,
memset(promise, 0, sizeof(*promise));
promise->pp_refcnt = 1; /* This function itself keeps a reference */
memcpy(promise->pp_content_buf, header_block_buf, p - header_block_buf);
promise->pp_content_len = p - header_block_buf - 1;
promise->pp_content_len = p - header_block_buf;
promise->pp_id = conn->ifc_u.ser.ifser_next_push_id++;
lsquic_mm_put_4k(conn->ifc_pub.mm, header_block_buf);
promise->pp_u_id.buf[8] = PPKT_ID;
el = lsquic_hash_insert(conn->ifc_pub.u.ietf.promises,
promise->pp_u_id.buf, sizeof(promise->pp_u_id.buf), promise,
&promise->pp_id, sizeof(promise->pp_id), promise,
&promise->pp_hash_id);
if (!el)
{
@ -3457,19 +3441,6 @@ ietf_full_conn_ci_push_stream (struct lsquic_conn *lconn, void *hset,
free(uh);
return -1;
}
el = lsquic_hash_insert(conn->ifc_pub.u.ietf.promises,
promise->pp_content_buf, promise->pp_content_len + 1, promise,
&promise->pp_hash_content);
if (!el)
{
LSQ_WARN("cannot insert push promise (content)");
undo_stream_creation(conn, pushed_stream);
if (own_hset)
conn->ifc_enpub->enp_hsi_if->hsi_discard_header_set(hset);
lsquic_pp_put(promise, conn->ifc_pub.u.ietf.promises);
free(uh);
return -1;
}
if (0 != lsquic_stream_push_promise(dep_stream, promise))
{

View File

@ -1,12 +1,12 @@
/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc. See LICENSE. */
/*
* lsquic_hq.h -- HTTP over QUIC (HQ) types
* lsquic_hq.h -- HTTP/3 (originally "HTTP over QUIC" or HQ) types
*/
#ifndef LSQUIC_HQ_H
#define LSQUIC_HQ_H 1
/* [draft-ietf-quic-http-15] Section 4 */
/* [draft-ietf-quic-http-27] Section 11.2.1 */
enum hq_frame_type
{
HQFT_DATA = 0,
@ -16,7 +16,6 @@ enum hq_frame_type
HQFT_PUSH_PROMISE = 5,
HQFT_GOAWAY = 7,
HQFT_MAX_PUSH_ID = 0xD,
HQFT_DUPLICATE_PUSH = 0xE,
/* This frame is made up and its type is never written to stream.
* Nevertheless, just to be on the safe side, give it a value as
* described in [draft-ietf-quic-http-20] Section 4.2.10.

View File

@ -1689,13 +1689,10 @@ ietf_mini_conn_ci_tick (struct lsquic_conn *lconn, lsquic_time_t now)
}
else if (conn->imc_flags & IMC_HSK_OK)
{
if (conn->imc_conn.cn_version > LSQVER_ID24)
{
if (lconn->cn_esf.i->esfi_in_init(lconn->cn_enc_session))
LSQ_DEBUG("still in init, defer HANDSHAKE_DONE");
else if (0 != imico_generate_handshake_done(conn))
goto close_on_error;
}
if (lconn->cn_esf.i->esfi_in_init(lconn->cn_enc_session))
LSQ_DEBUG("still in init, defer HANDSHAKE_DONE");
else if (0 != imico_generate_handshake_done(conn))
goto close_on_error;
tick |= TICK_PROMOTE;
}

View File

@ -316,7 +316,6 @@ struct parse_funcs
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) ( \
@ -326,8 +325,6 @@ 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

@ -1117,85 +1117,6 @@ ietf_v1_parse_frame_type (const unsigned char *buf, size_t len)
}
static enum quic_frame_type
ietf_id24_parse_frame_type (const unsigned char *buf, size_t len)
{
/* This one does not have QUIC_FRAME_HANDSHAKE_DONE */
static const enum quic_frame_type byte2type[0x40] =
{
[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,
};
if (len > 1 && buf[0] < 0x40)
return byte2type[buf[0]];
else
return QUIC_FRAME_INVALID;
}
static unsigned
ietf_v1_path_chal_frame_size (void)
{
@ -1770,7 +1691,7 @@ lsquic_ietf_v1_parse_packet_in_long_begin (struct lsquic_packet_in *packet_in,
const unsigned char *const end = p + length;
lsquic_ver_tag_t tag;
enum header_type header_type;
unsigned dcil, scil, odcil;
unsigned dcil, scil;
int verneg, r;
unsigned char first_byte;
uint64_t payload_len, token_len;
@ -1865,32 +1786,18 @@ lsquic_ietf_v1_parse_packet_in_long_begin (struct lsquic_packet_in *packet_in,
case HETY_RETRY:
if (p >= end)
return -1;
if (LSQVER_ID24 == lsquic_tag2ver(tag))
{
odcil = *p++;
if (p + odcil > end || odcil > MAX_CID_LEN)
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_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 */
}
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;
@ -2165,22 +2072,6 @@ ietf_v1_parse_ack_frequency_frame (const unsigned char *buf, size_t buf_len,
}
static int
ietf_id24_gen_ack_frequency_frame (unsigned char *buf, size_t buf_len,
uint64_t seqno, uint64_t pack_tol, uint64_t upd_mad)
{
return -1;
}
static int
ietf_id24_parse_ack_frequency_frame (const unsigned char *buf, size_t buf_len,
uint64_t *seqno, uint64_t *pack_tol, uint64_t *upd_mad)
{
return -1;
}
static unsigned
ietf_v1_ack_frequency_frame_size (uint64_t seqno, uint64_t pack_tol,
uint64_t upd_mad)
@ -2197,93 +2088,6 @@ ietf_v1_handshake_done_frame_size (void)
}
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,
.pf_gen_ack_frequency_frame = ietf_id24_gen_ack_frequency_frame,
.pf_parse_ack_frequency_frame = ietf_id24_parse_ack_frequency_frame,
.pf_ack_frequency_frame_size = ietf_v1_ack_frequency_frame_size,
};
const struct parse_funcs lsquic_parse_funcs_ietf_v1 =
{
.pf_gen_reg_pkt_header = ietf_v1_gen_reg_pkt_header,

View File

@ -355,7 +355,7 @@ prq_new_req (struct pr_queue *prq, enum packet_req_type type,
version = lsquic_tag2ver(ver_tag);
}
else /* Got to set it to something sensible... */
version = LSQVER_ID24;
version = LSQVER_ID25;
lsquic_scid_from_packet_in(packet_in, &scid);
return lsquic_prq_new_req(prq, type, flags, version, packet_in->pi_data_sz,

View File

@ -6,12 +6,6 @@ struct lsquic_hash_elem;
struct lsquic_stream;
enum push_promise_key_type {
PPKT_ID,
PPKT_CONTENT,
};
struct push_promise
{
/* A push promise is associated with a single stream, while a stream can
@ -21,19 +15,10 @@ struct push_promise
* frames can be sent out.
*/
SLIST_ENTRY(push_promise) pp_next;
/* Push promises are stored in the same hash and can be searched either
* by ID or by content. To differentiate the two keys, the key type is
* appended at the end PPKT_ID or PPKT_CONTENT.
*/
struct lsquic_hash_elem pp_hash_id,
pp_hash_content;
union {
uint64_t id;
unsigned char buf[9];
} pp_u_id;
#define pp_id pp_u_id.id
/* Push promises are stored a hash and can be searched by ID */
struct lsquic_hash_elem pp_hash_id;
uint64_t pp_id;
struct lsquic_stream *pp_pushed_stream;
/* This does not include the last key-type byte: */
size_t pp_content_len;
/* Number of streams holding a reference to this push promise. When this
* value becomes zero, the push promise is destroyed. See lsquic_pp_put().
@ -64,7 +49,7 @@ struct push_promise
unsigned pp_write_off;
unsigned char pp_encoded_push_id[8];
/* The content buffer is the header block: it does not include Header
* Block Prefix. It is followed by one-byte key type PPKT_CONTENT.
* Block Prefix.
*/
unsigned char pp_content_buf[0];
};
@ -77,9 +62,6 @@ struct push_promise
LSQ_DEBUG("destroy push promise %"PRIu64, (promise_)->pp_id); \
if ((promise_)->pp_hash_id.qhe_flags & QHE_HASHED) \
lsquic_hash_erase(all_promises_, &(promise_)->pp_hash_id); \
if ((promise_)->pp_hash_content.qhe_flags & QHE_HASHED) \
lsquic_hash_erase(all_promises_, \
&(promise_)->pp_hash_content); \
free(promise); \
} \
} \

View File

@ -147,9 +147,6 @@ stream_write_buf (struct lsquic_stream *stream, const void *buf, size_t sz);
static size_t
active_hq_frame_sizes (const struct lsquic_stream *);
static void
on_write_dp_wrapper (struct lsquic_stream *, lsquic_stream_ctx_t *);
static void
on_write_pp_wrapper (struct lsquic_stream *, lsquic_stream_ctx_t *);
@ -1986,8 +1983,6 @@ static void
assert(stream->stream_flags & STREAM_PUSHING);
if (stream_is_pushing_promise(stream))
return on_write_pp_wrapper;
else if (stream->sm_dup_push_off < stream->sm_dup_push_len)
return on_write_dp_wrapper;
else
return stream->stream_if->on_write;
}
@ -4081,7 +4076,6 @@ update_type_hist_and_check (const struct lsquic_stream *stream,
code = CODE_DATA;
break;
case HQFT_PUSH_PROMISE:
case HQFT_DUPLICATE_PUSH:
/* [draft-ietf-quic-http-24], Section 7 */
if ((stream->id & SIT_MASK) == SIT_BIDI_CLIENT
&& !(stream->sm_bflags & SMBF_SERVER))
@ -4566,128 +4560,6 @@ lsquic_stream_can_push (const struct lsquic_stream *stream)
}
static size_t
dp_reader_read (void *lsqr_ctx, void *buf, size_t count)
{
struct lsquic_stream *const stream = lsqr_ctx;
unsigned char *dst = buf;
unsigned char *const end = buf + count;
size_t len;
len = MIN((size_t) (stream->sm_dup_push_len - stream->sm_dup_push_off),
(size_t) (end - dst));
memcpy(dst, stream->sm_dup_push_buf + stream->sm_dup_push_off, len);
stream->sm_dup_push_off += len;
if (stream->sm_dup_push_len == stream->sm_dup_push_off)
LSQ_DEBUG("finish writing duplicate push");
return len;
}
static size_t
dp_reader_size (void *lsqr_ctx)
{
struct lsquic_stream *const stream = lsqr_ctx;
return stream->sm_dup_push_len - stream->sm_dup_push_off;
}
static void
init_dp_reader (struct lsquic_stream *stream, struct lsquic_reader *reader)
{
reader->lsqr_read = dp_reader_read;
reader->lsqr_size = dp_reader_size;
reader->lsqr_ctx = stream;
}
static void
on_write_dp_wrapper (struct lsquic_stream *stream, lsquic_stream_ctx_t *h)
{
struct lsquic_reader dp_reader;
ssize_t nw;
int want_write;
assert(stream->sm_dup_push_off < stream->sm_dup_push_len);
init_dp_reader(stream, &dp_reader);
nw = stream_write(stream, &dp_reader);
if (nw > 0)
{
LSQ_DEBUG("wrote %zd bytes more of duplicate push (%s)",
nw, stream->sm_dup_push_off == stream->sm_dup_push_len ?
"done" : "not done");
if (stream->sm_dup_push_off == stream->sm_dup_push_len)
{
/* Restore want_write flag */
want_write = !!(stream->sm_qflags & SMQF_WANT_WRITE);
if (want_write != stream->sm_saved_want_write)
(void) lsquic_stream_wantwrite(stream,
stream->sm_saved_want_write);
}
}
else if (nw < 0)
{
LSQ_WARN("could not write duplicate push (wrapper)");
/* XXX What should happen if we hit an error? TODO */
}
}
int
lsquic_stream_duplicate_push (struct lsquic_stream *stream, uint64_t push_id)
{
struct lsquic_reader dp_reader;
unsigned bits, len;
ssize_t nw;
assert(stream->sm_bflags & SMBF_IETF);
assert(lsquic_stream_can_push(stream));
bits = vint_val2bits(push_id);
len = 1 << bits;
if (!stream_activate_hq_frame(stream,
stream->sm_payload + stream->sm_n_buffered, HQFT_DUPLICATE_PUSH,
SHF_FIXED_SIZE, len))
return -1;
stream->stream_flags |= STREAM_PUSHING;
stream->sm_dup_push_len = len;
stream->sm_dup_push_off = 0;
vint_write(stream->sm_dup_push_buf, push_id, bits, 1 << bits);
init_dp_reader(stream, &dp_reader);
nw = stream_write(stream, &dp_reader);
if (nw > 0)
{
if (stream->sm_dup_push_off == stream->sm_dup_push_len)
LSQ_DEBUG("fully wrote DUPLICATE_PUSH %"PRIu64, push_id);
else
{
LSQ_DEBUG("partially wrote DUPLICATE_PUSH %"PRIu64, push_id);
stream->stream_flags |= STREAM_NOPUSH;
stream->sm_saved_want_write =
!!(stream->sm_qflags & SMQF_WANT_WRITE);
stream_wantwrite(stream, 1);
}
return 0;
}
else
{
if (nw < 0)
LSQ_WARN("failure writing DUPLICATE_PUSH");
stream->stream_flags |= STREAM_NOPUSH;
stream->stream_flags &= ~STREAM_PUSHING;
return -1;
}
}
static size_t
pp_reader_read (void *lsqr_ctx, void *buf, size_t count)
{

View File

@ -341,10 +341,6 @@ struct lsquic_stream
signed char sm_saved_want_write;
signed char sm_has_frame;
unsigned char sm_dup_push_off;
unsigned char sm_dup_push_len;
unsigned char sm_dup_push_buf[8];
#if LSQUIC_KEEP_STREAM_HISTORY
sm_hist_idx_t sm_hist_idx;
#endif
@ -592,9 +588,6 @@ lsquic_stream_qdec_unblocked (struct lsquic_stream *);
int
lsquic_stream_can_push (const struct lsquic_stream *);
int
lsquic_stream_duplicate_push (struct lsquic_stream *, uint64_t push_id);
int
lsquic_stream_push_promise (struct lsquic_stream *, struct push_promise *);

View File

@ -57,7 +57,7 @@ tpi_val_2_enum (uint64_t tpi_val)
}
static const unsigned short enum_2_tpi_val[LAST_TPI + 1] =
static const unsigned enum_2_tpi_val[LAST_TPI + 1] =
{
[TPI_ORIGINAL_CONNECTION_ID] = 0x0,
[TPI_MAX_IDLE_TIMEOUT] = 0x1,
@ -183,6 +183,500 @@ lsquic_tp_has_pref_ipv6 (const struct transport_params *params)
int
lsquic_tp_encode (const struct transport_params *params, int is_server,
unsigned char *const buf, size_t bufsz)
{
unsigned char *p;
size_t need;
uint16_t u16;
enum transport_param_id tpi;
unsigned set;
unsigned bits[LAST_TPI + 1][3 /* ID, length, value */];
need = 0;
set = params->tp_set; /* Will turn bits off for default values */
if (is_server)
{
if (set & (1 << TPI_ORIGINAL_CONNECTION_ID))
{
bits[TPI_ORIGINAL_CONNECTION_ID][0]
= vint_val2bits(enum_2_tpi_val[TPI_ORIGINAL_CONNECTION_ID]);
#if __GNUC__
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
#pragma GCC diagnostic ignored "-Wtype-limits"
#endif
bits[TPI_ORIGINAL_CONNECTION_ID][1]
= vint_val2bits(params->tp_original_cid.len);
#if __GNUC__
#pragma GCC diagnostic pop
#pragma GCC diagnostic pop
#endif
need += (1 << bits[TPI_ORIGINAL_CONNECTION_ID][0])
+ (1 << bits[TPI_ORIGINAL_CONNECTION_ID][1])
+ params->tp_original_cid.len;
}
if (set & (1 << TPI_STATELESS_RESET_TOKEN))
{
bits[TPI_STATELESS_RESET_TOKEN][0]
= vint_val2bits(enum_2_tpi_val[TPI_STATELESS_RESET_TOKEN]);
bits[TPI_STATELESS_RESET_TOKEN][1]
= vint_val2bits(sizeof(params->tp_stateless_reset_token));
need += (1 << bits[TPI_STATELESS_RESET_TOKEN][0])
+ (1 << bits[TPI_STATELESS_RESET_TOKEN][1])
+ sizeof(params->tp_stateless_reset_token);
}
if (set & (1 << TPI_PREFERRED_ADDRESS))
{
bits[TPI_PREFERRED_ADDRESS][0]
= vint_val2bits(enum_2_tpi_val[TPI_PREFERRED_ADDRESS]);
bits[TPI_PREFERRED_ADDRESS][1] = vint_val2bits(
preferred_address_size(params));
need += (1 << bits[TPI_PREFERRED_ADDRESS][0])
+ (1 << bits[TPI_PREFERRED_ADDRESS][1])
+ preferred_address_size(params);
}
}
#if LSQUIC_TEST_QUANTUM_READINESS
else if (set & (1 << TPI_QUANTUM_READINESS))
{
bits[TPI_QUANTUM_READINESS][0]
= vint_val2bits(enum_2_tpi_val[TPI_QUANTUM_READINESS]);
bits[TPI_QUANTUM_READINESS][1] = vint_val2bits(QUANTUM_READY_SZ);
need += (1 << bits[TPI_QUANTUM_READINESS][0])
+ (1 << bits[TPI_QUANTUM_READINESS][1])
+ QUANTUM_READY_SZ;
}
#endif
for (tpi = 0; tpi <= MAX_NUMERIC_TPI; ++tpi)
if (set & (1 << tpi))
{
if (tpi > MAX_NUM_WITH_DEF_TPI
|| params->tp_numerics[tpi] != def_vals[tpi])
{
if (params->tp_numerics[tpi] >= min_vals[tpi]
&& params->tp_numerics[tpi] <= max_vals[tpi])
{
bits[tpi][0] = vint_val2bits(enum_2_tpi_val[tpi]);
bits[tpi][2] = vint_val2bits(params->tp_numerics[tpi]);
bits[tpi][1] = vint_val2bits(bits[tpi][2]);
need += (1 << bits[tpi][0])
+ (1 << bits[tpi][1])
+ (1 << bits[tpi][2]);
}
else if (params->tp_numerics[tpi] > max_vals[tpi])
{
LSQ_DEBUG("numeric value of %s is too large (%"PRIu64" vs "
"maximum of %"PRIu64")", tpi2str[tpi],
params->tp_numerics[tpi], max_vals[tpi]);
return -1;
}
else
{
LSQ_DEBUG("numeric value of %s is too small (%"PRIu64" vs "
"minimum " "of %"PRIu64")",
tpi2str[tpi], params->tp_numerics[tpi], min_vals[tpi]);
return -1;
}
}
else
set &= ~(1 << tpi); /* Don't write default value */
}
for (; tpi <= MAX_EMPTY_TPI; ++tpi)
if (set & (1 << tpi))
{
bits[tpi][0] = vint_val2bits(enum_2_tpi_val[tpi]);
need += (1 << bits[tpi][0]) + 1 /* Zero length byte */;
}
if (need > bufsz || need > UINT16_MAX)
{
errno = ENOBUFS;
return -1;
}
p = buf;
#define WRITE_TO_P(src, len) do { \
memcpy(p, src, len); \
p += len; \
} while (0)
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define WRITE_UINT_TO_P(val, width) do { \
u##width = bswap_##width(val); \
WRITE_TO_P(&u##width, sizeof(u##width)); \
} while (0)
#else
#define WRITE_UINT_TO_P(val, width) do { \
u##width = val; \
WRITE_TO_P(&u##width, sizeof(u##width)); \
} while (0)
#endif
for (tpi = 0; tpi <= LAST_TPI; ++tpi)
if (set & (1 << tpi))
{
vint_write(p, enum_2_tpi_val[tpi], bits[tpi][0],
1 << bits[tpi][0]);
p += 1 << bits[tpi][0];
switch (tpi)
{
case TPI_MAX_IDLE_TIMEOUT:
case TPI_MAX_PACKET_SIZE:
case TPI_INIT_MAX_DATA:
case TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL:
case TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE:
case TPI_INIT_MAX_STREAM_DATA_UNI:
case TPI_INIT_MAX_STREAMS_BIDI:
case TPI_INIT_MAX_STREAMS_UNI:
case TPI_ACK_DELAY_EXPONENT:
case TPI_MAX_ACK_DELAY:
case TPI_ACTIVE_CONNECTION_ID_LIMIT:
case TPI_LOSS_BITS:
case TPI_MIN_ACK_DELAY:
vint_write(p, 1 << bits[tpi][2], bits[tpi][1],
1 << bits[tpi][1]);
p += 1 << bits[tpi][1];
vint_write(p, params->tp_numerics[tpi], bits[tpi][2],
1 << bits[tpi][2]);
p += 1 << bits[tpi][2];
break;
case TPI_ORIGINAL_CONNECTION_ID:
vint_write(p, params->tp_original_cid.len, bits[tpi][1],
1 << bits[tpi][1]);
p += 1 << bits[tpi][1];
WRITE_TO_P(params->tp_original_cid.idbuf,
params->tp_original_cid.len);
break;
case TPI_STATELESS_RESET_TOKEN:
vint_write(p, sizeof(params->tp_stateless_reset_token),
bits[tpi][1], 1 << bits[tpi][1]);
p += 1 << bits[tpi][1];
WRITE_TO_P(params->tp_stateless_reset_token,
sizeof(params->tp_stateless_reset_token));
break;
case TPI_PREFERRED_ADDRESS:
vint_write(p, preferred_address_size(params),
bits[tpi][1], 1 << bits[tpi][1]);
p += 1 << bits[tpi][1];
WRITE_UINT_TO_P(preferred_address_size(params), 16);
WRITE_TO_P(&params->tp_preferred_address.ipv4_addr,
sizeof(params->tp_preferred_address.ipv4_addr));
WRITE_UINT_TO_P(params->tp_preferred_address.ipv4_port, 16);
WRITE_TO_P(&params->tp_preferred_address.ipv6_addr,
sizeof(params->tp_preferred_address.ipv6_addr));
WRITE_UINT_TO_P(params->tp_preferred_address.ipv6_port, 16);
*p++ = params->tp_preferred_address.cid.len;
WRITE_TO_P(params->tp_preferred_address.cid.idbuf,
params->tp_preferred_address.cid.len);
WRITE_TO_P(params->tp_preferred_address.srst,
sizeof(params->tp_preferred_address.srst));
break;
case TPI_DISABLE_ACTIVE_MIGRATION:
*p++ = 0;
break;
#if LSQUIC_TEST_QUANTUM_READINESS
case TPI_QUANTUM_READINESS:
vint_write(p, QUANTUM_READY_SZ,
bits[tpi][1], 1 << bits[tpi][1]);
p += 1 << bits[tpi][1];
memset(p, 'Q', QUANTUM_READY_SZ);
p += QUANTUM_READY_SZ;
break;
#endif
}
}
assert(buf + need == p);
return (int) (p - buf);
#undef WRITE_TO_P
#undef WRITE_UINT_TO_P
}
int
lsquic_tp_decode (const unsigned char *const buf, size_t bufsz,
int is_server,
struct transport_params *params)
{
const unsigned char *p, *end, *q;
uint64_t len, param_id;
uint16_t tlen;
enum transport_param_id tpi;
unsigned set_of_ids;
int s;
p = buf;
end = buf + bufsz;
*params = TP_INITIALIZER();
#define EXPECT_LEN(expected_len) do { \
if (expected_len != len) \
return -1; \
} while (0)
#define EXPECT_AT_LEAST(expected_len) do { \
if ((expected_len) > (uintptr_t) (p + len - q)) \
return -1; \
} while (0)
set_of_ids = 0;
while (p < end)
{
s = vint_read(p, end, &param_id);
if (s < 0)
return -1;
p += s;
s = vint_read(p, end, &len);
if (s < 0)
return -1;
p += s;
if ((ptrdiff_t) len > end - p)
return -1;
tpi = tpi_val_2_enum(param_id);
if (tpi <= LAST_TPI)
{
if (set_of_ids & (1 << tpi))
return -1;
set_of_ids |= 1 << tpi;
}
switch (tpi)
{
case TPI_MAX_IDLE_TIMEOUT:
case TPI_MAX_PACKET_SIZE:
case TPI_INIT_MAX_DATA:
case TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL:
case TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE:
case TPI_INIT_MAX_STREAM_DATA_UNI:
case TPI_INIT_MAX_STREAMS_BIDI:
case TPI_INIT_MAX_STREAMS_UNI:
case TPI_ACK_DELAY_EXPONENT:
case TPI_MAX_ACK_DELAY:
case TPI_ACTIVE_CONNECTION_ID_LIMIT:
case TPI_LOSS_BITS:
case TPI_MIN_ACK_DELAY:
switch (len)
{
case 1:
case 2:
case 4:
case 8:
s = vint_read(p, p + len, &params->tp_numerics[tpi]);
if (s == (int) len)
{
if (params->tp_numerics[tpi] > max_vals[tpi])
{
LSQ_DEBUG("numeric value of %s is too large "
"(%"PRIu64" vs maximum of %"PRIu64, tpi2str[tpi],
params->tp_numerics[tpi], max_vals[tpi]);
return -1;
}
else if (params->tp_numerics[tpi] < min_vals[tpi])
{
LSQ_DEBUG("numeric value of %s is too small "
"(%"PRIu64" vs minimum of %"PRIu64, tpi2str[tpi],
params->tp_numerics[tpi], min_vals[tpi]);
return -1;
}
break;
}
else
{
LSQ_DEBUG("cannot read the value of numeric transport "
"param %s of length %"PRIu64, tpi2str[tpi], len);
return -1;
}
default:
LSQ_DEBUG("invalid length=%"PRIu64" for numeric transport "
"parameter %s", len, tpi2str[tpi]);
return -1;
}
break;
case TPI_DISABLE_ACTIVE_MIGRATION:
EXPECT_LEN(0);
break;
case TPI_STATELESS_RESET_TOKEN:
/* Client MUST not include reset token,
* see [draft-ietf-quic-transport-11], Section 6.4.1
*/
if (!is_server)
return -1;
EXPECT_LEN(sizeof(params->tp_stateless_reset_token));
memcpy(params->tp_stateless_reset_token, p,
sizeof(params->tp_stateless_reset_token));
break;
case TPI_ORIGINAL_CONNECTION_ID:
/* Client MUST not original connecti ID,
* see [draft-ietf-quic-transport-15], Section 6.6.1
*/
if (!is_server)
return -1;
if (len > MAX_CID_LEN)
return -1;
memcpy(params->tp_original_cid.idbuf, p, len);
params->tp_original_cid.len = len;
break;
case TPI_PREFERRED_ADDRESS:
/* Client MUST not include preferred address,
* see [draft-ietf-quic-transport-12], Section 6.4.1
*/
if (!is_server)
return -1;
q = p;
EXPECT_AT_LEAST(sizeof(params->tp_preferred_address.ipv4_addr));
memcpy(params->tp_preferred_address.ipv4_addr, q,
sizeof(params->tp_preferred_address.ipv4_addr));
q += sizeof(params->tp_preferred_address.ipv4_addr);
EXPECT_AT_LEAST(sizeof(params->tp_preferred_address.ipv4_port));
READ_UINT(params->tp_preferred_address.ipv4_port, 16, q, 2);
q += 2;
EXPECT_AT_LEAST(sizeof(params->tp_preferred_address.ipv6_addr));
memcpy(params->tp_preferred_address.ipv6_addr, q,
sizeof(params->tp_preferred_address.ipv6_addr));
q += sizeof(params->tp_preferred_address.ipv6_addr);
EXPECT_AT_LEAST(sizeof(params->tp_preferred_address.ipv6_port));
READ_UINT(params->tp_preferred_address.ipv6_port, 16, q, 2);
q += 2;
EXPECT_AT_LEAST(1);
tlen = *q;
q += 1;
if (tlen < 4 || tlen > MAX_CID_LEN)
{
LSQ_DEBUG("preferred server address contains invalid "
"CID length of %"PRIu16" bytes", tlen);
return -1;
}
EXPECT_AT_LEAST(tlen);
memcpy(params->tp_preferred_address.cid.idbuf, q, tlen);
params->tp_preferred_address.cid.len = tlen;
q += tlen;
EXPECT_AT_LEAST(sizeof(params->tp_preferred_address.srst));
memcpy(params->tp_preferred_address.srst, q,
sizeof(params->tp_preferred_address.srst));
q += sizeof(params->tp_preferred_address.srst);
if (q != p + len)
return -1;
break;
default:
/* Do nothing: skip this transport parameter */
break;
}
p += len;
if (tpi <= LAST_TPI)
{
params->tp_set |= 1 << tpi;
params->tp_decoded |= 1 << tpi;
}
}
if (p != end)
return -1;
if ((params->tp_set & (1 << TPI_MIN_ACK_DELAY))
&& params->tp_numerics[TPI_MIN_ACK_DELAY]
> params->tp_numerics[TPI_MAX_ACK_DELAY] * 1000)
{
LSQ_DEBUG("min_ack_delay (%"PRIu64" usec) is larger than "
"max_ack_delay (%"PRIu64" ms)",
params->tp_numerics[TPI_MIN_ACK_DELAY],
params->tp_numerics[TPI_MAX_ACK_DELAY]);
return -1;
}
return (int) (end - buf);
#undef EXPECT_LEN
}
void
lsquic_tp_to_str (const struct transport_params *params, char *buf, size_t sz)
{
char *const end = buf + sz;
int nw;
enum transport_param_id tpi;
char tok_str[sizeof(params->tp_stateless_reset_token) * 2 + 1];
char addr_str[INET6_ADDRSTRLEN];
for (tpi = 0; tpi <= MAX_NUMERIC_TPI; ++tpi)
if (params->tp_set & (1 << tpi))
{
nw = snprintf(buf, end - buf, "%.*s%s: %"PRIu64,
(buf + sz > end) << 1, "; ", tpi2str[tpi],
params->tp_numerics[tpi]);
buf += nw;
if (buf >= end)
return;
}
for (; tpi <= MAX_EMPTY_TPI; ++tpi)
if (params->tp_set & (1 << TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL))
{
nw = snprintf(buf, end - buf, "%.*s%s",
(buf + sz > end) << 1, "; ", tpi2str[tpi]);
buf += nw;
if (buf >= end)
return;
}
#if LSQUIC_TEST_QUANTUM_READINESS
if (params->tp_set & (1 << TPI_QUANTUM_READINESS))
{
nw = snprintf(buf, end - buf, "%.*s%s",
(buf + sz > end) << 1, "; ", tpi2str[TPI_QUANTUM_READINESS]);
buf += nw;
if (buf >= end)
return;
}
#endif
if (params->tp_set & (1 << TPI_STATELESS_RESET_TOKEN))
{
lsquic_hexstr(params->tp_stateless_reset_token,
sizeof(params->tp_stateless_reset_token), tok_str, sizeof(tok_str));
nw = snprintf(buf, end - buf, "; stateless_reset_token: %s", tok_str);
buf += nw;
if (buf >= end)
return;
}
if (params->tp_set & (1 << TPI_ORIGINAL_CONNECTION_ID))
{
char cidbuf_[MAX_CID_LEN * 2 + 1];
nw = snprintf(buf, end - buf, "; original DCID (ODCID): %"CID_FMT,
CID_BITS(&params->tp_original_cid));
buf += nw;
if (buf >= end)
return;
}
if (lsquic_tp_has_pref_ipv4(params))
{
if (inet_ntop(AF_INET, params->tp_preferred_address.ipv4_addr,
addr_str, sizeof(addr_str)))
{
nw = snprintf(buf, end - buf, "; IPv4 preferred address: %s:%u",
addr_str, params->tp_preferred_address.ipv4_port);
buf += nw;
if (buf >= end)
return;
}
}
if (lsquic_tp_has_pref_ipv6(params))
{
if (inet_ntop(AF_INET6, params->tp_preferred_address.ipv6_addr,
addr_str, sizeof(addr_str)))
{
nw = snprintf(buf, end - buf, "; IPv6 preferred address: %s:%u",
addr_str, params->tp_preferred_address.ipv6_port);
buf += nw;
if (buf >= end)
return;
}
}
}
int
lsquic_tp_encode_id25 (const struct transport_params *params, int is_server,
unsigned char *const buf, size_t bufsz)
{
unsigned char *p;
size_t need = 2;
@ -348,7 +842,7 @@ lsquic_tp_encode (const struct transport_params *params, int is_server,
int
lsquic_tp_decode (const unsigned char *const buf, size_t bufsz,
lsquic_tp_decode_id25 (const unsigned char *const buf, size_t bufsz,
int is_server,
struct transport_params *params)
{
@ -543,86 +1037,3 @@ lsquic_tp_decode (const unsigned char *const buf, size_t bufsz,
return (int) (end - buf);
#undef EXPECT_LEN
}
void
lsquic_tp_to_str (const struct transport_params *params, char *buf, size_t sz)
{
char *const end = buf + sz;
int nw;
enum transport_param_id tpi;
char tok_str[sizeof(params->tp_stateless_reset_token) * 2 + 1];
char addr_str[INET6_ADDRSTRLEN];
for (tpi = 0; tpi <= MAX_NUMERIC_TPI; ++tpi)
if (params->tp_set & (1 << tpi))
{
nw = snprintf(buf, end - buf, "%.*s%s: %"PRIu64,
(buf + sz > end) << 1, "; ", tpi2str[tpi],
params->tp_numerics[tpi]);
buf += nw;
if (buf >= end)
return;
}
for (; tpi <= MAX_EMPTY_TPI; ++tpi)
if (params->tp_set & (1 << TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL))
{
nw = snprintf(buf, end - buf, "%.*s%s",
(buf + sz > end) << 1, "; ", tpi2str[tpi]);
buf += nw;
if (buf >= end)
return;
}
#if LSQUIC_TEST_QUANTUM_READINESS
if (params->tp_set & (1 << TPI_QUANTUM_READINESS))
{
nw = snprintf(buf, end - buf, "%.*s%s",
(buf + sz > end) << 1, "; ", tpi2str[TPI_QUANTUM_READINESS]);
buf += nw;
if (buf >= end)
return;
}
#endif
if (params->tp_set & (1 << TPI_STATELESS_RESET_TOKEN))
{
lsquic_hexstr(params->tp_stateless_reset_token,
sizeof(params->tp_stateless_reset_token), tok_str, sizeof(tok_str));
nw = snprintf(buf, end - buf, "; stateless_reset_token: %s", tok_str);
buf += nw;
if (buf >= end)
return;
}
if (params->tp_set & (1 << TPI_ORIGINAL_CONNECTION_ID))
{
char cidbuf_[MAX_CID_LEN * 2 + 1];
nw = snprintf(buf, end - buf, "; original DCID (ODCID): %"CID_FMT,
CID_BITS(&params->tp_original_cid));
buf += nw;
if (buf >= end)
return;
}
if (lsquic_tp_has_pref_ipv4(params))
{
if (inet_ntop(AF_INET, params->tp_preferred_address.ipv4_addr,
addr_str, sizeof(addr_str)))
{
nw = snprintf(buf, end - buf, "; IPv4 preferred address: %s:%u",
addr_str, params->tp_preferred_address.ipv4_port);
buf += nw;
if (buf >= end)
return;
}
}
if (lsquic_tp_has_pref_ipv6(params))
{
if (inet_ntop(AF_INET6, params->tp_preferred_address.ipv6_addr,
addr_str, sizeof(addr_str)))
{
nw = snprintf(buf, end - buf, "; IPv6 preferred address: %s:%u",
addr_str, params->tp_preferred_address.ipv6_port);
buf += nw;
if (buf >= end)
return;
}
}
}

View File

@ -134,6 +134,14 @@ lsquic_tp_decode (const unsigned char *buf, size_t bufsz,
int is_server,
struct transport_params *);
int
lsquic_tp_encode_id25 (const struct transport_params *, int is_server,
unsigned char *buf, size_t bufsz);
int
lsquic_tp_decode_id25 (const unsigned char *buf, size_t bufsz,
int is_server, struct transport_params *);
void
lsquic_tp_to_str (const struct transport_params *params, char *buf, size_t sz);

View File

@ -6,7 +6,7 @@
/* See [draft-ietf-quic-transport-11], section-7.1 */
#define vint_val2bits(val) ( \
(val >= (1 << 6)) + (val >= (1 << 14)) + (val >= (1 << 30)))
((val) >= (1 << 6)) + ((val) >= (1 << 14)) + ((val) >= (1 << 30)))
#define vint_size(val) (1u << vint_val2bits(val))

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_ID24] = { 0xFF, 0, 0, 24, },
[LSQVER_ID25] = { 0xFF, 0, 0, 25, },
[LSQVER_ID27] = { 0xFF, 0, 0, 27, },
[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_ID24] = "FF000018",
[LSQVER_ID25] = "FF000019",
[LSQVER_ID27] = "FF00001B",
[LSQVER_VERNEG] = "FAFAFAFA",
};

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-24\x5h3-25";
const unsigned char alpn[] = "\x5h3-25\x5h3-27";
int r;
r = SSL_select_next_proto((unsigned char **) out, outlen, in, inlen,

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_ID24);
pf = select_pf_by_ver(LSQVER_ID25);
if (!test->skip_gen)
{
rechist.acki = &test->acki;

View File

@ -17,7 +17,7 @@
static struct lsquic_conn lconn = LSCONN_INITIALIZER_CIDLEN(lconn, 0);
static const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_ID24);
static const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_ID25);
static void

View File

@ -33,7 +33,7 @@ struct test {
static const struct test tests[] = {
{ .lineno = __LINE__,
.pf = select_pf_by_ver(LSQVER_ID24),
.pf = select_pf_by_ver(LSQVER_ID25),
.offset = 0,
.data_sz = 10,
.data = "0123456789",
@ -49,7 +49,7 @@ static const struct test tests[] = {
},
{ .lineno = __LINE__,
.pf = select_pf_by_ver(LSQVER_ID24),
.pf = select_pf_by_ver(LSQVER_ID25),
.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_ID24);
static const struct parse_funcs *g_pf = select_pf_by_ver(LSQVER_ID25);
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_ID24;
tobjs->lconn.cn_version = LSQVER_ID25;
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_ID24);
tobjs->lconn.cn_version = LSQVER_ID24;
tobjs->lconn.cn_pf = select_pf_by_ver(LSQVER_ID25);
tobjs->lconn.cn_version = LSQVER_ID25;
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_ID24 : LSQVER_043;
LSQVER_ID25 : 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;
@ -2243,7 +2243,7 @@ test_changing_pack_size (void)
enum lsquic_version versions_to_test[3] =
{
LSQVER_046,
LSQVER_ID24,
LSQVER_ID25,
};
for (i = 0; i < 3; i++)
@ -3173,7 +3173,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_ID24);
g_pf = select_pf_by_ver(LSQVER_ID25);
main_test_packetization();
return 0;

View File

@ -279,7 +279,7 @@ static const struct test tests[] = {
*/
{ .lineno = __LINE__,
.pf = select_pf_by_ver(LSQVER_ID24),
.pf = select_pf_by_ver(LSQVER_ID25),
.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_ID24),
.pf = select_pf_by_ver(LSQVER_ID25),
.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_ID24),
.pf = select_pf_by_ver(LSQVER_ID25),
.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_ID24),
.pf = select_pf_by_ver(LSQVER_ID25),
.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_ID24),
.pf = select_pf_by_ver(LSQVER_ID25),
.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_ID24),
.pf = select_pf_by_ver(LSQVER_ID25),
.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_ID24),
select_pf_by_ver(LSQVER_ID25),
/* 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_ID24),
select_pf_by_ver(LSQVER_ID25),
/* 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_ID24),
select_pf_by_ver(LSQVER_ID25),
/* 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_ID24),
select_pf_by_ver(LSQVER_ID25),
/* 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_ID24),
select_pf_by_ver(LSQVER_ID25),
/* 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_ID24),
select_pf_by_ver(LSQVER_ID25),
/* 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_ID24),
select_pf_by_ver(LSQVER_ID25),
/* 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_ID24),
select_pf_by_ver(LSQVER_ID25),
/* 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_ID24),
select_pf_by_ver(LSQVER_ID25),
/* TYPE OFF DLEN FIN */
{ 0x10 | 1<<2 | 1<<1 | 1<<0,
0x81, 0x23, 0x00, 0xE4, /* Stream ID */

View File

@ -44,9 +44,8 @@ static const struct trapa_test tests[] =
.params = {
TP_DEFAULT_VALUES,
},
.enc_len = 2,
.enc_len = 0,
.encoded =
/* Overall length */ "\x00\x00"
/* Trailer to make the end easily visible in gdb: */
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
},
@ -69,15 +68,14 @@ static const struct trapa_test tests[] =
.tp_active_connection_id_limit = 7,
},
.is_server = 0,
.enc_len = 39,
.enc_len = 25,
.encoded =
/* Overall length */ "\x00\x25"
/* Idle timeout */ "\x00\x01\x00\x02\x67\x10"
/* Packet size */ "\x00\x03\x00\x01\x00"
/* Max data */ "\x00\x04\x00\x04\x80\x00\xAA\xBB"
/* Bidi local */ "\x00\x05\x00\x04\x92\x34\x88\x77"
/* Ack delay exp */ "\x00\x0A\x00\x01\x00"
/* Active CID limit */ "\x00\x0E\x00\x01\x07"
/* Idle timeout */ "\x01\x02\x67\x10"
/* Packet size */ "\x03\x01\x00"
/* Max data */ "\x04\x04\x80\x00\xAA\xBB"
/* Bidi local */ "\x05\x04\x92\x34\x88\x77"
/* Ack delay exp */ "\x0A\x01\x00"
/* Active CID limit */ "\x0E\x01\x07"
/* Trailer to make the end easily visible in gdb: */
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
},
@ -109,13 +107,12 @@ static const struct trapa_test tests[] =
},
.is_server = 1,
.addl_set = 1 << TPI_DISABLE_ACTIVE_MIGRATION,
.enc_len = 32,
.enc_len = 22,
.encoded =
/* Overall length */ "\x00\x1E"
/* Packet size */ "\x00\x03\x00\x02\x43\x33"
/* Max data */ "\x00\x04\x00\x04\x80\x12\x34\x56"
/* Bidi local */ "\x00\x05\x00\x08\xC0\x00\x00\x00\xAB\xCD\xEF\x88"
/* Migration */ "\x00\x0C\x00\x00"
/* Packet size */ "\x03\x02\x43\x33"
/* Max data */ "\x04\x04\x80\x12\x34\x56"
/* Bidi local */ "\x05\x08\xC0\x00\x00\x00\xAB\xCD\xEF\x88"
/* Migration */ "\x0C\x00"
/* Trailer to make the end easily visible in gdb: */
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
},
@ -139,11 +136,11 @@ static const struct trapa_test tests[] =
},
.is_server = 1,
.addl_set = 1 << TPI_PREFERRED_ADDRESS,
.enc_len = 0x3E + 2,
.enc_len = 0x3A,
.dec_len = 0x3A,
.encoded =
/* Overall length */ "\x00\x3E"
/* Preferred Address */"\x00\x0D"
"\x00\x34"
/* Preferred Address */"\x0D"
"\x34"
"\x01\x02\x03\x04"
"\x12\x34"
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
@ -151,7 +148,7 @@ static const struct trapa_test tests[] =
"\x0B" /* CID len */
"\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A"
"\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F"
/* Packet size */ "\x00\x03\x00\x02\x43\x33"
/* Packet size */ "\x03\x02\x43\x33"
/* Trailer to make the end easily visible in gdb: */
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
},
@ -196,7 +193,7 @@ run_test (const struct trapa_test *test)
if (test->flags & TEST_ENCODE)
{
s = lsquic_tp_encode(&source_params, test->is_server, buf, sizeof(buf));
assert(s > 0);
assert(s >= 0);
assert((size_t) s == test->enc_len);
assert(0 == memcmp(test->encoded, buf, s));
}
@ -206,12 +203,12 @@ run_test (const struct trapa_test *test)
if (test->dec_len)
dec_len = test->dec_len;
else
dec_len = sizeof(buf);
dec_len = test->enc_len;
s = lsquic_tp_decode(test->encoded, dec_len,
test->is_server, &decoded_params);
if (!test->expect_decode_err)
{
assert(s > 0);
assert(s >= 0);
assert((size_t) s == test->enc_len);
/* The decoder initializes all default values, so set the flag
* accordingly: