Release 2.15.0

- [FEATURE] QUIC and HTTP/3 Internet Draft 28 support.
- [BUGFIX] Ignore Retry packets after other packets are decrypted
  successfully.
- [BUGFIX] Transport parameter decoding: CID no longer has 4-byte
  length minimum.
- http_client: fix and optimize lsxpack_header allocator.
- Drop support for Internet Draft 25.
This commit is contained in:
Dmitri Tikhonov 2020-05-27 10:26:32 -04:00
parent 4d221313f7
commit fb73393fef
33 changed files with 1124 additions and 631 deletions

View File

@ -1,3 +1,13 @@
2020-05-27
- 2.15.0
- [FEATURE] QUIC and HTTP/3 Internet Draft 28 support.
- [BUGFIX] Ignore Retry packets after other packets are decrypted
successfully.
- [BUGFIX] Transport parameter decoding: CID no longer has 4-byte
length minimum.
- http_client: fix and optimize lsxpack_header allocator.
- Drop support for Internet Draft 25.
2020-05-19
- 2.14.8
- Support Android.

View File

@ -220,6 +220,7 @@ struct lsquic_conn_ctx {
struct hset_elem
{
STAILQ_ENTRY(hset_elem) next;
size_t nalloc;
struct lsxpack_header xhdr;
};
@ -999,16 +1000,19 @@ hset_prepare_decode (void *hset_p, struct lsxpack_header *xhdr,
}
STAILQ_INSERT_TAIL(hset, el, next);
lsxpack_header_prepare_decode(&el->xhdr, buf, 0, req_space);
el->nalloc = req_space;
}
else
{
el = (struct hset_elem *) ((char *) xhdr
- offsetof(struct hset_elem, xhdr));
if (req_space <= xhdr->val_len)
if (req_space <= el->nalloc)
{
LSQ_ERROR("requested space is smaller than already allocated");
return NULL;
}
if (req_space < el->nalloc * 2)
req_space = el->nalloc * 2;
buf = realloc(el->xhdr.buf, req_space);
if (!buf)
{
@ -1017,6 +1021,7 @@ hset_prepare_decode (void *hset_p, struct lsxpack_header *xhdr,
}
el->xhdr.buf = buf;
el->xhdr.val_len = req_space;
el->nalloc = req_space;
}
return &el->xhdr;

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

View File

@ -1915,11 +1915,6 @@ set_engine_option (struct lsquic_engine_settings *settings,
settings->es_qpack_dec_max_size = atoi(val);
return 0;
}
if (0 == strncmp(name, "max_packet_size_rx", 18))
{
settings->es_max_packet_size_rx = atoi(val);
return 0;
}
break;
case 20:
if (0 == strncmp(name, "max_header_list_size", 20))
@ -1945,6 +1940,13 @@ set_engine_option (struct lsquic_engine_settings *settings,
return 0;
}
break;
case 23:
if (0 == strncmp(name, "max_udp_payload_size_rx", 18))
{
settings->es_max_udp_payload_size_rx = atoi(val);
return 0;
}
break;
case 24:
if (0 == strncmp(name, "init_max_stream_data_uni", 24))
{

View File

@ -693,7 +693,7 @@ settings structure:
Default value is @ref LSQUIC_DF_TIMESTAMPS
.. member:: unsigned short es_max_packet_size_rx
.. member:: unsigned short es_max_udp_payload_size_rx
Maximum packet size we are willing to receive. This is sent to
peer in transport parameters: the library does not enforce this
@ -701,7 +701,7 @@ settings structure:
If set to zero, limit is not set.
Default value is :macro:`LSQUIC_DF_MAX_PACKET_SIZE_RX`
Default value is :macro:`LSQUIC_DF_MAX_UDP_PAYLOAD_SIZE_RX`
To initialize the settings structure to library defaults, use the following
convenience function:
@ -877,7 +877,7 @@ out of date. Please check your :file:`lsquic.h` for actual values.*
Delayed ACKs are off by default.
.. macro:: LSQUIC_DF_MAX_PACKET_SIZE_RX
.. macro:: LSQUIC_DF_MAX_UDP_PAYLOAD_SIZE_RX
By default, incoming packet size is not limited.
@ -1099,7 +1099,7 @@ callback.
In client mode, a new connection is created by
.. function:: lsquic_conn_t * lsquic_engine_connect (lsquic_engine_t *engine, enum lsquic_version version, const struct sockaddr *local_sa, const struct sockaddr *peer_sa, void *peer_ctx, lsquic_conn_ctx_t *conn_ctx, const char *sni, unsigned short max_packet_size, const unsigned char *zero_rtt, size_t zero_rtt_len, const unsigned char *token, size_t token_sz)
.. function:: lsquic_conn_t * lsquic_engine_connect (lsquic_engine_t *engine, enum lsquic_version version, const struct sockaddr *local_sa, const struct sockaddr *peer_sa, void *peer_ctx, lsquic_conn_ctx_t *conn_ctx, const char *sni, unsigned short max_udp_payload_size, const unsigned char *zero_rtt, size_t zero_rtt_len, const unsigned char *token, size_t token_sz)
:param engine: Engine to use.
@ -1132,7 +1132,7 @@ In client mode, a new connection is created by
The SNI is required for Google QUIC connections; it is optional for
IETF QUIC and may be set to NULL.
:param max_packet_size:
:param max_udp_payload_size:
Maximum packet size. If set to zero, it is inferred based on `peer_sa`
and `version`.
@ -1168,11 +1168,7 @@ Closing Connections
Mark connection as going away: send GOAWAY frame and do not accept
any more incoming streams, nor generate streams of our own.
In the server mode, of course, we can call this function just fine in both
Google and IETF QUIC.
In client mode, calling this function in for an IETF QUIC connection does
not do anything, as the client MUST NOT send GOAWAY frames.
Only applicable to HTTP/3 and GQUIC connections. Otherwise a no-op.
.. function:: void lsquic_conn_close (lsquic_conn_t *conn)

View File

@ -24,9 +24,9 @@ copyright = u'2020, LiteSpeed Technologies'
author = u'LiteSpeed Technologies'
# The short X.Y version
version = u'2.14'
version = u'2.15'
# The full version, including alpha/beta/rc tags
release = u'2.14.8'
release = u'2.15.0'
# -- General configuration ---------------------------------------------------

View File

@ -16,7 +16,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-25, and ID-27.
Currently supported QUIC versions are Q043, Q046, Q050, ID-27, and ID-28.
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 14
#define LSQUIC_PATCH_VERSION 8
#define LSQUIC_MINOR_VERSION 15
#define LSQUIC_PATCH_VERSION 0
/**
* Engine flags:
@ -76,16 +76,16 @@ enum lsquic_version
#define LSQUIC_EXPERIMENTAL_Q098 0
#endif
/**
* IETF QUIC Draft-25
*/
LSQVER_ID25,
/**
* IETF QUIC Draft-27
*/
LSQVER_ID27,
/**
* IETF QUIC Draft-28
*/
LSQVER_ID28,
/**
* 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-25, and Draft-27.
* We currently support versions 43, 46, 50, Draft-27, and Draft-28.
* @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_ID25) | (1 << LSQVER_ID27) \
#define LSQUIC_IETF_VERSIONS ((1 << LSQVER_ID27) | (1 << LSQVER_ID28) \
| (1 << LSQVER_VERNEG))
#define LSQUIC_IETF_DRAFT_VERSIONS ((1 << LSQVER_ID25) | (1 << LSQVER_ID27) \
#define LSQUIC_IETF_DRAFT_VERSIONS ((1 << LSQVER_ID27) | (1 << LSQVER_ID28) \
| (1 << LSQVER_VERNEG))
enum lsquic_hsk_status
@ -341,7 +341,7 @@ typedef struct ssl_ctx_st * (*lsquic_lookup_cert_f)(
#define LSQUIC_DF_CC_ALGO 1
/** By default, incoming packet size is not limited. */
#define LSQUIC_DF_MAX_PACKET_SIZE_RX 0
#define LSQUIC_DF_MAX_UDP_PAYLOAD_SIZE_RX 0
struct lsquic_engine_settings {
/**
@ -749,9 +749,9 @@ struct lsquic_engine_settings {
*
* If set to zero, limit is not set.
*
* Default value is @ref LSQUIC_DF_MAX_PACKET_SIZE_RX
* Default value is @ref LSQUIC_DF_MAX_UDP_PAYLOAD_SIZE_RX
*/
unsigned short es_max_packet_size_rx;
unsigned short es_max_udp_payload_size_rx;
};
/* Initialize `settings' to default values */
@ -1078,7 +1078,7 @@ lsquic_engine_new (unsigned lsquic_engine_flags,
* To let the engine specify QUIC version, use N_LSQVER. If zero-rtt info
* is supplied, version is picked from there instead.
*
* If `max_packet_size' is set to zero, it is inferred based on `peer_sa':
* If `max_udp_payload_size' is set to zero, it is inferred based on `peer_sa':
* 1350 for IPv6 and 1370 for IPv4.
*/
lsquic_conn_t *
@ -1086,7 +1086,7 @@ lsquic_engine_connect (lsquic_engine_t *, enum lsquic_version,
const struct sockaddr *local_sa,
const struct sockaddr *peer_sa,
void *peer_ctx, lsquic_conn_ctx_t *conn_ctx,
const char *hostname, unsigned short max_packet_size,
const char *hostname, unsigned short max_udp_payload_size,
const unsigned char *zero_rtt, size_t zero_rtt_len,
/** Resumption token: optional */
const unsigned char *token, size_t token_sz);
@ -1174,12 +1174,7 @@ lsquic_conn_cancel_pending_streams (lsquic_conn_t *, unsigned n);
* Mark connection as going away: send GOAWAY frame and do not accept
* any more incoming streams, nor generate streams of our own.
*
* In the server mode, of course, we can call this function just fine in both
* Google and IETF QUIC.
*
* In client mode, calling this function in for an IETF QUIC connection does
* not do anything, as the client MUST NOT send GOAWAY frames.
* See [draft-ietf-quic-http-17] Section 4.2.7.
* Only applicable to HTTP/3 and GQUIC connections. Otherwise a no-op.
*/
void
lsquic_conn_going_away (lsquic_conn_t *);

View File

@ -33,6 +33,8 @@ enum alarm_id {
AL_PATH_CHAL,
AL_PATH_CHAL_0 = AL_PATH_CHAL,
AL_PATH_CHAL_1,
AL_PATH_CHAL_2,
AL_PATH_CHAL_3,
AL_SESS_TICKET,
AL_BLOCKED_KA, /* Blocked Keep-Alive */
MAX_LSQUIC_ALARMS
@ -51,6 +53,8 @@ enum alarm_id_bit {
ALBIT_CID_THROT = 1 << AL_CID_THROT,
ALBIT_PATH_CHAL_0 = 1 << AL_PATH_CHAL_0,
ALBIT_PATH_CHAL_1 = 1 << AL_PATH_CHAL_1,
ALBIT_PATH_CHAL_2 = 1 << AL_PATH_CHAL_2,
ALBIT_PATH_CHAL_3 = 1 << AL_PATH_CHAL_3,
ALBIT_SESS_TICKET = 1 << AL_SESS_TICKET,
ALBIT_BLOCKED_KA = 1 << AL_BLOCKED_KA,
};

View File

@ -243,6 +243,10 @@ struct conn_iface
/* Optional method. Only used by the IETF client code. */
void
(*ci_drop_crypto_streams) (struct lsquic_conn *);
/* Optional method. Only used by IETF connections */
void
(*ci_count_garbage) (struct lsquic_conn *, size_t);
};
#define LSCONN_CCE_BITS 3

View File

@ -276,6 +276,9 @@ struct enc_session_funcs_iquic
(*esfi_reset_dcid) (enc_session_t *, const struct lsquic_cid *,
const struct lsquic_cid *);
void
(*esfi_set_iscid) (enc_session_t *, const struct lsquic_packet_in *);
int
(*esfi_init_server) (enc_session_t *);
@ -288,7 +291,8 @@ struct enc_session_funcs_iquic
const struct lsquic_cid *,
void *(crypto_streams)[4],
const struct crypto_stream_if *,
const struct lsquic_cid *odcid);
const struct lsquic_cid *odcid,
const struct lsquic_cid *iscid );
void
(*esfi_shake_stream)(enc_session_t *, struct lsquic_stream *,
@ -328,8 +332,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_ID25 ? &lsquic_enc_session_common_ietf_v1 : \
ver == LSQVER_ID27 ? &lsquic_enc_session_common_ietf_v1 : \
ver == LSQVER_ID28 ? &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_h3_alpns[] = {
{ LSQVER_ID25, (unsigned char *) "\x05h3-25", },
{ LSQVER_ID27, (unsigned char *) "\x05h3-27", },
{ LSQVER_VERNEG, (unsigned char *) "\x05h3-27", },
{ LSQVER_ID28, (unsigned char *) "\x05h3-28", },
{ LSQVER_VERNEG, (unsigned char *) "\x05h3-28", },
};
struct enc_sess_iquic;
@ -221,6 +221,8 @@ struct enc_sess_iquic
struct header_prot *esi_hsk_hps;
lsquic_packno_t esi_max_packno[N_PNS];
lsquic_cid_t esi_odcid;
lsquic_cid_t esi_rscid; /* Retry SCID */
lsquic_cid_t esi_iscid; /* Initial SCID */
unsigned esi_key_phase;
enum {
ESI_INITIALIZED = 1 << 0,
@ -237,6 +239,9 @@ struct enc_sess_iquic
ESI_WANT_TICKET = 1 << 11,
ESI_RECV_QL_BITS = 1 << 12,
ESI_SEND_QL_BITS = 1 << 13,
ESI_RSCID = 1 << 14,
ESI_ISCID = 1 << 15,
ESI_RETRY = 1 << 16, /* Connection was retried */
} esi_flags;
enum evp_aead_direction_t
esi_dir[2]; /* client, server */
@ -429,9 +434,15 @@ gen_trans_params (struct enc_sess_iquic *enc_sess, unsigned char *buf,
const struct lsquic_engine_settings *const settings =
&enc_sess->esi_enpub->enp_settings;
struct transport_params params;
const enum lsquic_version version = enc_sess->esi_conn->cn_version;
int len;
memset(&params, 0, sizeof(params));
if (version > LSQVER_ID27)
{
params.tp_initial_source_cid = *CN_SCID(enc_sess->esi_conn);
params.tp_set |= 1 << TPI_INITIAL_SOURCE_CID;
}
if (enc_sess->esi_flags & ESI_SERVER)
{
const struct lsquic_conn *const lconn = enc_sess->esi_conn;
@ -442,8 +453,8 @@ gen_trans_params (struct enc_sess_iquic *enc_sess, unsigned char *buf,
if (enc_sess->esi_flags & ESI_ODCID)
{
params.tp_original_cid = enc_sess->esi_odcid;
params.tp_set |= 1 << TPI_ORIGINAL_CONNECTION_ID;
params.tp_original_dest_cid = enc_sess->esi_odcid;
params.tp_set |= 1 << TPI_ORIGINAL_DEST_CID;
}
#if LSQUIC_PREFERRED_ADDR
char addr_buf[INET6_ADDRSTRLEN + 6 /* port */ + 1];
@ -544,10 +555,10 @@ gen_trans_params (struct enc_sess_iquic *enc_sess, unsigned char *buf,
| (1 << TPI_MAX_ACK_DELAY)
| (1 << TPI_ACTIVE_CONNECTION_ID_LIMIT)
;
if (settings->es_max_packet_size_rx)
if (settings->es_max_udp_payload_size_rx)
{
params.tp_max_packet_size = settings->es_max_packet_size_rx;
params.tp_set |= 1 << TPI_MAX_PACKET_SIZE;
params.tp_max_udp_payload_size = settings->es_max_udp_payload_size_rx;
params.tp_set |= 1 << TPI_MAX_UDP_PAYLOAD_SIZE;
}
if (!settings->es_allow_migration)
params.tp_set |= 1 << TPI_DISABLE_ACTIVE_MIGRATION;
@ -564,10 +575,15 @@ gen_trans_params (struct enc_sess_iquic *enc_sess, unsigned char *buf,
if (settings->es_timestamps)
params.tp_set |= 1 << TPI_TIMESTAMPS;
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);
len = (version == LSQVER_ID27 ? lsquic_tp_encode_27 : lsquic_tp_encode)(
&params, enc_sess->esi_flags & ESI_SERVER, buf, bufsz);
if (len >= 0)
{
char str[MAX_TP_STR_SZ];
LSQ_DEBUG("generated transport parameters buffer of %d bytes", len);
LSQ_DEBUG("%s", ((version == LSQVER_ID27 ? lsquic_tp_to_str_27
: lsquic_tp_to_str)(&params, str, sizeof(str)), str));
}
else
LSQ_WARN("cannot generate transport parameters: %d", errno);
return len;
@ -726,6 +742,9 @@ iquic_esfi_create_client (const char *hostname,
enc_sess->esi_dir[0] = evp_aead_seal;
enc_sess->esi_dir[1] = evp_aead_open;
enc_sess->esi_odcid = *dcid;
enc_sess->esi_flags |= ESI_ODCID;
LSQ_DEBUGC("created client, DCID: %"CID_FMT, CID_BITS(dcid));
{
const char *log;
@ -793,7 +812,8 @@ iquic_esfi_create_server (struct lsquic_engine_public *enpub,
struct lsquic_conn *lconn, const lsquic_cid_t *first_dcid,
void *(crypto_streams)[4],
const struct crypto_stream_if *cryst_if,
const struct lsquic_cid *odcid)
const struct lsquic_cid *odcid,
const struct lsquic_cid *iscid )
{
struct enc_sess_iquic *enc_sess;
@ -819,6 +839,8 @@ iquic_esfi_create_server (struct lsquic_engine_public *enpub,
enc_sess->esi_odcid = *odcid;
enc_sess->esi_flags |= ESI_ODCID;
}
enc_sess->esi_iscid = *iscid;
enc_sess->esi_flags |= ESI_ISCID;
init_frals(enc_sess);
@ -1470,6 +1492,7 @@ get_peer_transport_params (struct enc_sess_iquic *enc_sess)
const uint8_t *params_buf;
size_t bufsz;
char *params_str;
const enum lsquic_version version = enc_sess->esi_conn->cn_version;
SSL_get_peer_quic_transport_params(enc_sess->esi_ssl, &params_buf, &bufsz);
if (!params_buf)
@ -1479,8 +1502,8 @@ get_peer_transport_params (struct enc_sess_iquic *enc_sess)
}
LSQ_DEBUG("have peer transport parameters (%zu bytes)", bufsz);
if (0 > (enc_sess->esi_conn->cn_version == LSQVER_ID25
? lsquic_tp_decode_id25 : lsquic_tp_decode)(params_buf, bufsz,
if (0 > (version == LSQVER_ID27 ? lsquic_tp_decode_27
: lsquic_tp_decode)(params_buf, bufsz,
!(enc_sess->esi_flags & ESI_SERVER),
trans_params))
{
@ -1501,30 +1524,70 @@ get_peer_transport_params (struct enc_sess_iquic *enc_sess)
return -1;
}
if ((enc_sess->esi_flags & (ESI_ODCID|ESI_SERVER)) == ESI_ODCID)
const lsquic_cid_t *const cids[LAST_TPI + 1] = {
[TP_CID_IDX(TPI_ORIGINAL_DEST_CID)] = enc_sess->esi_flags & ESI_ODCID ? &enc_sess->esi_odcid : NULL,
[TP_CID_IDX(TPI_RETRY_SOURCE_CID)] = enc_sess->esi_flags & ESI_RSCID ? &enc_sess->esi_rscid : NULL,
[TP_CID_IDX(TPI_INITIAL_SOURCE_CID)] = enc_sess->esi_flags & ESI_ISCID ? &enc_sess->esi_iscid : NULL,
};
unsigned must_have, must_not_have = 0;
if (version > LSQVER_ID27)
{
if (!(trans_params->tp_set & (1 << TPI_ORIGINAL_CONNECTION_ID)))
must_have = 1 << TPI_INITIAL_SOURCE_CID;
if (enc_sess->esi_flags & ESI_SERVER)
must_not_have |= 1 << TPI_ORIGINAL_DEST_CID;
else
must_have |= 1 << TPI_ORIGINAL_DEST_CID;
if ((enc_sess->esi_flags & (ESI_RETRY|ESI_SERVER)) == ESI_RETRY)
must_have |= 1 << TPI_RETRY_SOURCE_CID;
else
must_not_have |= 1 << TPI_RETRY_SOURCE_CID;
}
else if ((enc_sess->esi_flags & (ESI_RETRY|ESI_SERVER)) == ESI_RETRY)
must_have = 1 << TPI_ORIGINAL_DEST_CID;
enum transport_param_id tpi;
for (tpi = FIRST_TP_CID; tpi <= LAST_TP_CID; ++tpi)
{
if (!(must_have & (1 << tpi)))
continue;
if (!(trans_params->tp_set & (1 << tpi)))
{
LSQ_DEBUG("server did not produce original DCID (ODCID)");
LSQ_DEBUG("server did not produce %s", lsquic_tpi2str[tpi]);
return -1;
}
if (LSQUIC_CIDS_EQ(&enc_sess->esi_odcid,
&trans_params->tp_original_cid))
LSQ_DEBUG("ODCID values match");
if (!cids[TP_CID_IDX(tpi)])
{
LSQ_WARN("do not have CID %s for checking",
lsquic_tpi2str[tpi]);
return -1;
}
if (LSQUIC_CIDS_EQ(cids[TP_CID_IDX(tpi)],
&trans_params->tp_cids[TP_CID_IDX(tpi)]))
LSQ_DEBUG("%s values match", lsquic_tpi2str[tpi]);
else
{
if (LSQ_LOG_ENABLED(LSQ_LOG_DEBUG))
{
char cidbuf[2][MAX_CID_LEN * 2 + 1];
lsquic_cid2str(&enc_sess->esi_odcid, cidbuf[0]);
lsquic_cid2str(&trans_params->tp_original_cid, cidbuf[1]);
LSQ_DEBUG("server provided ODCID %s that does not match "
"our ODCID %s", cidbuf[1], cidbuf[0]);
LSQ_DEBUG("server provided %s %"CID_FMT" that does not "
"match ours %"CID_FMT, lsquic_tpi2str[tpi],
CID_BITS_B(&trans_params->tp_cids[TP_CID_IDX(tpi)],
cidbuf[0]),
CID_BITS_B(cids[TP_CID_IDX(tpi)], cidbuf[1]));
}
return -1;
}
}
for (tpi = FIRST_TP_CID; tpi <= LAST_TP_CID; ++tpi)
if (must_not_have & (1 << tpi) & trans_params->tp_set)
{
LSQ_DEBUG("server transport parameters unexpectedly contain %s",
lsquic_tpi2str[tpi]);
return -1;
}
if ((trans_params->tp_set & (1 << TPI_LOSS_BITS))
&& enc_sess->esi_enpub->enp_settings.es_ql_bits)
{
@ -2239,6 +2302,21 @@ iquic_esf_zero_rtt_enabled (enc_session_t *enc_session_p)
}
static void
iquic_esfi_set_iscid (enc_session_t *enc_session_p,
const struct lsquic_packet_in *packet_in)
{
struct enc_sess_iquic *const enc_sess = enc_session_p;
if (!(enc_sess->esi_flags & ESI_ISCID))
{
lsquic_scid_from_packet_in(packet_in, &enc_sess->esi_iscid);
enc_sess->esi_flags |= ESI_ISCID;
LSQ_DEBUGC("set ISCID to %"CID_FMT, CID_BITS(&enc_sess->esi_iscid));
}
}
static int
iquic_esfi_reset_dcid (enc_session_t *enc_session_p,
const lsquic_cid_t *old_dcid, const lsquic_cid_t *new_dcid)
@ -2247,7 +2325,8 @@ iquic_esfi_reset_dcid (enc_session_t *enc_session_p,
struct crypto_ctx_pair *pair;
enc_sess->esi_odcid = *old_dcid;
enc_sess->esi_flags |= ESI_ODCID;
enc_sess->esi_rscid = *new_dcid;
enc_sess->esi_flags |= ESI_ODCID|ESI_RSCID|ESI_RETRY;
/* Free previous handshake keys */
assert(enc_sess->esi_hsk_pairs);
@ -2340,6 +2419,7 @@ const struct enc_session_funcs_iquic lsquic_enc_session_iquic_ietf_v1 =
= iquic_esfi_get_peer_transport_params,
.esfi_reset_dcid = iquic_esfi_reset_dcid,
.esfi_init_server = iquic_esfi_init_server,
.esfi_set_iscid = iquic_esfi_set_iscid,
.esfi_set_streams = iquic_esfi_set_streams,
.esfi_create_server = iquic_esfi_create_server,
.esfi_shake_stream = iquic_esfi_shake_stream,

View File

@ -223,6 +223,7 @@ struct lsquic_engine
struct min_heap conns_out;
struct eng_hist history;
unsigned batch_size;
struct lsquic_conn *curr_conn;
struct pr_queue *pr_queue;
struct attq *attq;
/* Track time last time a packet was sent to give new connections
@ -1320,8 +1321,12 @@ process_packet_in (lsquic_engine_t *engine, lsquic_packet_in_t *packet_in,
}
if (engine->flags & ENG_SERVER)
{
conn = find_or_create_conn(engine, packet_in, ppstate, sa_local,
sa_peer, peer_ctx, packet_in_size);
if (!engine->curr_conn)
engine->curr_conn = conn;
}
else
conn = find_conn(engine, packet_in, ppstate, sa_local);
@ -2641,6 +2646,20 @@ process_connections (lsquic_engine_t *engine, conn_iter_f next_conn,
}
static void
maybe_count_garbage (struct lsquic_engine *engine, size_t garbage_sz)
{
/* This is not very pretty (action at a distance via engine->curr_conn),
* but it's the cheapest I can come up with to handle the "count garbage
* toward amplification limit" requirement in
* [draft-ietf-quic-transport-28] Section 8.1.
*/
if (engine->curr_conn && engine->curr_conn->cn_if->ci_count_garbage)
engine->curr_conn->cn_if->ci_count_garbage(engine->curr_conn,
garbage_sz);
}
/* Return 0 if packet is being processed by a real connection, 1 if the
* packet was processed, but not by a connection, and -1 on error.
*/
@ -2692,6 +2711,7 @@ lsquic_engine_packet_in (lsquic_engine_t *engine,
else
parse_packet_in_begin = lsquic_parse_packet_in_begin;
engine->curr_conn = NULL;
n_zeroes = 0;
is_ietf = 0;
do
@ -2709,6 +2729,7 @@ lsquic_engine_packet_in (lsquic_engine_t *engine,
engine->pub.enp_settings.es_scid_len, &ppstate))
{
LSQ_DEBUG("Cannot parse incoming packet's header");
maybe_count_garbage(engine, packet_end - packet_in_data);
lsquic_mm_put_packet_in(&engine->pub.enp_mm, packet_in);
s = 1;
break;
@ -2724,6 +2745,7 @@ lsquic_engine_packet_in (lsquic_engine_t *engine,
&& LSQUIC_CIDS_EQ(&packet_in->pi_dcid, &cid)))
{
packet_in_data += packet_in->pi_data_sz;
maybe_count_garbage(engine, packet_in->pi_data_sz);
continue;
}
}

View File

@ -144,7 +144,7 @@ enum more_flags
};
#define N_PATHS 2
#define N_PATHS 4
enum send
{
@ -154,9 +154,13 @@ enum send
SEND_PATH_CHAL,
SEND_PATH_CHAL_PATH_0 = SEND_PATH_CHAL + 0,
SEND_PATH_CHAL_PATH_1 = SEND_PATH_CHAL + 1,
SEND_PATH_CHAL_PATH_2 = SEND_PATH_CHAL + 2,
SEND_PATH_CHAL_PATH_3 = SEND_PATH_CHAL + 3,
SEND_PATH_RESP,
SEND_PATH_RESP_PATH_0 = SEND_PATH_RESP + 0,
SEND_PATH_RESP_PATH_1 = SEND_PATH_RESP + 1,
SEND_PATH_RESP_PATH_2 = SEND_PATH_RESP + 2,
SEND_PATH_RESP_PATH_3 = SEND_PATH_RESP + 3,
SEND_MAX_DATA,
SEND_PING,
SEND_NEW_CID,
@ -181,9 +185,13 @@ enum send_flags
SF_SEND_PATH_CHAL = 1 << SEND_PATH_CHAL,
SF_SEND_PATH_CHAL_PATH_0 = 1 << SEND_PATH_CHAL_PATH_0,
SF_SEND_PATH_CHAL_PATH_1 = 1 << SEND_PATH_CHAL_PATH_1,
SF_SEND_PATH_CHAL_PATH_2 = 1 << SEND_PATH_CHAL_PATH_2,
SF_SEND_PATH_CHAL_PATH_3 = 1 << SEND_PATH_CHAL_PATH_3,
SF_SEND_PATH_RESP = 1 << SEND_PATH_RESP,
SF_SEND_PATH_RESP_PATH_0 = 1 << SEND_PATH_RESP_PATH_0,
SF_SEND_PATH_RESP_PATH_1 = 1 << SEND_PATH_RESP_PATH_1,
SF_SEND_PATH_RESP_PATH_2 = 1 << SEND_PATH_RESP_PATH_2,
SF_SEND_PATH_RESP_PATH_3 = 1 << SEND_PATH_RESP_PATH_3,
SF_SEND_NEW_CID = 1 << SEND_NEW_CID,
SF_SEND_RETIRE_CID = 1 << SEND_RETIRE_CID,
SF_SEND_CONN_CLOSE = 1 << SEND_CONN_CLOSE,
@ -464,6 +472,10 @@ ietf_full_conn_ci_get_log_cid (const struct lsquic_conn *);
static void
ietf_full_conn_ci_destroy (struct lsquic_conn *);
static int
insert_new_dcid (struct ietf_full_conn *, uint64_t seqno,
const lsquic_cid_t *, const unsigned char *token, int update_cur_dcid);
static unsigned
highest_bit_set (unsigned sz)
{
@ -652,11 +664,11 @@ migra_begin (struct ietf_full_conn *conn, struct conn_path *copath,
copath->cop_path.np_pack_size = IQUIC_MAX_IPv6_PACKET_SZ;
else
copath->cop_path.np_pack_size = IQUIC_MAX_IPv4_PACKET_SZ;
if ((params->tp_set & (1 << TPI_MAX_PACKET_SIZE))
&& params->tp_numerics[TPI_MAX_PACKET_SIZE]
if ((params->tp_set & (1 << TPI_MAX_UDP_PAYLOAD_SIZE))
&& params->tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE]
< copath->cop_path.np_pack_size)
copath->cop_path.np_pack_size
= params->tp_numerics[TPI_MAX_PACKET_SIZE];
= params->tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE];
memcpy(&copath->cop_path.np_local_addr, NP_LOCAL_SA(CUR_NPATH(conn)),
sizeof(copath->cop_path.np_local_addr));
memcpy(&copath->cop_path.np_peer_addr, dest_sa,
@ -1113,6 +1125,8 @@ ietf_full_conn_init (struct ietf_full_conn *conn,
conn->ifc_max_ack_packno[PNS_APP] = IQUIC_INVALID_PACKNO;
conn->ifc_paths[0].cop_path.np_path_id = 0;
conn->ifc_paths[1].cop_path.np_path_id = 1;
conn->ifc_paths[2].cop_path.np_path_id = 2;
conn->ifc_paths[3].cop_path.np_path_id = 3;
#define valid_stream_id(v) ((v) <= VINT_MAX_VALUE)
conn->ifc_max_req_id = VINT_MAX_VALUE + 1;
conn->ifc_ping_unretx_thresh = 20;
@ -2740,7 +2754,7 @@ ietf_full_conn_ci_going_away (struct lsquic_conn *lconn)
{
struct ietf_full_conn *conn = (struct ietf_full_conn *) lconn;
if ((conn->ifc_flags & (IFC_SERVER|IFC_HTTP)) == (IFC_SERVER|IFC_HTTP))
if (conn->ifc_flags & IFC_HTTP)
{
if (!(conn->ifc_flags & (IFC_CLOSING|IFC_GOING_AWAY)))
{
@ -2760,7 +2774,7 @@ ietf_full_conn_ci_going_away (struct lsquic_conn *lconn)
}
}
else
LSQ_NOTICE("going away has no effect in IETF QUIC");
LSQ_NOTICE("going away has no effect in non-HTTP mode");
}
@ -2834,8 +2848,8 @@ retire_cid_from_tp (struct ietf_full_conn *conn,
}
static int
begin_migra_or_retire_cid (struct ietf_full_conn *conn,
static enum { BM_MIGRATING, BM_NOT_MIGRATING, BM_ERROR, }
try_to_begin_migration (struct ietf_full_conn *conn,
const struct transport_params *params)
{
struct conn_path *copath;
@ -2853,8 +2867,7 @@ begin_migra_or_retire_cid (struct ietf_full_conn *conn,
LSQ_DEBUG("TP disables migration: retire PreferredAddress CID");
else
LSQ_DEBUG("Migration not allowed: retire PreferredAddress CID");
retire_cid_from_tp(conn, params);
return 0;
return BM_NOT_MIGRATING;
}
is_ipv6 = NP_IS_IPv6(CUR_NPATH(conn));
@ -2867,8 +2880,7 @@ begin_migra_or_retire_cid (struct ietf_full_conn *conn,
*/
LSQ_DEBUG("Cannot migrate from IPv%u to IPv%u", is_ipv6 ? 6 : 4,
is_ipv6 ? 4 : 6);
retire_cid_from_tp(conn, params);
return 0;
return BM_NOT_MIGRATING;
}
if (0 == params->tp_preferred_address.cid.len)
@ -2877,15 +2889,14 @@ begin_migra_or_retire_cid (struct ietf_full_conn *conn,
* DCID becomes available.
*/
LSQ_DEBUG("Cannot migrate using zero-length DCID");
retire_cid_from_tp(conn, params);
return 0;
return BM_NOT_MIGRATING;
}
dce = get_new_dce(conn);
if (!dce)
{
ABORT_WARN("cannot allocate DCE");
return -1;
return BM_ERROR;
}
memset(dce, 0, sizeof(*dce));
@ -2902,7 +2913,7 @@ begin_migra_or_retire_cid (struct ietf_full_conn *conn,
{
lsquic_malo_put(dce);
ABORT_WARN("cannot insert DCE");
return -1;
return BM_ERROR;
}
}
@ -2925,7 +2936,7 @@ begin_migra_or_retire_cid (struct ietf_full_conn *conn,
assert(!(conn->ifc_used_paths & (1 << (copath - conn->ifc_paths))));
migra_begin(conn, copath, dce, (struct sockaddr *) &sockaddr, params);
return 0;
return BM_MIGRATING;
}
@ -2938,10 +2949,33 @@ maybe_start_migration (struct ietf_full_conn *conn)
params = lconn->cn_esf.i->esfi_get_peer_transport_params(
lconn->cn_enc_session);
if (params->tp_set & (1 << TPI_PREFERRED_ADDRESS))
{
if (0 != begin_migra_or_retire_cid(conn, params))
switch (try_to_begin_migration(conn, params))
{
case BM_MIGRATING:
break;
case BM_NOT_MIGRATING:
if (lconn->cn_version == LSQVER_ID27)
retire_cid_from_tp(conn, params);
else
{
/*
* [draft-ietf-quic-transport-28] Section 5.1.1:
" Connection IDs that are issued and not
" retired are considered active; any active connection ID is valid for
" use with the current connection at any time, in any packet type.
" This includes the connection ID issued by the server via the
" preferred_address transport parameter.
*/
LSQ_DEBUG("not migrating: save DCID from transport params");
(void) insert_new_dcid(conn, 1,
&params->tp_preferred_address.cid,
params->tp_preferred_address.srst, 0);
}
break;
case BM_ERROR:
ABORT_QUIETLY(0, TEC_INTERNAL_ERROR, "error initiating migration");
}
break;
}
}
@ -2955,7 +2989,7 @@ handshake_ok (struct lsquic_conn *lconn)
const struct transport_params *params;
enum stream_id_type sit;
uint64_t limit;
char buf[0x200];
char buf[MAX_TP_STR_SZ];
fiu_return_on("full_conn_ietf/handshake_ok", -1);
@ -2973,7 +3007,8 @@ handshake_ok (struct lsquic_conn *lconn)
}
LSQ_DEBUG("peer transport parameters: %s",
(lsquic_tp_to_str(params, buf, sizeof(buf)), buf));
((lconn->cn_version == LSQVER_ID27 ? lsquic_tp_to_str_27
: lsquic_tp_to_str)(params, buf, sizeof(buf)), buf));
if ((params->tp_set & (1 << TPI_LOSS_BITS))
&& conn->ifc_settings->es_ql_bits == 2)
@ -3088,12 +3123,12 @@ handshake_ok (struct lsquic_conn *lconn)
conn->ifc_max_peer_ack_usec = params->tp_max_ack_delay * 1000;
if ((params->tp_set & (1 << TPI_MAX_PACKET_SIZE))
&& params->tp_numerics[TPI_MAX_PACKET_SIZE]
if ((params->tp_set & (1 << TPI_MAX_UDP_PAYLOAD_SIZE))
&& params->tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE]
< CUR_NPATH(conn)->np_pack_size)
{
CUR_NPATH(conn)->np_pack_size
= params->tp_numerics[TPI_MAX_PACKET_SIZE];
= params->tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE];
LSQ_DEBUG("decrease packet size to %hu bytes",
CUR_NPATH(conn)->np_pack_size);
}
@ -3937,6 +3972,20 @@ generate_path_chal_1 (struct ietf_full_conn *conn, lsquic_time_t now)
}
static void
generate_path_chal_2 (struct ietf_full_conn *conn, lsquic_time_t now)
{
generate_path_chal_frame(conn, now, 2);
}
static void
generate_path_chal_3 (struct ietf_full_conn *conn, lsquic_time_t now)
{
generate_path_chal_frame(conn, now, 3);
}
static void
generate_path_resp_frame (struct ietf_full_conn *conn, lsquic_time_t now,
unsigned path_id)
@ -3986,6 +4035,20 @@ generate_path_resp_1 (struct ietf_full_conn *conn, lsquic_time_t now)
}
static void
generate_path_resp_2 (struct ietf_full_conn *conn, lsquic_time_t now)
{
generate_path_resp_frame(conn, now, 2);
}
static void
generate_path_resp_3 (struct ietf_full_conn *conn, lsquic_time_t now)
{
generate_path_resp_frame(conn, now, 3);
}
static struct lsquic_packet_out *
ietf_full_conn_ci_next_packet_to_send (struct lsquic_conn *lconn, size_t size)
{
@ -5140,17 +5203,91 @@ retire_dcids_prior_to (struct ietf_full_conn *conn, unsigned retire_prior_to)
}
static int
insert_new_dcid (struct ietf_full_conn *conn, uint64_t seqno,
const lsquic_cid_t *cid, const unsigned char *token, int update_cur_dcid)
{
struct dcid_elem **dce, **el;
char tokstr[IQUIC_SRESET_TOKEN_SZ * 2 + 1];
dce = NULL;
for (el = conn->ifc_dces; el < conn->ifc_dces + sizeof(conn->ifc_dces)
/ sizeof(conn->ifc_dces[0]); ++el)
if (*el)
{
if ((*el)->de_seqno == seqno)
{
if (!LSQUIC_CIDS_EQ(&(*el)->de_cid, cid))
{
ABORT_QUIETLY(0, TEC_PROTOCOL_VIOLATION,
"NEW_CONNECTION_ID: already have CID seqno %"PRIu64
" but with a different CID", seqno);
return -1;
}
else
{
LSQ_DEBUG("Ignore duplicate CID seqno %"PRIu64, seqno);
return 0;
}
}
else if (LSQUIC_CIDS_EQ(&(*el)->de_cid, cid))
{
ABORT_QUIETLY(0, TEC_PROTOCOL_VIOLATION,
"NEW_CONNECTION_ID: received the same CID with sequence "
"numbers %u and %"PRIu64, (*el)->de_seqno, seqno);
return -1;
}
else if (((*el)->de_flags & DE_SRST)
&& 0 == memcmp((*el)->de_srst, token,
IQUIC_SRESET_TOKEN_SZ))
{
ABORT_QUIETLY(0, TEC_PROTOCOL_VIOLATION,
"NEW_CONNECTION_ID: received second instance of reset "
"token %s in seqno %"PRIu64", same as in seqno %u",
(lsquic_hexstr(token, IQUIC_SRESET_TOKEN_SZ, tokstr,
sizeof(tokstr)), tokstr),
seqno, (*el)->de_seqno);
return -1;
}
}
else if (!dce)
dce = el;
if (!dce)
{
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 -1;
}
*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;
if (update_cur_dcid)
*CUR_DCID(conn) = *cid;
}
else
LSQ_WARN("cannot allocate dce to insert DCID seqno %"PRIu64, seqno);
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)
{
struct dcid_elem **dce, **el;
const unsigned char *token;
const char *action_str;
lsquic_cid_t cid;
uint64_t seqno, retire_prior_to;
int parsed_len, update_cur_dcid;
char tokstr[IQUIC_SRESET_TOKEN_SZ * 2 + 1];
parsed_len = conn->ifc_conn.cn_pf->pf_parse_new_conn_id(p, len,
&seqno, &retire_prior_to, &cid, &token);
@ -5194,71 +5331,9 @@ process_new_connection_id_frame (struct ietf_full_conn *conn,
else
update_cur_dcid = 0;
dce = NULL;
for (el = conn->ifc_dces; el < conn->ifc_dces + sizeof(conn->ifc_dces)
/ sizeof(conn->ifc_dces[0]); ++el)
if (*el)
{
if ((*el)->de_seqno == seqno)
{
if (!LSQUIC_CIDS_EQ(&(*el)->de_cid, &cid))
{
ABORT_QUIETLY(0, TEC_PROTOCOL_VIOLATION,
"NEW_CONNECTION_ID: already have CID seqno %"PRIu64
" but with a different CID", seqno);
return 0;
}
else
{
LSQ_DEBUG("Ignore duplicate CID seqno %"PRIu64, seqno);
return parsed_len;
}
}
else if (LSQUIC_CIDS_EQ(&(*el)->de_cid, &cid))
{
ABORT_QUIETLY(0, TEC_PROTOCOL_VIOLATION,
"NEW_CONNECTION_ID: received the same CID with sequence "
"numbers %u and %"PRIu64, (*el)->de_seqno, seqno);
return 0;
}
else if (((*el)->de_flags & DE_SRST)
&& 0 == memcmp((*el)->de_srst, token,
IQUIC_SRESET_TOKEN_SZ))
{
ABORT_QUIETLY(0, TEC_PROTOCOL_VIOLATION,
"NEW_CONNECTION_ID: received second instance of reset "
"token %s in seqno %"PRIu64", same as in seqno %u",
(lsquic_hexstr(token, IQUIC_SRESET_TOKEN_SZ, tokstr,
sizeof(tokstr)), tokstr),
seqno, (*el)->de_seqno);
return 0;
}
}
else if (!dce)
dce = el;
if (!dce)
{
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);
if (0 != insert_new_dcid(conn, seqno, &cid, token, update_cur_dcid))
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 (alloc failure)";
action_str = "Saved";
end:
LSQ_DEBUGC("Got new connection ID from peer: seq=%"PRIu64"; "
@ -5642,7 +5717,8 @@ process_packet_frame (struct ietf_full_conn *conn,
enc_level = lsquic_packet_in_enc_level(packet_in);
type = conn->ifc_conn.cn_pf->pf_parse_frame_type(p, len);
if (lsquic_legal_frames_by_level[enc_level] & (1 << type))
if (lsquic_legal_frames_by_level[conn->ifc_conn.cn_version][enc_level]
& (1 << type))
{
LSQ_DEBUG("about to process %s frame", frame_type_2_str[type]);
packet_in->pi_frame_types |= 1 << type;
@ -5724,11 +5800,11 @@ init_new_path (struct ietf_full_conn *conn, struct conn_path *path,
path->cop_path.np_pack_size = IQUIC_MAX_IPv4_PACKET_SZ;
params = lconn->cn_esf.i->esfi_get_peer_transport_params(
lconn->cn_enc_session);
if (params && (params->tp_set & (1 << TPI_MAX_PACKET_SIZE))
&& params->tp_numerics[TPI_MAX_PACKET_SIZE]
if (params && (params->tp_set & (1 << TPI_MAX_UDP_PAYLOAD_SIZE))
&& params->tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE]
< path->cop_path.np_pack_size)
path->cop_path.np_pack_size
= params->tp_numerics[TPI_MAX_PACKET_SIZE];
= params->tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE];
LSQ_DEBUG("initialized path %u", (unsigned) (path - conn->ifc_paths));
@ -6158,6 +6234,9 @@ process_regular_packet (struct ietf_full_conn *conn,
return process_retry_packet(conn, packet_in);
pns = lsquic_hety2pns[ packet_in->pi_header_type ];
if (pns == PNS_INIT)
conn->ifc_conn.cn_esf.i->esfi_set_iscid(conn->ifc_conn.cn_enc_session,
packet_in);
if ((pns == PNS_INIT && (conn->ifc_flags & IFC_IGNORE_INIT))
|| (pns == PNS_HSK && (conn->ifc_flags & IFC_IGNORE_HSK)))
{
@ -6241,6 +6320,10 @@ process_regular_packet (struct ietf_full_conn *conn,
"decrypter reports protocol violation");
return -1;
case DECPI_OK:
/* Receiving any other type of packet precludes subsequent retries.
* We only set it if decryption is successful.
*/
conn->ifc_flags |= IFC_RETRIED;
break;
}
}
@ -6344,13 +6427,6 @@ process_incoming_packet_verneg (struct ietf_full_conn *conn,
if (lsquic_packet_in_is_verneg(packet_in))
{
if (!verneg_ok(conn))
{
ABORT_ERROR("version negotiation not permitted in this version "
"of QUIC");
return -1;
}
LSQ_DEBUG("Processing version-negotiation packet");
if (conn->ifc_u.cli.ifcli_ver_neg.vn_state != VN_START)
@ -6383,10 +6459,26 @@ process_incoming_packet_verneg (struct ietf_full_conn *conn,
}
}
/* [draft-ietf-quic-transport-28] Section 6.2:
" A client MUST discard a Version Negotiation packet that lists the
" QUIC version selected by the client.
*/
if (versions & (1 << conn->ifc_u.cli.ifcli_ver_neg.vn_ver))
{
ABORT_ERROR("server replied with version we support: %s",
LSQ_DEBUG("server replied with version we sent, %s, ignore",
lsquic_ver2str[conn->ifc_u.cli.ifcli_ver_neg.vn_ver]);
return 0;
}
/* [draft-ietf-quic-transport-28] Section 6.2:
" A client that supports only this version of QUIC MUST abandon the
" current connection attempt if it receives a Version Negotiation
" packet [...]
*/
if (!verneg_ok(conn))
{
ABORT_ERROR("version negotiation not permitted in this version "
"of QUIC");
return -1;
}
@ -6530,8 +6622,12 @@ static void (*const send_funcs[N_SEND])(
[SEND_STOP_SENDING] = generate_stop_sending_frames,
[SEND_PATH_CHAL_PATH_0] = generate_path_chal_0,
[SEND_PATH_CHAL_PATH_1] = generate_path_chal_1,
[SEND_PATH_CHAL_PATH_2] = generate_path_chal_2,
[SEND_PATH_CHAL_PATH_3] = generate_path_chal_3,
[SEND_PATH_RESP_PATH_0] = generate_path_resp_0,
[SEND_PATH_RESP_PATH_1] = generate_path_resp_1,
[SEND_PATH_RESP_PATH_2] = generate_path_resp_2,
[SEND_PATH_RESP_PATH_3] = generate_path_resp_3,
[SEND_PING] = generate_ping_frame,
[SEND_HANDSHAKE_DONE] = generate_handshake_done_frame,
[SEND_ACK_FREQUENCY] = generate_ack_frequency_frame,
@ -6543,7 +6639,9 @@ static void (*const send_funcs[N_SEND])(
|SF_SEND_STREAMS_BLOCKED_UNI|SF_SEND_STREAMS_BLOCKED_BIDI\
|SF_SEND_MAX_STREAMS_UNI|SF_SEND_MAX_STREAMS_BIDI\
|SF_SEND_PATH_CHAL_PATH_0|SF_SEND_PATH_CHAL_PATH_1\
|SF_SEND_PATH_CHAL_PATH_2|SF_SEND_PATH_CHAL_PATH_3\
|SF_SEND_PATH_RESP_PATH_0|SF_SEND_PATH_RESP_PATH_1\
|SF_SEND_PATH_RESP_PATH_2|SF_SEND_PATH_RESP_PATH_3\
|SF_SEND_PING|SF_SEND_HANDSHAKE_DONE\
|SF_SEND_ACK_FREQUENCY\
|SF_SEND_STOP_SENDING)
@ -7119,6 +7217,17 @@ ietf_full_conn_ci_drop_crypto_streams (struct lsquic_conn *lconn)
}
void
ietf_full_conn_ci_count_garbage (struct lsquic_conn *lconn, size_t garbage_sz)
{
struct ietf_full_conn *conn = (struct ietf_full_conn *) lconn;
conn->ifc_pub.bytes_in = garbage_sz;
LSQ_DEBUG("count %zd bytes of garbage, new value: %u bytes", garbage_sz,
conn->ifc_pub.bytes_in);
}
#define IETF_FULL_CONN_FUNCS \
.ci_abort = ietf_full_conn_ci_abort, \
.ci_abort_error = ietf_full_conn_ci_abort_error, \
@ -7127,6 +7236,7 @@ ietf_full_conn_ci_drop_crypto_streams (struct lsquic_conn *lconn)
.ci_cancel_pending_streams = ietf_full_conn_ci_cancel_pending_streams, \
.ci_client_call_on_new = ietf_full_conn_ci_client_call_on_new, \
.ci_close = ietf_full_conn_ci_close, \
.ci_count_garbage = ietf_full_conn_ci_count_garbage, \
.ci_destroy = ietf_full_conn_ci_destroy, \
.ci_drain_time = ietf_full_conn_ci_drain_time, \
.ci_drop_crypto_streams = ietf_full_conn_ci_drop_crypto_streams, \

View File

@ -4,7 +4,7 @@
/* Things specific to the IETF version of QUIC that do not fit anywhere else */
/* [draft-ietf-quic-transport-25] Section 22.4 */
/* [draft-ietf-quic-transport-28] Section 20 */
enum trans_error_code
{
TEC_NO_ERROR = 0x0,
@ -19,6 +19,7 @@ enum trans_error_code
TEC_CONNECTION_ID_LIMIT_ERROR = 0x9,
TEC_PROTOCOL_VIOLATION = 0xA,
TEC_INVALID_TOKEN = 0xB,
TEC_APPLICATION_ERROR = 0xC,
TEC_CRYPTO_BUFFER_EXCEEDED = 0xD,
};

View File

@ -248,8 +248,10 @@ lsquic_logger_lopt (const char *optarg);
#define CID_FMT ".*s"
#define CID_BITS(cid) 2 * (int) (cid)->len, \
(lsquic_cid2str(cid, cidbuf_), cidbuf_)
#define CID_BITS_B(cid, b) 2 * (int) (cid)->len, \
(lsquic_cid2str(cid, b), b)
#define CID_BITS(cid) CID_BITS_B(cid, cidbuf_)
void
lsquic_cid2str (const struct lsquic_cid *, char *out);

View File

@ -188,12 +188,12 @@ imico_maybe_process_params (struct ietf_mini_conn *conn)
{
conn->imc_flags |= IMC_HAVE_TP;
conn->imc_ack_exp = params->tp_ack_delay_exponent;
if (params->tp_set & (1 << TPI_MAX_PACKET_SIZE))
if (params->tp_set & (1 << TPI_MAX_UDP_PAYLOAD_SIZE))
{
if (params->tp_numerics[TPI_MAX_PACKET_SIZE]
if (params->tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE]
< conn->imc_path.np_pack_size)
conn->imc_path.np_pack_size =
params->tp_numerics[TPI_MAX_PACKET_SIZE];
params->tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE];
}
LSQ_DEBUG("read transport params, packet size is set to %hu bytes",
conn->imc_path.np_pack_size);
@ -493,6 +493,7 @@ lsquic_mini_conn_ietf_new (struct lsquic_engine_public *enpub,
conn->imc_conn.cn_cur_cce_idx = 1;
conn->imc_conn.cn_flags = LSCONN_MINI|LSCONN_IETF|LSCONN_SERVER;
conn->imc_conn.cn_version = version;
for (i = 0; i < N_ENC_LEVS; ++i)
{
@ -503,7 +504,7 @@ lsquic_mini_conn_ietf_new (struct lsquic_engine_public *enpub,
esfi = select_esf_iquic_by_ver(version);
enc_sess = esfi->esfi_create_server(enpub, &conn->imc_conn,
&packet_in->pi_dcid, conn->imc_stream_ps, &crypto_stream_if,
odcid);
&conn->imc_cces[0].cce_cid, &conn->imc_path.np_dcid);
if (!enc_sess)
{
lsquic_malo_put(conn);
@ -518,7 +519,6 @@ lsquic_mini_conn_ietf_new (struct lsquic_engine_public *enpub,
if (getenv("LSQUIC_CN_PACK_SIZE"))
conn->imc_path.np_pack_size = atoi(getenv("LSQUIC_CN_PACK_SIZE"));
#endif
conn->imc_conn.cn_version = version;
conn->imc_conn.cn_pf = select_pf_by_ver(version);
conn->imc_conn.cn_esf.i = esfi;
conn->imc_conn.cn_enc_session = enc_sess;
@ -1099,7 +1099,8 @@ imico_process_packet_frame (struct ietf_mini_conn *conn,
enc_level = lsquic_packet_in_enc_level(packet_in);
type = conn->imc_conn.cn_pf->pf_parse_frame_type(p, len);
if (lsquic_legal_frames_by_level[enc_level] & (1 << type))
if (lsquic_legal_frames_by_level[conn->imc_conn.cn_version][enc_level]
& (1 << type))
{
packet_in->pi_frame_types |= 1 << type;
return imico_process_frames[type](conn, packet_in, p, len);
@ -1193,6 +1194,17 @@ ietf_mini_conn_ci_packet_in (struct lsquic_conn *lconn,
enum dec_packin dec_packin;
enum packnum_space pns;
/* Update "bytes in" count as early as possible. From
* [draft-ietf-quic-transport-28] Section 8.1:
" For the purposes of
" avoiding amplification prior to address validation, servers MUST
" count all of the payload bytes received in datagrams that are
" uniquely attributed to a single connection. This includes datagrams
" that contain packets that are successfully processed and datagrams
" that contain packets that are all discarded.
*/
conn->imc_bytes_in += packet_in->pi_data_sz;
if (conn->imc_flags & IMC_ERROR)
{
LSQ_DEBUG("ignore incoming packet: connection is in error state");
@ -1216,7 +1228,6 @@ ietf_mini_conn_ci_packet_in (struct lsquic_conn *lconn,
}
EV_LOG_PACKET_IN(LSQUIC_LOG_CONN_ID, packet_in);
conn->imc_bytes_in += packet_in->pi_data_sz + IQUIC_TAG_LEN;
if (pns == PNS_APP)
{
@ -1580,7 +1591,7 @@ imico_generate_conn_close (struct ietf_mini_conn *conn)
else if (conn->imc_flags & IMC_BAD_TRANS_PARAMS)
{
is_app = 0;
error_code = TEC_NO_ERROR;
error_code = TEC_PROTOCOL_VIOLATION;
reason = "bad transport parameters";
rlen = 24;
}
@ -1607,7 +1618,7 @@ imico_generate_conn_close (struct ietf_mini_conn *conn)
}
/* [draft-ietf-quic-transport-23] Section 12.2:
/* [draft-ietf-quic-transport-28] Section 10.3.1:
*
" A client will always know whether the server has Handshake keys (see
" Section 17.2.2.1), but it is possible that a server does not know
@ -1615,7 +1626,25 @@ imico_generate_conn_close (struct ietf_mini_conn *conn)
" server SHOULD send a CONNECTION_CLOSE frame in both Handshake and
" Initial packets to ensure that at least one of them is processable by
" the client.
--- 8< ---
" Sending a CONNECTION_CLOSE of type 0x1d in an Initial or Handshake
" packet could expose application state or be used to alter application
" state. A CONNECTION_CLOSE of type 0x1d MUST be replaced by a
" CONNECTION_CLOSE of type 0x1c when sending the frame in Initial or
" Handshake packets. Otherwise, information about the application
" state might be revealed. Endpoints MUST clear the value of the
" Reason Phrase field and SHOULD use the APPLICATION_ERROR code when
" converting to a CONNECTION_CLOSE of type 0x1c.
*/
LSQ_DEBUG("sending CONNECTION_CLOSE, is_app: %d, error code: %u, "
"reason: %.*s", is_app, error_code, rlen, reason);
if (is_app && conn->imc_conn.cn_version > LSQVER_ID27)
{
LSQ_DEBUG("convert to 0x1C, replace code and reason");
is_app = 0;
error_code = TEC_APPLICATION_ERROR;
rlen = 0;
}
pns = (conn->imc_flags >> IMCBIT_PNS_BIT_SHIFT) & 3;
switch ((!!(conn->imc_flags & IMC_HSK_PACKET_SENT) << 1)
@ -1844,9 +1873,21 @@ ietf_mini_conn_ci_record_addrs (struct lsquic_conn *lconn, void *peer_ctx,
}
void
ietf_mini_conn_ci_count_garbage (struct lsquic_conn *lconn, size_t garbage_sz)
{
struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn;
conn->imc_bytes_in += garbage_sz;
LSQ_DEBUG("count %zd bytes of garbage, new value: %u bytes", garbage_sz,
conn->imc_bytes_in);
}
static const struct conn_iface mini_conn_ietf_iface = {
.ci_abort_error = ietf_mini_conn_ci_abort_error,
.ci_client_call_on_new = ietf_mini_conn_ci_client_call_on_new,
.ci_count_garbage = ietf_mini_conn_ci_count_garbage,
.ci_destroy = ietf_mini_conn_ci_destroy,
.ci_get_engine = ietf_mini_conn_ci_get_engine,
.ci_get_log_cid = ietf_mini_conn_ci_get_log_cid,

View File

@ -238,6 +238,6 @@ extern const char *const lsquic_pns2str[];
ALL_IQUIC_FRAMES & ~(QUIC_FTBIT_PADDING|QUIC_FTBIT_PATH_RESPONSE \
|QUIC_FTBIT_PATH_CHALLENGE|QUIC_FTBIT_ACK|QUIC_FTBIT_TIMESTAMP))
extern const enum quic_ft_bit lsquic_legal_frames_by_level[];
extern const enum quic_ft_bit lsquic_legal_frames_by_level[][4];
#endif

View File

@ -217,9 +217,38 @@ lsquic_cid_from_packet (const unsigned char *buf, size_t bufsz,
}
/* See [draft-ietf-quic-transport-25], Section 12.4 (Table 3) */
const enum quic_ft_bit lsquic_legal_frames_by_level[N_ENC_LEVS] =
/* See [draft-ietf-quic-transport-28], Section 12.4 (Table 3) */
const enum quic_ft_bit lsquic_legal_frames_by_level[N_LSQVER][N_ENC_LEVS] =
{
[LSQVER_ID28] = {
[ENC_LEV_CLEAR] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
| QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE,
[ENC_LEV_EARLY] = QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
| QUIC_FTBIT_STREAM | QUIC_FTBIT_RST_STREAM
| QUIC_FTBIT_BLOCKED | QUIC_FTBIT_CONNECTION_CLOSE
| QUIC_FTBIT_MAX_DATA | QUIC_FTBIT_MAX_STREAM_DATA
| QUIC_FTBIT_MAX_STREAMS | QUIC_FTBIT_STREAM_BLOCKED
| 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,
[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
| QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE
| QUIC_FTBIT_STREAM | QUIC_FTBIT_RST_STREAM
| QUIC_FTBIT_BLOCKED
| QUIC_FTBIT_MAX_DATA | QUIC_FTBIT_MAX_STREAM_DATA
| QUIC_FTBIT_MAX_STREAMS | QUIC_FTBIT_STREAM_BLOCKED
| 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_ACK_FREQUENCY
| QUIC_FTBIT_RETIRE_CONNECTION_ID | QUIC_FTBIT_NEW_TOKEN
| QUIC_FTBIT_TIMESTAMP
,
},
[LSQVER_ID27] = {
[ENC_LEV_CLEAR] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
| QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE,
[ENC_LEV_EARLY] = QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
@ -246,4 +275,5 @@ const enum quic_ft_bit lsquic_legal_frames_by_level[N_ENC_LEVS] =
| QUIC_FTBIT_RETIRE_CONNECTION_ID | QUIC_FTBIT_NEW_TOKEN
| QUIC_FTBIT_TIMESTAMP
,
},
};

View File

@ -355,7 +355,7 @@ lsquic_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_ID25;
version = LSQVER_ID27;
lsquic_scid_from_packet_in(packet_in, &scid);
return lsquic_prq_new_req_ext(prq, type, flags, version,

View File

@ -31,7 +31,7 @@
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define TOKGEN_VERSION 1
#define TOKGEN_VERSION 2
#define CRYPTER_KEY_SIZE 16
#define SRST_MAX_PRK_SIZE EVP_MAX_MD_SIZE
@ -65,6 +65,8 @@ struct crypter
};
struct token_generator
{
/* We encrypt different token types using different keys. */

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,7 @@ enum transport_param_id
* Numeric transport parameters that have default values:
*/
TPI_MAX_IDLE_TIMEOUT,
TPI_MAX_PACKET_SIZE,
TPI_MAX_UDP_PAYLOAD_SIZE,
TPI_INIT_MAX_DATA,
TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL,
TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE,
@ -45,7 +45,12 @@ enum transport_param_id
* Custom handlers:
*/
TPI_PREFERRED_ADDRESS,
TPI_ORIGINAL_CONNECTION_ID,
/* CIDs must be in a contiguous range for tp_cids array to work */
#define FIRST_TP_CID TPI_ORIGINAL_DEST_CID
TPI_ORIGINAL_DEST_CID,
TPI_INITIAL_SOURCE_CID,
#define LAST_TP_CID TPI_RETRY_SOURCE_CID
TPI_RETRY_SOURCE_CID,
#if LSQUIC_TEST_QUANTUM_READINESS
/* https://github.com/quicwg/base-drafts/wiki/Quantum-Readiness-test */
#define QUANTUM_READY_SZ 1200
@ -54,6 +59,8 @@ enum transport_param_id
TPI_STATELESS_RESET_TOKEN, LAST_TPI = TPI_STATELESS_RESET_TOKEN
};
#define TP_CID_IDX(tpi_) ((tpi_) - FIRST_TP_CID)
struct transport_params
{
@ -72,7 +79,7 @@ struct transport_params
#define tp_max_idle_timeout tp_numerics[TPI_MAX_IDLE_TIMEOUT]
#define tp_init_max_streams_bidi tp_numerics[TPI_INIT_MAX_STREAMS_BIDI]
#define tp_init_max_streams_uni tp_numerics[TPI_INIT_MAX_STREAMS_UNI]
#define tp_max_packet_size tp_numerics[TPI_MAX_PACKET_SIZE]
#define tp_max_udp_payload_size tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE]
#define tp_ack_delay_exponent tp_numerics[TPI_ACK_DELAY_EXPONENT]
#define tp_max_ack_delay tp_numerics[TPI_MAX_ACK_DELAY]
#define tp_active_connection_id_limit tp_numerics[TPI_ACTIVE_CONNECTION_ID_LIMIT]
@ -87,10 +94,20 @@ struct transport_params
lsquic_cid_t cid;
uint8_t srst[IQUIC_SRESET_TOKEN_SZ];
} tp_preferred_address;
lsquic_cid_t tp_original_cid;
lsquic_cid_t tp_cids[3];
#define tp_original_dest_cid tp_cids[TP_CID_IDX(TPI_ORIGINAL_DEST_CID)]
#define tp_initial_source_cid tp_cids[TP_CID_IDX(TPI_INITIAL_SOURCE_CID)]
#define tp_retry_source_cid tp_cids[TP_CID_IDX(TPI_RETRY_SOURCE_CID)]
};
#define TP_DEF_MAX_PACKET_SIZE 65527
#define MAX_TP_STR_SZ ((LAST_TPI + 1) * \
(34 /* longest entry in tt2str */ + 2 /* semicolon */ + 2 /* colon */) \
+ INET_ADDRSTRLEN + INET6_ADDRSTRLEN + 5 /* Port */ * 2 \
+ MAX_CID_LEN * 2 * 4 /* there are four CIDs */ \
+ 11 * (MAX_NUMERIC_TPI + 1) \
+ IQUIC_SRESET_TOKEN_SZ * 2 * 2 /* there are two reset tokens */)
#define TP_DEF_MAX_UDP_PAYLOAD_SIZE 65527
#define TP_DEF_ACK_DELAY_EXP 3
#define TP_DEF_INIT_MAX_STREAMS_UNI 0
#define TP_DEF_INIT_MAX_STREAMS_BIDI 0
@ -111,7 +128,7 @@ struct transport_params
.tp_active_connection_id_limit = TP_DEF_ACTIVE_CONNECTION_ID_LIMIT, \
.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_max_udp_payload_size = TP_DEF_MAX_UDP_PAYLOAD_SIZE, \
.tp_ack_delay_exponent = TP_DEF_ACK_DELAY_EXP, \
.tp_init_max_streams_bidi = TP_DEF_INIT_MAX_STREAMS_BIDI, \
.tp_init_max_streams_uni = TP_DEF_INIT_MAX_STREAMS_UNI, \
@ -135,16 +152,20 @@ lsquic_tp_decode (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);
int
lsquic_tp_encode_id25 (const struct transport_params *, int is_server,
lsquic_tp_encode_27 (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 *);
lsquic_tp_decode_27 (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);
lsquic_tp_to_str_27 (const struct transport_params *params, char *buf, size_t sz);
int
lsquic_tp_has_pref_ipv4 (const struct transport_params *);
@ -152,4 +173,6 @@ lsquic_tp_has_pref_ipv4 (const struct transport_params *);
int
lsquic_tp_has_pref_ipv6 (const struct transport_params *);
extern const char * const lsquic_tpi2str[LAST_TPI + 1];
#endif

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_ID25] = { 0xFF, 0, 0, 25, },
[LSQVER_ID27] = { 0xFF, 0, 0, 27, },
[LSQVER_ID28] = { 0xFF, 0, 0, 28, },
[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_ID25] = "FF000019",
[LSQVER_ID27] = "FF00001B",
[LSQVER_ID28] = "FF00001C",
[LSQVER_VERNEG] = "FAFAFAFA",
};

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_ID25);
pf = select_pf_by_ver(LSQVER_ID27);
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_ID25);
static const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_ID27);
static void

View File

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

View File

@ -59,7 +59,7 @@
#include "lsquic_hq.h"
#include "lsquic_data_in_if.h"
static const struct parse_funcs *g_pf = select_pf_by_ver(LSQVER_ID25);
static const struct parse_funcs *g_pf = select_pf_by_ver(LSQVER_ID27);
struct test_ctl_settings
{
@ -302,7 +302,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_ID25;
tobjs->lconn.cn_version = LSQVER_ID27;
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

@ -161,8 +161,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_ID25);
tobjs->lconn.cn_version = LSQVER_ID25;
tobjs->lconn.cn_pf = select_pf_by_ver(LSQVER_ID27);
tobjs->lconn.cn_version = LSQVER_ID27;
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_ID25 : LSQVER_043;
LSQVER_ID27 : 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_ID25,
LSQVER_ID27,
};
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_ID25);
g_pf = select_pf_by_ver(LSQVER_ID27);
main_test_packetization();
return 0;

View File

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

View File

@ -58,18 +58,20 @@ static const struct trapa_test tests[] =
| (1 << TPI_INIT_MAX_DATA)
| (1 << TPI_MAX_IDLE_TIMEOUT)
| (1 << TPI_MAX_ACK_DELAY)
| (1 << TPI_MAX_PACKET_SIZE)
| (1 << TPI_MAX_UDP_PAYLOAD_SIZE)
| (1 << TPI_ACK_DELAY_EXPONENT)
| (1 << TPI_INITIAL_SOURCE_CID)
| (1 << TPI_ACTIVE_CONNECTION_ID_LIMIT),
.tp_init_max_stream_data_bidi_local = 0x12348877,
.tp_init_max_data = 0xAABB,
.tp_max_packet_size = 1213,
.tp_max_udp_payload_size = 1213,
.tp_max_idle_timeout = 10 * 1000,
.tp_max_ack_delay = TP_DEF_MAX_ACK_DELAY,
.tp_active_connection_id_limit = 7,
.tp_initial_source_cid = { .len = 8, .u_cid.id = 0x0807060504030201ull, },
},
.is_server = 0,
.enc_len = 26,
.enc_len = 36,
.encoded =
/* Idle timeout */ "\x01\x02\x67\x10"
/* Packet size */ "\x03\x02\x44\xBD"
@ -77,6 +79,7 @@ static const struct trapa_test tests[] =
/* Bidi local */ "\x05\x04\x92\x34\x88\x77"
/* Ack delay exp */ "\x0A\x01\x00"
/* Active CID limit */ "\x0E\x01\x07"
/* Initial SCID */ "\x0F\x08\x01\x02\x03\x04\x05\x06\x07\x08"
/* 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"
},
@ -104,7 +107,7 @@ static const struct trapa_test tests[] =
TP_DEFAULT_VALUES,
.tp_init_max_data = 0x123456,
.tp_init_max_stream_data_bidi_local = 0xABCDEF88,
.tp_max_packet_size = 0x555,
.tp_max_udp_payload_size = 0x555,
},
.is_server = 1,
.addl_set = 1 << TPI_DISABLE_ACTIVE_MIGRATION,
@ -125,7 +128,7 @@ static const struct trapa_test tests[] =
.params = {
TP_DEFAULT_VALUES,
.tp_max_ack_delay = 25,
.tp_max_packet_size = 0x555,
.tp_max_udp_payload_size = 0x555,
.tp_preferred_address = {
.ipv4_addr = "\x01\x02\x03\x04",
.ipv4_port = 0x1234,
@ -172,8 +175,8 @@ params_are_equal (const struct transport_params *a,
&& a->tp_preferred_address.ipv4_port == b->tp_preferred_address.ipv4_port
&& a->tp_preferred_address.ipv6_port == b->tp_preferred_address.ipv6_port
&& a->tp_preferred_address.cid.len == b->tp_preferred_address.cid.len
&& MCMP(tp_original_cid.idbuf)
&& a->tp_original_cid.len == b->tp_original_cid.len
&& MCMP(tp_original_dest_cid.idbuf)
&& a->tp_original_dest_cid.len == b->tp_original_dest_cid.len
;
#undef MCMP
}