mirror of
				https://gitea.invidious.io/iv-org/litespeed-quic.git
				synced 2024-08-15 00:53:43 +00:00 
			
		
		
		
	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
					
				
					 26 changed files with 359 additions and 273 deletions
				
			
		
							
								
								
									
										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…
	
	Add table
		Add a link
		
	
		Reference in a new issue