Release 2.18.0
- [API] Rename "0-RTT" to "session resumption." In IETF QUIC, "0-RTT" always refers to early data, meaning a request that the server can reply to in the very first return flight. A more appropriate name for what we support on the client site is "session resumption," which is standard TLS terminology. Later, when we add support for 0-RTT (early data), we can use the 0-RTT terminology again, this time in proper context. - [BUGFIX] Do not set certificate callback if ea_lookup_cert is NULL. - [BUGFIX] Make connection tickable when it's marked as closed. - [BUGFIX] Fail certificate lookup if SNI is not present in HTTP mode. - Several documentation fixes and improvements. - Minor code cleanup.
This commit is contained in:
parent
da99665b1c
commit
7483dee074
15
CHANGELOG
15
CHANGELOG
|
@ -1,3 +1,18 @@
|
|||
2020-07-06
|
||||
- 2.18.0
|
||||
- [API] Rename "0-RTT" to "session resumption." In IETF QUIC, "0-RTT"
|
||||
always refers to early data, meaning a request that the server can
|
||||
reply to in the very first return flight. A more appropriate name
|
||||
for what we support on the client site is "session resumption," which
|
||||
is standard TLS terminology. Later, when we add support for 0-RTT
|
||||
(early data), we can use the 0-RTT terminology again, this time in
|
||||
proper context.
|
||||
- [BUGFIX] Do not set certificate callback if ea_lookup_cert is NULL.
|
||||
- [BUGFIX] Make connection tickable when it's marked as closed.
|
||||
- [BUGFIX] Fail certificate lookup if SNI is not present in HTTP mode.
|
||||
- Several documentation fixes and improvements.
|
||||
- Minor code cleanup.
|
||||
|
||||
2020-06-24
|
||||
- 2.17.2
|
||||
- [BUGFIX] Infinite loop in stream: advance read offset when discarding
|
||||
|
|
|
@ -15,7 +15,7 @@ and OpenLiteSpeed. We think it is free of major problems. Nevertheless, do
|
|||
not hesitate to report bugs back to us. Even better, send us fixes and
|
||||
improvements!
|
||||
|
||||
Currently supported QUIC versions are Q043, Q046, Q050, ID-27, and ID-28.
|
||||
Currently supported QUIC versions are Q043, Q046, Q050, ID-27, ID-28, and ID-29.
|
||||
Support for newer versions will be added soon after they are released.
|
||||
|
||||
Documentation
|
||||
|
|
|
@ -187,10 +187,10 @@ struct http_client_ctx {
|
|||
unsigned hcc_reset_after_nbytes;
|
||||
unsigned hcc_retire_cid_after_nbytes;
|
||||
|
||||
char *hcc_zero_rtt_file_name;
|
||||
char *hcc_sess_resume_file_name;
|
||||
|
||||
enum {
|
||||
HCC_SKIP_0RTT = (1 << 0),
|
||||
HCC_SKIP_SESS_RESUME = (1 << 0),
|
||||
HCC_SEEN_FIN = (1 << 1),
|
||||
HCC_ABORT_ON_INCOMPLETE = (1 << 2),
|
||||
} hcc_flags;
|
||||
|
@ -212,7 +212,7 @@ struct lsquic_conn_ctx {
|
|||
* never exceed hcc_cc_reqs_per_conn in client_ctx.
|
||||
*/
|
||||
enum {
|
||||
CH_ZERO_RTT_SAVED = 1 << 0,
|
||||
CH_SESSION_RESUME_SAVED = 1 << 0,
|
||||
} ch_flags;
|
||||
};
|
||||
|
||||
|
@ -240,31 +240,31 @@ create_connections (struct http_client_ctx *client_ctx)
|
|||
{
|
||||
size_t len;
|
||||
FILE *file;
|
||||
unsigned char zero_rtt[0x2000];
|
||||
unsigned char sess_resume[0x2000];
|
||||
|
||||
if (0 == (client_ctx->hcc_flags & HCC_SKIP_0RTT)
|
||||
&& client_ctx->hcc_zero_rtt_file_name)
|
||||
if (0 == (client_ctx->hcc_flags & HCC_SKIP_SESS_RESUME)
|
||||
&& client_ctx->hcc_sess_resume_file_name)
|
||||
{
|
||||
file = fopen(client_ctx->hcc_zero_rtt_file_name, "rb");
|
||||
file = fopen(client_ctx->hcc_sess_resume_file_name, "rb");
|
||||
if (!file)
|
||||
{
|
||||
LSQ_DEBUG("cannot open %s for reading: %s",
|
||||
client_ctx->hcc_zero_rtt_file_name, strerror(errno));
|
||||
client_ctx->hcc_sess_resume_file_name, strerror(errno));
|
||||
goto no_file;
|
||||
}
|
||||
len = fread(zero_rtt, 1, sizeof(zero_rtt), file);
|
||||
len = fread(sess_resume, 1, sizeof(sess_resume), file);
|
||||
if (0 == len && !feof(file))
|
||||
LSQ_WARN("error reading %s: %s",
|
||||
client_ctx->hcc_zero_rtt_file_name, strerror(errno));
|
||||
client_ctx->hcc_sess_resume_file_name, strerror(errno));
|
||||
fclose(file);
|
||||
LSQ_INFO("create connection zero_rtt %zu bytes", len);
|
||||
LSQ_INFO("create connection sess_resume %zu bytes", len);
|
||||
}
|
||||
else no_file:
|
||||
len = 0;
|
||||
|
||||
while (client_ctx->hcc_n_open_conns < client_ctx->hcc_concurrency &&
|
||||
client_ctx->hcc_total_n_reqs > 0)
|
||||
if (0 != prog_connect(client_ctx->prog, len ? zero_rtt : NULL, len))
|
||||
if (0 != prog_connect(client_ctx->prog, len ? sess_resume : NULL, len))
|
||||
{
|
||||
LSQ_ERROR("connection failed");
|
||||
exit(EXIT_FAILURE);
|
||||
|
@ -377,7 +377,7 @@ http_client_on_conn_closed (lsquic_conn_t *conn)
|
|||
static int
|
||||
hsk_status_ok (enum lsquic_hsk_status status)
|
||||
{
|
||||
return status == LSQ_HSK_OK || status == LSQ_HSK_0RTT_OK;
|
||||
return status == LSQ_HSK_OK || status == LSQ_HSK_RESUMED_OK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -389,13 +389,14 @@ http_client_on_hsk_done (lsquic_conn_t *conn, enum lsquic_hsk_status status)
|
|||
|
||||
if (hsk_status_ok(status))
|
||||
LSQ_INFO("handshake success %s",
|
||||
status == LSQ_HSK_0RTT_OK ? "with 0-RTT" : "");
|
||||
status == LSQ_HSK_RESUMED_OK ? "(session resumed)" : "");
|
||||
else if (status == LSQ_HSK_FAIL)
|
||||
LSQ_INFO("handshake failed");
|
||||
else if (status == LSQ_HSK_0RTT_FAIL)
|
||||
else if (status == LSQ_HSK_RESUMED_FAIL)
|
||||
{
|
||||
LSQ_INFO("handshake failed because of 0-RTT, will retry without it");
|
||||
client_ctx->hcc_flags |= HCC_SKIP_0RTT;
|
||||
LSQ_INFO("handshake failed because of session resumption, will retry "
|
||||
"without it");
|
||||
client_ctx->hcc_flags |= HCC_SKIP_SESS_RESUME;
|
||||
++client_ctx->hcc_concurrency;
|
||||
++client_ctx->hcc_total_n_reqs;
|
||||
}
|
||||
|
@ -423,7 +424,7 @@ http_client_on_hsk_done (lsquic_conn_t *conn, enum lsquic_hsk_status status)
|
|||
|
||||
|
||||
static void
|
||||
http_client_on_zero_rtt_info (lsquic_conn_t *conn, const unsigned char *buf,
|
||||
http_client_on_sess_resume_info (lsquic_conn_t *conn, const unsigned char *buf,
|
||||
size_t bufsz)
|
||||
{
|
||||
lsquic_conn_ctx_t *const conn_h = lsquic_conn_get_ctx(conn);
|
||||
|
@ -431,35 +432,36 @@ http_client_on_zero_rtt_info (lsquic_conn_t *conn, const unsigned char *buf,
|
|||
FILE *file;
|
||||
size_t nw;
|
||||
|
||||
assert(client_ctx->hcc_zero_rtt_file_name);
|
||||
assert(client_ctx->hcc_sess_resume_file_name);
|
||||
|
||||
/* Our client is rather limited: only one file and only one ticket per
|
||||
* connection can be saved.
|
||||
*/
|
||||
if (conn_h->ch_flags & CH_ZERO_RTT_SAVED)
|
||||
if (conn_h->ch_flags & CH_SESSION_RESUME_SAVED)
|
||||
{
|
||||
LSQ_DEBUG("zero-rtt already saved for this connection");
|
||||
LSQ_DEBUG("session resumption information already saved for this "
|
||||
"connection");
|
||||
return;
|
||||
}
|
||||
|
||||
file = fopen(client_ctx->hcc_zero_rtt_file_name, "wb");
|
||||
file = fopen(client_ctx->hcc_sess_resume_file_name, "wb");
|
||||
if (!file)
|
||||
{
|
||||
LSQ_WARN("cannot open %s for writing: %s",
|
||||
client_ctx->hcc_zero_rtt_file_name, strerror(errno));
|
||||
client_ctx->hcc_sess_resume_file_name, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
nw = fwrite(buf, 1, bufsz, file);
|
||||
if (nw == bufsz)
|
||||
{
|
||||
LSQ_DEBUG("wrote %zd bytes of zero-rtt information to %s",
|
||||
nw, client_ctx->hcc_zero_rtt_file_name);
|
||||
conn_h->ch_flags |= CH_ZERO_RTT_SAVED;
|
||||
LSQ_DEBUG("wrote %zd bytes of session resumption information to %s",
|
||||
nw, client_ctx->hcc_sess_resume_file_name);
|
||||
conn_h->ch_flags |= CH_SESSION_RESUME_SAVED;
|
||||
}
|
||||
else
|
||||
LSQ_WARN("error: fwrite(%s) returns %zd instead of %zd: %s",
|
||||
client_ctx->hcc_zero_rtt_file_name, nw, bufsz, strerror(errno));
|
||||
client_ctx->hcc_sess_resume_file_name, nw, bufsz, strerror(errno));
|
||||
|
||||
fclose(file);
|
||||
}
|
||||
|
@ -1536,8 +1538,8 @@ main (int argc, char **argv)
|
|||
client_ctx.hcc_retire_cid_after_nbytes = atoi(optarg);
|
||||
break;
|
||||
case '0':
|
||||
http_client_if.on_zero_rtt_info = http_client_on_zero_rtt_info;
|
||||
client_ctx.hcc_zero_rtt_file_name = optarg;
|
||||
http_client_if.on_sess_resume_info = http_client_on_sess_resume_info;
|
||||
client_ctx.hcc_sess_resume_file_name = optarg;
|
||||
break;
|
||||
default:
|
||||
if (0 != prog_set_opt(&prog, opt, optarg))
|
||||
|
|
|
@ -376,7 +376,7 @@ prog_eb (struct prog *prog)
|
|||
|
||||
|
||||
int
|
||||
prog_connect (struct prog *prog, unsigned char *zero_rtt, size_t zero_rtt_len)
|
||||
prog_connect (struct prog *prog, unsigned char *sess_resume, size_t sess_resume_len)
|
||||
{
|
||||
struct service_port *sport;
|
||||
|
||||
|
@ -388,7 +388,7 @@ prog_connect (struct prog *prog, unsigned char *zero_rtt, size_t zero_rtt_len)
|
|||
/* SNI is required for HTTP */
|
||||
: prog->prog_engine_flags & LSENG_HTTP ? sport->host
|
||||
: NULL,
|
||||
prog->prog_max_packet_size, zero_rtt, zero_rtt_len,
|
||||
prog->prog_max_packet_size, sess_resume, sess_resume_len,
|
||||
sport->sp_token_buf, sport->sp_token_sz))
|
||||
return -1;
|
||||
|
||||
|
|
115
docs/apiref.rst
115
docs/apiref.rst
|
@ -54,6 +54,10 @@ developed by the IETF. Both types are included in a single enum:
|
|||
|
||||
IETF QUIC version ID 28
|
||||
|
||||
.. member:: LSQVER_ID29
|
||||
|
||||
IETF QUIC version ID 29
|
||||
|
||||
.. member:: N_LSQVER
|
||||
|
||||
Special value indicating the number of versions in the enum. It
|
||||
|
@ -73,7 +77,7 @@ List of versions in which the server never includes CID in short packets.
|
|||
|
||||
Experimental versions.
|
||||
|
||||
.. macro: LSQUIC_DEPRECATED_VERSIONS
|
||||
.. macro:: LSQUIC_DEPRECATED_VERSIONS
|
||||
|
||||
Deprecated versions.
|
||||
|
||||
|
@ -114,7 +118,7 @@ LSQUIC declares several types used by many of its public functions. They are:
|
|||
|
||||
.. type:: lsquic_conn_ctx_t
|
||||
|
||||
Connection context. This is the return value of :func:`on_new_conn()`.
|
||||
Connection context. This is the return value of :member:`lsquic_stream_if.on_new_conn`.
|
||||
To LSQUIC, this is just an opaque pointer. User code is expected to
|
||||
use it for its own purposes.
|
||||
|
||||
|
@ -186,7 +190,8 @@ created:
|
|||
|
||||
Create a new engine.
|
||||
|
||||
:param flags: This is is a bitmask of ``LSENG_SERVER``` and ``LSENG_HTTP``.
|
||||
:param flags: This is is a bitmask of :macro:`LSENG_SERVER` and
|
||||
:macro:`LSENG_HTTP`.
|
||||
:param api: Pointer to an initialized :type:`lsquic_engine_api`.
|
||||
|
||||
The engine can be instantiated either in server mode (when ``LSENG_SERVER``
|
||||
|
@ -197,6 +202,18 @@ created:
|
|||
for Google QUIC connections and HTTP/3 functionality for IETF QUIC
|
||||
connections.
|
||||
|
||||
.. macro:: LSENG_SERVER
|
||||
|
||||
One of possible bitmask values passed as first argument to
|
||||
:type:`lsquic_engine_new`. When set, the engine instance
|
||||
will be in the server mode.
|
||||
|
||||
.. macro:: LSENG_HTTP
|
||||
|
||||
One of possible bitmask values passed as first argument to
|
||||
:type:`lsquic_engine_new`. When set, the engine instance
|
||||
will enable HTTP functionality.
|
||||
|
||||
.. function:: void lsquic_engine_cooldown (lsquic_engine_t *engine)
|
||||
|
||||
This function closes all mini connections and marks all full connections
|
||||
|
@ -268,6 +285,11 @@ optional members.
|
|||
In a multi-process setup, it may be useful to observe the CID
|
||||
lifecycle. This optional set of callbacks makes it possible.
|
||||
|
||||
.. member:: const char *ea_alpn
|
||||
|
||||
The optional ALPN string is used by the client if :macro:`LSENG_HTTP`
|
||||
is not set.
|
||||
|
||||
.. _apiref-engine-settings:
|
||||
|
||||
Engine Settings
|
||||
|
@ -307,17 +329,27 @@ settings structure:
|
|||
|
||||
.. member:: unsigned es_max_cfcw
|
||||
|
||||
This value is used to specify maximum allowed value connection flow
|
||||
control window is allowed to reach due to window auto-tuning. By
|
||||
default, this value is zero, which means that CFCW is not allowed
|
||||
to increase from its initial value.
|
||||
This value is used to specify maximum allowed value CFCW is allowed
|
||||
to reach due to window auto-tuning. By default, this value is zero,
|
||||
which means that CFCW is not allowed to increase from its initial
|
||||
value.
|
||||
|
||||
This setting is applicable to both gQUIC and IETF QUIC.
|
||||
|
||||
See :member:`lsquic_engine_settings.es_cfcw`,
|
||||
:member:`lsquic_engine_settings.es_init_max_data`.
|
||||
|
||||
.. member:: unsigned es_max_sfcw
|
||||
|
||||
This value is used to specify maximum allowed value stream flow
|
||||
control window is allowed to reach due to window auto-tuning. By
|
||||
default, this value is zero, which means that CFCW is not allowed
|
||||
to increase from its initial value.
|
||||
This value is used to specify the maximum value stream flow control
|
||||
window is allowed to reach due to auto-tuning. By default, this
|
||||
value is zero, meaning that auto-tuning is turned off.
|
||||
|
||||
This setting is applicable to both gQUIC and IETF QUIC.
|
||||
|
||||
See :member:`lsquic_engine_settings.es_sfcw`,
|
||||
:member:`lsquic_engine_settings.es_init_max_stream_data_bidi_local`,
|
||||
:member:`lsquic_engine_settings.es_init_max_stream_data_bidi_remote`.
|
||||
|
||||
.. member:: unsigned es_max_streams_in
|
||||
|
||||
|
@ -397,9 +429,11 @@ settings structure:
|
|||
(source-addr, dest-addr) tuple, thereby making it necessary to create
|
||||
a socket for each connection.
|
||||
|
||||
This option has no effect in Q046, as the server never includes
|
||||
This option has no effect in Q046 and Q050, as the server never includes
|
||||
CIDs in the short packets.
|
||||
|
||||
This setting is applicable to gQUIC only.
|
||||
|
||||
The default is :func:`LSQUIC_DF_SUPPORT_TCID0`.
|
||||
|
||||
.. member:: int es_support_nstp
|
||||
|
@ -421,6 +455,8 @@ settings structure:
|
|||
receives corresponding Public Reset packet. The default is to
|
||||
ignore these packets.
|
||||
|
||||
The default is :macro:`LSQUIC_DF_HONOR_PRST`.
|
||||
|
||||
.. member:: int es_send_prst
|
||||
|
||||
If set to true value, the library will send Public Reset packets
|
||||
|
@ -457,7 +493,7 @@ settings structure:
|
|||
|
||||
.. member:: unsigned es_proc_time_thresh
|
||||
|
||||
If set, this value specifies that number of microseconds that
|
||||
If set, this value specifies the number of microseconds that
|
||||
:func:`lsquic_engine_process_conns()` and
|
||||
:func:`lsquic_engine_send_unsent_packets()` are allowed to spend
|
||||
before returning.
|
||||
|
@ -842,7 +878,7 @@ out of date. Please check your :file:`lsquic.h` for actual values.*
|
|||
|
||||
Default clock granularity is 1000 microseconds.
|
||||
|
||||
.. macro:: LSQUIC_DF_SCID_LEN 8
|
||||
.. macro:: LSQUIC_DF_SCID_LEN
|
||||
|
||||
The default value is 8 for simplicity and speed.
|
||||
|
||||
|
@ -987,7 +1023,7 @@ that the library uses to send packets.
|
|||
|
||||
ECN may be set by IETF QUIC connections if ``es_ecn`` is set.
|
||||
|
||||
.. type: typedef int (*lsquic_packets_out_f)(void *packets_out_ctx, const struct lsquic_out_spec *out_spec, unsigned n_packets_out)
|
||||
.. type:: typedef int (*lsquic_packets_out_f)(void *packets_out_ctx, const struct lsquic_out_spec *out_spec, unsigned n_packets_out)
|
||||
|
||||
Returns number of packets successfully sent out or -1 on error. -1 should
|
||||
only be returned if no packets were sent out. If -1 is returned or if the
|
||||
|
@ -1010,7 +1046,9 @@ that the library uses to send packets.
|
|||
.. function:: int lsquic_engine_has_unsent_packets (lsquic_engine_t *engine)
|
||||
|
||||
Returns true if engine has some unsent packets. This happens if
|
||||
``ea_packets_out()`` could not send everything out.
|
||||
:member:`lsquic_engine_api.ea_packets_out` could not send everything out
|
||||
or if processing deadline was exceeded (see
|
||||
:member:`lsquic_engine_settings.es_proc_time_thresh`).
|
||||
|
||||
.. function:: void lsquic_engine_send_unsent_packets (lsquic_engine_t *engine)
|
||||
|
||||
|
@ -1028,8 +1066,7 @@ the engine to communicate with the user code:
|
|||
|
||||
.. type:: struct lsquic_stream_if
|
||||
|
||||
.. member:: lsquic_conn_ctx_t *(*on_new_conn)(void *stream_if_ctx,
|
||||
lsquic_conn_t *);
|
||||
.. member:: lsquic_conn_ctx_t *(*on_new_conn)(void *stream_if_ctx, lsquic_conn_t *)
|
||||
|
||||
Called when a new connection has been created. In server mode,
|
||||
this means that the handshake has been successful. In client mode,
|
||||
|
@ -1104,10 +1141,10 @@ the engine to communicate with the user code:
|
|||
|
||||
This callback is optional.
|
||||
|
||||
.. member:: void (*on_zero_rtt_info)(lsquic_conn_t *c, const unsigned char *, size_t)
|
||||
.. member:: void (*on_sess_resume_info)(lsquic_conn_t *c, const unsigned char *, size_t)
|
||||
|
||||
This callback lets client record information needed to
|
||||
perform a zero-RTT handshake next time around.
|
||||
perform session resumption next time around.
|
||||
|
||||
This callback is optional.
|
||||
|
||||
|
@ -1115,19 +1152,19 @@ Creating Connections
|
|||
--------------------
|
||||
|
||||
In server mode, the connections are created by the library based on incoming
|
||||
packets. After handshake is completed, the library calls :func:`on_new_conn()`
|
||||
packets. After handshake is completed, the library calls :member:`lsquic_stream_if.on_new_conn`
|
||||
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_udp_payload_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 *sess_resume, size_t sess_resume_len, const unsigned char *token, size_t token_sz)
|
||||
|
||||
:param engine: Engine to use.
|
||||
|
||||
:param version:
|
||||
|
||||
To let the engine specify QUIC version, use N_LSQVER. If zero-rtt info is
|
||||
supplied, version is picked from there instead.
|
||||
To let the engine specify QUIC version, use N_LSQVER. If session resumption
|
||||
information is supplied, version is picked from there instead.
|
||||
|
||||
:param local_sa:
|
||||
|
||||
|
@ -1139,7 +1176,7 @@ In client mode, a new connection is created by
|
|||
|
||||
:param peer_ctx:
|
||||
|
||||
Context associated with the connection. This is what gets passed to TODO.
|
||||
Context associated with the peer. This is what gets passed to TODO.
|
||||
|
||||
:param conn_ctx:
|
||||
|
||||
|
@ -1158,14 +1195,14 @@ In client mode, a new connection is created by
|
|||
Maximum packet size. If set to zero, it is inferred based on `peer_sa`
|
||||
and `version`.
|
||||
|
||||
:param zero_rtt:
|
||||
:param sess_resume:
|
||||
|
||||
Pointer to previously saved zero-RTT data needed for TLS resumption.
|
||||
May be NULL.
|
||||
Pointer to previously saved session resumption data needed for
|
||||
TLS resumption. May be NULL.
|
||||
|
||||
:param zero_rtt_len:
|
||||
:param sess_resume_len:
|
||||
|
||||
Size of zero-RTT data.
|
||||
Size of session resumption data.
|
||||
|
||||
:param token:
|
||||
|
||||
|
@ -1173,7 +1210,7 @@ In client mode, a new connection is created by
|
|||
packet. Tokens are used by IETF QUIC to pre-validate client
|
||||
connections, potentially avoiding a retry.
|
||||
|
||||
See ``on_new_token`` callback in :type:`lsquic_stream_if`:
|
||||
See :member:`lsquic_stream_if.on_new_token` callback.
|
||||
|
||||
May be NULL.
|
||||
|
||||
|
@ -1193,7 +1230,8 @@ Closing Connections
|
|||
|
||||
.. function:: void lsquic_conn_close (lsquic_conn_t *conn)
|
||||
|
||||
This closes the connection. ``on_conn_closed()`` and ``on_close()`` callbacks will be called.
|
||||
This closes the connection. :member:`lsquic_stream_if.on_conn_closed`
|
||||
and :member:`lsquic_stream_if.on_close` callbacks will be called.
|
||||
|
||||
Creating Streams
|
||||
----------------
|
||||
|
@ -1390,10 +1428,6 @@ more information.
|
|||
|
||||
the buffer for headers
|
||||
|
||||
.. member:: const char *name_ptr
|
||||
|
||||
the name pointer can be optionally set for encoding
|
||||
|
||||
.. member:: uint32_t name_hash
|
||||
|
||||
hash value for name
|
||||
|
@ -1593,7 +1627,7 @@ Push Promises
|
|||
Only makes sense in server mode: the client cannot push a stream and this
|
||||
function always returns false in client mode.
|
||||
|
||||
.. function: int lsquic_stream_is_pushed (const lsquic_stream_t *stream)
|
||||
.. function:: int lsquic_stream_is_pushed (const lsquic_stream_t *stream)
|
||||
|
||||
:return: Boolean value indicating whether this is a pushed stream.
|
||||
|
||||
|
@ -1621,6 +1655,7 @@ Stream Priorities
|
|||
.. function:: int lsquic_stream_set_priority (lsquic_stream_t *stream, unsigned priority)
|
||||
|
||||
Set stream priority. Valid priority values are 1 through 256, inclusive.
|
||||
Lower value means higher priority.
|
||||
|
||||
:return: 0 on success of -1 on failure (this happens if priority value is invalid).
|
||||
|
||||
|
@ -1799,16 +1834,16 @@ Miscellaneous Types
|
|||
|
||||
If not specified, malloc() and free() are used.
|
||||
|
||||
.. member:: void * (*pmi_allocate) (void *pmi_ctx, void *conn_ctx, unsigned short sz, char is_ipv6)
|
||||
.. member:: void * (*pmi_allocate) (void *pmi_ctx, void *peer_ctx, unsigned short sz, char is_ipv6)
|
||||
|
||||
Allocate buffer for sending.
|
||||
|
||||
.. member:: void (*pmi_release) (void *pmi_ctx, void *conn_ctx, void *buf, char is_ipv6)
|
||||
.. member:: void (*pmi_release) (void *pmi_ctx, void *peer_ctx, void *buf, char is_ipv6)
|
||||
|
||||
This function is used to release the allocated buffer after it is
|
||||
sent via ``ea_packets_out()``.
|
||||
|
||||
.. member:: void (*pmi_return) (void *pmi_ctx, void *conn_ctx, void *buf, char is_ipv6)
|
||||
.. member:: void (*pmi_return) (void *pmi_ctx, void *peer_ctx, void *buf, char is_ipv6)
|
||||
|
||||
If allocated buffer is not going to be sent, return it to the
|
||||
caller using this function.
|
||||
|
|
|
@ -24,9 +24,9 @@ copyright = u'2020, LiteSpeed Technologies'
|
|||
author = u'LiteSpeed Technologies'
|
||||
|
||||
# The short X.Y version
|
||||
version = u'2.17'
|
||||
version = u'2.18'
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = u'2.17.2'
|
||||
release = u'2.18.0'
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
|
|
@ -91,11 +91,12 @@ Engine instantiation is performed by :func:`lsquic_engine_new()`:
|
|||
lsquic_engine_t *engine
|
||||
= lsquic_engine_new(LSENG_SERVER|LSENG_HTTP, &engine_api);
|
||||
|
||||
The engine mode is selected by using the ``LSENG_SERVER`` flag. If
|
||||
present, the engine will be in server mode; if not, the engine will
|
||||
be in client mode.
|
||||
The engine mode is selected by using the :macro:`LSENG_SERVER` flag.
|
||||
If present, the engine will be in server mode; if not, the engine will
|
||||
be in client mode. If you need both server and client functionality
|
||||
in your program, instantiate two engines (or as many as you like).
|
||||
|
||||
Using the ``LSENG_HTTP`` flag enables the HTTP behavior: The library
|
||||
Using the :macro:`LSENG_HTTP` flag enables the HTTP behavior: The library
|
||||
hides the interaction between the HTTP application layer and the QUIC
|
||||
transport layer and presents a simple, unified (between Google QUIC and
|
||||
HTTP/3) way of sending and receiving HTTP messages. Behind the scenes,
|
||||
|
|
132
include/lsquic.h
132
include/lsquic.h
|
@ -24,8 +24,8 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#define LSQUIC_MAJOR_VERSION 2
|
||||
#define LSQUIC_MINOR_VERSION 17
|
||||
#define LSQUIC_PATCH_VERSION 2
|
||||
#define LSQUIC_MINOR_VERSION 18
|
||||
#define LSQUIC_PATCH_VERSION 0
|
||||
|
||||
/**
|
||||
* Engine flags:
|
||||
|
@ -131,18 +131,18 @@ enum lsquic_hsk_status
|
|||
*/
|
||||
LSQ_HSK_FAIL,
|
||||
/**
|
||||
* The handshake succeeded without 0-RTT.
|
||||
* The handshake succeeded without session resumption.
|
||||
*/
|
||||
LSQ_HSK_OK,
|
||||
/**
|
||||
* The handshake succeeded with 0-RTT.
|
||||
* The handshake succeeded with session resumption.
|
||||
*/
|
||||
LSQ_HSK_0RTT_OK,
|
||||
LSQ_HSK_RESUMED_OK,
|
||||
/**
|
||||
* The handshake failed because of 0-RTT (early data rejected). Retry
|
||||
* the connection without 0-RTT.
|
||||
* Session resumption failed. Retry the connection without session
|
||||
* resumption.
|
||||
*/
|
||||
LSQ_HSK_0RTT_FAIL,
|
||||
LSQ_HSK_RESUMED_FAIL,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -181,11 +181,7 @@ struct lsquic_stream_if {
|
|||
void (*on_close) (lsquic_stream_t *s, lsquic_stream_ctx_t *h);
|
||||
/* This callback in only called in client mode */
|
||||
/**
|
||||
* When handshake is completed, this callback is called. `ok' is set
|
||||
* to true if handshake was successful; otherwise, `ok' is set to
|
||||
* false.
|
||||
*
|
||||
* This callback is optional.
|
||||
* When handshake is completed, this optional callback is called.
|
||||
*/
|
||||
void (*on_hsk_done)(lsquic_conn_t *c, enum lsquic_hsk_status s);
|
||||
/**
|
||||
|
@ -196,9 +192,9 @@ struct lsquic_stream_if {
|
|||
size_t token_size);
|
||||
/**
|
||||
* This optional callback lets client record information needed to
|
||||
* perform a zero-RTT handshake next time around.
|
||||
* perform a session resumption next time around.
|
||||
*/
|
||||
void (*on_zero_rtt_info)(lsquic_conn_t *c, const unsigned char *, size_t);
|
||||
void (*on_sess_resume_info)(lsquic_conn_t *c, const unsigned char *, size_t);
|
||||
};
|
||||
|
||||
struct ssl_ctx_st;
|
||||
|
@ -206,7 +202,7 @@ struct ssl_st;
|
|||
struct lsxpack_header;
|
||||
|
||||
/**
|
||||
* QUIC engine in server role needs access to certificates. This is
|
||||
* QUIC engine in server mode needs access to certificates. This is
|
||||
* accomplished by providing a callback and a context to the engine
|
||||
* constructor.
|
||||
*/
|
||||
|
@ -397,10 +393,22 @@ struct lsquic_engine_settings {
|
|||
* which means that CFCW is not allowed to increase from its initial
|
||||
* value.
|
||||
*
|
||||
* @see es_cfcw
|
||||
* This setting is applicable to both gQUIC and IETF QUIC.
|
||||
*
|
||||
* @see es_cfcw, @see es_init_max_data.
|
||||
*/
|
||||
unsigned es_max_cfcw;
|
||||
|
||||
/**
|
||||
* This value is used to specify the maximum value stream flow control
|
||||
* window is allowed to reach due to auto-tuning. By default, this
|
||||
* value is zero, meaning that auto-tuning is turned off.
|
||||
*
|
||||
* This setting is applicable to both gQUIC and IETF QUIC.
|
||||
*
|
||||
* @see es_sfcw, @see es_init_max_stream_data_bidi_remote,
|
||||
* @see es_init_max_stream_data_bidi_local.
|
||||
*/
|
||||
unsigned es_max_sfcw;
|
||||
|
||||
/** MIDS */
|
||||
|
@ -470,9 +478,11 @@ struct lsquic_engine_settings {
|
|||
* (source-addr, dest-addr) tuple, thereby making it necessary to create
|
||||
* a socket for each connection.
|
||||
*
|
||||
* This option has no effect in Q046, as the server never includes
|
||||
* This option has no effect in Q046 and Q050, as the server never includes
|
||||
* CIDs in the short packets.
|
||||
*
|
||||
* This setting is applicable to gQUIC only.
|
||||
*
|
||||
* The default is @ref LSQUIC_DF_SUPPORT_TCID0.
|
||||
*/
|
||||
int es_support_tcid0;
|
||||
|
@ -486,6 +496,8 @@ struct lsquic_engine_settings {
|
|||
*
|
||||
* This option does not affect the server, as it must support NSTP mode
|
||||
* if it was specified by the client.
|
||||
*
|
||||
* This setting is applicable to gQUIC only.
|
||||
*/
|
||||
int es_support_nstp;
|
||||
|
||||
|
@ -493,6 +505,8 @@ struct lsquic_engine_settings {
|
|||
* If set to true value, the library will drop connections when it
|
||||
* receives corresponding Public Reset packet. The default is to
|
||||
* ignore these packets.
|
||||
*
|
||||
* The default is @ref LSQUIC_DF_HONOR_PRST.
|
||||
*/
|
||||
int es_honor_prst;
|
||||
|
||||
|
@ -533,7 +547,7 @@ struct lsquic_engine_settings {
|
|||
int es_rw_once;
|
||||
|
||||
/**
|
||||
* If set, this value specifies that number of microseconds that
|
||||
* If set, this value specifies the number of microseconds that
|
||||
* @ref lsquic_engine_process_conns() and
|
||||
* @ref lsquic_engine_send_unsent_packets() are allowed to spend
|
||||
* before returning.
|
||||
|
@ -563,6 +577,29 @@ struct lsquic_engine_settings {
|
|||
*/
|
||||
unsigned es_clock_granularity;
|
||||
|
||||
/**
|
||||
* Congestion control algorithm to use.
|
||||
*
|
||||
* 0: Use default (@ref LSQUIC_DF_CC_ALGO)
|
||||
* 1: Cubic
|
||||
* 2: BBR
|
||||
*/
|
||||
unsigned es_cc_algo;
|
||||
|
||||
/**
|
||||
* No progress timeout.
|
||||
*
|
||||
* If connection does not make progress for this number of seconds, the
|
||||
* connection is dropped. Here, progress is defined as user streams
|
||||
* being written to or read from.
|
||||
*
|
||||
* If this value is zero, this timeout is disabled.
|
||||
*
|
||||
* Default value is @ref LSQUIC_DF_NOPROGRESS_TIMEOUT_SERVER in server
|
||||
* mode and @ref LSQUIC_DF_NOPROGRESS_TIMEOUT_CLIENT in client mode.
|
||||
*/
|
||||
unsigned es_noprogress_timeout;
|
||||
|
||||
/* The following settings are specific to IETF QUIC. */
|
||||
/* vvvvvvvvvvv */
|
||||
|
||||
|
@ -578,15 +615,27 @@ struct lsquic_engine_settings {
|
|||
unsigned es_init_max_data;
|
||||
|
||||
/**
|
||||
* Initial max stream data.
|
||||
* Initial maximum amount of stream data allowed to be sent on streams
|
||||
* created by remote end (peer).
|
||||
*
|
||||
* This is a transport parameter.
|
||||
*
|
||||
* Depending on the engine mode, the default value is either
|
||||
* @ref LSQUIC_DF_INIT_MAX_STREAM_DATA_CLIENT or
|
||||
* @ref LSQUIC_DF_INIT_MAX_STREAM_DATA_BIDI_REMOTE_CLIENT or
|
||||
* @ref LSQUIC_DF_INIT_MAX_STREAM_DATA_BIDI_REMOTE_SERVER.
|
||||
*/
|
||||
unsigned es_init_max_stream_data_bidi_remote;
|
||||
|
||||
/**
|
||||
* Initial maximum amount of stream data allowed to be sent on streams
|
||||
* created by remote end (peer).
|
||||
*
|
||||
* This is a transport parameter.
|
||||
*
|
||||
* Depending on the engine mode, the default value is either
|
||||
* @ref LSQUIC_DF_INIT_MAX_STREAM_DATA_BIDI_LOCAL_CLIENT or
|
||||
* @ref LSQUIC_DF_INIT_MAX_STREAM_DATA_BIDI_LOCAL_SERVER.
|
||||
*/
|
||||
unsigned es_init_max_stream_data_bidi_local;
|
||||
|
||||
/**
|
||||
|
@ -710,15 +759,6 @@ struct lsquic_engine_settings {
|
|||
*/
|
||||
int es_allow_migration;
|
||||
|
||||
/**
|
||||
* Congestion control algorithm to use.
|
||||
*
|
||||
* 0: Use default (@ref LSQUIC_DF_CC_ALGO)
|
||||
* 1: Cubic
|
||||
* 2: BBR
|
||||
*/
|
||||
unsigned es_cc_algo;
|
||||
|
||||
/**
|
||||
* Use QL loss bits. Allowed values are:
|
||||
* 0: Do not use loss bits
|
||||
|
@ -763,20 +803,6 @@ struct lsquic_engine_settings {
|
|||
* Default value is @ref LSQUIC_DF_MAX_UDP_PAYLOAD_SIZE_RX
|
||||
*/
|
||||
unsigned short es_max_udp_payload_size_rx;
|
||||
|
||||
/**
|
||||
* No progress timeout.
|
||||
*
|
||||
* If connection does not make progress for this number of seconds, the
|
||||
* connection is dropped. Here, progress is defined as user streams
|
||||
* being written to or read from.
|
||||
*
|
||||
* If this value is zero, this timeout is disabled.
|
||||
*
|
||||
* Default value is @ref LSQUIC_DF_NOPROGRESS_TIMEOUT_SERVER in server
|
||||
* mode and @ref LSQUIC_DF_NOPROGRESS_TIMEOUT_CLIENT in client mode.
|
||||
*/
|
||||
unsigned es_noprogress_timeout;
|
||||
};
|
||||
|
||||
/* Initialize `settings' to default values */
|
||||
|
@ -881,19 +907,19 @@ struct lsquic_packout_mem_if
|
|||
/**
|
||||
* Allocate buffer for sending.
|
||||
*/
|
||||
void * (*pmi_allocate) (void *pmi_ctx, void *conn_ctx, unsigned short sz,
|
||||
void * (*pmi_allocate) (void *pmi_ctx, void *peer_ctx, unsigned short sz,
|
||||
char is_ipv6);
|
||||
/**
|
||||
* This function is used to release the allocated buffer after it is
|
||||
* sent via @ref ea_packets_out.
|
||||
*/
|
||||
void (*pmi_release) (void *pmi_ctx, void *conn_ctx, void *buf,
|
||||
void (*pmi_release) (void *pmi_ctx, void *peer_ctx, void *buf,
|
||||
char is_ipv6);
|
||||
/**
|
||||
* If allocated buffer is not going to be sent, return it to the caller
|
||||
* using this function.
|
||||
*/
|
||||
void (*pmi_return) (void *pmi_ctx, void *conn_ctx, void *buf,
|
||||
void (*pmi_return) (void *pmi_ctx, void *peer_ctx, void *buf,
|
||||
char is_ipv6);
|
||||
};
|
||||
|
||||
|
@ -1076,7 +1102,7 @@ struct lsquic_engine_api
|
|||
void *ea_keylog_ctx;
|
||||
|
||||
/**
|
||||
* The optional ALPN string is used by the client @ref LSENG_HTTP
|
||||
* The optional ALPN string is used by the client if @ref LSENG_HTTP
|
||||
* is not set.
|
||||
*/
|
||||
const char *ea_alpn;
|
||||
|
@ -1102,8 +1128,8 @@ lsquic_engine_new (unsigned lsquic_engine_flags,
|
|||
/**
|
||||
* Create a client connection to peer identified by `peer_ctx'.
|
||||
*
|
||||
* To let the engine specify QUIC version, use N_LSQVER. If zero-rtt info
|
||||
* is supplied, version is picked from there instead.
|
||||
* To let the engine specify QUIC version, use N_LSQVER. If session resumption
|
||||
* information is supplied, version is picked from there instead.
|
||||
*
|
||||
* If `max_udp_payload_size' is set to zero, it is inferred based on `peer_sa':
|
||||
* 1350 for IPv6 and 1370 for IPv4.
|
||||
|
@ -1114,7 +1140,7 @@ lsquic_engine_connect (lsquic_engine_t *, enum lsquic_version,
|
|||
const struct sockaddr *peer_sa,
|
||||
void *peer_ctx, lsquic_conn_ctx_t *conn_ctx,
|
||||
const char *hostname, unsigned short max_udp_payload_size,
|
||||
const unsigned char *zero_rtt, size_t zero_rtt_len,
|
||||
const unsigned char *sess_resume, size_t sess_resume_len,
|
||||
/** Resumption token: optional */
|
||||
const unsigned char *token, size_t token_sz);
|
||||
|
||||
|
@ -1147,7 +1173,8 @@ lsquic_engine_process_conns (lsquic_engine_t *engine);
|
|||
|
||||
/**
|
||||
* Returns true if engine has some unsent packets. This happens if
|
||||
* @ref ea_packets_out() could not send everything out.
|
||||
* @ref ea_packets_out() could not send everything out or if processing
|
||||
* deadline was exceeded (see @ref es_proc_time_thresh).
|
||||
*/
|
||||
int
|
||||
lsquic_engine_has_unsent_packets (lsquic_engine_t *engine);
|
||||
|
@ -1452,6 +1479,7 @@ unsigned lsquic_stream_priority (const lsquic_stream_t *s);
|
|||
|
||||
/**
|
||||
* Set stream priority. Valid priority values are 1 through 256, inclusive.
|
||||
* Lower value means higher priority.
|
||||
*
|
||||
* @retval 0 Success.
|
||||
* @retval -1 Priority value is invalid.
|
||||
|
|
|
@ -110,8 +110,8 @@ hsk_client_on_read (lsquic_stream_t *stream, struct lsquic_stream_ctx *sh)
|
|||
if (c_hsk->lconn->cn_esf.g->esf_is_hsk_done(c_hsk->lconn->cn_enc_session))
|
||||
{
|
||||
LSQ_DEBUG("handshake is successful, inform connection");
|
||||
status = (c_hsk->lconn->cn_esf_c->esf_did_zero_rtt_succeed(
|
||||
c_hsk->lconn->cn_enc_session)) ? LSQ_HSK_0RTT_OK : LSQ_HSK_OK;
|
||||
status = (c_hsk->lconn->cn_esf_c->esf_did_sess_resume_succeed(
|
||||
c_hsk->lconn->cn_enc_session)) ? LSQ_HSK_RESUMED_OK : LSQ_HSK_OK;
|
||||
c_hsk->lconn->cn_if->ci_hsk_done(c_hsk->lconn, status);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -115,10 +115,10 @@ struct enc_session_funcs_common
|
|||
(*esf_verify_reset_token) (enc_session_t *, const unsigned char *, size_t);
|
||||
|
||||
int
|
||||
(*esf_did_zero_rtt_succeed) (enc_session_t *);
|
||||
(*esf_did_sess_resume_succeed) (enc_session_t *);
|
||||
|
||||
int
|
||||
(*esf_is_zero_rtt_enabled) (enc_session_t *);
|
||||
(*esf_is_sess_resume_enabled) (enc_session_t *);
|
||||
|
||||
void
|
||||
(*esf_set_conn) (enc_session_t *, struct lsquic_conn *);
|
||||
|
@ -231,11 +231,12 @@ struct enc_session_funcs_gquic
|
|||
size_t
|
||||
(*esf_mem_used)(enc_session_t *);
|
||||
|
||||
/* Zero-rtt serialization needs the knowledge of the QUIC version, that's
|
||||
* why there is a separate method for thus. Plus, we want to be able to
|
||||
* call it after the "handshake is done" callback is called.
|
||||
/* Session resumption serialization needs the knowledge of the QUIC
|
||||
* version, that's why there is a separate method for thus. Plus, we
|
||||
* want to be able to call it after the "handshake is done" callback
|
||||
* is called.
|
||||
*/
|
||||
void (*esf_maybe_dispatch_zero_rtt) (enc_session_t *,
|
||||
void (*esf_maybe_dispatch_sess_resume) (enc_session_t *,
|
||||
void (*cb)(struct lsquic_conn *, const unsigned char *, size_t));
|
||||
|
||||
void (*esf_reset_cid) (enc_session_t *, const lsquic_cid_t *);
|
||||
|
@ -361,7 +362,7 @@ extern const struct lsquic_stream_if lsquic_mini_cry_sm_if;
|
|||
#define ALERT_NO_APPLICATION_PROTOCOL 120
|
||||
|
||||
enum lsquic_version
|
||||
lsquic_zero_rtt_version (const unsigned char *, size_t);
|
||||
lsquic_sess_resume_version (const unsigned char *, size_t);
|
||||
|
||||
/* This is seems to be true for all of the ciphers used by IETF QUIC.
|
||||
* XXX: Perhaps add a check?
|
||||
|
|
|
@ -20,7 +20,7 @@ const char *const lsquic_enclev2str[] =
|
|||
|
||||
|
||||
enum lsquic_version
|
||||
lsquic_zero_rtt_version (const unsigned char *buf, size_t bufsz)
|
||||
lsquic_sess_resume_version (const unsigned char *buf, size_t bufsz)
|
||||
{
|
||||
lsquic_ver_tag_t tag;
|
||||
|
||||
|
|
|
@ -247,8 +247,8 @@ struct enc_sess_iquic
|
|||
char *esi_sni_bypass;
|
||||
#endif
|
||||
const unsigned char *esi_alpn;
|
||||
unsigned char *esi_zero_rtt_buf;
|
||||
size_t esi_zero_rtt_sz;
|
||||
unsigned char *esi_sess_resume_buf;
|
||||
size_t esi_sess_resume_sz;
|
||||
/* Need MD and AEAD for key rotation */
|
||||
const EVP_MD *esi_md;
|
||||
const EVP_AEAD *esi_aead;
|
||||
|
@ -649,7 +649,7 @@ gen_trans_params (struct enc_sess_iquic *enc_sess, unsigned char *buf,
|
|||
* uint8_t trapa_buf[ trapa_size ]
|
||||
*/
|
||||
|
||||
#define ZERO_RTT_VERSION 1
|
||||
#define SESS_RESUME_VERSION 1
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#define READ_NUM(var_, ptr_) do { \
|
||||
|
@ -674,31 +674,33 @@ maybe_create_SSL_SESSION (struct enc_sess_iquic *enc_sess,
|
|||
uint32_t rtt_ver, ticket_sz, trapa_sz;
|
||||
const unsigned char *ticket_buf, *trapa_buf, *p;
|
||||
const unsigned char *const end
|
||||
= enc_sess->esi_zero_rtt_buf + enc_sess->esi_zero_rtt_sz;
|
||||
= enc_sess->esi_sess_resume_buf + enc_sess->esi_sess_resume_sz;
|
||||
|
||||
if (enc_sess->esi_zero_rtt_sz
|
||||
if (enc_sess->esi_sess_resume_sz
|
||||
< sizeof(ver_tag) + sizeof(rtt_ver) + sizeof(ticket_sz))
|
||||
{
|
||||
LSQ_DEBUG("rtt buf too short");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p = enc_sess->esi_zero_rtt_buf;
|
||||
p = enc_sess->esi_sess_resume_buf;
|
||||
memcpy(&ver_tag, p, sizeof(ver_tag));
|
||||
p += sizeof(ver_tag);
|
||||
quic_ver = lsquic_tag2ver(ver_tag);
|
||||
if (quic_ver != enc_sess->esi_ver_neg->vn_ver)
|
||||
{
|
||||
LSQ_DEBUG("negotiated version %s does not match that in the zero-rtt "
|
||||
"info buffer", lsquic_ver2str[enc_sess->esi_ver_neg->vn_ver]);
|
||||
LSQ_DEBUG("negotiated version %s does not match that in the session "
|
||||
"resumption nfo buffer",
|
||||
lsquic_ver2str[enc_sess->esi_ver_neg->vn_ver]);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
READ_NUM(rtt_ver, p);
|
||||
if (rtt_ver != ZERO_RTT_VERSION)
|
||||
if (rtt_ver != SESS_RESUME_VERSION)
|
||||
{
|
||||
LSQ_DEBUG("cannot use zero-rtt buffer: encoded using %"PRIu32", "
|
||||
"while current version is %u", rtt_ver, ZERO_RTT_VERSION);
|
||||
LSQ_DEBUG("cannot use session resumption buffer: encoded using "
|
||||
"%"PRIu32", while current version is %u",
|
||||
rtt_ver, SESS_RESUME_VERSION);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -759,7 +761,7 @@ iquic_esfi_create_client (const char *hostname,
|
|||
struct lsquic_engine_public *enpub, struct lsquic_conn *lconn,
|
||||
const lsquic_cid_t *dcid, const struct ver_neg *ver_neg,
|
||||
void *crypto_streams[4], const struct crypto_stream_if *cryst_if,
|
||||
const unsigned char *zero_rtt, size_t zero_rtt_sz,
|
||||
const unsigned char *sess_resume, size_t sess_resume_sz,
|
||||
struct lsquic_alarmset *alset, unsigned max_streams_uni)
|
||||
{
|
||||
struct enc_sess_iquic *enc_sess;
|
||||
|
@ -814,24 +816,24 @@ iquic_esfi_create_client (const char *hostname,
|
|||
/* Have to wait until the call to init_client() -- this is when the
|
||||
* result of version negotiation is known.
|
||||
*/
|
||||
if (zero_rtt && zero_rtt_sz)
|
||||
if (sess_resume && sess_resume_sz)
|
||||
{
|
||||
enc_sess->esi_zero_rtt_buf = malloc(zero_rtt_sz);
|
||||
if (enc_sess->esi_zero_rtt_buf)
|
||||
enc_sess->esi_sess_resume_buf = malloc(sess_resume_sz);
|
||||
if (enc_sess->esi_sess_resume_buf)
|
||||
{
|
||||
memcpy(enc_sess->esi_zero_rtt_buf, zero_rtt, zero_rtt_sz);
|
||||
enc_sess->esi_zero_rtt_sz = zero_rtt_sz;
|
||||
memcpy(enc_sess->esi_sess_resume_buf, sess_resume, sess_resume_sz);
|
||||
enc_sess->esi_sess_resume_sz = sess_resume_sz;
|
||||
}
|
||||
else
|
||||
enc_sess->esi_zero_rtt_sz = 0;
|
||||
enc_sess->esi_sess_resume_sz = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
enc_sess->esi_zero_rtt_buf = NULL;
|
||||
enc_sess->esi_zero_rtt_sz = 0;
|
||||
enc_sess->esi_sess_resume_buf = NULL;
|
||||
enc_sess->esi_sess_resume_sz = 0;
|
||||
}
|
||||
|
||||
if (enc_sess->esi_enpub->enp_stream_if->on_zero_rtt_info)
|
||||
if (enc_sess->esi_enpub->enp_stream_if->on_sess_resume_info)
|
||||
enc_sess->esi_flags |= ESI_WANT_TICKET;
|
||||
enc_sess->esi_alset = alset;
|
||||
lsquic_alarmset_init_alarm(enc_sess->esi_alset, AL_SESS_TICKET,
|
||||
|
@ -1145,10 +1147,14 @@ iquic_lookup_cert (SSL *ssl, void *arg)
|
|||
#endif
|
||||
if (!server_name)
|
||||
{
|
||||
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;
|
||||
{
|
||||
LSQ_DEBUG("SNI is not set, but is required in HTTP/3: "
|
||||
"fail certificate lookup");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
LSQ_DEBUG("cert lookup: server name is not set");
|
||||
}
|
||||
|
||||
path = enc_sess->esi_conn->cn_if->ci_get_path(enc_sess->esi_conn, NULL);
|
||||
|
@ -1268,7 +1274,8 @@ iquic_esfi_init_server (enc_session_t *enc_session_p)
|
|||
}
|
||||
|
||||
SSL_clear_options(enc_sess->esi_ssl, SSL_OP_NO_TLSv1_3);
|
||||
SSL_set_cert_cb(enc_sess->esi_ssl, iquic_lookup_cert, enc_sess);
|
||||
if (enc_sess->esi_enpub->enp_lookup_cert)
|
||||
SSL_set_cert_cb(enc_sess->esi_ssl, iquic_lookup_cert, enc_sess);
|
||||
SSL_set_ex_data(enc_sess->esi_ssl, s_idx, enc_sess);
|
||||
SSL_set_accept_state(enc_sess->esi_ssl);
|
||||
LSQ_DEBUG("initialized server enc session");
|
||||
|
@ -1305,13 +1312,14 @@ iquic_new_session_cb (SSL *ssl, SSL_SESSION *session)
|
|||
size_t trapa_sz, buf_sz;
|
||||
|
||||
enc_sess = SSL_get_ex_data(ssl, s_idx);
|
||||
assert(enc_sess->esi_enpub->enp_stream_if->on_zero_rtt_info);
|
||||
assert(enc_sess->esi_enpub->enp_stream_if->on_sess_resume_info);
|
||||
|
||||
SSL_get_peer_quic_transport_params(enc_sess->esi_ssl, &trapa_buf,
|
||||
&trapa_sz);
|
||||
if (!(trapa_buf + trapa_sz))
|
||||
{
|
||||
LSQ_WARN("no transport parameters: cannot generate zero-rtt info");
|
||||
LSQ_WARN("no transport parameters: cannot generate session "
|
||||
"resumption info");
|
||||
return 0;
|
||||
}
|
||||
if (trapa_sz > UINT32_MAX)
|
||||
|
@ -1347,7 +1355,7 @@ iquic_new_session_cb (SSL *ssl, SSL_SESSION *session)
|
|||
memcpy(p, &tag, sizeof(tag));
|
||||
p += sizeof(tag);
|
||||
|
||||
WRITE_NUM(num, ZERO_RTT_VERSION, p);
|
||||
WRITE_NUM(num, SESS_RESUME_VERSION, p);
|
||||
WRITE_NUM(num, ticket_sz, p);
|
||||
memcpy(p, ticket_buf, ticket_sz);
|
||||
p += ticket_sz;
|
||||
|
@ -1358,9 +1366,9 @@ iquic_new_session_cb (SSL *ssl, SSL_SESSION *session)
|
|||
assert(buf + buf_sz == p);
|
||||
OPENSSL_free(ticket_buf);
|
||||
|
||||
LSQ_DEBUG("generated %zu bytes of zero-rtt buffer", buf_sz);
|
||||
LSQ_DEBUG("generated %zu bytes of session resumption buffer", buf_sz);
|
||||
|
||||
enc_sess->esi_enpub->enp_stream_if->on_zero_rtt_info(enc_sess->esi_conn,
|
||||
enc_sess->esi_enpub->enp_stream_if->on_sess_resume_info(enc_sess->esi_conn,
|
||||
buf, buf_sz);
|
||||
free(buf);
|
||||
enc_sess->esi_flags &= ~ESI_WANT_TICKET;
|
||||
|
@ -1410,7 +1418,7 @@ init_client (struct enc_sess_iquic *const enc_sess)
|
|||
SSL_CTX_set_max_proto_version(ssl_ctx, TLS1_3_VERSION);
|
||||
SSL_CTX_set_default_verify_paths(ssl_ctx);
|
||||
SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_CLIENT);
|
||||
if (enc_sess->esi_enpub->enp_stream_if->on_zero_rtt_info)
|
||||
if (enc_sess->esi_enpub->enp_stream_if->on_sess_resume_info)
|
||||
SSL_CTX_sess_set_new_cb(ssl_ctx, iquic_new_session_cb);
|
||||
if (enc_sess->esi_enpub->enp_kli)
|
||||
SSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback);
|
||||
|
@ -1465,7 +1473,7 @@ init_client (struct enc_sess_iquic *const enc_sess)
|
|||
}
|
||||
free(enc_sess->esi_hostname);
|
||||
enc_sess->esi_hostname = NULL;
|
||||
if (enc_sess->esi_zero_rtt_buf)
|
||||
if (enc_sess->esi_sess_resume_buf)
|
||||
{
|
||||
ssl_session = maybe_create_SSL_SESSION(enc_sess, ssl_ctx);
|
||||
if (ssl_session)
|
||||
|
@ -1744,7 +1752,7 @@ iquic_esfi_handshake (struct enc_sess_iquic *enc_sess)
|
|||
return IHS_WANT_WRITE;
|
||||
case SSL_ERROR_EARLY_DATA_REJECTED:
|
||||
LSQ_DEBUG("early data rejected");
|
||||
hsk_status = LSQ_HSK_0RTT_FAIL;
|
||||
hsk_status = LSQ_HSK_RESUMED_FAIL;
|
||||
goto err;
|
||||
/* fall through */
|
||||
default:
|
||||
|
@ -1767,14 +1775,14 @@ iquic_esfi_handshake (struct enc_sess_iquic *enc_sess)
|
|||
hsk_status = LSQ_HSK_OK;
|
||||
LSQ_DEBUG("handshake reported complete");
|
||||
EV_LOG_HSK_COMPLETED(LSQUIC_LOG_CONN_ID);
|
||||
/* The ESI_USE_SSL_TICKET flag indicates if the client attempted 0-RTT.
|
||||
* If the handshake is complete, and the client attempted 0-RTT, it
|
||||
* must have succeeded.
|
||||
/* The ESI_USE_SSL_TICKET flag indicates if the client attempted session
|
||||
* resumption. If the handshake is complete, and the client attempted
|
||||
* session resumption, it must have succeeded.
|
||||
*/
|
||||
if (enc_sess->esi_flags & ESI_USE_SSL_TICKET)
|
||||
{
|
||||
hsk_status = LSQ_HSK_0RTT_OK;
|
||||
EV_LOG_ZERO_RTT(LSQUIC_LOG_CONN_ID);
|
||||
hsk_status = LSQ_HSK_RESUMED_OK;
|
||||
EV_LOG_SESSION_RESUMPTION(LSQUIC_LOG_CONN_ID);
|
||||
}
|
||||
|
||||
if (0 != maybe_get_peer_transport_params(enc_sess))
|
||||
|
@ -1844,7 +1852,7 @@ iquic_esfi_destroy (enc_session_t *enc_session_p)
|
|||
free_handshake_keys(enc_sess);
|
||||
cleanup_hp(&enc_sess->esi_hp);
|
||||
|
||||
free(enc_sess->esi_zero_rtt_buf);
|
||||
free(enc_sess->esi_sess_resume_buf);
|
||||
free(enc_sess->esi_hostname);
|
||||
free(enc_sess);
|
||||
}
|
||||
|
@ -2407,10 +2415,10 @@ iquic_esf_alg_keysize (enc_session_t *enc_session_p)
|
|||
|
||||
|
||||
static int
|
||||
iquic_esf_zero_rtt_enabled (enc_session_t *enc_session_p)
|
||||
iquic_esf_sess_resume_enabled (enc_session_t *enc_session_p)
|
||||
{
|
||||
struct enc_sess_iquic *const enc_sess = enc_session_p;
|
||||
return enc_sess->esi_zero_rtt_buf != NULL;
|
||||
return enc_sess->esi_sess_resume_buf != NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2555,7 +2563,7 @@ const struct enc_session_funcs_common lsquic_enc_session_common_ietf_v1 =
|
|||
.esf_cipher = iquic_esf_cipher,
|
||||
.esf_keysize = iquic_esf_keysize,
|
||||
.esf_alg_keysize = iquic_esf_alg_keysize,
|
||||
.esf_is_zero_rtt_enabled = iquic_esf_zero_rtt_enabled,
|
||||
.esf_is_sess_resume_enabled = iquic_esf_sess_resume_enabled,
|
||||
.esf_set_conn = iquic_esf_set_conn,
|
||||
};
|
||||
|
||||
|
@ -2573,7 +2581,7 @@ const struct enc_session_funcs_common lsquic_enc_session_common_ietf_v1_no_flush
|
|||
.esf_cipher = iquic_esf_cipher,
|
||||
.esf_keysize = iquic_esf_keysize,
|
||||
.esf_alg_keysize = iquic_esf_alg_keysize,
|
||||
.esf_is_zero_rtt_enabled = iquic_esf_zero_rtt_enabled,
|
||||
.esf_is_sess_resume_enabled = iquic_esf_sess_resume_enabled,
|
||||
.esf_set_conn = iquic_esf_set_conn,
|
||||
};
|
||||
|
||||
|
|
|
@ -1580,7 +1580,7 @@ lsquic_engine_connect (lsquic_engine_t *engine, enum lsquic_version version,
|
|||
const struct sockaddr *peer_sa,
|
||||
void *peer_ctx, lsquic_conn_ctx_t *conn_ctx,
|
||||
const char *hostname, unsigned short max_packet_size,
|
||||
const unsigned char *zero_rtt, size_t zero_rtt_len,
|
||||
const unsigned char *sess_resume, size_t sess_resume_len,
|
||||
const unsigned char *token, size_t token_sz)
|
||||
{
|
||||
lsquic_conn_t *conn;
|
||||
|
@ -1606,14 +1606,14 @@ lsquic_engine_connect (lsquic_engine_t *engine, enum lsquic_version version,
|
|||
return NULL;
|
||||
flags = engine->flags & (ENG_SERVER|ENG_HTTP);
|
||||
is_ipv4 = peer_sa->sa_family == AF_INET;
|
||||
if (zero_rtt && zero_rtt_len)
|
||||
if (sess_resume && sess_resume_len)
|
||||
{
|
||||
version = lsquic_zero_rtt_version(zero_rtt, zero_rtt_len);
|
||||
version = lsquic_sess_resume_version(sess_resume, sess_resume_len);
|
||||
if (version >= N_LSQVER)
|
||||
{
|
||||
LSQ_INFO("zero-rtt version is bad, won't use");
|
||||
zero_rtt = NULL;
|
||||
zero_rtt_len = 0;
|
||||
LSQ_INFO("session resumption version is bad, won't use");
|
||||
sess_resume = NULL;
|
||||
sess_resume_len = 0;
|
||||
}
|
||||
}
|
||||
if (version >= N_LSQVER)
|
||||
|
@ -1627,11 +1627,11 @@ lsquic_engine_connect (lsquic_engine_t *engine, enum lsquic_version version,
|
|||
if (versions & LSQUIC_IETF_VERSIONS)
|
||||
conn = lsquic_ietf_full_conn_client_new(&engine->pub, versions,
|
||||
flags, hostname, max_packet_size,
|
||||
is_ipv4, zero_rtt, zero_rtt_len, token, token_sz);
|
||||
is_ipv4, sess_resume, sess_resume_len, token, token_sz);
|
||||
else
|
||||
conn = lsquic_gquic_full_conn_client_new(&engine->pub, versions,
|
||||
flags, hostname, max_packet_size, is_ipv4,
|
||||
zero_rtt, zero_rtt_len);
|
||||
sess_resume, sess_resume_len);
|
||||
if (!conn)
|
||||
goto err;
|
||||
EV_LOG_CREATE_CONN(lsquic_conn_log_cid(conn), local_sa, peer_sa);
|
||||
|
|
|
@ -554,9 +554,9 @@ lsquic_ev_log_hsk_completed (const lsquic_cid_t *cid)
|
|||
|
||||
|
||||
void
|
||||
lsquic_ev_log_zero_rtt (const lsquic_cid_t *cid)
|
||||
lsquic_ev_log_sess_resume (const lsquic_cid_t *cid)
|
||||
{
|
||||
LCID("zero_rtt successful");
|
||||
LCID("sess_resume successful");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -311,13 +311,13 @@ lsquic_ev_log_hsk_completed (const lsquic_cid_t *);
|
|||
|
||||
|
||||
void
|
||||
lsquic_ev_log_zero_rtt (const lsquic_cid_t *);
|
||||
lsquic_ev_log_sess_resume (const lsquic_cid_t *);
|
||||
|
||||
#define EV_LOG_ZERO_RTT(...) do { \
|
||||
#define EV_LOG_SESSION_RESUMPTION(...) do { \
|
||||
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
|
||||
lsquic_ev_log_zero_rtt(__VA_ARGS__); \
|
||||
lsquic_ev_log_sess_resume(__VA_ARGS__); \
|
||||
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_QLOG)) \
|
||||
lsquic_qlog_zero_rtt(__VA_ARGS__); \
|
||||
lsquic_qlog_sess_resume(__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
void
|
||||
|
|
|
@ -717,21 +717,21 @@ lsquic_gquic_full_conn_client_new (struct lsquic_engine_public *enpub,
|
|||
unsigned versions, unsigned flags,
|
||||
const char *hostname, unsigned short max_packet_size,
|
||||
int is_ipv4,
|
||||
const unsigned char *zero_rtt, size_t zero_rtt_len)
|
||||
const unsigned char *sess_resume, size_t sess_resume_len)
|
||||
{
|
||||
struct full_conn *conn;
|
||||
enum lsquic_version version, zero_rtt_version;
|
||||
enum lsquic_version version, sess_resume_version;
|
||||
lsquic_cid_t cid;
|
||||
const struct enc_session_funcs_gquic *esf_g;
|
||||
|
||||
versions &= (~LSQUIC_IETF_VERSIONS & LSQUIC_SUPPORTED_VERSIONS);
|
||||
assert(versions);
|
||||
version = highest_bit_set(versions);
|
||||
if (zero_rtt)
|
||||
if (sess_resume)
|
||||
{
|
||||
zero_rtt_version = lsquic_zero_rtt_version(zero_rtt, zero_rtt_len);
|
||||
if (zero_rtt_version < N_LSQVER && ((1 << zero_rtt_version) & versions))
|
||||
version = zero_rtt_version;
|
||||
sess_resume_version = lsquic_sess_resume_version(sess_resume, sess_resume_len);
|
||||
if (sess_resume_version < N_LSQVER && ((1 << sess_resume_version) & versions))
|
||||
version = sess_resume_version;
|
||||
}
|
||||
esf_g = select_esf_gquic_by_ver(version);
|
||||
lsquic_generate_cid_gquic(&cid);
|
||||
|
@ -751,7 +751,7 @@ lsquic_gquic_full_conn_client_new (struct lsquic_engine_public *enpub,
|
|||
conn->fc_conn.cn_esf.g = esf_g;
|
||||
conn->fc_conn.cn_enc_session =
|
||||
conn->fc_conn.cn_esf.g->esf_create_client(&conn->fc_conn, hostname,
|
||||
cid, conn->fc_enpub, zero_rtt, zero_rtt_len);
|
||||
cid, conn->fc_enpub, sess_resume, sess_resume_len);
|
||||
if (!conn->fc_conn.cn_enc_session)
|
||||
{
|
||||
LSQ_WARN("could not create enc session: %s", strerror(errno));
|
||||
|
@ -1368,10 +1368,10 @@ full_conn_ci_n_avail_streams (const lsquic_conn_t *lconn)
|
|||
|
||||
|
||||
static int
|
||||
handshake_done_or_doing_zero_rtt (const struct full_conn *conn)
|
||||
handshake_done_or_doing_sess_resume (const struct full_conn *conn)
|
||||
{
|
||||
return (conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE)
|
||||
|| conn->fc_conn.cn_esf_c->esf_is_zero_rtt_enabled(
|
||||
|| conn->fc_conn.cn_esf_c->esf_is_sess_resume_enabled(
|
||||
conn->fc_conn.cn_enc_session);
|
||||
}
|
||||
|
||||
|
@ -1380,7 +1380,7 @@ static void
|
|||
full_conn_ci_make_stream (struct lsquic_conn *lconn)
|
||||
{
|
||||
struct full_conn *conn = (struct full_conn *) lconn;
|
||||
if (handshake_done_or_doing_zero_rtt(conn)
|
||||
if (handshake_done_or_doing_sess_resume(conn)
|
||||
&& full_conn_ci_n_avail_streams(lconn) > 0)
|
||||
{
|
||||
if (!new_stream(conn, generate_stream_id(conn), SCF_CALL_ON_NEW))
|
||||
|
@ -3463,7 +3463,7 @@ full_conn_ci_tick (lsquic_conn_t *lconn, lsquic_time_t now)
|
|||
}
|
||||
|
||||
lsquic_send_ctl_set_buffer_stream_packets(&conn->fc_send_ctl, 0);
|
||||
if (!handshake_done_or_doing_zero_rtt(conn))
|
||||
if (!handshake_done_or_doing_sess_resume(conn))
|
||||
{
|
||||
process_hsk_stream_write_events(conn);
|
||||
goto end_write;
|
||||
|
@ -3639,12 +3639,12 @@ full_conn_ci_hsk_done (lsquic_conn_t *lconn, enum lsquic_hsk_status status)
|
|||
lsquic_alarmset_unset(&conn->fc_alset, AL_HANDSHAKE);
|
||||
switch (status)
|
||||
{
|
||||
case LSQ_HSK_0RTT_FAIL:
|
||||
case LSQ_HSK_RESUMED_FAIL:
|
||||
case LSQ_HSK_FAIL:
|
||||
conn->fc_flags |= FC_HSK_FAILED;
|
||||
break;
|
||||
case LSQ_HSK_OK:
|
||||
case LSQ_HSK_0RTT_OK:
|
||||
case LSQ_HSK_RESUMED_OK:
|
||||
if (0 == apply_peer_settings(conn))
|
||||
{
|
||||
if (conn->fc_flags & FC_HTTP)
|
||||
|
@ -3658,12 +3658,12 @@ full_conn_ci_hsk_done (lsquic_conn_t *lconn, enum lsquic_hsk_status status)
|
|||
if (conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_hsk_done)
|
||||
conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_hsk_done(lconn,
|
||||
status);
|
||||
if (status == LSQ_HSK_OK || status == LSQ_HSK_0RTT_OK)
|
||||
if (status == LSQ_HSK_OK || status == LSQ_HSK_RESUMED_OK)
|
||||
{
|
||||
if (conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_zero_rtt_info)
|
||||
conn->fc_conn.cn_esf.g->esf_maybe_dispatch_zero_rtt(
|
||||
if (conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_sess_resume_info)
|
||||
conn->fc_conn.cn_esf.g->esf_maybe_dispatch_sess_resume(
|
||||
conn->fc_conn.cn_enc_session,
|
||||
conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_zero_rtt_info);
|
||||
conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_sess_resume_info);
|
||||
if (conn->fc_n_delayed_streams)
|
||||
create_delayed_streams(conn);
|
||||
if (!(conn->fc_flags & FC_SERVER))
|
||||
|
@ -3721,6 +3721,7 @@ full_conn_ci_close (struct lsquic_conn *lconn)
|
|||
conn->fc_flags |= FC_CLOSING;
|
||||
if (!(conn->fc_flags & FC_GOAWAY_SENT))
|
||||
conn->fc_flags |= FC_SEND_GOAWAY;
|
||||
lsquic_engine_add_conn_to_tickable(conn->fc_enpub, lconn);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4204,7 +4205,7 @@ full_conn_ci_is_tickable (lsquic_conn_t *lconn)
|
|||
LSQ_DEBUG("tickable: there are sending streams");
|
||||
goto check_can_send;
|
||||
}
|
||||
if (handshake_done_or_doing_zero_rtt(conn))
|
||||
if (handshake_done_or_doing_sess_resume(conn))
|
||||
{
|
||||
TAILQ_FOREACH(stream, &conn->fc_pub.write_streams,
|
||||
next_write_stream)
|
||||
|
@ -4302,7 +4303,7 @@ lsquic_gquic_full_conn_srej (struct lsquic_conn *lconn)
|
|||
struct lsquic_stream *stream;
|
||||
enum lsquic_version version;
|
||||
|
||||
if (lconn->cn_esf_c->esf_is_zero_rtt_enabled(conn->fc_conn.cn_enc_session))
|
||||
if (lconn->cn_esf_c->esf_is_sess_resume_enabled(conn->fc_conn.cn_enc_session))
|
||||
{
|
||||
/* We need to do this because we do not clean up any data that may
|
||||
* have been already sent. This is left an optimization for the
|
||||
|
@ -4310,7 +4311,7 @@ lsquic_gquic_full_conn_srej (struct lsquic_conn *lconn)
|
|||
*/
|
||||
LSQ_DEBUG("received SREJ when 0RTT was on: fail handshake and let "
|
||||
"caller retry");
|
||||
full_conn_ci_hsk_done(lconn, LSQ_HSK_0RTT_FAIL);
|
||||
full_conn_ci_hsk_done(lconn, LSQ_HSK_RESUMED_FAIL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,14 +11,14 @@ lsquic_gquic_full_conn_client_new (struct lsquic_engine_public *,
|
|||
unsigned flags /* Only FC_SERVER and FC_HTTP */,
|
||||
const char *hostname, unsigned short max_packet_size,
|
||||
int is_ipv4,
|
||||
const unsigned char *zero_rtt, size_t zero_rtt_len);
|
||||
const unsigned char *sess_resume, size_t sess_resume_len);
|
||||
|
||||
struct lsquic_conn *
|
||||
lsquic_ietf_full_conn_client_new (struct lsquic_engine_public *,
|
||||
unsigned versions,
|
||||
unsigned flags /* Only FC_SERVER and FC_HTTP */,
|
||||
const char *hostname, unsigned short max_packet_size, int is_ipv4,
|
||||
const unsigned char *zero_rtt, size_t,
|
||||
const unsigned char *sess_resume, size_t,
|
||||
const unsigned char *token, size_t);
|
||||
|
||||
typedef struct lsquic_conn *
|
||||
|
|
|
@ -1158,12 +1158,12 @@ struct lsquic_conn *
|
|||
lsquic_ietf_full_conn_client_new (struct lsquic_engine_public *enpub,
|
||||
unsigned versions, unsigned flags,
|
||||
const char *hostname, unsigned short max_packet_size, int is_ipv4,
|
||||
const unsigned char *zero_rtt, size_t zero_rtt_sz,
|
||||
const unsigned char *sess_resume, size_t sess_resume_sz,
|
||||
const unsigned char *token, size_t token_sz)
|
||||
{
|
||||
const struct enc_session_funcs_iquic *esfi;
|
||||
struct ietf_full_conn *conn;
|
||||
enum lsquic_version ver, zero_rtt_version;
|
||||
enum lsquic_version ver, sess_resume_version;
|
||||
lsquic_time_t now;
|
||||
|
||||
conn = calloc(1, sizeof(*conn));
|
||||
|
@ -1181,11 +1181,11 @@ lsquic_ietf_full_conn_client_new (struct lsquic_engine_public *enpub,
|
|||
assert(versions);
|
||||
versions &= LSQUIC_IETF_VERSIONS;
|
||||
ver = highest_bit_set(versions);
|
||||
if (zero_rtt)
|
||||
if (sess_resume)
|
||||
{
|
||||
zero_rtt_version = lsquic_zero_rtt_version(zero_rtt, zero_rtt_sz);
|
||||
if (zero_rtt_version < N_LSQVER && ((1 << zero_rtt_version) & versions))
|
||||
ver = zero_rtt_version;
|
||||
sess_resume_version = lsquic_sess_resume_version(sess_resume, sess_resume_sz);
|
||||
if (sess_resume_version < N_LSQVER && ((1 << sess_resume_version) & versions))
|
||||
ver = sess_resume_version;
|
||||
}
|
||||
esfi = select_esf_iquic_by_ver(ver);
|
||||
|
||||
|
@ -1252,7 +1252,7 @@ lsquic_ietf_full_conn_client_new (struct lsquic_engine_public *enpub,
|
|||
conn->ifc_enpub, &conn->ifc_conn, CUR_DCID(conn),
|
||||
&conn->ifc_u.cli.ifcli_ver_neg,
|
||||
(void **) conn->ifc_u.cli.crypto_streams, &crypto_stream_if,
|
||||
zero_rtt, zero_rtt_sz, &conn->ifc_alset,
|
||||
sess_resume, sess_resume_sz, &conn->ifc_alset,
|
||||
conn->ifc_max_streams_in[SD_UNI]);
|
||||
if (!conn->ifc_conn.cn_enc_session)
|
||||
goto err2;
|
||||
|
@ -2560,6 +2560,7 @@ ietf_full_conn_ci_close (struct lsquic_conn *lconn)
|
|||
}
|
||||
conn->ifc_flags |= IFC_CLOSING;
|
||||
conn->ifc_send_flags |= SF_SEND_CONN_CLOSE;
|
||||
lsquic_engine_add_conn_to_tickable(conn->ifc_enpub, lconn);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3279,7 +3280,7 @@ ietf_full_conn_ci_hsk_done (struct lsquic_conn *lconn,
|
|||
switch (status)
|
||||
{
|
||||
case LSQ_HSK_OK:
|
||||
case LSQ_HSK_0RTT_OK:
|
||||
case LSQ_HSK_RESUMED_OK:
|
||||
if (0 == handshake_ok(lconn))
|
||||
{
|
||||
if (!(conn->ifc_flags & IFC_SERVER))
|
||||
|
@ -3297,7 +3298,7 @@ ietf_full_conn_ci_hsk_done (struct lsquic_conn *lconn,
|
|||
assert(0);
|
||||
/* fall-through */
|
||||
case LSQ_HSK_FAIL:
|
||||
case LSQ_HSK_0RTT_FAIL:
|
||||
case LSQ_HSK_RESUMED_FAIL:
|
||||
handshake_failed(lconn);
|
||||
break;
|
||||
}
|
||||
|
@ -7102,10 +7103,10 @@ ietf_full_conn_ci_n_avail_streams (const struct lsquic_conn *lconn)
|
|||
|
||||
|
||||
static int
|
||||
handshake_done_or_doing_zero_rtt (const struct ietf_full_conn *conn)
|
||||
handshake_done_or_doing_sess_resume (const struct ietf_full_conn *conn)
|
||||
{
|
||||
return (conn->ifc_conn.cn_flags & LSCONN_HANDSHAKE_DONE)
|
||||
|| conn->ifc_conn.cn_esf_c->esf_is_zero_rtt_enabled(
|
||||
|| conn->ifc_conn.cn_esf_c->esf_is_sess_resume_enabled(
|
||||
conn->ifc_conn.cn_enc_session);
|
||||
}
|
||||
|
||||
|
@ -7115,7 +7116,7 @@ ietf_full_conn_ci_make_stream (struct lsquic_conn *lconn)
|
|||
{
|
||||
struct ietf_full_conn *const conn = (struct ietf_full_conn *) lconn;
|
||||
|
||||
if (handshake_done_or_doing_zero_rtt(conn)
|
||||
if (handshake_done_or_doing_sess_resume(conn)
|
||||
&& ietf_full_conn_ci_n_avail_streams(lconn) > 0)
|
||||
{
|
||||
if (0 != create_bidi_stream_out(conn))
|
||||
|
|
|
@ -201,7 +201,7 @@ typedef struct c_cert_item_st
|
|||
} c_cert_item_t;
|
||||
|
||||
|
||||
struct lsquic_zero_rtt_storage
|
||||
struct lsquic_sess_resume_storage
|
||||
{
|
||||
uint32_t quic_version_tag;
|
||||
uint32_t serializer_version;
|
||||
|
@ -592,7 +592,7 @@ enum rtt_deserialize_return_type
|
|||
#define RTT_SERIALIZER_VERSION (1 << 0)
|
||||
|
||||
static void
|
||||
lsquic_enc_session_serialize_zero_rtt(struct lsquic_zero_rtt_storage *storage,
|
||||
lsquic_enc_session_serialize_sess_resume(struct lsquic_sess_resume_storage *storage,
|
||||
enum lsquic_version version,
|
||||
const lsquic_session_cache_info_t *info,
|
||||
const c_cert_item_t *cert_item)
|
||||
|
@ -643,8 +643,8 @@ lsquic_enc_session_serialize_zero_rtt(struct lsquic_zero_rtt_storage *storage,
|
|||
} while (0) \
|
||||
|
||||
static enum rtt_deserialize_return_type
|
||||
lsquic_enc_session_deserialize_zero_rtt(
|
||||
const struct lsquic_zero_rtt_storage *storage,
|
||||
lsquic_enc_session_deserialize_sess_resume(
|
||||
const struct lsquic_sess_resume_storage *storage,
|
||||
size_t storage_size,
|
||||
const struct lsquic_engine_settings *settings,
|
||||
lsquic_session_cache_info_t *info,
|
||||
|
@ -824,12 +824,12 @@ maybe_log_secrets (struct lsquic_enc_session *enc_session)
|
|||
static enc_session_t *
|
||||
lsquic_enc_session_create_client (struct lsquic_conn *lconn, const char *domain,
|
||||
lsquic_cid_t cid, const struct lsquic_engine_public *enpub,
|
||||
const unsigned char *zero_rtt, size_t zero_rtt_len)
|
||||
const unsigned char *sess_resume, size_t sess_resume_len)
|
||||
{
|
||||
lsquic_session_cache_info_t *info;
|
||||
struct lsquic_enc_session *enc_session;
|
||||
c_cert_item_t *item;
|
||||
const struct lsquic_zero_rtt_storage *zero_rtt_storage;
|
||||
const struct lsquic_sess_resume_storage *sess_resume_storage;
|
||||
|
||||
if (!domain)
|
||||
{
|
||||
|
@ -849,7 +849,7 @@ lsquic_enc_session_create_client (struct lsquic_conn *lconn, const char *domain,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (zero_rtt && zero_rtt_len > sizeof(struct lsquic_zero_rtt_storage))
|
||||
if (sess_resume && sess_resume_len > sizeof(struct lsquic_sess_resume_storage))
|
||||
{
|
||||
item = calloc(1, sizeof(*item));
|
||||
if (!item)
|
||||
|
@ -858,22 +858,22 @@ lsquic_enc_session_create_client (struct lsquic_conn *lconn, const char *domain,
|
|||
free(info);
|
||||
return NULL;
|
||||
}
|
||||
zero_rtt_storage = (const struct lsquic_zero_rtt_storage *)zero_rtt;
|
||||
switch (lsquic_enc_session_deserialize_zero_rtt(zero_rtt_storage,
|
||||
zero_rtt_len,
|
||||
sess_resume_storage = (const struct lsquic_sess_resume_storage *)sess_resume;
|
||||
switch (lsquic_enc_session_deserialize_sess_resume(sess_resume_storage,
|
||||
sess_resume_len,
|
||||
&enpub->enp_settings,
|
||||
info, item))
|
||||
{
|
||||
case RTT_DESERIALIZE_BAD_QUIC_VER:
|
||||
LSQ_ERROR("provided zero_rtt has unsupported QUIC version");
|
||||
LSQ_ERROR("provided sess_resume has unsupported QUIC version");
|
||||
free(item);
|
||||
break;
|
||||
case RTT_DESERIALIZE_BAD_SERIAL_VER:
|
||||
LSQ_ERROR("provided zero_rtt has bad serializer version");
|
||||
LSQ_ERROR("provided sess_resume has bad serializer version");
|
||||
free(item);
|
||||
break;
|
||||
case RTT_DESERIALIZE_BAD_CERT_SIZE:
|
||||
LSQ_ERROR("provided zero_rtt has bad cert size");
|
||||
LSQ_ERROR("provided sess_resume has bad cert size");
|
||||
free(item);
|
||||
break;
|
||||
case RTT_DESERIALIZE_OK:
|
||||
|
@ -2728,7 +2728,7 @@ lsquic_enc_session_handle_chlo_reply (enc_session_t *enc_session_p,
|
|||
enc_session->hsk_state = HSK_COMPLETED;
|
||||
EV_LOG_HSK_COMPLETED(&enc_session->cid);
|
||||
if (!(enc_session->es_flags & ES_RECV_REJ))
|
||||
EV_LOG_ZERO_RTT(&enc_session->cid);
|
||||
EV_LOG_SESSION_RESUMPTION(&enc_session->cid);
|
||||
break;
|
||||
default:
|
||||
ret = 1; /* XXX Why 1? */
|
||||
|
@ -3599,7 +3599,7 @@ lsquic_enc_session_verify_reset_token (enc_session_t *enc_session_p,
|
|||
|
||||
|
||||
static int
|
||||
lsquic_enc_session_did_zero_rtt_succeed (enc_session_t *enc_session_p)
|
||||
lsquic_enc_session_did_sess_resume_succeed (enc_session_t *enc_session_p)
|
||||
{
|
||||
struct lsquic_enc_session *const enc_session = enc_session_p;
|
||||
return !(enc_session->es_flags & ES_RECV_REJ);
|
||||
|
@ -3607,7 +3607,7 @@ lsquic_enc_session_did_zero_rtt_succeed (enc_session_t *enc_session_p)
|
|||
|
||||
|
||||
static int
|
||||
lsquic_enc_session_is_zero_rtt_enabled (enc_session_t *enc_session_p)
|
||||
lsquic_enc_session_is_sess_resume_enabled (enc_session_t *enc_session_p)
|
||||
{
|
||||
struct lsquic_enc_session *const enc_session = enc_session_p;
|
||||
return enc_session->info && enc_session->cert_item;
|
||||
|
@ -3689,7 +3689,7 @@ lsquic_enc_session_get_server_cert_chain (enc_session_t *enc_session_p)
|
|||
|
||||
|
||||
static void
|
||||
maybe_dispatch_zero_rtt (enc_session_t *enc_session_p,
|
||||
maybe_dispatch_sess_resume (enc_session_t *enc_session_p,
|
||||
void (*cb)(struct lsquic_conn *, const unsigned char *, size_t))
|
||||
{
|
||||
struct lsquic_enc_session *const enc_session = enc_session_p;
|
||||
|
@ -3700,7 +3700,7 @@ maybe_dispatch_zero_rtt (enc_session_t *enc_session_p,
|
|||
|
||||
if (!(enc_session->info && enc_session->cert_item && cb))
|
||||
{
|
||||
LSQ_DEBUG("no zero-rtt information or callback is not set");
|
||||
LSQ_DEBUG("no session resumption information or callback is not set");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3709,17 +3709,18 @@ maybe_dispatch_zero_rtt (enc_session_t *enc_session_p,
|
|||
sz += sizeof(uint32_t);
|
||||
sz += lsquic_str_len(&enc_session->cert_item->crts[i]);
|
||||
}
|
||||
sz += sizeof(struct lsquic_zero_rtt_storage);
|
||||
sz += sizeof(struct lsquic_sess_resume_storage);
|
||||
|
||||
buf = malloc(sz);
|
||||
if (!buf)
|
||||
{
|
||||
LSQ_WARN("malloc failed: cannot allocate %zu bytes for zero-rtt", sz);
|
||||
LSQ_WARN("malloc failed: cannot allocate %zu bytes for session "
|
||||
"resumption", sz);
|
||||
return;
|
||||
}
|
||||
|
||||
lsquic_enc_session_serialize_zero_rtt(
|
||||
(struct lsquic_zero_rtt_storage *) buf, lconn->cn_version,
|
||||
lsquic_enc_session_serialize_sess_resume(
|
||||
(struct lsquic_sess_resume_storage *) buf, lconn->cn_version,
|
||||
enc_session->info, enc_session->cert_item);
|
||||
|
||||
cb(lconn, buf, sz);
|
||||
|
@ -3796,8 +3797,8 @@ struct enc_session_funcs_common lsquic_enc_session_common_gquic_1 =
|
|||
.esf_tag_len = GQUIC_PACKET_HASH_SZ,
|
||||
.esf_get_server_cert_chain = lsquic_enc_session_get_server_cert_chain,
|
||||
.esf_verify_reset_token = lsquic_enc_session_verify_reset_token,
|
||||
.esf_did_zero_rtt_succeed = lsquic_enc_session_did_zero_rtt_succeed,
|
||||
.esf_is_zero_rtt_enabled = lsquic_enc_session_is_zero_rtt_enabled,
|
||||
.esf_did_sess_resume_succeed = lsquic_enc_session_did_sess_resume_succeed,
|
||||
.esf_is_sess_resume_enabled = lsquic_enc_session_is_sess_resume_enabled,
|
||||
.esf_set_conn = gquic_esf_set_conn,
|
||||
};
|
||||
|
||||
|
@ -4225,8 +4226,8 @@ struct enc_session_funcs_common lsquic_enc_session_common_gquic_2 =
|
|||
.esf_alg_keysize = lsquic_enc_session_alg_keysize,
|
||||
.esf_get_server_cert_chain = lsquic_enc_session_get_server_cert_chain,
|
||||
.esf_verify_reset_token = lsquic_enc_session_verify_reset_token,
|
||||
.esf_did_zero_rtt_succeed = lsquic_enc_session_did_zero_rtt_succeed,
|
||||
.esf_is_zero_rtt_enabled = lsquic_enc_session_is_zero_rtt_enabled,
|
||||
.esf_did_sess_resume_succeed = lsquic_enc_session_did_sess_resume_succeed,
|
||||
.esf_is_sess_resume_enabled = lsquic_enc_session_is_sess_resume_enabled,
|
||||
.esf_set_conn = gquic_esf_set_conn,
|
||||
/* These are different from gquic_1: */
|
||||
.esf_encrypt_packet = gquic2_esf_encrypt_packet,
|
||||
|
@ -4266,7 +4267,7 @@ struct enc_session_funcs_gquic lsquic_enc_session_gquic_gquic_1 =
|
|||
.esf_gen_chlo = lsquic_enc_session_gen_chlo,
|
||||
.esf_handle_chlo_reply = lsquic_enc_session_handle_chlo_reply,
|
||||
.esf_mem_used = lsquic_enc_session_mem_used,
|
||||
.esf_maybe_dispatch_zero_rtt = maybe_dispatch_zero_rtt,
|
||||
.esf_maybe_dispatch_sess_resume = maybe_dispatch_sess_resume,
|
||||
.esf_reset_cid = lsquic_enc_session_reset_cid,
|
||||
};
|
||||
|
||||
|
|
|
@ -111,6 +111,6 @@ enum hsk_failure_reason
|
|||
};
|
||||
|
||||
enum lsquic_version
|
||||
lsquic_zero_rtt_version (const unsigned char *, size_t);
|
||||
lsquic_sess_resume_version (const unsigned char *, size_t);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -590,7 +590,7 @@ ietf_mini_conn_ci_hsk_done (struct lsquic_conn *lconn,
|
|||
switch (status)
|
||||
{
|
||||
case LSQ_HSK_OK:
|
||||
case LSQ_HSK_0RTT_OK:
|
||||
case LSQ_HSK_RESUMED_OK:
|
||||
conn->imc_flags |= IMC_HSK_OK;
|
||||
conn->imc_conn.cn_flags |= LSCONN_HANDSHAKE_DONE;
|
||||
LSQ_DEBUG("handshake OK");
|
||||
|
|
|
@ -83,6 +83,7 @@ lsquic_qlog_create_connection (const lsquic_cid_t* cid,
|
|||
lsquic_time_now(), ip_version, srcip, dstip, srcport, dstport);
|
||||
}
|
||||
|
||||
|
||||
#define QLOG_FRAME_DICT_PREFIX_COMMA ",{\"frame_type\":\""
|
||||
#define QLOG_FRAME_DICT_PREFIX "{\"frame_type\":\""
|
||||
#define QLOG_FRAME_DICT_SUFFIX "\"}"
|
||||
|
@ -170,7 +171,7 @@ lsquic_qlog_hsk_completed (const lsquic_cid_t* cid)
|
|||
|
||||
|
||||
void
|
||||
lsquic_qlog_zero_rtt (const lsquic_cid_t* cid)
|
||||
lsquic_qlog_sess_resume (const lsquic_cid_t* cid)
|
||||
{
|
||||
LCID("[%" PRIu64 ",\"RECOVERY\",\"RTT_UPDATE\",\"PACKET_RX\","
|
||||
"{\"zero_rtt\":\"successful\"}]", lsquic_time_now());
|
||||
|
|
|
@ -80,7 +80,7 @@ void
|
|||
lsquic_qlog_hsk_completed (const lsquic_cid_t *);
|
||||
|
||||
void
|
||||
lsquic_qlog_zero_rtt (const lsquic_cid_t *);
|
||||
lsquic_qlog_sess_resume (const lsquic_cid_t *);
|
||||
|
||||
void
|
||||
lsquic_qlog_check_certs (const lsquic_cid_t *, const lsquic_str_t **, size_t);
|
||||
|
|
|
@ -412,7 +412,7 @@ lsquic_stream_destroy (lsquic_stream_t *);
|
|||
* failure. The latter may be caused by flow control violation or
|
||||
* invalid stream frame data, e.g. overlapping segments.
|
||||
*
|
||||
* Note that the caller does gives up control of `frame' no matter
|
||||
* Note that the caller gives up control of `frame' no matter
|
||||
* what this function returns.
|
||||
*
|
||||
* This data is read by the user using lsquic_stream_read() function.
|
||||
|
@ -436,9 +436,6 @@ lsquic_stream_rst_in (lsquic_stream_t *, uint64_t offset, uint64_t error_code);
|
|||
void
|
||||
lsquic_stream_stop_sending_in (struct lsquic_stream *, uint64_t error_code);
|
||||
|
||||
ssize_t
|
||||
lsquic_stream_read (lsquic_stream_t *stream, void *buf, size_t len);
|
||||
|
||||
uint64_t
|
||||
lsquic_stream_read_offset (const lsquic_stream_t *stream);
|
||||
|
||||
|
@ -448,11 +445,6 @@ lsquic_stream_read_offset (const lsquic_stream_t *stream);
|
|||
int
|
||||
lsquic_stream_tosend_fin (const lsquic_stream_t *stream);
|
||||
|
||||
/* Data to be sent out to the network is written using lsquic_stream_write().
|
||||
*/
|
||||
ssize_t
|
||||
lsquic_stream_write (lsquic_stream_t *stream, const void *buf, size_t len);
|
||||
|
||||
void
|
||||
lsquic_stream_window_update (lsquic_stream_t *stream, uint64_t offset);
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
struct ver_neg {
|
||||
unsigned vn_supp; /* Remaining options, including `vn_ver' */
|
||||
enum lsquic_version vn_ver; /* If client, current version sent to server
|
||||
* (zero_rtt version or highest supported);
|
||||
* (sess_resume version or highest supported);
|
||||
* if server, this is set to negotiated version.
|
||||
*/
|
||||
enum ver_neg_state {
|
||||
|
|
|
@ -44,7 +44,7 @@ main (void)
|
|||
|
||||
lsquic_qlog_packet_rx(&cid, NULL, NULL, 0);
|
||||
lsquic_qlog_hsk_completed(&cid);
|
||||
lsquic_qlog_zero_rtt(&cid);
|
||||
lsquic_qlog_sess_resume(&cid);
|
||||
lsquic_qlog_check_certs(&cid, NULL, 0);
|
||||
|
||||
lsquic_qlog_version_negotiation(&cid, NULL, NULL);
|
||||
|
|
Loading…
Reference in New Issue