Release 2.12.0

- [FEATURE] QUIC timestamps extension.
- [API] New: ea_alpn that is used when not in HTTP mode.
- [BUGFIX] SNI is mandatory only for HTTP/3 and gQUIC.
- [BUGFIX] Benign double-free -- issue #110.
- [BUGFIX] Printing of transport parameters.
This commit is contained in:
Dmitri Tikhonov 2020-03-02 08:53:41 -05:00
parent fa4561dcea
commit afe3d36359
24 changed files with 279 additions and 34 deletions

View file

@ -1,3 +1,11 @@
2020-03-02
- 2.12.0
- [FEATURE] QUIC timestamps extension.
- [API] New: ea_alpn that is used when not in HTTP mode.
- [BUGFIX] SNI is mandatory only for HTTP/3 and gQUIC.
- [BUGFIX] Benign double-free -- issue #110.
- [BUGFIX] Printing of transport parameters.
2020-02-24
- 2.11.1
- [FEATURE] QUIC and HTTP/3 Internet Draft 27 support.

View file

@ -239,7 +239,7 @@ optional members.
.. member:: struct ssl_ctx_st * (*ea_get_ssl_ctx)(void *peer_ctx)
Get SSL_CTX associated with a peer context. Mandatory in server
mode.
mode. This is use for default values for SSL instantiation.
.. member:: const struct lsquic_hset_if *ea_hsi_if
.. member:: void *ea_hsi_ctx
@ -268,6 +268,8 @@ optional members.
In a multi-process setup, it may be useful to observe the CID
lifecycle. This optional set of callbacks makes it possible.
.. _apiref-engine-settings:
Engine Settings
---------------
@ -348,7 +350,7 @@ settings structure:
.. member:: unsigned es_max_header_list_size
This corresponds to SETTINGS_MAX_HEADER_LIST_SIZE
(RFC 7540, Section 6.5.2). 0 means no limit. Defaults
(:rfc:`7540#section-6.5.2`). 0 means no limit. Defaults
to :func:`LSQUIC_DF_MAX_HEADER_LIST_SIZE`.
.. member:: const char *es_ua
@ -685,6 +687,12 @@ settings structure:
Default value is :macro:`LSQUIC_DF_DELAYED_ACKS`
.. member:: int es_timestamps
Enable timestamps extension. Allowed values are 0 and 1.
Default value is @ref LSQUIC_DF_TIMESTAMPS
To initialize the settings structure to library defaults, use the following
convenience function:
@ -940,7 +948,7 @@ that the library uses to send packets.
.. member:: int ecn
ECN: Valid values are 0 - 3. See RFC 3168.
ECN: Valid values are 0 - 3. See :rfc:`3168`.
ECN may be set by IETF QUIC connections if ``es_ecn`` is set.
@ -1465,7 +1473,7 @@ fields yourself. In that case, the header set must be "read" from the stream vi
Get header set associated with the stream. The header set is created by
``hsi_create_header_set()`` callback. After this call, the ownership of
the header set is trasnferred to the caller.
the header set is transferred to the caller.
This call must precede calls to :func:`lsquic_stream_read()`,
:func:`lsquic_stream_readv()`, and :func:`lsquic_stream_readf()`.

View file

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

View file

@ -1,2 +1,71 @@
Getting Started with LSQUIC
===========================
Getting Started
===============
Supported Platforms
-------------------
LSQUIC compiles and runs on Linux, FreeBSD, and Mac OS. It has been
tested on i386, x86_64, as well as Raspberry Pi.
Windows support is on the TODO list.
Dependencies
------------
LSQUIC library uses:
- zlib_;
- BoringSSL_; and
- `ls-qpack`_ (as a Git submodule).
The accompanying demo command-line tools use libevent_.
What's in the box
-----------------
- ``src/liblsquic`` -- the library
- ``test`` -- demo client and server programs
- ``test/unittests`` -- unit tests
Building
--------
To build the library, follow instructions in the README_ file.
Demo Examples
-------------
Fetch Google home page:
::
./http_client -s www.google.com -p / -o version=Q050
Run your own server (it does not touch the filesystem, don't worry):
::
./http_server -c www.example.com,fullchain.pem,privkey.pem -s 0.0.0.0:4433
Grab a page from your server:
::
./http_client -H www.example.com -s 127.0.0.1:4433 -p /
You can play with various options, of which there are many. Use
the ``-h`` command-line flag to see them.
Next steps
----------
If you want to use LSQUIC in your program, check out the :doc:`tutorial` and
the :doc:`apiref`.
:doc:`internals` covers some library internals.
.. _zlib: https://www.zlib.net/
.. _BoringSSL: https://boringssl.googlesource.com/boringssl/
.. _`ls-qpack`: https://github.com/litespeedtech/ls-qpack
.. _libevent: https://libevent.org/
.. _README: https://github.com/litespeedtech/lsquic/blob/master/README.md

View file

@ -3,9 +3,6 @@ LSQUIC Documentation
This is the documentation for LSQUIC_ |release|, last updated |today|.
Introduction
------------
LiteSpeed QUIC (LSQUIC) Library is an open-source implementation of QUIC
and HTTP/3 functionality for servers and clients. LSQUIC is:
@ -38,7 +35,9 @@ Contents
:maxdepth: 2
gettingstarted
tutorial
apiref
internals
Indices and tables
==================

11
docs/internals.rst Normal file
View file

@ -0,0 +1,11 @@
*********
Internals
*********
Connection Management
=====================
References to connections can exist in six different places in an
engine.
.. image:: lsquic-engine-conns.png

View file

@ -0,0 +1 @@
<mxfile host="www.draw.io" modified="2020-02-21T20:56:15.366Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0" etag="X7KTg7RjNxutHAnzRWEE" version="12.7.3"><diagram id="g-XUBOnqw-Le0S7dI5B8" name="Page-1">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</diagram></mxfile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

View file

@ -24,8 +24,8 @@ extern "C" {
#endif
#define LSQUIC_MAJOR_VERSION 2
#define LSQUIC_MINOR_VERSION 11
#define LSQUIC_PATCH_VERSION 1
#define LSQUIC_MINOR_VERSION 12
#define LSQUIC_PATCH_VERSION 0
/**
* Engine flags:
@ -205,6 +205,9 @@ struct ssl_st;
* constructor.
*/
/* `sni' may be NULL if engine is not HTTP mode and client TLS transport
* parameters did not include the SNI.
*/
typedef struct ssl_ctx_st * (*lsquic_lookup_cert_f)(
void *lsquic_cert_lookup_ctx, const struct sockaddr *local, const char *sni);
@ -330,6 +333,9 @@ typedef struct ssl_ctx_st * (*lsquic_lookup_cert_f)(
/** Turn off delayed ACKs extension by default */
#define LSQUIC_DF_DELAYED_ACKS 0
/** Turn on timestamp extension by default */
#define LSQUIC_DF_TIMESTAMPS 1
/* 1: Cubic; 2: BBR */
#define LSQUIC_DF_CC_ALGO 1
@ -724,6 +730,13 @@ struct lsquic_engine_settings {
* Default value is @ref LSQUIC_DF_DELAYED_ACKS
*/
int es_delayed_acks;
/**
* Enable timestamps extension. Allowed values are 0 and 1.
*
* Default value is @ref LSQUIC_DF_TIMESTAMPS
*/
int es_timestamps;
};
/* Initialize `settings' to default values */
@ -1312,7 +1325,7 @@ lsquic_stream_send_headers (lsquic_stream_t *s,
/**
* Get header set associated with the stream. The header set is created by
* @ref hsi_create_header_set() callback. After this call, the ownership of
* the header set is trasnferred to the caller.
* the header set is transferred to the caller.
*
* This call must precede calls to @ref lsquic_stream_read() and
* @ref lsquic_stream_readv().

View file

@ -558,6 +558,8 @@ gen_trans_params (struct enc_sess_iquic *enc_sess, unsigned char *buf,
params.tp_numerics[TPI_MIN_ACK_DELAY] = 10000; /* TODO: make into a constant? make configurable? */
params.tp_set |= 1 << TPI_MIN_ACK_DELAY;
}
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);
@ -1035,8 +1037,10 @@ iquic_lookup_cert (SSL *ssl, void *arg)
#endif
if (!server_name)
{
LSQ_DEBUG("cert lookup: server name is not set, skip");
return 1;
LSQ_DEBUG("cert lookup: server name is not set");
/* SNI is required in HTTP/3 */
if (enc_sess->esi_enpub->enp_flags & ENPUB_HTTP)
return 1;
}
path = enc_sess->esi_conn->cn_if->ci_get_path(enc_sess->esi_conn, NULL);
@ -1049,7 +1053,8 @@ iquic_lookup_cert (SSL *ssl, void *arg)
{
if (SSL_set_SSL_CTX(enc_sess->esi_ssl, ssl_ctx))
{
LSQ_DEBUG("looked up cert for %s", server_name);
LSQ_DEBUG("looked up cert for %s", server_name
? server_name : "<no SNI>");
if (enc_sess->esi_enpub->enp_kli)
SSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback);
SSL_set_verify(enc_sess->esi_ssl,
@ -1070,7 +1075,8 @@ iquic_lookup_cert (SSL *ssl, void *arg)
}
else
{
LSQ_DEBUG("could not look up cert for %s", server_name);
LSQ_DEBUG("could not look up cert for %s", server_name
? server_name : "<no SNI>");
return 0;
}
}

View file

@ -335,6 +335,7 @@ lsquic_engine_init_settings (struct lsquic_engine_settings *settings,
settings->es_ql_bits = LSQUIC_DF_QL_BITS;
settings->es_spin = LSQUIC_DF_SPIN;
settings->es_delayed_acks = LSQUIC_DF_DELAYED_ACKS;
settings->es_timestamps = LSQUIC_DF_TIMESTAMPS;
}
@ -1636,7 +1637,7 @@ remove_conn_from_hash (lsquic_engine_t *engine, lsquic_conn_t *conn)
static void
refflags2str (enum lsquic_conn_flags flags, char s[6])
refflags2str (enum lsquic_conn_flags flags, char s[7])
{
*s = 'C'; s += !!(flags & LSCONN_CLOSING);
*s = 'H'; s += !!(flags & LSCONN_HASHED);

View file

@ -133,6 +133,7 @@ enum ifull_conn_flags
IFC_MIGRA = 1 << 27,
IFC_SPIN = 1 << 28, /* Spin bits are enabled */
IFC_DELAYED_ACKS = 1 << 29, /* Delayed ACKs are enabled */
IFC_TIMESTAMPS = 1 << 30, /* Timestamps are enabled */
};
@ -334,6 +335,7 @@ struct ietf_full_conn
struct transport_params ifc_peer_param;
STAILQ_HEAD(, stream_id_to_ss)
ifc_stream_ids_to_ss;
lsquic_time_t ifc_created;
lsquic_time_t ifc_saved_ack_received;
lsquic_packno_t ifc_max_ack_packno[N_PNS];
lsquic_packno_t ifc_max_non_probing;
@ -1215,6 +1217,7 @@ lsquic_ietf_full_conn_client_new (struct lsquic_engine_public *enpub,
LSQ_DEBUG("negotiating version %s",
lsquic_ver2str[conn->ifc_u.cli.ifcli_ver_neg.vn_ver]);
conn->ifc_process_incoming_packet = process_incoming_packet_verneg;
conn->ifc_created = now;
LSQ_DEBUG("logging using %s SCID",
LSQUIC_LOG_CONN_ID == CN_SCID(&conn->ifc_conn) ? "client" : "server");
return &conn->ifc_conn;
@ -1431,6 +1434,7 @@ lsquic_ietf_full_conn_server_new (struct lsquic_engine_public *enpub,
if (0 != handshake_ok(&conn->ifc_conn))
goto err3;
conn->ifc_created = imc->imc_created;
if (conn->ifc_idle_to)
lsquic_alarmset_set(&conn->ifc_alset, AL_IDLE,
imc->imc_created + conn->ifc_idle_to);
@ -1506,6 +1510,33 @@ ietf_full_conn_ci_cancel_pending_streams (struct lsquic_conn *lconn, unsigned n)
}
/* Best effort. If timestamp frame does not fit, oh well */
static void
generate_timestamp_frame (struct ietf_full_conn *conn,
struct lsquic_packet_out *packet_out, lsquic_time_t now)
{
uint64_t timestamp;
int w;
timestamp = (now - conn->ifc_created) >> TP_DEF_ACK_DELAY_EXP;
w = conn->ifc_conn.cn_pf->pf_gen_timestamp_frame(
packet_out->po_data + packet_out->po_data_sz,
lsquic_packet_out_avail(packet_out), timestamp);
if (w < 0)
{
LSQ_DEBUG("could not generate TIMESTAMP frame");
return;
}
LSQ_DEBUG("generated TIMESTAMP(%"PRIu64" us) frame",
timestamp << TP_DEF_ACK_DELAY_EXP);
EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "generated TIMESTAMP(%"
PRIu64" us) frame", timestamp << TP_DEF_ACK_DELAY_EXP);
packet_out->po_frame_types |= 1 << QUIC_FRAME_TIMESTAMP;
lsquic_send_ctl_incr_pack_sz(&conn->ifc_send_ctl, packet_out, w);
packet_out->po_regen_sz += w;
}
static int
generate_ack_frame_for_pns (struct ietf_full_conn *conn,
struct lsquic_packet_out *packet_out, enum packnum_space pns,
@ -1561,6 +1592,9 @@ generate_ack_frame_for_pns (struct ietf_full_conn *conn,
lsquic_send_ctl_sanity_check(&conn->ifc_send_ctl);
LSQ_DEBUG("%s ACK state reset", lsquic_pns2str[pns]);
if (pns == PNS_APP && (conn->ifc_flags & IFC_TIMESTAMPS))
generate_timestamp_frame(conn, packet_out, now);
return 0;
}
@ -3013,6 +3047,12 @@ handshake_ok (struct lsquic_conn *lconn)
LSQ_DEBUG("delayed ACKs enabled");
conn->ifc_flags |= IFC_DELAYED_ACKS;
}
if (conn->ifc_settings->es_timestamps
&& (params->tp_set & (1 << TPI_TIMESTAMPS)))
{
LSQ_DEBUG("timestamps enabled");
conn->ifc_flags |= IFC_TIMESTAMPS;
}
conn->ifc_max_peer_ack_usec = params->tp_max_ack_delay * 1000;
@ -5583,6 +5623,36 @@ process_ack_frequency_frame (struct ietf_full_conn *conn,
}
static unsigned
process_timestamp_frame (struct ietf_full_conn *conn,
struct lsquic_packet_in *packet_in, const unsigned char *p, size_t len)
{
uint64_t timestamp;
int parsed_len;
if (!(conn->ifc_flags & IFC_TIMESTAMPS))
{
ABORT_QUIETLY(0, TEC_PROTOCOL_VIOLATION,
"Received unexpected TIMESTAMP frame (not negotiated)");
return 0;
}
parsed_len = conn->ifc_conn.cn_pf->pf_parse_timestamp_frame(p, len,
&timestamp);
if (parsed_len < 0)
return 0;
timestamp <<= conn->ifc_cfg.ack_exp;
EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "TIMESTAMP(%"PRIu64" us)", timestamp);
LSQ_DEBUG("TIMESTAMP(%"PRIu64" us) (%"PRIu64" << %"PRIu8")", timestamp,
timestamp >> conn->ifc_cfg.ack_exp, conn->ifc_cfg.ack_exp);
/* We don't do anything with the timestamp */
return parsed_len;
}
typedef unsigned (*process_frame_f)(
struct ietf_full_conn *, struct lsquic_packet_in *,
const unsigned char *p, size_t);
@ -5611,6 +5681,7 @@ static process_frame_f const process_frames[N_QUIC_FRAMES] =
[QUIC_FRAME_CRYPTO] = process_crypto_frame,
[QUIC_FRAME_HANDSHAKE_DONE] = process_handshake_done_frame,
[QUIC_FRAME_ACK_FREQUENCY] = process_ack_frequency_frame,
[QUIC_FRAME_TIMESTAMP] = process_timestamp_frame,
};

View file

@ -1049,6 +1049,8 @@ static unsigned (*const imico_process_frames[N_QUIC_FRAMES])
/* STREAM frame can only come in the App PNS and we delay those packets: */
[QUIC_FRAME_STREAM] = imico_process_invalid_frame,
[QUIC_FRAME_HANDSHAKE_DONE] = imico_process_invalid_frame,
[QUIC_FRAME_ACK_FREQUENCY] = imico_process_invalid_frame,
[QUIC_FRAME_TIMESTAMP] = imico_process_invalid_frame,
};

View file

@ -384,8 +384,6 @@ lsquic_mm_put_packet_out (struct lsquic_mm *mm,
poolst_freed(&mm->packet_out_bstats[idx]);
if (poolst_has_new_sample(&mm->packet_out_bstats[idx]))
maybe_shrink_packet_out_bufs(mm, idx);
if (packet_out->po_bwp_state)
lsquic_malo_put(packet_out->po_bwp_state);
#else
free(packet_out->po_data);
#endif

View file

@ -35,6 +35,7 @@ enum quic_frame_type
QUIC_FRAME_NEW_TOKEN, /* I */
QUIC_FRAME_HANDSHAKE_DONE, /* I */
QUIC_FRAME_ACK_FREQUENCY, /* I */
QUIC_FRAME_TIMESTAMP, /* I */
N_QUIC_FRAMES
};
@ -64,6 +65,7 @@ enum quic_ft_bit {
QUIC_FTBIT_RETIRE_CONNECTION_ID = 1 << QUIC_FRAME_RETIRE_CONNECTION_ID,
QUIC_FTBIT_HANDSHAKE_DONE = 1 << QUIC_FRAME_HANDSHAKE_DONE,
QUIC_FTBIT_ACK_FREQUENCY = 1 << QUIC_FRAME_ACK_FREQUENCY,
QUIC_FTBIT_TIMESTAMP = 1 << QUIC_FRAME_TIMESTAMP,
};
static const char * const frame_type_2_str[N_QUIC_FRAMES] = {
@ -92,6 +94,7 @@ static const char * const frame_type_2_str[N_QUIC_FRAMES] = {
[QUIC_FRAME_RETIRE_CONNECTION_ID] = "QUIC_FRAME_RETIRE_CONNECTION_ID",
[QUIC_FRAME_HANDSHAKE_DONE] = "QUIC_FRAME_HANDSHAKE_DONE",
[QUIC_FRAME_ACK_FREQUENCY] = "QUIC_FRAME_ACK_FREQUENCY",
[QUIC_FRAME_TIMESTAMP] = "QUIC_FRAME_TIMESTAMP",
};
#define QUIC_FRAME_PRELEN (sizeof("QUIC_FRAME_"))
@ -128,6 +131,7 @@ static const char * const frame_type_2_str[N_QUIC_FRAMES] = {
QUIC_FRAME_SLEN(QUIC_FRAME_NEW_TOKEN) + 1 + \
QUIC_FRAME_SLEN(QUIC_FRAME_HANDSHAKE_DONE) + 1 + \
QUIC_FRAME_SLEN(QUIC_FRAME_ACK_FREQUENCY) + 1 + \
QUIC_FRAME_SLEN(QUIC_FRAME_TIMESTAMP) + 1 + \
0
@ -217,6 +221,7 @@ extern const char *const lsquic_pns2str[];
| QUIC_FTBIT_NEW_TOKEN \
| QUIC_FTBIT_HANDSHAKE_DONE \
| QUIC_FTBIT_ACK_FREQUENCY \
| QUIC_FTBIT_TIMESTAMP \
| QUIC_FTBIT_CRYPTO )
/* [draft-ietf-quic-transport-24] Section 1.2 */
@ -231,7 +236,7 @@ extern const char *const lsquic_pns2str[];
*/
#define IQUIC_FRAME_RETX_MASK ( \
ALL_IQUIC_FRAMES & ~(QUIC_FTBIT_PADDING|QUIC_FTBIT_PATH_RESPONSE \
|QUIC_FTBIT_PATH_CHALLENGE|QUIC_FTBIT_ACK))
|QUIC_FTBIT_PATH_CHALLENGE|QUIC_FTBIT_ACK|QUIC_FTBIT_TIMESTAMP))
extern const enum quic_ft_bit lsquic_legal_frames_by_level[];

View file

@ -18,7 +18,7 @@ enum PACKET_PUBLIC_FLAGS
#define GQUIC_FRAME_REGEN_MASK ((1 << QUIC_FRAME_ACK) \
| (1 << QUIC_FRAME_PATH_CHALLENGE) | (1 << QUIC_FRAME_PATH_RESPONSE) \
| (1 << QUIC_FRAME_STOP_WAITING))
| (1 << QUIC_FRAME_STOP_WAITING) | (1 << QUIC_FRAME_TIMESTAMP))
#define GQUIC_FRAME_REGENERATE(frame_type) ((1 << (frame_type)) & GQUIC_FRAME_REGEN_MASK)

View file

@ -310,6 +310,10 @@ struct parse_funcs
unsigned
(*pf_ack_frequency_frame_size) (uint64_t seqno, uint64_t pack_tol,
uint64_t upd_mad);
int
(*pf_gen_timestamp_frame) (unsigned char *buf, size_t buf_len, uint64_t);
int
(*pf_parse_timestamp_frame) (const unsigned char *buf, size_t, uint64_t *);
};

View file

@ -243,5 +243,7 @@ const enum quic_ft_bit lsquic_legal_frames_by_level[N_ENC_LEVS] =
| 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_RETIRE_CONNECTION_ID | QUIC_FTBIT_NEW_TOKEN
| QUIC_FTBIT_TIMESTAMP
,
};

View file

@ -46,6 +46,9 @@
#define CHECK_SPACE(need, pstart, pend) \
do { if ((intptr_t) (need) > ((pend) - (pstart))) { return -1; } } while (0)
#define FRAME_TYPE_ACK_FREQUENCY 0xAF
#define FRAME_TYPE_TIMESTAMP 0x2F5
static int
ietf_v1_gen_one_varint (unsigned char *, size_t, unsigned char, uint64_t);
@ -1109,7 +1112,8 @@ ietf_v1_parse_frame_type (const unsigned char *buf, size_t len)
if (s > 0 && (unsigned) s == (1u << vint_val2bits(val)))
switch (val)
{
case 0xAF: return QUIC_FRAME_ACK_FREQUENCY;
case FRAME_TYPE_ACK_FREQUENCY: return QUIC_FRAME_ACK_FREQUENCY;
case FRAME_TYPE_TIMESTAMP: return QUIC_FRAME_TIMESTAMP;
default: break;
}
@ -2059,7 +2063,7 @@ ietf_v1_gen_ack_frequency_frame (unsigned char *buf, size_t buf_len,
uint64_t seqno, uint64_t pack_tol, uint64_t upd_mad)
{
return ietf_v1_gen_frame_with_varints(buf, buf_len, 4,
(uint64_t[]){ 0xAF, seqno, pack_tol, upd_mad });
(uint64_t[]){ FRAME_TYPE_ACK_FREQUENCY, seqno, pack_tol, upd_mad });
}
@ -2068,7 +2072,8 @@ ietf_v1_parse_ack_frequency_frame (const unsigned char *buf, size_t buf_len,
uint64_t *seqno, uint64_t *pack_tol, uint64_t *upd_mad)
{
return ietf_v1_parse_frame_with_varints(buf, buf_len,
0xAF, 3, (uint64_t *[]) { seqno, pack_tol, upd_mad });
FRAME_TYPE_ACK_FREQUENCY,
3, (uint64_t *[]) { seqno, pack_tol, upd_mad });
}
@ -2077,7 +2082,7 @@ ietf_v1_ack_frequency_frame_size (uint64_t seqno, uint64_t pack_tol,
uint64_t upd_mad)
{
return ietf_v1_frame_with_varints_size(4,
(uint64_t[]){ 0xAF, seqno, pack_tol, upd_mad });
(uint64_t[]){ FRAME_TYPE_ACK_FREQUENCY, seqno, pack_tol, upd_mad });
}
@ -2088,6 +2093,24 @@ ietf_v1_handshake_done_frame_size (void)
}
static int
ietf_v1_gen_timestamp_frame (unsigned char *buf, size_t buf_len,
uint64_t timestamp)
{
return ietf_v1_gen_frame_with_varints(buf, buf_len, 2,
(uint64_t[]){ FRAME_TYPE_TIMESTAMP, timestamp });
}
static int
ietf_v1_parse_timestamp_frame (const unsigned char *buf, size_t buf_len,
uint64_t *timestamp)
{
return ietf_v1_parse_frame_with_varints(buf, buf_len,
FRAME_TYPE_TIMESTAMP, 1, (uint64_t *[]) { timestamp });
}
const struct parse_funcs lsquic_parse_funcs_ietf_v1 =
{
.pf_gen_reg_pkt_header = ietf_v1_gen_reg_pkt_header,
@ -2156,4 +2179,6 @@ const struct parse_funcs lsquic_parse_funcs_ietf_v1 =
.pf_gen_ack_frequency_frame = ietf_v1_gen_ack_frequency_frame,
.pf_parse_ack_frequency_frame = ietf_v1_parse_ack_frequency_frame,
.pf_ack_frequency_frame_size = ietf_v1_ack_frequency_frame_size,
.pf_gen_timestamp_frame = ietf_v1_gen_timestamp_frame,
.pf_parse_timestamp_frame = ietf_v1_parse_timestamp_frame,
};

View file

@ -52,6 +52,7 @@ tpi_val_2_enum (uint64_t tpi_val)
#endif
case 0x1057: return TPI_LOSS_BITS;
case 0xDE1A: return TPI_MIN_ACK_DELAY;
case 0x7157: return TPI_TIMESTAMPS;
default: return INT_MAX;
}
}
@ -79,6 +80,7 @@ static const unsigned enum_2_tpi_val[LAST_TPI + 1] =
#endif
[TPI_LOSS_BITS] = 0x1057,
[TPI_MIN_ACK_DELAY] = 0xDE1A,
[TPI_TIMESTAMPS] = 0x7157,
};
@ -104,6 +106,7 @@ static const char * const tpi2str[LAST_TPI + 1] =
#endif
[TPI_LOSS_BITS] = "loss_bits",
[TPI_MIN_ACK_DELAY] = "min_ack_delay",
[TPI_TIMESTAMPS] = "timestamps",
};
@ -378,6 +381,7 @@ lsquic_tp_encode (const struct transport_params *params, int is_server,
sizeof(params->tp_preferred_address.srst));
break;
case TPI_DISABLE_ACTIVE_MIGRATION:
case TPI_TIMESTAMPS:
*p++ = 0;
break;
#if LSQUIC_TEST_QUANTUM_READINESS
@ -500,6 +504,7 @@ lsquic_tp_decode (const unsigned char *const buf, size_t bufsz,
}
break;
case TPI_DISABLE_ACTIVE_MIGRATION:
case TPI_TIMESTAMPS:
EXPECT_LEN(0);
break;
case TPI_STATELESS_RESET_TOKEN:
@ -615,7 +620,7 @@ lsquic_tp_to_str (const struct transport_params *params, char *buf, size_t sz)
return;
}
for (; tpi <= MAX_EMPTY_TPI; ++tpi)
if (params->tp_set & (1 << TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL))
if (params->tp_set & (1 << tpi))
{
nw = snprintf(buf, end - buf, "%.*s%s",
(buf + sz > end) << 1, "; ", tpi2str[tpi]);
@ -825,6 +830,7 @@ lsquic_tp_encode_id25 (const struct transport_params *params, int is_server,
sizeof(params->tp_preferred_address.srst));
break;
case TPI_DISABLE_ACTIVE_MIGRATION:
case TPI_TIMESTAMPS:
WRITE_UINT_TO_P(0, 16);
break;
#if LSQUIC_TEST_QUANTUM_READINESS
@ -948,6 +954,7 @@ lsquic_tp_decode_id25 (const unsigned char *const buf, size_t bufsz,
}
break;
case TPI_DISABLE_ACTIVE_MIGRATION:
case TPI_TIMESTAMPS:
EXPECT_LEN(0);
break;
case TPI_STATELESS_RESET_TOKEN:

View file

@ -38,6 +38,7 @@ enum transport_param_id
/*
* Empty transport parameters:
*/
TPI_TIMESTAMPS,
TPI_DISABLE_ACTIVE_MIGRATION, MAX_EMPTY_TPI = TPI_DISABLE_ACTIVE_MIGRATION,
/*

View file

@ -371,7 +371,10 @@ prog_connect (struct prog *prog, unsigned char *zero_rtt, size_t zero_rtt_len)
if (NULL == lsquic_engine_connect(prog->prog_engine, N_LSQVER,
(struct sockaddr *) &sport->sp_local_addr,
(struct sockaddr *) &sport->sas, sport, NULL,
prog->prog_hostname ? prog->prog_hostname : sport->host,
prog->prog_hostname ? prog->prog_hostname
/* SNI is required for HTTP */
: prog->prog_engine_flags & LSENG_HTTP ? sport->host
: NULL,
prog->prog_max_packet_size, zero_rtt, zero_rtt_len,
sport->sp_token_buf, sport->sp_token_sz))
return -1;

View file

@ -134,21 +134,27 @@ struct ssl_ctx_st *
lookup_cert (void *cert_lu_ctx, const struct sockaddr *sa_UNUSED,
const char *sni)
{
struct lsquic_hash_elem *el;
struct server_cert *server_cert;
if (!cert_lu_ctx)
return NULL;
if (!sni)
if (sni)
el = lsquic_hash_find(cert_lu_ctx, sni, strlen(sni));
else
{
LSQ_INFO("SNI is not set");
return NULL;
el = lsquic_hash_first(cert_lu_ctx);
}
struct lsquic_hash_elem *el = lsquic_hash_find(cert_lu_ctx, sni, strlen(sni));
struct server_cert *server_cert = NULL;
if (el)
{
server_cert = lsquic_hashelem_getdata(el);
if (server_cert)
return server_cert->ce_ssl_ctx;
}
return NULL;
}

View file

@ -1802,6 +1802,11 @@ set_engine_option (struct lsquic_engine_settings *settings,
settings->es_honor_prst = atoi(val);
return 0;
}
if (0 == strncmp(name, "timestamps", 10))
{
settings->es_timestamps = atoi(val);
return 0;
}
break;
case 11:
if (0 == strncmp(name, "ping_period", 11))