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:
Dmitri Tikhonov 2020-07-06 17:35:21 -04:00
parent da99665b1c
commit 7483dee074
26 changed files with 359 additions and 273 deletions

View file

@ -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 2020-06-24
- 2.17.2 - 2.17.2
- [BUGFIX] Infinite loop in stream: advance read offset when discarding - [BUGFIX] Infinite loop in stream: advance read offset when discarding

View file

@ -15,7 +15,7 @@ and OpenLiteSpeed. We think it is free of major problems. Nevertheless, do
not hesitate to report bugs back to us. Even better, send us fixes and not hesitate to report bugs back to us. Even better, send us fixes and
improvements! 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. Support for newer versions will be added soon after they are released.
Documentation Documentation

View file

@ -187,10 +187,10 @@ struct http_client_ctx {
unsigned hcc_reset_after_nbytes; unsigned hcc_reset_after_nbytes;
unsigned hcc_retire_cid_after_nbytes; unsigned hcc_retire_cid_after_nbytes;
char *hcc_zero_rtt_file_name; char *hcc_sess_resume_file_name;
enum { enum {
HCC_SKIP_0RTT = (1 << 0), HCC_SKIP_SESS_RESUME = (1 << 0),
HCC_SEEN_FIN = (1 << 1), HCC_SEEN_FIN = (1 << 1),
HCC_ABORT_ON_INCOMPLETE = (1 << 2), HCC_ABORT_ON_INCOMPLETE = (1 << 2),
} hcc_flags; } hcc_flags;
@ -212,7 +212,7 @@ struct lsquic_conn_ctx {
* never exceed hcc_cc_reqs_per_conn in client_ctx. * never exceed hcc_cc_reqs_per_conn in client_ctx.
*/ */
enum { enum {
CH_ZERO_RTT_SAVED = 1 << 0, CH_SESSION_RESUME_SAVED = 1 << 0,
} ch_flags; } ch_flags;
}; };
@ -240,31 +240,31 @@ create_connections (struct http_client_ctx *client_ctx)
{ {
size_t len; size_t len;
FILE *file; FILE *file;
unsigned char zero_rtt[0x2000]; unsigned char sess_resume[0x2000];
if (0 == (client_ctx->hcc_flags & HCC_SKIP_0RTT) if (0 == (client_ctx->hcc_flags & HCC_SKIP_SESS_RESUME)
&& client_ctx->hcc_zero_rtt_file_name) && 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) if (!file)
{ {
LSQ_DEBUG("cannot open %s for reading: %s", 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; 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)) if (0 == len && !feof(file))
LSQ_WARN("error reading %s: %s", 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); fclose(file);
LSQ_INFO("create connection zero_rtt %zu bytes", len); LSQ_INFO("create connection sess_resume %zu bytes", len);
} }
else no_file: else no_file:
len = 0; len = 0;
while (client_ctx->hcc_n_open_conns < client_ctx->hcc_concurrency && while (client_ctx->hcc_n_open_conns < client_ctx->hcc_concurrency &&
client_ctx->hcc_total_n_reqs > 0) 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"); LSQ_ERROR("connection failed");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -377,7 +377,7 @@ http_client_on_conn_closed (lsquic_conn_t *conn)
static int static int
hsk_status_ok (enum lsquic_hsk_status status) 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)) if (hsk_status_ok(status))
LSQ_INFO("handshake success %s", 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) else if (status == LSQ_HSK_FAIL)
LSQ_INFO("handshake failed"); 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"); LSQ_INFO("handshake failed because of session resumption, will retry "
client_ctx->hcc_flags |= HCC_SKIP_0RTT; "without it");
client_ctx->hcc_flags |= HCC_SKIP_SESS_RESUME;
++client_ctx->hcc_concurrency; ++client_ctx->hcc_concurrency;
++client_ctx->hcc_total_n_reqs; ++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 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) size_t bufsz)
{ {
lsquic_conn_ctx_t *const conn_h = lsquic_conn_get_ctx(conn); 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; FILE *file;
size_t nw; 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 /* Our client is rather limited: only one file and only one ticket per
* connection can be saved. * 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; return;
} }
file = fopen(client_ctx->hcc_zero_rtt_file_name, "wb"); file = fopen(client_ctx->hcc_sess_resume_file_name, "wb");
if (!file) if (!file)
{ {
LSQ_WARN("cannot open %s for writing: %s", 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; return;
} }
nw = fwrite(buf, 1, bufsz, file); nw = fwrite(buf, 1, bufsz, file);
if (nw == bufsz) if (nw == bufsz)
{ {
LSQ_DEBUG("wrote %zd bytes of zero-rtt information to %s", LSQ_DEBUG("wrote %zd bytes of session resumption information to %s",
nw, client_ctx->hcc_zero_rtt_file_name); nw, client_ctx->hcc_sess_resume_file_name);
conn_h->ch_flags |= CH_ZERO_RTT_SAVED; conn_h->ch_flags |= CH_SESSION_RESUME_SAVED;
} }
else else
LSQ_WARN("error: fwrite(%s) returns %zd instead of %zd: %s", 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); fclose(file);
} }
@ -1536,8 +1538,8 @@ main (int argc, char **argv)
client_ctx.hcc_retire_cid_after_nbytes = atoi(optarg); client_ctx.hcc_retire_cid_after_nbytes = atoi(optarg);
break; break;
case '0': case '0':
http_client_if.on_zero_rtt_info = http_client_on_zero_rtt_info; http_client_if.on_sess_resume_info = http_client_on_sess_resume_info;
client_ctx.hcc_zero_rtt_file_name = optarg; client_ctx.hcc_sess_resume_file_name = optarg;
break; break;
default: default:
if (0 != prog_set_opt(&prog, opt, optarg)) if (0 != prog_set_opt(&prog, opt, optarg))

View file

@ -376,7 +376,7 @@ prog_eb (struct prog *prog)
int 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; 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 */ /* SNI is required for HTTP */
: prog->prog_engine_flags & LSENG_HTTP ? sport->host : prog->prog_engine_flags & LSENG_HTTP ? sport->host
: NULL, : 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)) sport->sp_token_buf, sport->sp_token_sz))
return -1; return -1;

View file

@ -54,6 +54,10 @@ developed by the IETF. Both types are included in a single enum:
IETF QUIC version ID 28 IETF QUIC version ID 28
.. member:: LSQVER_ID29
IETF QUIC version ID 29
.. member:: N_LSQVER .. member:: N_LSQVER
Special value indicating the number of versions in the enum. It 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. Experimental versions.
.. macro: LSQUIC_DEPRECATED_VERSIONS .. macro:: LSQUIC_DEPRECATED_VERSIONS
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 .. 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 To LSQUIC, this is just an opaque pointer. User code is expected to
use it for its own purposes. use it for its own purposes.
@ -186,7 +190,8 @@ created:
Create a new engine. 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`. :param api: Pointer to an initialized :type:`lsquic_engine_api`.
The engine can be instantiated either in server mode (when ``LSENG_SERVER`` 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 for Google QUIC connections and HTTP/3 functionality for IETF QUIC
connections. 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) .. function:: void lsquic_engine_cooldown (lsquic_engine_t *engine)
This function closes all mini connections and marks all full connections 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 In a multi-process setup, it may be useful to observe the CID
lifecycle. This optional set of callbacks makes it possible. 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: .. _apiref-engine-settings:
Engine Settings Engine Settings
@ -307,17 +329,27 @@ settings structure:
.. member:: unsigned es_max_cfcw .. member:: unsigned es_max_cfcw
This value is used to specify maximum allowed value connection flow This value is used to specify maximum allowed value CFCW is allowed
control window is allowed to reach due to window auto-tuning. By to reach due to window auto-tuning. By default, this value is zero,
default, this value is zero, which means that CFCW is not allowed which means that CFCW is not allowed to increase from its initial
to increase from its initial value. 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 .. member:: unsigned es_max_sfcw
This value is used to specify maximum allowed value stream flow This value is used to specify the maximum value stream flow control
control window is allowed to reach due to window auto-tuning. By window is allowed to reach due to auto-tuning. By default, this
default, this value is zero, which means that CFCW is not allowed value is zero, meaning that auto-tuning is turned off.
to increase from its initial value.
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 .. member:: unsigned es_max_streams_in
@ -397,9 +429,11 @@ settings structure:
(source-addr, dest-addr) tuple, thereby making it necessary to create (source-addr, dest-addr) tuple, thereby making it necessary to create
a socket for each connection. 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. CIDs in the short packets.
This setting is applicable to gQUIC only.
The default is :func:`LSQUIC_DF_SUPPORT_TCID0`. The default is :func:`LSQUIC_DF_SUPPORT_TCID0`.
.. member:: int es_support_nstp .. member:: int es_support_nstp
@ -421,6 +455,8 @@ settings structure:
receives corresponding Public Reset packet. The default is to receives corresponding Public Reset packet. The default is to
ignore these packets. ignore these packets.
The default is :macro:`LSQUIC_DF_HONOR_PRST`.
.. member:: int es_send_prst .. member:: int es_send_prst
If set to true value, the library will send Public Reset packets If set to true value, the library will send Public Reset packets
@ -457,7 +493,7 @@ settings structure:
.. member:: unsigned es_proc_time_thresh .. 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_process_conns()` and
:func:`lsquic_engine_send_unsent_packets()` are allowed to spend :func:`lsquic_engine_send_unsent_packets()` are allowed to spend
before returning. before returning.
@ -842,7 +878,7 @@ out of date. Please check your :file:`lsquic.h` for actual values.*
Default clock granularity is 1000 microseconds. 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. 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. 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 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 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) .. function:: int lsquic_engine_has_unsent_packets (lsquic_engine_t *engine)
Returns true if engine has some unsent packets. This happens if 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) .. 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 .. type:: struct lsquic_stream_if
.. member:: lsquic_conn_ctx_t *(*on_new_conn)(void *stream_if_ctx, .. member:: lsquic_conn_ctx_t *(*on_new_conn)(void *stream_if_ctx, lsquic_conn_t *)
lsquic_conn_t *);
Called when a new connection has been created. In server mode, Called when a new connection has been created. In server mode,
this means that the handshake has been successful. In client 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. 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 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. This callback is optional.
@ -1115,19 +1152,19 @@ Creating Connections
-------------------- --------------------
In server mode, the connections are created by the library based on incoming 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. callback.
In client mode, a new connection is created by 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 engine: Engine to use.
:param version: :param version:
To let the engine specify QUIC version, use N_LSQVER. If zero-rtt info is To let the engine specify QUIC version, use N_LSQVER. If session resumption
supplied, version is picked from there instead. information is supplied, version is picked from there instead.
:param local_sa: :param local_sa:
@ -1139,7 +1176,7 @@ In client mode, a new connection is created by
:param peer_ctx: :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: :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` Maximum packet size. If set to zero, it is inferred based on `peer_sa`
and `version`. and `version`.
:param zero_rtt: :param sess_resume:
Pointer to previously saved zero-RTT data needed for TLS resumption. Pointer to previously saved session resumption data needed for
May be NULL. 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: :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 packet. Tokens are used by IETF QUIC to pre-validate client
connections, potentially avoiding a retry. 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. May be NULL.
@ -1193,7 +1230,8 @@ Closing Connections
.. function:: void lsquic_conn_close (lsquic_conn_t *conn) .. 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 Creating Streams
---------------- ----------------
@ -1390,10 +1428,6 @@ more information.
the buffer for headers the buffer for headers
.. member:: const char *name_ptr
the name pointer can be optionally set for encoding
.. member:: uint32_t name_hash .. member:: uint32_t name_hash
hash value for name hash value for name
@ -1593,7 +1627,7 @@ Push Promises
Only makes sense in server mode: the client cannot push a stream and this Only makes sense in server mode: the client cannot push a stream and this
function always returns false in client mode. 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. :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) .. function:: int lsquic_stream_set_priority (lsquic_stream_t *stream, unsigned priority)
Set stream priority. Valid priority values are 1 through 256, inclusive. 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). :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. 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. 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 This function is used to release the allocated buffer after it is
sent via ``ea_packets_out()``. 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 If allocated buffer is not going to be sent, return it to the
caller using this function. caller using this function.

View file

@ -24,9 +24,9 @@ copyright = u'2020, LiteSpeed Technologies'
author = u'LiteSpeed Technologies' author = u'LiteSpeed Technologies'
# The short X.Y version # The short X.Y version
version = u'2.17' version = u'2.18'
# The full version, including alpha/beta/rc tags # The full version, including alpha/beta/rc tags
release = u'2.17.2' release = u'2.18.0'
# -- General configuration --------------------------------------------------- # -- General configuration ---------------------------------------------------

View file

@ -91,11 +91,12 @@ Engine instantiation is performed by :func:`lsquic_engine_new()`:
lsquic_engine_t *engine lsquic_engine_t *engine
= lsquic_engine_new(LSENG_SERVER|LSENG_HTTP, &engine_api); = lsquic_engine_new(LSENG_SERVER|LSENG_HTTP, &engine_api);
The engine mode is selected by using the ``LSENG_SERVER`` flag. If The engine mode is selected by using the :macro:`LSENG_SERVER` flag.
present, the engine will be in server mode; if not, the engine will If present, the engine will be in server mode; if not, the engine will
be in client mode. 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 hides the interaction between the HTTP application layer and the QUIC
transport layer and presents a simple, unified (between Google QUIC and transport layer and presents a simple, unified (between Google QUIC and
HTTP/3) way of sending and receiving HTTP messages. Behind the scenes, HTTP/3) way of sending and receiving HTTP messages. Behind the scenes,

View file

@ -24,8 +24,8 @@ extern "C" {
#endif #endif
#define LSQUIC_MAJOR_VERSION 2 #define LSQUIC_MAJOR_VERSION 2
#define LSQUIC_MINOR_VERSION 17 #define LSQUIC_MINOR_VERSION 18
#define LSQUIC_PATCH_VERSION 2 #define LSQUIC_PATCH_VERSION 0
/** /**
* Engine flags: * Engine flags:
@ -131,18 +131,18 @@ enum lsquic_hsk_status
*/ */
LSQ_HSK_FAIL, LSQ_HSK_FAIL,
/** /**
* The handshake succeeded without 0-RTT. * The handshake succeeded without session resumption.
*/ */
LSQ_HSK_OK, 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 * Session resumption failed. Retry the connection without session
* the connection without 0-RTT. * 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); void (*on_close) (lsquic_stream_t *s, lsquic_stream_ctx_t *h);
/* This callback in only called in client mode */ /* This callback in only called in client mode */
/** /**
* When handshake is completed, this callback is called. `ok' is set * When handshake is completed, this optional callback is called.
* to true if handshake was successful; otherwise, `ok' is set to
* false.
*
* This callback is optional.
*/ */
void (*on_hsk_done)(lsquic_conn_t *c, enum lsquic_hsk_status s); 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); size_t token_size);
/** /**
* This optional callback lets client record information needed to * 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; struct ssl_ctx_st;
@ -206,7 +202,7 @@ struct ssl_st;
struct lsxpack_header; 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 * accomplished by providing a callback and a context to the engine
* constructor. * constructor.
*/ */
@ -397,10 +393,22 @@ struct lsquic_engine_settings {
* which means that CFCW is not allowed to increase from its initial * which means that CFCW is not allowed to increase from its initial
* value. * 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; 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; unsigned es_max_sfcw;
/** MIDS */ /** MIDS */
@ -470,9 +478,11 @@ struct lsquic_engine_settings {
* (source-addr, dest-addr) tuple, thereby making it necessary to create * (source-addr, dest-addr) tuple, thereby making it necessary to create
* a socket for each connection. * 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. * CIDs in the short packets.
* *
* This setting is applicable to gQUIC only.
*
* The default is @ref LSQUIC_DF_SUPPORT_TCID0. * The default is @ref LSQUIC_DF_SUPPORT_TCID0.
*/ */
int es_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 * This option does not affect the server, as it must support NSTP mode
* if it was specified by the client. * if it was specified by the client.
*
* This setting is applicable to gQUIC only.
*/ */
int es_support_nstp; int es_support_nstp;
@ -493,6 +505,8 @@ struct lsquic_engine_settings {
* If set to true value, the library will drop connections when it * If set to true value, the library will drop connections when it
* receives corresponding Public Reset packet. The default is to * receives corresponding Public Reset packet. The default is to
* ignore these packets. * ignore these packets.
*
* The default is @ref LSQUIC_DF_HONOR_PRST.
*/ */
int es_honor_prst; int es_honor_prst;
@ -533,7 +547,7 @@ struct lsquic_engine_settings {
int es_rw_once; 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_process_conns() and
* @ref lsquic_engine_send_unsent_packets() are allowed to spend * @ref lsquic_engine_send_unsent_packets() are allowed to spend
* before returning. * before returning.
@ -563,6 +577,29 @@ struct lsquic_engine_settings {
*/ */
unsigned es_clock_granularity; 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. */ /* The following settings are specific to IETF QUIC. */
/* vvvvvvvvvvv */ /* vvvvvvvvvvv */
@ -578,15 +615,27 @@ struct lsquic_engine_settings {
unsigned es_init_max_data; 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. * This is a transport parameter.
* *
* Depending on the engine mode, the default value is either * 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. * @ref LSQUIC_DF_INIT_MAX_STREAM_DATA_BIDI_REMOTE_SERVER.
*/ */
unsigned es_init_max_stream_data_bidi_remote; 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; unsigned es_init_max_stream_data_bidi_local;
/** /**
@ -710,15 +759,6 @@ struct lsquic_engine_settings {
*/ */
int es_allow_migration; 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: * Use QL loss bits. Allowed values are:
* 0: Do not use loss bits * 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 * Default value is @ref LSQUIC_DF_MAX_UDP_PAYLOAD_SIZE_RX
*/ */
unsigned short es_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 */ /* Initialize `settings' to default values */
@ -881,19 +907,19 @@ struct lsquic_packout_mem_if
/** /**
* Allocate buffer for sending. * 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); char is_ipv6);
/** /**
* This function is used to release the allocated buffer after it is * This function is used to release the allocated buffer after it is
* sent via @ref ea_packets_out. * 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); char is_ipv6);
/** /**
* If allocated buffer is not going to be sent, return it to the caller * If allocated buffer is not going to be sent, return it to the caller
* using this function. * 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); char is_ipv6);
}; };
@ -1076,7 +1102,7 @@ struct lsquic_engine_api
void *ea_keylog_ctx; 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. * is not set.
*/ */
const char *ea_alpn; 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'. * Create a client connection to peer identified by `peer_ctx'.
* *
* To let the engine specify QUIC version, use N_LSQVER. If zero-rtt info * To let the engine specify QUIC version, use N_LSQVER. If session resumption
* is supplied, version is picked from there instead. * 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': * If `max_udp_payload_size' is set to zero, it is inferred based on `peer_sa':
* 1350 for IPv6 and 1370 for IPv4. * 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, const struct sockaddr *peer_sa,
void *peer_ctx, lsquic_conn_ctx_t *conn_ctx, void *peer_ctx, lsquic_conn_ctx_t *conn_ctx,
const char *hostname, unsigned short max_udp_payload_size, 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 */ /** Resumption token: optional */
const unsigned char *token, size_t token_sz); 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 * 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 int
lsquic_engine_has_unsent_packets (lsquic_engine_t *engine); 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. * Set stream priority. Valid priority values are 1 through 256, inclusive.
* Lower value means higher priority.
* *
* @retval 0 Success. * @retval 0 Success.
* @retval -1 Priority value is invalid. * @retval -1 Priority value is invalid.

View file

@ -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)) if (c_hsk->lconn->cn_esf.g->esf_is_hsk_done(c_hsk->lconn->cn_enc_session))
{ {
LSQ_DEBUG("handshake is successful, inform connection"); LSQ_DEBUG("handshake is successful, inform connection");
status = (c_hsk->lconn->cn_esf_c->esf_did_zero_rtt_succeed( status = (c_hsk->lconn->cn_esf_c->esf_did_sess_resume_succeed(
c_hsk->lconn->cn_enc_session)) ? LSQ_HSK_0RTT_OK : LSQ_HSK_OK; 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); c_hsk->lconn->cn_if->ci_hsk_done(c_hsk->lconn, status);
} }
else else

View file

@ -115,10 +115,10 @@ struct enc_session_funcs_common
(*esf_verify_reset_token) (enc_session_t *, const unsigned char *, size_t); (*esf_verify_reset_token) (enc_session_t *, const unsigned char *, size_t);
int int
(*esf_did_zero_rtt_succeed) (enc_session_t *); (*esf_did_sess_resume_succeed) (enc_session_t *);
int int
(*esf_is_zero_rtt_enabled) (enc_session_t *); (*esf_is_sess_resume_enabled) (enc_session_t *);
void void
(*esf_set_conn) (enc_session_t *, struct lsquic_conn *); (*esf_set_conn) (enc_session_t *, struct lsquic_conn *);
@ -231,11 +231,12 @@ struct enc_session_funcs_gquic
size_t size_t
(*esf_mem_used)(enc_session_t *); (*esf_mem_used)(enc_session_t *);
/* Zero-rtt serialization needs the knowledge of the QUIC version, that's /* Session resumption serialization needs the knowledge of the QUIC
* why there is a separate method for thus. Plus, we want to be able to * version, that's why there is a separate method for thus. Plus, we
* call it after the "handshake is done" callback is called. * 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 (*cb)(struct lsquic_conn *, const unsigned char *, size_t));
void (*esf_reset_cid) (enc_session_t *, const lsquic_cid_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 #define ALERT_NO_APPLICATION_PROTOCOL 120
enum lsquic_version 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. /* This is seems to be true for all of the ciphers used by IETF QUIC.
* XXX: Perhaps add a check? * XXX: Perhaps add a check?

View file

@ -20,7 +20,7 @@ const char *const lsquic_enclev2str[] =
enum lsquic_version 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; lsquic_ver_tag_t tag;

View file

@ -247,8 +247,8 @@ struct enc_sess_iquic
char *esi_sni_bypass; char *esi_sni_bypass;
#endif #endif
const unsigned char *esi_alpn; const unsigned char *esi_alpn;
unsigned char *esi_zero_rtt_buf; unsigned char *esi_sess_resume_buf;
size_t esi_zero_rtt_sz; size_t esi_sess_resume_sz;
/* Need MD and AEAD for key rotation */ /* Need MD and AEAD for key rotation */
const EVP_MD *esi_md; const EVP_MD *esi_md;
const EVP_AEAD *esi_aead; 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 ] * uint8_t trapa_buf[ trapa_size ]
*/ */
#define ZERO_RTT_VERSION 1 #define SESS_RESUME_VERSION 1
#if __BYTE_ORDER == __LITTLE_ENDIAN #if __BYTE_ORDER == __LITTLE_ENDIAN
#define READ_NUM(var_, ptr_) do { \ #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; uint32_t rtt_ver, ticket_sz, trapa_sz;
const unsigned char *ticket_buf, *trapa_buf, *p; const unsigned char *ticket_buf, *trapa_buf, *p;
const unsigned char *const end 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)) < sizeof(ver_tag) + sizeof(rtt_ver) + sizeof(ticket_sz))
{ {
LSQ_DEBUG("rtt buf too short"); LSQ_DEBUG("rtt buf too short");
return NULL; return NULL;
} }
p = enc_sess->esi_zero_rtt_buf; p = enc_sess->esi_sess_resume_buf;
memcpy(&ver_tag, p, sizeof(ver_tag)); memcpy(&ver_tag, p, sizeof(ver_tag));
p += sizeof(ver_tag); p += sizeof(ver_tag);
quic_ver = lsquic_tag2ver(ver_tag); quic_ver = lsquic_tag2ver(ver_tag);
if (quic_ver != enc_sess->esi_ver_neg->vn_ver) if (quic_ver != enc_sess->esi_ver_neg->vn_ver)
{ {
LSQ_DEBUG("negotiated version %s does not match that in the zero-rtt " LSQ_DEBUG("negotiated version %s does not match that in the session "
"info buffer", lsquic_ver2str[enc_sess->esi_ver_neg->vn_ver]); "resumption nfo buffer",
lsquic_ver2str[enc_sess->esi_ver_neg->vn_ver]);
return NULL; return NULL;
} }
READ_NUM(rtt_ver, p); 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", " LSQ_DEBUG("cannot use session resumption buffer: encoded using "
"while current version is %u", rtt_ver, ZERO_RTT_VERSION); "%"PRIu32", while current version is %u",
rtt_ver, SESS_RESUME_VERSION);
return NULL; return NULL;
} }
@ -759,7 +761,7 @@ iquic_esfi_create_client (const char *hostname,
struct lsquic_engine_public *enpub, struct lsquic_conn *lconn, struct lsquic_engine_public *enpub, struct lsquic_conn *lconn,
const lsquic_cid_t *dcid, const struct ver_neg *ver_neg, const lsquic_cid_t *dcid, const struct ver_neg *ver_neg,
void *crypto_streams[4], const struct crypto_stream_if *cryst_if, 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 lsquic_alarmset *alset, unsigned max_streams_uni)
{ {
struct enc_sess_iquic *enc_sess; 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 /* Have to wait until the call to init_client() -- this is when the
* result of version negotiation is known. * 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); enc_sess->esi_sess_resume_buf = malloc(sess_resume_sz);
if (enc_sess->esi_zero_rtt_buf) if (enc_sess->esi_sess_resume_buf)
{ {
memcpy(enc_sess->esi_zero_rtt_buf, zero_rtt, zero_rtt_sz); memcpy(enc_sess->esi_sess_resume_buf, sess_resume, sess_resume_sz);
enc_sess->esi_zero_rtt_sz = zero_rtt_sz; enc_sess->esi_sess_resume_sz = sess_resume_sz;
} }
else else
enc_sess->esi_zero_rtt_sz = 0; enc_sess->esi_sess_resume_sz = 0;
} }
else else
{ {
enc_sess->esi_zero_rtt_buf = NULL; enc_sess->esi_sess_resume_buf = NULL;
enc_sess->esi_zero_rtt_sz = 0; 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_flags |= ESI_WANT_TICKET;
enc_sess->esi_alset = alset; enc_sess->esi_alset = alset;
lsquic_alarmset_init_alarm(enc_sess->esi_alset, AL_SESS_TICKET, lsquic_alarmset_init_alarm(enc_sess->esi_alset, AL_SESS_TICKET,
@ -1145,10 +1147,14 @@ iquic_lookup_cert (SSL *ssl, void *arg)
#endif #endif
if (!server_name) 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) 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); path = enc_sess->esi_conn->cn_if->ci_get_path(enc_sess->esi_conn, NULL);
@ -1268,6 +1274,7 @@ iquic_esfi_init_server (enc_session_t *enc_session_p)
} }
SSL_clear_options(enc_sess->esi_ssl, SSL_OP_NO_TLSv1_3); SSL_clear_options(enc_sess->esi_ssl, SSL_OP_NO_TLSv1_3);
if (enc_sess->esi_enpub->enp_lookup_cert)
SSL_set_cert_cb(enc_sess->esi_ssl, iquic_lookup_cert, enc_sess); 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_ex_data(enc_sess->esi_ssl, s_idx, enc_sess);
SSL_set_accept_state(enc_sess->esi_ssl); SSL_set_accept_state(enc_sess->esi_ssl);
@ -1305,13 +1312,14 @@ iquic_new_session_cb (SSL *ssl, SSL_SESSION *session)
size_t trapa_sz, buf_sz; size_t trapa_sz, buf_sz;
enc_sess = SSL_get_ex_data(ssl, s_idx); 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, SSL_get_peer_quic_transport_params(enc_sess->esi_ssl, &trapa_buf,
&trapa_sz); &trapa_sz);
if (!(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; return 0;
} }
if (trapa_sz > UINT32_MAX) if (trapa_sz > UINT32_MAX)
@ -1347,7 +1355,7 @@ iquic_new_session_cb (SSL *ssl, SSL_SESSION *session)
memcpy(p, &tag, sizeof(tag)); memcpy(p, &tag, sizeof(tag));
p += 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); WRITE_NUM(num, ticket_sz, p);
memcpy(p, ticket_buf, ticket_sz); memcpy(p, ticket_buf, ticket_sz);
p += ticket_sz; p += ticket_sz;
@ -1358,9 +1366,9 @@ iquic_new_session_cb (SSL *ssl, SSL_SESSION *session)
assert(buf + buf_sz == p); assert(buf + buf_sz == p);
OPENSSL_free(ticket_buf); 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); buf, buf_sz);
free(buf); free(buf);
enc_sess->esi_flags &= ~ESI_WANT_TICKET; 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_max_proto_version(ssl_ctx, TLS1_3_VERSION);
SSL_CTX_set_default_verify_paths(ssl_ctx); SSL_CTX_set_default_verify_paths(ssl_ctx);
SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_CLIENT); 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); SSL_CTX_sess_set_new_cb(ssl_ctx, iquic_new_session_cb);
if (enc_sess->esi_enpub->enp_kli) if (enc_sess->esi_enpub->enp_kli)
SSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback); 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); free(enc_sess->esi_hostname);
enc_sess->esi_hostname = NULL; 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); ssl_session = maybe_create_SSL_SESSION(enc_sess, ssl_ctx);
if (ssl_session) if (ssl_session)
@ -1744,7 +1752,7 @@ iquic_esfi_handshake (struct enc_sess_iquic *enc_sess)
return IHS_WANT_WRITE; return IHS_WANT_WRITE;
case SSL_ERROR_EARLY_DATA_REJECTED: case SSL_ERROR_EARLY_DATA_REJECTED:
LSQ_DEBUG("early data rejected"); LSQ_DEBUG("early data rejected");
hsk_status = LSQ_HSK_0RTT_FAIL; hsk_status = LSQ_HSK_RESUMED_FAIL;
goto err; goto err;
/* fall through */ /* fall through */
default: default:
@ -1767,14 +1775,14 @@ iquic_esfi_handshake (struct enc_sess_iquic *enc_sess)
hsk_status = LSQ_HSK_OK; hsk_status = LSQ_HSK_OK;
LSQ_DEBUG("handshake reported complete"); LSQ_DEBUG("handshake reported complete");
EV_LOG_HSK_COMPLETED(LSQUIC_LOG_CONN_ID); EV_LOG_HSK_COMPLETED(LSQUIC_LOG_CONN_ID);
/* The ESI_USE_SSL_TICKET flag indicates if the client attempted 0-RTT. /* The ESI_USE_SSL_TICKET flag indicates if the client attempted session
* If the handshake is complete, and the client attempted 0-RTT, it * resumption. If the handshake is complete, and the client attempted
* must have succeeded. * session resumption, it must have succeeded.
*/ */
if (enc_sess->esi_flags & ESI_USE_SSL_TICKET) if (enc_sess->esi_flags & ESI_USE_SSL_TICKET)
{ {
hsk_status = LSQ_HSK_0RTT_OK; hsk_status = LSQ_HSK_RESUMED_OK;
EV_LOG_ZERO_RTT(LSQUIC_LOG_CONN_ID); EV_LOG_SESSION_RESUMPTION(LSQUIC_LOG_CONN_ID);
} }
if (0 != maybe_get_peer_transport_params(enc_sess)) 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); free_handshake_keys(enc_sess);
cleanup_hp(&enc_sess->esi_hp); 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->esi_hostname);
free(enc_sess); free(enc_sess);
} }
@ -2407,10 +2415,10 @@ iquic_esf_alg_keysize (enc_session_t *enc_session_p)
static int 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; 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_cipher = iquic_esf_cipher,
.esf_keysize = iquic_esf_keysize, .esf_keysize = iquic_esf_keysize,
.esf_alg_keysize = iquic_esf_alg_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, .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_cipher = iquic_esf_cipher,
.esf_keysize = iquic_esf_keysize, .esf_keysize = iquic_esf_keysize,
.esf_alg_keysize = iquic_esf_alg_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, .esf_set_conn = iquic_esf_set_conn,
}; };

View file

@ -1580,7 +1580,7 @@ lsquic_engine_connect (lsquic_engine_t *engine, enum lsquic_version version,
const struct sockaddr *peer_sa, const struct sockaddr *peer_sa,
void *peer_ctx, lsquic_conn_ctx_t *conn_ctx, void *peer_ctx, lsquic_conn_ctx_t *conn_ctx,
const char *hostname, unsigned short max_packet_size, 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) const unsigned char *token, size_t token_sz)
{ {
lsquic_conn_t *conn; lsquic_conn_t *conn;
@ -1606,14 +1606,14 @@ lsquic_engine_connect (lsquic_engine_t *engine, enum lsquic_version version,
return NULL; return NULL;
flags = engine->flags & (ENG_SERVER|ENG_HTTP); flags = engine->flags & (ENG_SERVER|ENG_HTTP);
is_ipv4 = peer_sa->sa_family == AF_INET; 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) if (version >= N_LSQVER)
{ {
LSQ_INFO("zero-rtt version is bad, won't use"); LSQ_INFO("session resumption version is bad, won't use");
zero_rtt = NULL; sess_resume = NULL;
zero_rtt_len = 0; sess_resume_len = 0;
} }
} }
if (version >= N_LSQVER) if (version >= N_LSQVER)
@ -1627,11 +1627,11 @@ lsquic_engine_connect (lsquic_engine_t *engine, enum lsquic_version version,
if (versions & LSQUIC_IETF_VERSIONS) if (versions & LSQUIC_IETF_VERSIONS)
conn = lsquic_ietf_full_conn_client_new(&engine->pub, versions, conn = lsquic_ietf_full_conn_client_new(&engine->pub, versions,
flags, hostname, max_packet_size, 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 else
conn = lsquic_gquic_full_conn_client_new(&engine->pub, versions, conn = lsquic_gquic_full_conn_client_new(&engine->pub, versions,
flags, hostname, max_packet_size, is_ipv4, flags, hostname, max_packet_size, is_ipv4,
zero_rtt, zero_rtt_len); sess_resume, sess_resume_len);
if (!conn) if (!conn)
goto err; goto err;
EV_LOG_CREATE_CONN(lsquic_conn_log_cid(conn), local_sa, peer_sa); EV_LOG_CREATE_CONN(lsquic_conn_log_cid(conn), local_sa, peer_sa);

View file

@ -554,9 +554,9 @@ lsquic_ev_log_hsk_completed (const lsquic_cid_t *cid)
void 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");
} }

View file

@ -311,13 +311,13 @@ lsquic_ev_log_hsk_completed (const lsquic_cid_t *);
void 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)) \ 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)) \ if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_QLOG)) \
lsquic_qlog_zero_rtt(__VA_ARGS__); \ lsquic_qlog_sess_resume(__VA_ARGS__); \
} while (0) } while (0)
void void

View file

@ -717,21 +717,21 @@ lsquic_gquic_full_conn_client_new (struct lsquic_engine_public *enpub,
unsigned versions, unsigned flags, unsigned versions, unsigned flags,
const char *hostname, unsigned short max_packet_size, const char *hostname, unsigned short max_packet_size,
int is_ipv4, 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; struct full_conn *conn;
enum lsquic_version version, zero_rtt_version; enum lsquic_version version, sess_resume_version;
lsquic_cid_t cid; lsquic_cid_t cid;
const struct enc_session_funcs_gquic *esf_g; const struct enc_session_funcs_gquic *esf_g;
versions &= (~LSQUIC_IETF_VERSIONS & LSQUIC_SUPPORTED_VERSIONS); versions &= (~LSQUIC_IETF_VERSIONS & LSQUIC_SUPPORTED_VERSIONS);
assert(versions); assert(versions);
version = highest_bit_set(versions); version = highest_bit_set(versions);
if (zero_rtt) if (sess_resume)
{ {
zero_rtt_version = lsquic_zero_rtt_version(zero_rtt, zero_rtt_len); sess_resume_version = lsquic_sess_resume_version(sess_resume, sess_resume_len);
if (zero_rtt_version < N_LSQVER && ((1 << zero_rtt_version) & versions)) if (sess_resume_version < N_LSQVER && ((1 << sess_resume_version) & versions))
version = zero_rtt_version; version = sess_resume_version;
} }
esf_g = select_esf_gquic_by_ver(version); esf_g = select_esf_gquic_by_ver(version);
lsquic_generate_cid_gquic(&cid); 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_esf.g = esf_g;
conn->fc_conn.cn_enc_session = conn->fc_conn.cn_enc_session =
conn->fc_conn.cn_esf.g->esf_create_client(&conn->fc_conn, hostname, 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) if (!conn->fc_conn.cn_enc_session)
{ {
LSQ_WARN("could not create enc session: %s", strerror(errno)); 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 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) 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); conn->fc_conn.cn_enc_session);
} }
@ -1380,7 +1380,7 @@ static void
full_conn_ci_make_stream (struct lsquic_conn *lconn) full_conn_ci_make_stream (struct lsquic_conn *lconn)
{ {
struct full_conn *conn = (struct full_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) && full_conn_ci_n_avail_streams(lconn) > 0)
{ {
if (!new_stream(conn, generate_stream_id(conn), SCF_CALL_ON_NEW)) 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); 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); process_hsk_stream_write_events(conn);
goto end_write; 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); lsquic_alarmset_unset(&conn->fc_alset, AL_HANDSHAKE);
switch (status) switch (status)
{ {
case LSQ_HSK_0RTT_FAIL: case LSQ_HSK_RESUMED_FAIL:
case LSQ_HSK_FAIL: case LSQ_HSK_FAIL:
conn->fc_flags |= FC_HSK_FAILED; conn->fc_flags |= FC_HSK_FAILED;
break; break;
case LSQ_HSK_OK: case LSQ_HSK_OK:
case LSQ_HSK_0RTT_OK: case LSQ_HSK_RESUMED_OK:
if (0 == apply_peer_settings(conn)) if (0 == apply_peer_settings(conn))
{ {
if (conn->fc_flags & FC_HTTP) 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) 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, conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_hsk_done(lconn,
status); 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) if (conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_sess_resume_info)
conn->fc_conn.cn_esf.g->esf_maybe_dispatch_zero_rtt( conn->fc_conn.cn_esf.g->esf_maybe_dispatch_sess_resume(
conn->fc_conn.cn_enc_session, 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) if (conn->fc_n_delayed_streams)
create_delayed_streams(conn); create_delayed_streams(conn);
if (!(conn->fc_flags & FC_SERVER)) if (!(conn->fc_flags & FC_SERVER))
@ -3721,6 +3721,7 @@ full_conn_ci_close (struct lsquic_conn *lconn)
conn->fc_flags |= FC_CLOSING; conn->fc_flags |= FC_CLOSING;
if (!(conn->fc_flags & FC_GOAWAY_SENT)) if (!(conn->fc_flags & FC_GOAWAY_SENT))
conn->fc_flags |= FC_SEND_GOAWAY; 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"); LSQ_DEBUG("tickable: there are sending streams");
goto check_can_send; 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, TAILQ_FOREACH(stream, &conn->fc_pub.write_streams,
next_write_stream) next_write_stream)
@ -4302,7 +4303,7 @@ lsquic_gquic_full_conn_srej (struct lsquic_conn *lconn)
struct lsquic_stream *stream; struct lsquic_stream *stream;
enum lsquic_version version; 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 /* 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 * 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 " LSQ_DEBUG("received SREJ when 0RTT was on: fail handshake and let "
"caller retry"); "caller retry");
full_conn_ci_hsk_done(lconn, LSQ_HSK_0RTT_FAIL); full_conn_ci_hsk_done(lconn, LSQ_HSK_RESUMED_FAIL);
return -1; return -1;
} }

View file

@ -11,14 +11,14 @@ lsquic_gquic_full_conn_client_new (struct lsquic_engine_public *,
unsigned flags /* Only FC_SERVER and FC_HTTP */, unsigned flags /* Only FC_SERVER and FC_HTTP */,
const char *hostname, unsigned short max_packet_size, const char *hostname, unsigned short max_packet_size,
int is_ipv4, 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 * struct lsquic_conn *
lsquic_ietf_full_conn_client_new (struct lsquic_engine_public *, lsquic_ietf_full_conn_client_new (struct lsquic_engine_public *,
unsigned versions, unsigned versions,
unsigned flags /* Only FC_SERVER and FC_HTTP */, unsigned flags /* Only FC_SERVER and FC_HTTP */,
const char *hostname, unsigned short max_packet_size, int is_ipv4, 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); const unsigned char *token, size_t);
typedef struct lsquic_conn * typedef struct lsquic_conn *

View file

@ -1158,12 +1158,12 @@ struct lsquic_conn *
lsquic_ietf_full_conn_client_new (struct lsquic_engine_public *enpub, lsquic_ietf_full_conn_client_new (struct lsquic_engine_public *enpub,
unsigned versions, unsigned flags, unsigned versions, unsigned flags,
const char *hostname, unsigned short max_packet_size, int is_ipv4, 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 unsigned char *token, size_t token_sz)
{ {
const struct enc_session_funcs_iquic *esfi; const struct enc_session_funcs_iquic *esfi;
struct ietf_full_conn *conn; struct ietf_full_conn *conn;
enum lsquic_version ver, zero_rtt_version; enum lsquic_version ver, sess_resume_version;
lsquic_time_t now; lsquic_time_t now;
conn = calloc(1, sizeof(*conn)); conn = calloc(1, sizeof(*conn));
@ -1181,11 +1181,11 @@ lsquic_ietf_full_conn_client_new (struct lsquic_engine_public *enpub,
assert(versions); assert(versions);
versions &= LSQUIC_IETF_VERSIONS; versions &= LSQUIC_IETF_VERSIONS;
ver = highest_bit_set(versions); ver = highest_bit_set(versions);
if (zero_rtt) if (sess_resume)
{ {
zero_rtt_version = lsquic_zero_rtt_version(zero_rtt, zero_rtt_sz); sess_resume_version = lsquic_sess_resume_version(sess_resume, sess_resume_sz);
if (zero_rtt_version < N_LSQVER && ((1 << zero_rtt_version) & versions)) if (sess_resume_version < N_LSQVER && ((1 << sess_resume_version) & versions))
ver = zero_rtt_version; ver = sess_resume_version;
} }
esfi = select_esf_iquic_by_ver(ver); 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_enpub, &conn->ifc_conn, CUR_DCID(conn),
&conn->ifc_u.cli.ifcli_ver_neg, &conn->ifc_u.cli.ifcli_ver_neg,
(void **) conn->ifc_u.cli.crypto_streams, &crypto_stream_if, (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]); conn->ifc_max_streams_in[SD_UNI]);
if (!conn->ifc_conn.cn_enc_session) if (!conn->ifc_conn.cn_enc_session)
goto err2; goto err2;
@ -2560,6 +2560,7 @@ ietf_full_conn_ci_close (struct lsquic_conn *lconn)
} }
conn->ifc_flags |= IFC_CLOSING; conn->ifc_flags |= IFC_CLOSING;
conn->ifc_send_flags |= SF_SEND_CONN_CLOSE; 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) switch (status)
{ {
case LSQ_HSK_OK: case LSQ_HSK_OK:
case LSQ_HSK_0RTT_OK: case LSQ_HSK_RESUMED_OK:
if (0 == handshake_ok(lconn)) if (0 == handshake_ok(lconn))
{ {
if (!(conn->ifc_flags & IFC_SERVER)) if (!(conn->ifc_flags & IFC_SERVER))
@ -3297,7 +3298,7 @@ ietf_full_conn_ci_hsk_done (struct lsquic_conn *lconn,
assert(0); assert(0);
/* fall-through */ /* fall-through */
case LSQ_HSK_FAIL: case LSQ_HSK_FAIL:
case LSQ_HSK_0RTT_FAIL: case LSQ_HSK_RESUMED_FAIL:
handshake_failed(lconn); handshake_failed(lconn);
break; break;
} }
@ -7102,10 +7103,10 @@ ietf_full_conn_ci_n_avail_streams (const struct lsquic_conn *lconn)
static int 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) 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); 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; 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) && ietf_full_conn_ci_n_avail_streams(lconn) > 0)
{ {
if (0 != create_bidi_stream_out(conn)) if (0 != create_bidi_stream_out(conn))

View file

@ -201,7 +201,7 @@ typedef struct c_cert_item_st
} c_cert_item_t; } c_cert_item_t;
struct lsquic_zero_rtt_storage struct lsquic_sess_resume_storage
{ {
uint32_t quic_version_tag; uint32_t quic_version_tag;
uint32_t serializer_version; uint32_t serializer_version;
@ -592,7 +592,7 @@ enum rtt_deserialize_return_type
#define RTT_SERIALIZER_VERSION (1 << 0) #define RTT_SERIALIZER_VERSION (1 << 0)
static void 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, enum lsquic_version version,
const lsquic_session_cache_info_t *info, const lsquic_session_cache_info_t *info,
const c_cert_item_t *cert_item) 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) \ } while (0) \
static enum rtt_deserialize_return_type static enum rtt_deserialize_return_type
lsquic_enc_session_deserialize_zero_rtt( lsquic_enc_session_deserialize_sess_resume(
const struct lsquic_zero_rtt_storage *storage, const struct lsquic_sess_resume_storage *storage,
size_t storage_size, size_t storage_size,
const struct lsquic_engine_settings *settings, const struct lsquic_engine_settings *settings,
lsquic_session_cache_info_t *info, lsquic_session_cache_info_t *info,
@ -824,12 +824,12 @@ maybe_log_secrets (struct lsquic_enc_session *enc_session)
static enc_session_t * static enc_session_t *
lsquic_enc_session_create_client (struct lsquic_conn *lconn, const char *domain, lsquic_enc_session_create_client (struct lsquic_conn *lconn, const char *domain,
lsquic_cid_t cid, const struct lsquic_engine_public *enpub, 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; lsquic_session_cache_info_t *info;
struct lsquic_enc_session *enc_session; struct lsquic_enc_session *enc_session;
c_cert_item_t *item; 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) if (!domain)
{ {
@ -849,7 +849,7 @@ lsquic_enc_session_create_client (struct lsquic_conn *lconn, const char *domain,
return NULL; 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)); item = calloc(1, sizeof(*item));
if (!item) if (!item)
@ -858,22 +858,22 @@ lsquic_enc_session_create_client (struct lsquic_conn *lconn, const char *domain,
free(info); free(info);
return NULL; return NULL;
} }
zero_rtt_storage = (const struct lsquic_zero_rtt_storage *)zero_rtt; sess_resume_storage = (const struct lsquic_sess_resume_storage *)sess_resume;
switch (lsquic_enc_session_deserialize_zero_rtt(zero_rtt_storage, switch (lsquic_enc_session_deserialize_sess_resume(sess_resume_storage,
zero_rtt_len, sess_resume_len,
&enpub->enp_settings, &enpub->enp_settings,
info, item)) info, item))
{ {
case RTT_DESERIALIZE_BAD_QUIC_VER: 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); free(item);
break; break;
case RTT_DESERIALIZE_BAD_SERIAL_VER: 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); free(item);
break; break;
case RTT_DESERIALIZE_BAD_CERT_SIZE: 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); free(item);
break; break;
case RTT_DESERIALIZE_OK: 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; enc_session->hsk_state = HSK_COMPLETED;
EV_LOG_HSK_COMPLETED(&enc_session->cid); EV_LOG_HSK_COMPLETED(&enc_session->cid);
if (!(enc_session->es_flags & ES_RECV_REJ)) if (!(enc_session->es_flags & ES_RECV_REJ))
EV_LOG_ZERO_RTT(&enc_session->cid); EV_LOG_SESSION_RESUMPTION(&enc_session->cid);
break; break;
default: default:
ret = 1; /* XXX Why 1? */ ret = 1; /* XXX Why 1? */
@ -3599,7 +3599,7 @@ lsquic_enc_session_verify_reset_token (enc_session_t *enc_session_p,
static int 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; struct lsquic_enc_session *const enc_session = enc_session_p;
return !(enc_session->es_flags & ES_RECV_REJ); 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 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; struct lsquic_enc_session *const enc_session = enc_session_p;
return enc_session->info && enc_session->cert_item; 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 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)) void (*cb)(struct lsquic_conn *, const unsigned char *, size_t))
{ {
struct lsquic_enc_session *const enc_session = enc_session_p; 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)) 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; return;
} }
@ -3709,17 +3709,18 @@ maybe_dispatch_zero_rtt (enc_session_t *enc_session_p,
sz += sizeof(uint32_t); sz += sizeof(uint32_t);
sz += lsquic_str_len(&enc_session->cert_item->crts[i]); 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); buf = malloc(sz);
if (!buf) 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; return;
} }
lsquic_enc_session_serialize_zero_rtt( lsquic_enc_session_serialize_sess_resume(
(struct lsquic_zero_rtt_storage *) buf, lconn->cn_version, (struct lsquic_sess_resume_storage *) buf, lconn->cn_version,
enc_session->info, enc_session->cert_item); enc_session->info, enc_session->cert_item);
cb(lconn, buf, sz); 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_tag_len = GQUIC_PACKET_HASH_SZ,
.esf_get_server_cert_chain = lsquic_enc_session_get_server_cert_chain, .esf_get_server_cert_chain = lsquic_enc_session_get_server_cert_chain,
.esf_verify_reset_token = lsquic_enc_session_verify_reset_token, .esf_verify_reset_token = lsquic_enc_session_verify_reset_token,
.esf_did_zero_rtt_succeed = lsquic_enc_session_did_zero_rtt_succeed, .esf_did_sess_resume_succeed = lsquic_enc_session_did_sess_resume_succeed,
.esf_is_zero_rtt_enabled = lsquic_enc_session_is_zero_rtt_enabled, .esf_is_sess_resume_enabled = lsquic_enc_session_is_sess_resume_enabled,
.esf_set_conn = gquic_esf_set_conn, .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_alg_keysize = lsquic_enc_session_alg_keysize,
.esf_get_server_cert_chain = lsquic_enc_session_get_server_cert_chain, .esf_get_server_cert_chain = lsquic_enc_session_get_server_cert_chain,
.esf_verify_reset_token = lsquic_enc_session_verify_reset_token, .esf_verify_reset_token = lsquic_enc_session_verify_reset_token,
.esf_did_zero_rtt_succeed = lsquic_enc_session_did_zero_rtt_succeed, .esf_did_sess_resume_succeed = lsquic_enc_session_did_sess_resume_succeed,
.esf_is_zero_rtt_enabled = lsquic_enc_session_is_zero_rtt_enabled, .esf_is_sess_resume_enabled = lsquic_enc_session_is_sess_resume_enabled,
.esf_set_conn = gquic_esf_set_conn, .esf_set_conn = gquic_esf_set_conn,
/* These are different from gquic_1: */ /* These are different from gquic_1: */
.esf_encrypt_packet = gquic2_esf_encrypt_packet, .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_gen_chlo = lsquic_enc_session_gen_chlo,
.esf_handle_chlo_reply = lsquic_enc_session_handle_chlo_reply, .esf_handle_chlo_reply = lsquic_enc_session_handle_chlo_reply,
.esf_mem_used = lsquic_enc_session_mem_used, .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, .esf_reset_cid = lsquic_enc_session_reset_cid,
}; };

View file

@ -111,6 +111,6 @@ enum hsk_failure_reason
}; };
enum lsquic_version enum lsquic_version
lsquic_zero_rtt_version (const unsigned char *, size_t); lsquic_sess_resume_version (const unsigned char *, size_t);
#endif #endif

View file

@ -590,7 +590,7 @@ ietf_mini_conn_ci_hsk_done (struct lsquic_conn *lconn,
switch (status) switch (status)
{ {
case LSQ_HSK_OK: case LSQ_HSK_OK:
case LSQ_HSK_0RTT_OK: case LSQ_HSK_RESUMED_OK:
conn->imc_flags |= IMC_HSK_OK; conn->imc_flags |= IMC_HSK_OK;
conn->imc_conn.cn_flags |= LSCONN_HANDSHAKE_DONE; conn->imc_conn.cn_flags |= LSCONN_HANDSHAKE_DONE;
LSQ_DEBUG("handshake OK"); LSQ_DEBUG("handshake OK");

View file

@ -83,6 +83,7 @@ lsquic_qlog_create_connection (const lsquic_cid_t* cid,
lsquic_time_now(), ip_version, srcip, dstip, srcport, dstport); lsquic_time_now(), ip_version, srcip, dstip, srcport, dstport);
} }
#define QLOG_FRAME_DICT_PREFIX_COMMA ",{\"frame_type\":\"" #define QLOG_FRAME_DICT_PREFIX_COMMA ",{\"frame_type\":\""
#define QLOG_FRAME_DICT_PREFIX "{\"frame_type\":\"" #define QLOG_FRAME_DICT_PREFIX "{\"frame_type\":\""
#define QLOG_FRAME_DICT_SUFFIX "\"}" #define QLOG_FRAME_DICT_SUFFIX "\"}"
@ -170,7 +171,7 @@ lsquic_qlog_hsk_completed (const lsquic_cid_t* cid)
void 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\"," LCID("[%" PRIu64 ",\"RECOVERY\",\"RTT_UPDATE\",\"PACKET_RX\","
"{\"zero_rtt\":\"successful\"}]", lsquic_time_now()); "{\"zero_rtt\":\"successful\"}]", lsquic_time_now());

View file

@ -80,7 +80,7 @@ void
lsquic_qlog_hsk_completed (const lsquic_cid_t *); lsquic_qlog_hsk_completed (const lsquic_cid_t *);
void void
lsquic_qlog_zero_rtt (const lsquic_cid_t *); lsquic_qlog_sess_resume (const lsquic_cid_t *);
void void
lsquic_qlog_check_certs (const lsquic_cid_t *, const lsquic_str_t **, size_t); lsquic_qlog_check_certs (const lsquic_cid_t *, const lsquic_str_t **, size_t);

View file

@ -412,7 +412,7 @@ lsquic_stream_destroy (lsquic_stream_t *);
* failure. The latter may be caused by flow control violation or * failure. The latter may be caused by flow control violation or
* invalid stream frame data, e.g. overlapping segments. * 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. * what this function returns.
* *
* This data is read by the user using lsquic_stream_read() function. * 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 void
lsquic_stream_stop_sending_in (struct lsquic_stream *, uint64_t error_code); 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 uint64_t
lsquic_stream_read_offset (const lsquic_stream_t *stream); lsquic_stream_read_offset (const lsquic_stream_t *stream);
@ -448,11 +445,6 @@ lsquic_stream_read_offset (const lsquic_stream_t *stream);
int int
lsquic_stream_tosend_fin (const lsquic_stream_t *stream); 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 void
lsquic_stream_window_update (lsquic_stream_t *stream, uint64_t offset); lsquic_stream_window_update (lsquic_stream_t *stream, uint64_t offset);

View file

@ -8,7 +8,7 @@
struct ver_neg { struct ver_neg {
unsigned vn_supp; /* Remaining options, including `vn_ver' */ unsigned vn_supp; /* Remaining options, including `vn_ver' */
enum lsquic_version vn_ver; /* If client, current version sent to server 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. * if server, this is set to negotiated version.
*/ */
enum ver_neg_state { enum ver_neg_state {

View file

@ -44,7 +44,7 @@ main (void)
lsquic_qlog_packet_rx(&cid, NULL, NULL, 0); lsquic_qlog_packet_rx(&cid, NULL, NULL, 0);
lsquic_qlog_hsk_completed(&cid); lsquic_qlog_hsk_completed(&cid);
lsquic_qlog_zero_rtt(&cid); lsquic_qlog_sess_resume(&cid);
lsquic_qlog_check_certs(&cid, NULL, 0); lsquic_qlog_check_certs(&cid, NULL, 0);
lsquic_qlog_version_negotiation(&cid, NULL, NULL); lsquic_qlog_version_negotiation(&cid, NULL, NULL);