mirror of
https://gitea.invidious.io/iv-org/litespeed-quic.git
synced 2024-08-15 00:53:43 +00:00
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:
parent
fa4561dcea
commit
afe3d36359
24 changed files with 279 additions and 34 deletions
|
@ -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.
|
||||
|
|
|
@ -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()`.
|
||||
|
|
|
@ -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 ---------------------------------------------------
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
11
docs/internals.rst
Normal 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
|
1
docs/lsquic-engine-conns.drawio
Normal file
1
docs/lsquic-engine-conns.drawio
Normal 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>
|
BIN
docs/lsquic-engine-conns.png
Normal file
BIN
docs/lsquic-engine-conns.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 95 KiB |
|
@ -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().
|
||||
|
|
|
@ -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)(¶ms, 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
×tamp);
|
||||
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,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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[];
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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 *);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
,
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -38,6 +38,7 @@ enum transport_param_id
|
|||
/*
|
||||
* Empty transport parameters:
|
||||
*/
|
||||
TPI_TIMESTAMPS,
|
||||
TPI_DISABLE_ACTIVE_MIGRATION, MAX_EMPTY_TPI = TPI_DISABLE_ACTIVE_MIGRATION,
|
||||
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in a new issue