mirror of
				https://gitea.invidious.io/iv-org/litespeed-quic.git
				synced 2024-08-15 00:53:43 +00:00 
			
		
		
		
	Release 2.17.0
- [FEATURE] QUIC and HTTP/3 Internet Draft 29 support. - [BUGFIX] Check that scheduled packets are also sendable when calculating a connection's "tickable" property. - [BUGFIX] Don't count scheduled packets as in-flight when pacer is checked on tick. - gQUIC: delay calling on_new for pushed stream until headers are available. - Allow nested calls to lsquic_engine_connect().
This commit is contained in:
		
							parent
							
								
									307ca7fe50
								
							
						
					
					
						commit
						4051ae3a1a
					
				
					 19 changed files with 343 additions and 56 deletions
				
			
		
							
								
								
									
										11
									
								
								CHANGELOG
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								CHANGELOG
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,3 +1,14 @@
 | 
			
		|||
2020-06-18
 | 
			
		||||
    - 2.17.0
 | 
			
		||||
    - [FEATURE] QUIC and HTTP/3 Internet Draft 29 support.
 | 
			
		||||
    - [BUGFIX] Check that scheduled packets are also sendable when
 | 
			
		||||
      calculating a connection's "tickable" property.
 | 
			
		||||
    - [BUGFIX] Don't count scheduled packets as in-flight when pacer is
 | 
			
		||||
      checked on tick.
 | 
			
		||||
    - gQUIC: delay calling on_new for pushed stream until headers are
 | 
			
		||||
      available.
 | 
			
		||||
    - Allow nested calls to lsquic_engine_connect().
 | 
			
		||||
 | 
			
		||||
2020-06-15
 | 
			
		||||
    - 2.16.3
 | 
			
		||||
    - [OPTIMIZATION] Stash up to two reordered packets in IETF mini conn
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,7 +21,7 @@ static int
 | 
			
		|||
select_alpn (SSL *ssl, const unsigned char **out, unsigned char *outlen,
 | 
			
		||||
                    const unsigned char *in, unsigned int inlen, void *arg)
 | 
			
		||||
{
 | 
			
		||||
    const unsigned char alpn[] = "\x5h3-27\x5h3-28";
 | 
			
		||||
    const unsigned char alpn[] = "\x5h3-27\x5h3-28\x5h3-29";
 | 
			
		||||
    int r;
 | 
			
		||||
 | 
			
		||||
    r = SSL_select_next_proto((unsigned char **) out, outlen, in, inlen,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,9 +24,9 @@ copyright = u'2020, LiteSpeed Technologies'
 | 
			
		|||
author = u'LiteSpeed Technologies'
 | 
			
		||||
 | 
			
		||||
# The short X.Y version
 | 
			
		||||
version = u'2.16'
 | 
			
		||||
version = u'2.17'
 | 
			
		||||
# The full version, including alpha/beta/rc tags
 | 
			
		||||
release = u'2.16.3'
 | 
			
		||||
release = u'2.17.0'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# -- General configuration ---------------------------------------------------
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,8 +24,8 @@ extern "C" {
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
#define LSQUIC_MAJOR_VERSION 2
 | 
			
		||||
#define LSQUIC_MINOR_VERSION 16
 | 
			
		||||
#define LSQUIC_PATCH_VERSION 3
 | 
			
		||||
#define LSQUIC_MINOR_VERSION 17
 | 
			
		||||
#define LSQUIC_PATCH_VERSION 0
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Engine flags:
 | 
			
		||||
| 
						 | 
				
			
			@ -86,6 +86,11 @@ enum lsquic_version
 | 
			
		|||
     */
 | 
			
		||||
    LSQVER_ID28,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * IETF QUIC Draft-29
 | 
			
		||||
     */
 | 
			
		||||
    LSQVER_ID29,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Special version to trigger version negotiation.
 | 
			
		||||
     * [draft-ietf-quic-transport-11], Section 3.
 | 
			
		||||
| 
						 | 
				
			
			@ -114,10 +119,10 @@ enum lsquic_version
 | 
			
		|||
#define LSQUIC_GQUIC_HEADER_VERSIONS (1 << LSQVER_043)
 | 
			
		||||
 | 
			
		||||
#define LSQUIC_IETF_VERSIONS ((1 << LSQVER_ID27) | (1 << LSQVER_ID28) \
 | 
			
		||||
                                                    | (1 << LSQVER_VERNEG))
 | 
			
		||||
                              | (1 << LSQVER_ID29) | (1 << LSQVER_VERNEG))
 | 
			
		||||
 | 
			
		||||
#define LSQUIC_IETF_DRAFT_VERSIONS ((1 << LSQVER_ID27) | (1 << LSQVER_ID28) \
 | 
			
		||||
                                                    | (1 << LSQVER_VERNEG))
 | 
			
		||||
                              | (1 << LSQVER_ID29) | (1 << LSQVER_VERNEG))
 | 
			
		||||
 | 
			
		||||
enum lsquic_hsk_status
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -334,6 +334,7 @@ extern const struct enc_session_funcs_iquic lsquic_enc_session_iquic_ietf_v1;
 | 
			
		|||
#define select_esf_common_by_ver(ver) ( \
 | 
			
		||||
    ver == LSQVER_ID27 ? &lsquic_enc_session_common_ietf_v1 : \
 | 
			
		||||
    ver == LSQVER_ID28 ? &lsquic_enc_session_common_ietf_v1 : \
 | 
			
		||||
    ver == LSQVER_ID29 ? &lsquic_enc_session_common_ietf_v1 : \
 | 
			
		||||
    ver == LSQVER_VERNEG ? &lsquic_enc_session_common_ietf_v1 : \
 | 
			
		||||
    ver == LSQVER_050 ? &lsquic_enc_session_common_gquic_2 : \
 | 
			
		||||
    &lsquic_enc_session_common_gquic_1 )
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -73,7 +73,8 @@ static const struct alpn_map {
 | 
			
		|||
} s_h3_alpns[] = {
 | 
			
		||||
    {   LSQVER_ID27, (unsigned char *) "\x05h3-27",     },
 | 
			
		||||
    {   LSQVER_ID28, (unsigned char *) "\x05h3-28",     },
 | 
			
		||||
    {   LSQVER_VERNEG, (unsigned char *) "\x05h3-28",     },
 | 
			
		||||
    {   LSQVER_ID29, (unsigned char *) "\x05h3-29",     },
 | 
			
		||||
    {   LSQVER_VERNEG, (unsigned char *) "\x05h3-29",     },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct enc_sess_iquic;
 | 
			
		||||
| 
						 | 
				
			
			@ -935,7 +936,8 @@ setup_handshake_keys (struct enc_sess_iquic *enc_sess, const lsquic_cid_t *cid)
 | 
			
		|||
    hp = &enc_sess->esi_hsk_hps[ENC_LEV_CLEAR];
 | 
			
		||||
 | 
			
		||||
    HKDF_extract(hsk_secret, &hsk_secret_sz, md, cid->idbuf, cid->len,
 | 
			
		||||
                                                        HSK_SALT, HSK_SALT_SZ);
 | 
			
		||||
                    enc_sess->esi_conn->cn_version < LSQVER_ID29
 | 
			
		||||
                    ? HSK_SALT_PRE29 : HSK_SALT, HSK_SALT_SZ);
 | 
			
		||||
    if (enc_sess->esi_flags & ESI_LOG_SECRETS)
 | 
			
		||||
    {
 | 
			
		||||
        LSQ_DEBUG("handshake salt: %s", HEXSTR(HSK_SALT, HSK_SALT_SZ, hexbuf));
 | 
			
		||||
| 
						 | 
				
			
			@ -1177,6 +1179,13 @@ iquic_esfi_init_server (enc_session_t *enc_session_p)
 | 
			
		|||
        LSQ_INFO("could not set stream method");
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    /* TODO: set to transport parameter string instead of the constant string */
 | 
			
		||||
    if (!SSL_set_quic_early_data_context(enc_sess->esi_ssl,
 | 
			
		||||
                                                (unsigned char *) "lsquic", 6))
 | 
			
		||||
    {
 | 
			
		||||
        LSQ_INFO("could not set early data context");
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    maybe_setup_key_logging(enc_sess);
 | 
			
		||||
 | 
			
		||||
    transpa_len = gen_trans_params(enc_sess, u.trans_params,
 | 
			
		||||
| 
						 | 
				
			
			@ -1756,7 +1765,7 @@ iquic_esfi_destroy (enc_session_t *enc_session_p)
 | 
			
		|||
    struct enc_sess_iquic *const enc_sess = enc_session_p;
 | 
			
		||||
    struct frab_list *fral;
 | 
			
		||||
    LSQ_DEBUG("iquic_esfi_destroy");
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    for (fral = enc_sess->esi_frals; fral < enc_sess->esi_frals
 | 
			
		||||
            + sizeof(enc_sess->esi_frals) / sizeof(enc_sess->esi_frals[0]);
 | 
			
		||||
                ++fral)
 | 
			
		||||
| 
						 | 
				
			
			@ -3004,3 +3013,23 @@ const struct lsquic_stream_if lsquic_mini_cry_sm_if =
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const unsigned char *const lsquic_retry_key_buf[N_IETF_RETRY_VERSIONS] =
 | 
			
		||||
{
 | 
			
		||||
    /* [draft-ietf-quic-tls-25] Section 5.8 */
 | 
			
		||||
    (unsigned char *)
 | 
			
		||||
        "\x4d\x32\xec\xdb\x2a\x21\x33\xc8\x41\xe4\x04\x3d\xf2\x7d\x44\x30",
 | 
			
		||||
    /* [draft-ietf-quic-tls-29] Section 5.8 */
 | 
			
		||||
    (unsigned char *)
 | 
			
		||||
        "\xcc\xce\x18\x7e\xd0\x9a\x09\xd0\x57\x28\x15\x5a\x6c\xb9\x6b\xe1",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const unsigned char *const lsquic_retry_nonce_buf[N_IETF_RETRY_VERSIONS] =
 | 
			
		||||
{
 | 
			
		||||
    /* [draft-ietf-quic-tls-25] Section 5.8 */
 | 
			
		||||
    (unsigned char *) "\x4d\x16\x11\xd0\x55\x13\xa5\x52\xc5\x87\xd5\x75",
 | 
			
		||||
    /* [draft-ietf-quic-tls-29] Section 5.8 */
 | 
			
		||||
    (unsigned char *) "\xe5\x49\x30\xf9\x7f\x21\x36\xf0\x53\x0a\x8c\x1c",
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -135,7 +135,9 @@ force_close_conn (lsquic_engine_t *engine, lsquic_conn_t *conn);
 | 
			
		|||
#define ENGINE_CALLS_INCR(e)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Nested calls to LSQUIC are not supported */
 | 
			
		||||
/* Nested calls to some LSQUIC functions are not supported.  Functions that
 | 
			
		||||
 * iterate over connections cannot be nested.
 | 
			
		||||
 */
 | 
			
		||||
#define ENGINE_IN(e) do {                               \
 | 
			
		||||
    assert(!((e)->pub.enp_flags & ENPUB_PROC));         \
 | 
			
		||||
    (e)->pub.enp_flags |= ENPUB_PROC;                   \
 | 
			
		||||
| 
						 | 
				
			
			@ -270,7 +272,7 @@ struct lsquic_engine
 | 
			
		|||
    int                                last_tick_diff;
 | 
			
		||||
#endif
 | 
			
		||||
    struct crand                       crand;
 | 
			
		||||
    EVP_AEAD_CTX                       retry_aead_ctx;
 | 
			
		||||
    EVP_AEAD_CTX                       retry_aead_ctx[N_IETF_RETRY_VERSIONS];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -483,6 +485,7 @@ lsquic_engine_new (unsigned flags,
 | 
			
		|||
{
 | 
			
		||||
    lsquic_engine_t *engine;
 | 
			
		||||
    size_t alpn_len;
 | 
			
		||||
    unsigned i;
 | 
			
		||||
    char err_buf[100];
 | 
			
		||||
 | 
			
		||||
    if (!api->ea_packets_out)
 | 
			
		||||
| 
						 | 
				
			
			@ -691,14 +694,17 @@ lsquic_engine_new (unsigned flags,
 | 
			
		|||
#if LSQUIC_CONN_STATS
 | 
			
		||||
    engine->stats_fh = api->ea_stats_fh;
 | 
			
		||||
#endif
 | 
			
		||||
    if (1 != EVP_AEAD_CTX_init(&engine->retry_aead_ctx, EVP_aead_aes_128_gcm(),
 | 
			
		||||
                            IETF_RETRY_KEY_BUF, IETF_RETRY_KEY_SZ, 16, NULL))
 | 
			
		||||
    {
 | 
			
		||||
        LSQ_ERROR("could not initialize retry AEAD ctx");
 | 
			
		||||
        lsquic_engine_destroy(engine);
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
    engine->pub.enp_retry_aead_ctx = &engine->retry_aead_ctx;
 | 
			
		||||
    for (i = 0; i < sizeof(engine->retry_aead_ctx)
 | 
			
		||||
                                    / sizeof(engine->retry_aead_ctx[0]); ++i)
 | 
			
		||||
        if (1 != EVP_AEAD_CTX_init(&engine->retry_aead_ctx[i],
 | 
			
		||||
                        EVP_aead_aes_128_gcm(), lsquic_retry_key_buf[i],
 | 
			
		||||
                        IETF_RETRY_KEY_SZ, 16, NULL))
 | 
			
		||||
        {
 | 
			
		||||
            LSQ_ERROR("could not initialize retry AEAD ctx #%u", i);
 | 
			
		||||
            lsquic_engine_destroy(engine);
 | 
			
		||||
            return NULL;
 | 
			
		||||
        }
 | 
			
		||||
    engine->pub.enp_retry_aead_ctx = engine->retry_aead_ctx;
 | 
			
		||||
 | 
			
		||||
    LSQ_INFO("instantiated engine");
 | 
			
		||||
    return engine;
 | 
			
		||||
| 
						 | 
				
			
			@ -1421,6 +1427,7 @@ lsquic_engine_destroy (lsquic_engine_t *engine)
 | 
			
		|||
{
 | 
			
		||||
    struct lsquic_hash_elem *el;
 | 
			
		||||
    lsquic_conn_t *conn;
 | 
			
		||||
    unsigned i;
 | 
			
		||||
 | 
			
		||||
    LSQ_DEBUG("destroying engine");
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
| 
						 | 
				
			
			@ -1515,8 +1522,9 @@ lsquic_engine_destroy (lsquic_engine_t *engine)
 | 
			
		|||
#if LSQUIC_COUNT_ENGINE_CALLS
 | 
			
		||||
    LSQ_NOTICE("number of calls into the engine: %lu", engine->n_engine_calls);
 | 
			
		||||
#endif
 | 
			
		||||
    if (engine->pub.enp_retry_aead_ctx)
 | 
			
		||||
        EVP_AEAD_CTX_cleanup(engine->pub.enp_retry_aead_ctx);
 | 
			
		||||
    for (i = 0; i < sizeof(engine->retry_aead_ctx)
 | 
			
		||||
                                    / sizeof(engine->retry_aead_ctx[0]); ++i)
 | 
			
		||||
        EVP_AEAD_CTX_cleanup(&engine->pub.enp_retry_aead_ctx[i]);
 | 
			
		||||
    free(engine->pub.enp_alpn);
 | 
			
		||||
    free(engine);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1579,7 +1587,7 @@ lsquic_engine_connect (lsquic_engine_t *engine, enum lsquic_version version,
 | 
			
		|||
    unsigned flags, versions;
 | 
			
		||||
    int is_ipv4;
 | 
			
		||||
 | 
			
		||||
    ENGINE_IN(engine);
 | 
			
		||||
    ENGINE_CALLS_INCR(engine);
 | 
			
		||||
 | 
			
		||||
    if (engine->flags & ENG_SERVER)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -1650,7 +1658,6 @@ lsquic_engine_connect (lsquic_engine_t *engine, enum lsquic_version version,
 | 
			
		|||
    lsquic_conn_set_ctx(conn, conn_ctx);
 | 
			
		||||
    conn->cn_if->ci_client_call_on_new(conn);
 | 
			
		||||
  end:
 | 
			
		||||
    ENGINE_OUT(engine);
 | 
			
		||||
    return conn;
 | 
			
		||||
  err:
 | 
			
		||||
    conn = NULL;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4060,7 +4060,7 @@ full_conn_ci_push_stream (struct lsquic_conn *lconn, void *hset,
 | 
			
		|||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pushed_stream = new_stream(conn, stream_id, SCF_CALL_ON_NEW);
 | 
			
		||||
    pushed_stream = new_stream(conn, stream_id, 0);
 | 
			
		||||
    if (!pushed_stream)
 | 
			
		||||
    {
 | 
			
		||||
        LSQ_WARN("cannot create stream: %s", strerror(errno));
 | 
			
		||||
| 
						 | 
				
			
			@ -4085,6 +4085,7 @@ full_conn_ci_push_stream (struct lsquic_conn *lconn, void *hset,
 | 
			
		|||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    lsquic_stream_call_on_new(pushed_stream);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4187,10 +4188,10 @@ full_conn_ci_is_tickable (lsquic_conn_t *lconn)
 | 
			
		|||
            LSQ_DEBUG("tickable: flags: 0x%X", conn->fc_flags & send_flags);
 | 
			
		||||
            goto check_can_send;
 | 
			
		||||
        }
 | 
			
		||||
        if (lsquic_send_ctl_n_scheduled(&conn->fc_send_ctl) > 0)
 | 
			
		||||
        if (lsquic_send_ctl_has_sendable(&conn->fc_send_ctl))
 | 
			
		||||
        {
 | 
			
		||||
            LSQ_DEBUG("tickable: has scheduled packets");
 | 
			
		||||
            return 1;   /* Don't check can_send */
 | 
			
		||||
            LSQ_DEBUG("tickable: has sendable packets");
 | 
			
		||||
            return 1;   /* Don't check can_send: already on scheduled queue */
 | 
			
		||||
        }
 | 
			
		||||
        if ((conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE)
 | 
			
		||||
                && lsquic_send_ctl_has_buffered(&conn->fc_send_ctl))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -410,6 +410,7 @@ struct ietf_full_conn
 | 
			
		|||
            struct ver_neg
 | 
			
		||||
                        ifcli_ver_neg;
 | 
			
		||||
            uint64_t    ifcli_max_push_id;
 | 
			
		||||
            uint64_t    ifcli_min_goaway_stream_id;
 | 
			
		||||
            enum {
 | 
			
		||||
                IFCLI_PUSH_ENABLED    = 1 << 0,
 | 
			
		||||
                IFCLI_HSK_SENT_OR_DEL = 1 << 1,
 | 
			
		||||
| 
						 | 
				
			
			@ -2889,13 +2890,19 @@ try_to_begin_migration (struct ietf_full_conn *conn,
 | 
			
		|||
        struct sockaddr_in6 v6;
 | 
			
		||||
    } sockaddr;
 | 
			
		||||
 | 
			
		||||
    if ((params->tp_set & (1 << TPI_DISABLE_ACTIVE_MIGRATION))
 | 
			
		||||
                                || !conn->ifc_settings->es_allow_migration)
 | 
			
		||||
    if (!conn->ifc_settings->es_allow_migration)
 | 
			
		||||
    {
 | 
			
		||||
        if (params->tp_set & (1 << TPI_DISABLE_ACTIVE_MIGRATION))
 | 
			
		||||
            LSQ_DEBUG("TP disables migration: retire PreferredAddress CID");
 | 
			
		||||
        else
 | 
			
		||||
            LSQ_DEBUG("Migration not allowed: retire PreferredAddress CID");
 | 
			
		||||
        LSQ_DEBUG("Migration not allowed: retire PreferredAddress CID");
 | 
			
		||||
        return BM_NOT_MIGRATING;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (conn->ifc_conn.cn_version <= LSQVER_ID28 /* Starting with ID-29,
 | 
			
		||||
        disable_active_migration TP applies only to the time period during
 | 
			
		||||
        the handshake.  Our client does not migrate during the handshake:
 | 
			
		||||
        this code runs only after handshake has succeeded. */
 | 
			
		||||
                && (params->tp_set & (1 << TPI_DISABLE_ACTIVE_MIGRATION)))
 | 
			
		||||
    {
 | 
			
		||||
        LSQ_DEBUG("TP disables migration: retire PreferredAddress CID");
 | 
			
		||||
        return BM_NOT_MIGRATING;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3547,10 +3554,10 @@ ietf_full_conn_ci_is_tickable (struct lsquic_conn *lconn)
 | 
			
		|||
            LSQ_DEBUG("tickable: send flags: 0x%X", conn->ifc_send_flags);
 | 
			
		||||
            goto check_can_send;
 | 
			
		||||
        }
 | 
			
		||||
        if (lsquic_send_ctl_n_scheduled(&conn->ifc_send_ctl) > 0)
 | 
			
		||||
        if (lsquic_send_ctl_has_sendable(&conn->ifc_send_ctl))
 | 
			
		||||
        {
 | 
			
		||||
            LSQ_DEBUG("tickable: has scheduled packets");
 | 
			
		||||
            return 1;   /* Don't check can_send */
 | 
			
		||||
            LSQ_DEBUG("tickable: has sendable packets");
 | 
			
		||||
            return 1;   /* Don't check can_send: already on scheduled queue */
 | 
			
		||||
        }
 | 
			
		||||
        if (conn->ifc_conn.cn_flags & LSCONN_SEND_BLOCKED)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -6046,6 +6053,7 @@ verify_retry_packet (struct ietf_full_conn *conn,
 | 
			
		|||
{
 | 
			
		||||
    unsigned char *pseudo_packet;
 | 
			
		||||
    size_t out_len, ad_len;
 | 
			
		||||
    unsigned ret_ver;
 | 
			
		||||
    int verified;
 | 
			
		||||
 | 
			
		||||
    if (1 + CUR_DCID(conn)->len + packet_in->pi_data_sz > 0x1000)
 | 
			
		||||
| 
						 | 
				
			
			@ -6070,11 +6078,13 @@ verify_retry_packet (struct ietf_full_conn *conn,
 | 
			
		|||
    memcpy(pseudo_packet + 1 + CUR_DCID(conn)->len, packet_in->pi_data,
 | 
			
		||||
                                                    packet_in->pi_data_sz);
 | 
			
		||||
 | 
			
		||||
    ret_ver = lsquic_version_2_retryver(conn->ifc_conn.cn_version);
 | 
			
		||||
    out_len = 0;
 | 
			
		||||
    ad_len = 1 + CUR_DCID(conn)->len + packet_in->pi_data_sz - 16;
 | 
			
		||||
    verified = 1 == EVP_AEAD_CTX_open(conn->ifc_enpub->enp_retry_aead_ctx,
 | 
			
		||||
    verified = 1 == EVP_AEAD_CTX_open(
 | 
			
		||||
                    &conn->ifc_enpub->enp_retry_aead_ctx[ret_ver],
 | 
			
		||||
                    pseudo_packet + ad_len, &out_len, out_len,
 | 
			
		||||
                    IETF_RETRY_NONCE_BUF, IETF_RETRY_NONCE_SZ,
 | 
			
		||||
                    lsquic_retry_nonce_buf[ret_ver], IETF_RETRY_NONCE_SZ,
 | 
			
		||||
                    pseudo_packet + ad_len, 16, pseudo_packet, ad_len)
 | 
			
		||||
            && out_len == 0;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -7472,7 +7482,7 @@ on_setting (void *ctx, uint64_t setting_id, uint64_t value)
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_goaway_server (void *ctx, uint64_t stream_id)
 | 
			
		||||
on_goaway_server_27 (void *ctx, uint64_t stream_id)
 | 
			
		||||
{
 | 
			
		||||
    struct ietf_full_conn *const conn = ctx;
 | 
			
		||||
    ABORT_QUIETLY(1, HEC_FRAME_UNEXPECTED,
 | 
			
		||||
| 
						 | 
				
			
			@ -7481,7 +7491,7 @@ on_goaway_server (void *ctx, uint64_t stream_id)
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_goaway (void *ctx, uint64_t stream_id)
 | 
			
		||||
on_goaway_client_28 (void *ctx, uint64_t stream_id)
 | 
			
		||||
{
 | 
			
		||||
    struct ietf_full_conn *const conn = ctx;
 | 
			
		||||
    struct lsquic_stream *stream;
 | 
			
		||||
| 
						 | 
				
			
			@ -7520,6 +7530,68 @@ on_goaway (void *ctx, uint64_t stream_id)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_goaway_client (void *ctx, uint64_t stream_id)
 | 
			
		||||
{
 | 
			
		||||
    struct ietf_full_conn *const conn = ctx;
 | 
			
		||||
    struct lsquic_stream *stream;
 | 
			
		||||
    struct lsquic_hash_elem *el;
 | 
			
		||||
    enum stream_id_type sit;
 | 
			
		||||
 | 
			
		||||
    sit = stream_id & SIT_MASK;
 | 
			
		||||
    if (sit != SIT_BIDI_CLIENT)
 | 
			
		||||
    {
 | 
			
		||||
        ABORT_QUIETLY(1, HEC_ID_ERROR,
 | 
			
		||||
                            "stream ID %"PRIu64" in GOAWAY frame", stream_id);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    LSQ_DEBUG("received GOAWAY frame, last good stream ID: %"PRIu64, stream_id);
 | 
			
		||||
 | 
			
		||||
    if (conn->ifc_conn.cn_flags & LSCONN_PEER_GOING_AWAY)
 | 
			
		||||
    {
 | 
			
		||||
        if (stream_id == conn->ifc_u.cli.ifcli_min_goaway_stream_id)
 | 
			
		||||
        {
 | 
			
		||||
            LSQ_DEBUG("ignore duplicate GOAWAY frame");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        if (stream_id > conn->ifc_u.cli.ifcli_min_goaway_stream_id)
 | 
			
		||||
        {
 | 
			
		||||
            ABORT_QUIETLY(1, HEC_ID_ERROR,
 | 
			
		||||
                "stream ID %"PRIu64" is larger than one already seen in a "
 | 
			
		||||
                "previous GOAWAY frame, %"PRIu64, stream_id,
 | 
			
		||||
                conn->ifc_u.cli.ifcli_min_goaway_stream_id);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        conn->ifc_u.cli.ifcli_min_goaway_stream_id = stream_id;
 | 
			
		||||
        conn->ifc_conn.cn_flags |= LSCONN_PEER_GOING_AWAY;
 | 
			
		||||
        if (conn->ifc_enpub->enp_stream_if->on_goaway_received)
 | 
			
		||||
            conn->ifc_enpub->enp_stream_if->on_goaway_received(&conn->ifc_conn);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (el = lsquic_hash_first(conn->ifc_pub.all_streams); el;
 | 
			
		||||
                             el = lsquic_hash_next(conn->ifc_pub.all_streams))
 | 
			
		||||
    {
 | 
			
		||||
        stream = lsquic_hashelem_getdata(el);
 | 
			
		||||
        if (stream->id >= stream_id
 | 
			
		||||
                            && (stream->id & SIT_MASK) == SIT_BIDI_CLIENT)
 | 
			
		||||
        {
 | 
			
		||||
            lsquic_stream_received_goaway(stream);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_goaway_server (void *ctx, uint64_t max_push_id)
 | 
			
		||||
{
 | 
			
		||||
    /* TODO: cancel pushes? */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_unexpected_frame (void *ctx, uint64_t frame_type)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -7529,7 +7601,49 @@ on_unexpected_frame (void *ctx, uint64_t frame_type)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static const struct hcsi_callbacks hcsi_callbacks_server =
 | 
			
		||||
static const struct hcsi_callbacks hcsi_callbacks_server_27 =
 | 
			
		||||
{
 | 
			
		||||
    .on_cancel_push         = on_cancel_push,
 | 
			
		||||
    .on_max_push_id         = on_max_push_id,
 | 
			
		||||
    .on_settings_frame      = on_settings_frame,
 | 
			
		||||
    .on_setting             = on_setting,
 | 
			
		||||
    .on_goaway              = on_goaway_server_27,
 | 
			
		||||
    .on_unexpected_frame    = on_unexpected_frame,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct hcsi_callbacks hcsi_callbacks_client_27 =
 | 
			
		||||
{
 | 
			
		||||
    .on_cancel_push         = on_cancel_push,
 | 
			
		||||
    .on_max_push_id         = on_max_push_id_client,
 | 
			
		||||
    .on_settings_frame      = on_settings_frame,
 | 
			
		||||
    .on_setting             = on_setting,
 | 
			
		||||
    .on_goaway              = on_goaway_client_28 /* sic */,
 | 
			
		||||
    .on_unexpected_frame    = on_unexpected_frame,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static const struct hcsi_callbacks hcsi_callbacks_server_28 =
 | 
			
		||||
{
 | 
			
		||||
    .on_cancel_push         = on_cancel_push,
 | 
			
		||||
    .on_max_push_id         = on_max_push_id,
 | 
			
		||||
    .on_settings_frame      = on_settings_frame,
 | 
			
		||||
    .on_setting             = on_setting,
 | 
			
		||||
    .on_goaway              = on_goaway_server /* sic */,
 | 
			
		||||
    .on_unexpected_frame    = on_unexpected_frame,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct hcsi_callbacks hcsi_callbacks_client_28 =
 | 
			
		||||
{
 | 
			
		||||
    .on_cancel_push         = on_cancel_push,
 | 
			
		||||
    .on_max_push_id         = on_max_push_id_client,
 | 
			
		||||
    .on_settings_frame      = on_settings_frame,
 | 
			
		||||
    .on_setting             = on_setting,
 | 
			
		||||
    .on_goaway              = on_goaway_client_28,
 | 
			
		||||
    .on_unexpected_frame    = on_unexpected_frame,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static const struct hcsi_callbacks hcsi_callbacks_server_29 =
 | 
			
		||||
{
 | 
			
		||||
    .on_cancel_push         = on_cancel_push,
 | 
			
		||||
    .on_max_push_id         = on_max_push_id,
 | 
			
		||||
| 
						 | 
				
			
			@ -7539,13 +7653,13 @@ static const struct hcsi_callbacks hcsi_callbacks_server =
 | 
			
		|||
    .on_unexpected_frame    = on_unexpected_frame,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct hcsi_callbacks hcsi_callbacks =
 | 
			
		||||
static const struct hcsi_callbacks hcsi_callbacks_client_29 =
 | 
			
		||||
{
 | 
			
		||||
    .on_cancel_push         = on_cancel_push,
 | 
			
		||||
    .on_max_push_id         = on_max_push_id_client,
 | 
			
		||||
    .on_settings_frame      = on_settings_frame,
 | 
			
		||||
    .on_setting             = on_setting,
 | 
			
		||||
    .on_goaway              = on_goaway,
 | 
			
		||||
    .on_goaway              = on_goaway_client,
 | 
			
		||||
    .on_unexpected_frame    = on_unexpected_frame,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -7554,10 +7668,36 @@ static lsquic_stream_ctx_t *
 | 
			
		|||
hcsi_on_new (void *stream_if_ctx, struct lsquic_stream *stream)
 | 
			
		||||
{
 | 
			
		||||
    struct ietf_full_conn *const conn = (void *) stream_if_ctx;
 | 
			
		||||
    const struct hcsi_callbacks *callbacks;
 | 
			
		||||
 | 
			
		||||
    conn->ifc_stream_hcsi = stream;
 | 
			
		||||
 | 
			
		||||
    switch ((!!(conn->ifc_flags & IFC_SERVER) << 8) | conn->ifc_conn.cn_version)
 | 
			
		||||
    {
 | 
			
		||||
        case (0 << 8) | LSQVER_ID27:
 | 
			
		||||
            callbacks = &hcsi_callbacks_client_27;
 | 
			
		||||
            break;
 | 
			
		||||
        case (1 << 8) | LSQVER_ID27:
 | 
			
		||||
            callbacks = &hcsi_callbacks_server_27;
 | 
			
		||||
            break;
 | 
			
		||||
        case (0 << 8) | LSQVER_ID28:
 | 
			
		||||
            callbacks = &hcsi_callbacks_client_28;
 | 
			
		||||
            break;
 | 
			
		||||
        case (1 << 8) | LSQVER_ID28:
 | 
			
		||||
            callbacks = &hcsi_callbacks_server_28;
 | 
			
		||||
            break;
 | 
			
		||||
        case (0 << 8) | LSQVER_ID29:
 | 
			
		||||
            callbacks = &hcsi_callbacks_client_29;
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            assert(0);
 | 
			
		||||
            /* fallthru */
 | 
			
		||||
        case (1 << 8) | LSQVER_ID29:
 | 
			
		||||
            callbacks = &hcsi_callbacks_server_29;
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
    lsquic_hcsi_reader_init(&conn->ifc_hcsi.reader, &conn->ifc_conn,
 | 
			
		||||
        conn->ifc_flags & IFC_SERVER ? &hcsi_callbacks_server : &hcsi_callbacks,
 | 
			
		||||
                            conn);
 | 
			
		||||
                                                            callbacks, conn);
 | 
			
		||||
    lsquic_stream_wantread(stream, 1);
 | 
			
		||||
    return stream_if_ctx;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,11 @@
 | 
			
		|||
/* [draft-ietf-quic-tls-23] Section 5.2 */
 | 
			
		||||
#define HSK_SALT_BUF "\xc3\xee\xf7\x12\xc7\x2e\xbb\x5a\x11\xa7" \
 | 
			
		||||
                     "\xd2\x43\x2b\xb4\x63\x65\xbe\xf9\xf5\x02"
 | 
			
		||||
#define HSK_SALT ((unsigned char *) HSK_SALT_BUF)
 | 
			
		||||
#define HSK_SALT_PRE29 ((unsigned char *) HSK_SALT_BUF)
 | 
			
		||||
/* [draft-ietf-quic-tls-29] Section 5.2 */
 | 
			
		||||
#define HSK_SALT ((unsigned char *) \
 | 
			
		||||
                     "\xaf\xbf\xec\x28\x99\x93\xd2\x4c\x9e\x97" \
 | 
			
		||||
                     "\x86\xf1\x9c\x61\x11\xe0\x43\x90\xa8\x99")
 | 
			
		||||
#define HSK_SALT_SZ (sizeof(HSK_SALT_BUF) - 1)
 | 
			
		||||
 | 
			
		||||
#define CLIENT_LABEL "client in"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,7 +9,7 @@ enum trans_error_code
 | 
			
		|||
{
 | 
			
		||||
    TEC_NO_ERROR                   =  0x0,
 | 
			
		||||
    TEC_INTERNAL_ERROR             =  0x1,
 | 
			
		||||
    TEC_SERVER_BUSY                =  0x2,
 | 
			
		||||
    TEC_CONNECTION_REFUSED         =  0x2,
 | 
			
		||||
    TEC_FLOW_CONTROL_ERROR         =  0x3,
 | 
			
		||||
    TEC_STREAM_LIMIT_ERROR         =  0x4,
 | 
			
		||||
    TEC_STREAM_STATE_ERROR         =  0x5,
 | 
			
		||||
| 
						 | 
				
			
			@ -27,11 +27,12 @@ enum trans_error_code
 | 
			
		|||
#define MAX_IETF_CONN_DCIDS 8
 | 
			
		||||
 | 
			
		||||
/* [draft-ietf-quic-tls-25] Section 5.8 */
 | 
			
		||||
#define IETF_RETRY_KEY_BUF ((unsigned char *) \
 | 
			
		||||
        "\x4d\x32\xec\xdb\x2a\x21\x33\xc8\x41\xe4\x04\x3d\xf2\x7d\x44\x30")
 | 
			
		||||
#define IETF_RETRY_KEY_SZ 16
 | 
			
		||||
#define IETF_RETRY_NONCE_BUF ((unsigned char *) \
 | 
			
		||||
                        "\x4d\x16\x11\xd0\x55\x13\xa5\x52\xc5\x87\xd5\x75")
 | 
			
		||||
#define IETF_RETRY_NONCE_SZ 12
 | 
			
		||||
 | 
			
		||||
#define N_IETF_RETRY_VERSIONS 2
 | 
			
		||||
extern const unsigned char *const lsquic_retry_key_buf[N_IETF_RETRY_VERSIONS];
 | 
			
		||||
extern const unsigned char *const lsquic_retry_nonce_buf[N_IETF_RETRY_VERSIONS];
 | 
			
		||||
#define lsquic_version_2_retryver(ver_) ((ver_) > LSQVER_ID28)
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1623,7 +1623,7 @@ imico_generate_conn_close (struct ietf_mini_conn *conn)
 | 
			
		|||
    else if (conn->imc_flags & IMC_BAD_TRANS_PARAMS)
 | 
			
		||||
    {
 | 
			
		||||
        is_app = 0;
 | 
			
		||||
        error_code = TEC_PROTOCOL_VIOLATION;
 | 
			
		||||
        error_code = TEC_TRANSPORT_PARAMETER_ERROR;
 | 
			
		||||
        reason = "bad transport parameters";
 | 
			
		||||
        rlen = 24;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -220,6 +220,34 @@ lsquic_cid_from_packet (const unsigned char *buf, size_t bufsz,
 | 
			
		|||
/* See [draft-ietf-quic-transport-28], Section 12.4 (Table 3) */
 | 
			
		||||
const enum quic_ft_bit lsquic_legal_frames_by_level[N_LSQVER][N_ENC_LEVS] =
 | 
			
		||||
{
 | 
			
		||||
    [LSQVER_ID29] = {
 | 
			
		||||
    [ENC_LEV_CLEAR] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
 | 
			
		||||
                    | QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE,
 | 
			
		||||
    [ENC_LEV_EARLY] = QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
 | 
			
		||||
                    | QUIC_FTBIT_STREAM | QUIC_FTBIT_RST_STREAM
 | 
			
		||||
                    | QUIC_FTBIT_BLOCKED | QUIC_FTBIT_CONNECTION_CLOSE
 | 
			
		||||
                    | QUIC_FTBIT_MAX_DATA | QUIC_FTBIT_MAX_STREAM_DATA
 | 
			
		||||
                    | QUIC_FTBIT_MAX_STREAMS | QUIC_FTBIT_STREAM_BLOCKED
 | 
			
		||||
                    | QUIC_FTBIT_STREAMS_BLOCKED
 | 
			
		||||
                    | QUIC_FTBIT_NEW_CONNECTION_ID | QUIC_FTBIT_STOP_SENDING
 | 
			
		||||
                    | QUIC_FTBIT_PATH_CHALLENGE | QUIC_FTBIT_PATH_RESPONSE
 | 
			
		||||
                    | QUIC_FTBIT_RETIRE_CONNECTION_ID,
 | 
			
		||||
    [ENC_LEV_INIT]  = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
 | 
			
		||||
                    | QUIC_FTBIT_ACK| QUIC_FTBIT_CONNECTION_CLOSE,
 | 
			
		||||
    [ENC_LEV_FORW]  = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
 | 
			
		||||
                    | QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE
 | 
			
		||||
                    | QUIC_FTBIT_STREAM | QUIC_FTBIT_RST_STREAM
 | 
			
		||||
                    | QUIC_FTBIT_BLOCKED
 | 
			
		||||
                    | QUIC_FTBIT_MAX_DATA | QUIC_FTBIT_MAX_STREAM_DATA
 | 
			
		||||
                    | QUIC_FTBIT_MAX_STREAMS | QUIC_FTBIT_STREAM_BLOCKED
 | 
			
		||||
                    | QUIC_FTBIT_STREAMS_BLOCKED
 | 
			
		||||
                    | QUIC_FTBIT_NEW_CONNECTION_ID | QUIC_FTBIT_STOP_SENDING
 | 
			
		||||
                    | QUIC_FTBIT_PATH_CHALLENGE | QUIC_FTBIT_PATH_RESPONSE
 | 
			
		||||
                    | QUIC_FTBIT_HANDSHAKE_DONE | QUIC_FTBIT_ACK_FREQUENCY
 | 
			
		||||
                    | QUIC_FTBIT_RETIRE_CONNECTION_ID | QUIC_FTBIT_NEW_TOKEN
 | 
			
		||||
                    | QUIC_FTBIT_TIMESTAMP
 | 
			
		||||
                    ,
 | 
			
		||||
    },
 | 
			
		||||
    [LSQVER_ID28] = {
 | 
			
		||||
    [ENC_LEV_CLEAR] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
 | 
			
		||||
                    | QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1369,7 +1369,7 @@ lsquic_send_ctl_pacer_blocked (struct lsquic_send_ctl *ctl)
 | 
			
		|||
{
 | 
			
		||||
    return (ctl->sc_flags & SC_PACE)
 | 
			
		||||
        && !lsquic_pacer_can_schedule(&ctl->sc_pacer,
 | 
			
		||||
                               ctl->sc_n_scheduled + ctl->sc_n_in_flight_all);
 | 
			
		||||
                                               ctl->sc_n_in_flight_all);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1674,6 +1674,45 @@ send_ctl_maybe_zero_pad (struct lsquic_send_ctl *ctl,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Predict whether lsquic_send_ctl_next_packet_to_send() will return a
 | 
			
		||||
 * packet by mimicking its logic.  Returns true if packet will be returned,
 | 
			
		||||
 * false otherwise.
 | 
			
		||||
 */
 | 
			
		||||
int
 | 
			
		||||
lsquic_send_ctl_next_packet_to_send_predict (struct lsquic_send_ctl *ctl)
 | 
			
		||||
{
 | 
			
		||||
    const struct lsquic_packet_out *packet_out;
 | 
			
		||||
    unsigned n_rtos;
 | 
			
		||||
 | 
			
		||||
    n_rtos = ~0u;
 | 
			
		||||
    TAILQ_FOREACH(packet_out, &ctl->sc_scheduled_packets, po_next)
 | 
			
		||||
    {
 | 
			
		||||
        if (!(packet_out->po_frame_types & (1 << QUIC_FRAME_ACK))
 | 
			
		||||
            && 0 == ctl->sc_next_limit
 | 
			
		||||
            && 0 != (n_rtos == ~0u ? /* Initialize once */
 | 
			
		||||
                    (n_rtos = send_ctl_get_n_consec_rtos(ctl)) : n_rtos))
 | 
			
		||||
        {
 | 
			
		||||
            LSQ_DEBUG("send prediction: no, n_rtos: %u", n_rtos);
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        if ((packet_out->po_flags & PO_REPACKNO)
 | 
			
		||||
                    && packet_out->po_regen_sz == packet_out->po_data_sz)
 | 
			
		||||
        {
 | 
			
		||||
            LSQ_DEBUG("send prediction: packet %"PRIu64" would be dropped, "
 | 
			
		||||
                "continue", packet_out->po_packno);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        LSQ_DEBUG("send prediction: yes, packet %"PRIu64", flags %u, frames 0x%X",
 | 
			
		||||
            packet_out->po_packno, (unsigned) packet_out->po_flags,
 | 
			
		||||
            (unsigned) packet_out->po_frame_types);
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    LSQ_DEBUG("send prediction: no, no matching scheduled packets");
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
lsquic_packet_out_t *
 | 
			
		||||
lsquic_send_ctl_next_packet_to_send (struct lsquic_send_ctl *ctl, size_t size)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -1685,6 +1724,9 @@ lsquic_send_ctl_next_packet_to_send (struct lsquic_send_ctl *ctl, size_t size)
 | 
			
		|||
    if (!packet_out)
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
    /* Note: keep logic in this function and in
 | 
			
		||||
     * lsquic_send_ctl_next_packet_to_send_predict() in synch.
 | 
			
		||||
     */
 | 
			
		||||
    if (!(packet_out->po_frame_types & (1 << QUIC_FRAME_ACK))
 | 
			
		||||
                                        && send_ctl_get_n_consec_rtos(ctl))
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -168,6 +168,9 @@ lsquic_send_ctl_delayed_one (lsquic_send_ctl_t *, struct lsquic_packet_out *);
 | 
			
		|||
struct lsquic_packet_out *
 | 
			
		||||
lsquic_send_ctl_next_packet_to_send (struct lsquic_send_ctl *, size_t);
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
lsquic_send_ctl_next_packet_to_send_predict (struct lsquic_send_ctl *);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
lsquic_send_ctl_expire_all (lsquic_send_ctl_t *ctl);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -387,4 +390,9 @@ lsquic_send_ctl_begin_optack_detection (struct lsquic_send_ctl *);
 | 
			
		|||
void
 | 
			
		||||
lsquic_send_ctl_path_validated (struct lsquic_send_ctl *);
 | 
			
		||||
 | 
			
		||||
/* Has immediately sendable packets */
 | 
			
		||||
#define lsquic_send_ctl_has_sendable(ctl_) \
 | 
			
		||||
    (lsquic_send_ctl_n_scheduled(ctl_) > 0 \
 | 
			
		||||
                && lsquic_send_ctl_next_packet_to_send_predict(ctl_))
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1747,6 +1747,14 @@ void
 | 
			
		|||
lsquic_stream_received_goaway (lsquic_stream_t *stream)
 | 
			
		||||
{
 | 
			
		||||
    SM_HISTORY_APPEND(stream, SHE_GOAWAY_IN);
 | 
			
		||||
 | 
			
		||||
    if (stream->stream_flags & STREAM_GOAWAY_IN)
 | 
			
		||||
    {
 | 
			
		||||
        LSQ_DEBUG("ignore duplicate GOAWAY");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    stream->stream_flags |= STREAM_GOAWAY_IN;
 | 
			
		||||
 | 
			
		||||
    if (0 == stream->read_offset &&
 | 
			
		||||
                            stream->data_in->di_if->di_empty(stream->data_in))
 | 
			
		||||
        fake_reset_unused_stream(stream);       /* Normal condition */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -208,7 +208,7 @@ enum stream_flags {
 | 
			
		|||
    STREAM_ONNEW_DONE   = 1 << 17,  /* on_new_stream has been called */
 | 
			
		||||
    STREAM_PUSHING      = 1 << 18,
 | 
			
		||||
    STREAM_NOPUSH       = 1 << 19,  /* Disallow further push promises */
 | 
			
		||||
    STREAM_UNUSED20     = 1 << 20,  /* Unused */
 | 
			
		||||
    STREAM_GOAWAY_IN    = 1 << 20,  /* Incoming GOAWAY has been processed */
 | 
			
		||||
    STREAM_UNUSED21     = 1 << 21,  /* Unused */
 | 
			
		||||
    STREAM_RST_ACKED    = 1 << 22,  /* Packet containing RST has been acked */
 | 
			
		||||
    STREAM_BLOCKED_SENT = 1 << 23,  /* Stays set once a STREAM_BLOCKED frame is sent */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,6 +20,7 @@ static const unsigned char version_tags[N_LSQVER][4] =
 | 
			
		|||
#endif
 | 
			
		||||
    [LSQVER_ID27] = { 0xFF, 0, 0, 27, },
 | 
			
		||||
    [LSQVER_ID28] = { 0xFF, 0, 0, 28, },
 | 
			
		||||
    [LSQVER_ID29] = { 0xFF, 0, 0, 29, },
 | 
			
		||||
    [LSQVER_VERNEG] = { 0xFA, 0xFA, 0xFA, 0xFA, },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -58,6 +59,7 @@ const char *const lsquic_ver2str[N_LSQVER] = {
 | 
			
		|||
#endif
 | 
			
		||||
    [LSQVER_ID27] = "FF00001B",
 | 
			
		||||
    [LSQVER_ID28] = "FF00001C",
 | 
			
		||||
    [LSQVER_ID29] = "FF00001D",
 | 
			
		||||
    [LSQVER_VERNEG] = "FAFAFAFA",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,7 +33,7 @@ main (void)
 | 
			
		|||
    };
 | 
			
		||||
 | 
			
		||||
    HKDF_extract(secret, &secret_len, md, dcid.idbuf, dcid.len,
 | 
			
		||||
                                                HSK_SALT, HSK_SALT_SZ);
 | 
			
		||||
                                                HSK_SALT_PRE29, HSK_SALT_SZ);
 | 
			
		||||
 | 
			
		||||
    assert(sizeof(expected_secret) == secret_len);
 | 
			
		||||
    assert(0 == memcmp(secret, expected_secret, sizeof(expected_secret)));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue