mirror of
				https://gitea.invidious.io/iv-org/litespeed-quic.git
				synced 2024-08-15 00:53:43 +00:00 
			
		
		
		
	Release 2.29.0
- [FEATURE] QUIC and HTTP/3 Internet Draft 34 support and v1 support. The latter is turned off by default. - Drop support for ID-28 and ID-32. - [BUGFIX] IETF QUIC mini conn receive history (trechist): allow unlimited inserts by dropping smallest elements. - [BUGFIX] gQUIC: set STTL to correct value, issue #226. - [BUGFIX] Account for poison packet gap when MTU probe was too large.
This commit is contained in:
		
							parent
							
								
									ac0ce07bd0
								
							
						
					
					
						commit
						26e8f082c9
					
				
					 29 changed files with 411 additions and 178 deletions
				
			
		| 
						 | 
				
			
			@ -8,7 +8,7 @@ task:
 | 
			
		|||
        - cd boringssl
 | 
			
		||||
        # This is so that both GQUIC and IETF branches build.  Just picking
 | 
			
		||||
        # a known good revision:
 | 
			
		||||
        - git checkout b117a3a0b7bd11fe6ebd503ec6b45d6b910b41a1
 | 
			
		||||
        - git checkout a2278d4d2cabe73f6663e3299ea7808edfa306b9
 | 
			
		||||
        - cmake .
 | 
			
		||||
        - make
 | 
			
		||||
        - cd -
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,7 +32,7 @@ before_script:
 | 
			
		|||
    - cd boringssl
 | 
			
		||||
    # This is so that both GQUIC and IETF branches build.  Just picking
 | 
			
		||||
    # a known good revision:
 | 
			
		||||
    - git checkout b117a3a0b7bd11fe6ebd503ec6b45d6b910b41a1
 | 
			
		||||
    - git checkout a2278d4d2cabe73f6663e3299ea7808edfa306b9
 | 
			
		||||
    - cmake .
 | 
			
		||||
    - make
 | 
			
		||||
    - cd -
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										10
									
								
								CHANGELOG
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								CHANGELOG
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,3 +1,13 @@
 | 
			
		|||
2021-02-10
 | 
			
		||||
    - 2.29.0
 | 
			
		||||
    - [FEATURE] QUIC and HTTP/3 Internet Draft 34 support and v1 support.
 | 
			
		||||
      The latter is turned off by default.
 | 
			
		||||
    - Drop support for ID-28 and ID-32.
 | 
			
		||||
    - [BUGFIX] IETF QUIC mini conn receive history (trechist): allow
 | 
			
		||||
      unlimited inserts by dropping smallest elements.
 | 
			
		||||
    - [BUGFIX] gQUIC: set STTL to correct value, issue #226.
 | 
			
		||||
    - [BUGFIX] Account for poison packet gap when MTU probe was too large.
 | 
			
		||||
 | 
			
		||||
2021-02-03
 | 
			
		||||
    - 2.28.0
 | 
			
		||||
    - [API] lsquic_ssl_sess_to_resume_info() is the new way to get
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,7 +17,7 @@ COPY ./ /src/lsquic/
 | 
			
		|||
 | 
			
		||||
RUN git clone https://boringssl.googlesource.com/boringssl && \
 | 
			
		||||
    cd boringssl && \
 | 
			
		||||
    git checkout b117a3a0b7bd11fe6ebd503ec6b45d6b910b41a1 && \
 | 
			
		||||
    git checkout a2278d4d2cabe73f6663e3299ea7808edfa306b9 && \
 | 
			
		||||
    cmake . && \
 | 
			
		||||
    make
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,8 +13,9 @@ and HTTP/3 functionality for servers and clients.  Most of the code in this
 | 
			
		|||
distribution is used in our own products: LiteSpeed Web Server, LiteSpeed ADC,
 | 
			
		||||
and OpenLiteSpeed.
 | 
			
		||||
 | 
			
		||||
Currently supported QUIC versions are Q043, Q046, Q050, ID-27, ID-28, ID-29,
 | 
			
		||||
and ID-32.  Support for newer versions is added soon after they are released.
 | 
			
		||||
Currently supported QUIC versions are v1 (disabled by default until the
 | 
			
		||||
QUIC RFC is released); Internet-Draft versions 34, 29, and 27;
 | 
			
		||||
and the older "Google" QUIC versions Q043, Q046, an Q050.
 | 
			
		||||
 | 
			
		||||
Documentation
 | 
			
		||||
-------------
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +49,7 @@ You may need to install pre-requisites like zlib and libevent.
 | 
			
		|||
2. Use specific BoringSSL version
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
git checkout b117a3a0b7bd11fe6ebd503ec6b45d6b910b41a1
 | 
			
		||||
git checkout a2278d4d2cabe73f6663e3299ea7808edfa306b9
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
3. Compile the library
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,7 +30,7 @@ build_script:
 | 
			
		|||
 | 
			
		||||
    cd boringssl
 | 
			
		||||
 | 
			
		||||
    git checkout b117a3a0b7bd11fe6ebd503ec6b45d6b910b41a1
 | 
			
		||||
    git checkout a2278d4d2cabe73f6663e3299ea7808edfa306b9
 | 
			
		||||
 | 
			
		||||
    cmake -DCMAKE_GENERATOR_PLATFORM=x64 --config Debug -DBUILD_SHARED_LIBS=OFF -DOPENSSL_NO_ASM=1 .
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,17 +50,18 @@ developed by the IETF.  Both types are included in a single enum:
 | 
			
		|||
 | 
			
		||||
        IETF QUIC version ID (Internet-Draft) 27; this version is deprecated.
 | 
			
		||||
 | 
			
		||||
    .. member:: LSQVER_ID28
 | 
			
		||||
 | 
			
		||||
        IETF QUIC version ID 28; this version is deprecated.
 | 
			
		||||
 | 
			
		||||
    .. member:: LSQVER_ID29
 | 
			
		||||
 | 
			
		||||
        IETF QUIC version ID 29
 | 
			
		||||
 | 
			
		||||
    .. member:: LSQVER_ID32
 | 
			
		||||
    .. member:: LSQVER_ID34
 | 
			
		||||
 | 
			
		||||
        IETF QUIC version ID 32
 | 
			
		||||
        IETF QUIC version ID 34
 | 
			
		||||
 | 
			
		||||
    .. member:: LSQVER_I001
 | 
			
		||||
 | 
			
		||||
        IETF QUIC version 1.  (This version is disabled by default until
 | 
			
		||||
        the QUIC RFC is released).
 | 
			
		||||
 | 
			
		||||
    .. member:: N_LSQVER
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,9 +24,9 @@ copyright = u'2021, LiteSpeed Technologies'
 | 
			
		|||
author = u'LiteSpeed Technologies'
 | 
			
		||||
 | 
			
		||||
# The short X.Y version
 | 
			
		||||
version = u'2.28'
 | 
			
		||||
version = u'2.29'
 | 
			
		||||
# The full version, including alpha/beta/rc tags
 | 
			
		||||
release = u'2.28.0'
 | 
			
		||||
release = u'2.29.0'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# -- General configuration ---------------------------------------------------
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,9 +16,9 @@ Most of the code in this distribution has been  used in our own products
 | 
			
		|||
-- `LiteSpeed Web Server`_, `LiteSpeed Web ADC`_, and OpenLiteSpeed_ --
 | 
			
		||||
since 2017.
 | 
			
		||||
 | 
			
		||||
Currently supported QUIC versions are Q043, Q046, Q050, ID-27, ID-28,
 | 
			
		||||
ID-29, and ID-32.
 | 
			
		||||
Support for newer versions will be added soon after they are released.
 | 
			
		||||
Currently supported QUIC versions are v1 (disabled by default until the
 | 
			
		||||
QUIC RFC is released); Internet-Draft versions 34, 29, and 27;
 | 
			
		||||
and the older "Google" QUIC versions Q043, Q046, an Q050.
 | 
			
		||||
 | 
			
		||||
LSQUIC is licensed under the `MIT License`_; see LICENSE in the source
 | 
			
		||||
distribution for details.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,7 +24,7 @@ extern "C" {
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
#define LSQUIC_MAJOR_VERSION 2
 | 
			
		||||
#define LSQUIC_MINOR_VERSION 28
 | 
			
		||||
#define LSQUIC_MINOR_VERSION 29
 | 
			
		||||
#define LSQUIC_PATCH_VERSION 0
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -81,20 +81,21 @@ enum lsquic_version
 | 
			
		|||
     */
 | 
			
		||||
    LSQVER_ID27,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * IETF QUIC Draft-28; this version is deprecated.
 | 
			
		||||
     */
 | 
			
		||||
    LSQVER_ID28,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * IETF QUIC Draft-29
 | 
			
		||||
     */
 | 
			
		||||
    LSQVER_ID29,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * IETF QUIC Draft-32
 | 
			
		||||
     * IETF QUIC Draft-34
 | 
			
		||||
     */
 | 
			
		||||
    LSQVER_ID32,
 | 
			
		||||
    LSQVER_ID34,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * IETF QUIC v1.  Functionally the same as Draft-34, but marked
 | 
			
		||||
     * experimental for now.
 | 
			
		||||
     */
 | 
			
		||||
    LSQVER_I001,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Special version to trigger version negotiation.
 | 
			
		||||
| 
						 | 
				
			
			@ -106,8 +107,8 @@ enum lsquic_version
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * We currently support versions 43, 46, 50, Draft-27, Draft-28, Draft-29,
 | 
			
		||||
 * and Draft-32.
 | 
			
		||||
 * We currently support versions 43, 46, 50, Draft-27, Draft-29, Draft-34,
 | 
			
		||||
 * and IETF QUIC v1.
 | 
			
		||||
 * @see lsquic_version
 | 
			
		||||
 */
 | 
			
		||||
#define LSQUIC_SUPPORTED_VERSIONS ((1 << N_LSQVER) - 1)
 | 
			
		||||
| 
						 | 
				
			
			@ -118,19 +119,21 @@ enum lsquic_version
 | 
			
		|||
#define LSQUIC_FORCED_TCID0_VERSIONS ((1 << LSQVER_046)|(1 << LSQVER_050))
 | 
			
		||||
 | 
			
		||||
#define LSQUIC_EXPERIMENTAL_VERSIONS ( \
 | 
			
		||||
                            (1 << LSQVER_I001) | \
 | 
			
		||||
                            (1 << LSQVER_VERNEG) | LSQUIC_EXPERIMENTAL_Q098)
 | 
			
		||||
 | 
			
		||||
#define LSQUIC_DEPRECATED_VERSIONS ((1 << LSQVER_ID27) | (1 << LSQVER_ID28))
 | 
			
		||||
#define LSQUIC_DEPRECATED_VERSIONS ((1 << LSQVER_ID27))
 | 
			
		||||
 | 
			
		||||
#define LSQUIC_GQUIC_HEADER_VERSIONS (1 << LSQVER_043)
 | 
			
		||||
 | 
			
		||||
#define LSQUIC_IETF_VERSIONS ((1 << LSQVER_ID27) | (1 << LSQVER_ID28) \
 | 
			
		||||
#define LSQUIC_IETF_VERSIONS ((1 << LSQVER_ID27) \
 | 
			
		||||
                          | (1 << LSQVER_ID29) \
 | 
			
		||||
                          | (1 << LSQVER_ID32) | (1 << LSQVER_VERNEG))
 | 
			
		||||
                          | (1 << LSQVER_ID34) \
 | 
			
		||||
                          | (1 << LSQVER_I001) | (1 << LSQVER_VERNEG))
 | 
			
		||||
 | 
			
		||||
#define LSQUIC_IETF_DRAFT_VERSIONS ((1 << LSQVER_ID27) | (1 << LSQVER_ID28) \
 | 
			
		||||
#define LSQUIC_IETF_DRAFT_VERSIONS ((1 << LSQVER_ID27) \
 | 
			
		||||
                                  | (1 << LSQVER_ID29) \
 | 
			
		||||
                                  | (1 << LSQVER_ID32) | (1 << LSQVER_VERNEG))
 | 
			
		||||
              | (1 << LSQVER_ID34) | (1 << LSQVER_VERNEG))
 | 
			
		||||
 | 
			
		||||
enum lsquic_hsk_status
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,6 +26,12 @@ while (<HEADER>) {
 | 
			
		|||
            push @all_versions, $1;
 | 
			
		||||
            push @all_alpns, "h3-$2";
 | 
			
		||||
        }
 | 
			
		||||
        if (/^\s*(LSQVER_I(\d{3}))\b/) {
 | 
			
		||||
            push @all_versions, $1;
 | 
			
		||||
            if (not grep 'h3' eq $_, @all_alpns) {
 | 
			
		||||
                push @all_alpns, "h3";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -339,9 +339,9 @@ 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_ID32 ? &lsquic_enc_session_common_ietf_v1 : \
 | 
			
		||||
    ver == LSQVER_ID34 ? &lsquic_enc_session_common_ietf_v1 : \
 | 
			
		||||
    ver == LSQVER_I001 ? &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 )
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -72,10 +72,10 @@ static const struct alpn_map {
 | 
			
		|||
    const unsigned char *alpn;
 | 
			
		||||
} s_h3_alpns[] = {
 | 
			
		||||
    {   LSQVER_ID27, (unsigned char *) "\x05h3-27",     },
 | 
			
		||||
    {   LSQVER_ID28, (unsigned char *) "\x05h3-28",     },
 | 
			
		||||
    {   LSQVER_ID29, (unsigned char *) "\x05h3-29",     },
 | 
			
		||||
    {   LSQVER_ID32, (unsigned char *) "\x05h3-32",     },
 | 
			
		||||
    {   LSQVER_VERNEG, (unsigned char *) "\x05h3-32",     },
 | 
			
		||||
    {   LSQVER_ID34, (unsigned char *) "\x05h3-34",     },
 | 
			
		||||
    {   LSQVER_I001, (unsigned char *) "\x02h3",        },
 | 
			
		||||
    {   LSQVER_VERNEG, (unsigned char *) "\x05h3-34",     },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct enc_sess_iquic;
 | 
			
		||||
| 
						 | 
				
			
			@ -926,6 +926,10 @@ iquic_esfi_create_client (const char *hostname,
 | 
			
		|||
            ERR_error_string(ERR_get_error(), errbuf));
 | 
			
		||||
        goto err;
 | 
			
		||||
    }
 | 
			
		||||
#if BORINGSSL_API_VERSION >= 13
 | 
			
		||||
    SSL_set_quic_use_legacy_codepoint(enc_sess->esi_ssl,
 | 
			
		||||
                            enc_sess->esi_ver_neg->vn_ver < LSQVER_ID34);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    transpa_len = gen_trans_params(enc_sess, trans_params,
 | 
			
		||||
                                                    sizeof(trans_params));
 | 
			
		||||
| 
						 | 
				
			
			@ -1109,6 +1113,7 @@ setup_handshake_keys (struct enc_sess_iquic *enc_sess, const lsquic_cid_t *cid)
 | 
			
		|||
    struct header_prot *hp;
 | 
			
		||||
    size_t hsk_secret_sz, key_len;
 | 
			
		||||
    unsigned cliser, i;
 | 
			
		||||
    const unsigned char *salt;
 | 
			
		||||
    unsigned char hsk_secret[EVP_MAX_MD_SIZE];
 | 
			
		||||
    unsigned char secret[2][SHA256_DIGEST_LENGTH];  /* client, server */
 | 
			
		||||
    unsigned char key[2][EVP_MAX_KEY_LENGTH];
 | 
			
		||||
| 
						 | 
				
			
			@ -1131,12 +1136,17 @@ setup_handshake_keys (struct enc_sess_iquic *enc_sess, const lsquic_cid_t *cid)
 | 
			
		|||
    pair->ykp_thresh = IQUIC_INVALID_PACKNO;
 | 
			
		||||
    hp = &enc_sess->esi_hsk_hps[ENC_LEV_CLEAR];
 | 
			
		||||
 | 
			
		||||
    if (enc_sess->esi_conn->cn_version < LSQVER_ID29)
 | 
			
		||||
        salt = HSK_SALT_PRE29;
 | 
			
		||||
    else if (enc_sess->esi_conn->cn_version < LSQVER_ID34)
 | 
			
		||||
        salt = HSK_SALT_PRE33;
 | 
			
		||||
    else
 | 
			
		||||
        salt = HSK_SALT;
 | 
			
		||||
    HKDF_extract(hsk_secret, &hsk_secret_sz, md, cid->idbuf, cid->len,
 | 
			
		||||
                    enc_sess->esi_conn->cn_version < LSQVER_ID29
 | 
			
		||||
                    ? HSK_SALT_PRE29 : HSK_SALT, HSK_SALT_SZ);
 | 
			
		||||
                    salt, HSK_SALT_SZ);
 | 
			
		||||
    if (enc_sess->esi_flags & ESI_LOG_SECRETS)
 | 
			
		||||
    {
 | 
			
		||||
        LSQ_DEBUG("handshake salt: %s", HEXSTR(HSK_SALT, HSK_SALT_SZ, hexbuf));
 | 
			
		||||
        LSQ_DEBUG("handshake salt: %s", HEXSTR(salt, HSK_SALT_SZ, hexbuf));
 | 
			
		||||
        LSQ_DEBUG("handshake secret: %s", HEXSTR(hsk_secret, hsk_secret_sz,
 | 
			
		||||
                                                                    hexbuf));
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1382,6 +1392,10 @@ iquic_esfi_init_server (enc_session_t *enc_session_p)
 | 
			
		|||
            ERR_error_string(ERR_get_error(), u.errbuf));
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
#if BORINGSSL_API_VERSION >= 13
 | 
			
		||||
    SSL_set_quic_use_legacy_codepoint(enc_sess->esi_ssl,
 | 
			
		||||
                            enc_sess->esi_conn->cn_version < LSQVER_ID34);
 | 
			
		||||
#endif
 | 
			
		||||
    if (!(SSL_set_quic_method(enc_sess->esi_ssl, &cry_quic_method)))
 | 
			
		||||
    {
 | 
			
		||||
        LSQ_INFO("could not set stream method");
 | 
			
		||||
| 
						 | 
				
			
			@ -3327,6 +3341,9 @@ const unsigned char *const lsquic_retry_key_buf[N_IETF_RETRY_VERSIONS] =
 | 
			
		|||
    /* [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",
 | 
			
		||||
    /* [draft-ietf-quic-tls-33] Section 5.8 */
 | 
			
		||||
    (unsigned char *)
 | 
			
		||||
        "\xbe\x0c\x69\x0b\x9f\x66\x57\x5a\x1d\x76\x6b\x54\xe3\x68\xc8\x4e",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3336,6 +3353,8 @@ const unsigned char *const lsquic_retry_nonce_buf[N_IETF_RETRY_VERSIONS] =
 | 
			
		|||
    (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",
 | 
			
		||||
    /* [draft-ietf-quic-tls-33] Section 5.8 */
 | 
			
		||||
    (unsigned char *) "\x46\x15\x99\xd3\x5d\x63\x2b\xf2\x23\x98\x25\xbb",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -674,7 +674,7 @@ lsquic_engine_new (unsigned flags,
 | 
			
		|||
        {
 | 
			
		||||
            int sz = lsquic_enc_sess_ietf_gen_quic_ctx(
 | 
			
		||||
                        &engine->pub.enp_settings,
 | 
			
		||||
                        i == 0 ? LSQVER_ID27 : LSQVER_ID28,
 | 
			
		||||
                        i == 0 ? LSQVER_ID27 : LSQVER_ID29,
 | 
			
		||||
                        engine->pub.enp_quic_ctx_buf[i],
 | 
			
		||||
                        sizeof(engine->pub.enp_quic_ctx_buf));
 | 
			
		||||
            if (sz < 0)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3314,7 +3314,7 @@ try_to_begin_migration (struct ietf_full_conn *conn,
 | 
			
		|||
        return BM_NOT_MIGRATING;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (conn->ifc_conn.cn_version <= LSQVER_ID28 /* Starting with ID-29,
 | 
			
		||||
    if (conn->ifc_conn.cn_version <= LSQVER_ID27 /* 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. */
 | 
			
		||||
| 
						 | 
				
			
			@ -7566,16 +7566,16 @@ process_incoming_packet_verneg (struct ietf_full_conn *conn,
 | 
			
		|||
         */
 | 
			
		||||
        if (!verneg_ok(conn))
 | 
			
		||||
        {
 | 
			
		||||
            ABORT_ERROR("version negotiation not permitted in this version "
 | 
			
		||||
                                                                    "of QUIC");
 | 
			
		||||
            ABORT_WITH_FLAG(conn, LSQ_LOG_NOTICE, IFC_ERROR,
 | 
			
		||||
                "version negotiation not permitted in this version of QUIC");
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        versions &= conn->ifc_u.cli.ifcli_ver_neg.vn_supp;
 | 
			
		||||
        if (0 == versions)
 | 
			
		||||
        {
 | 
			
		||||
            ABORT_ERROR("client does not support any of the server-specified "
 | 
			
		||||
                        "versions");
 | 
			
		||||
            ABORT_WITH_FLAG(conn, LSQ_LOG_NOTICE, IFC_ERROR,
 | 
			
		||||
                "client does not support any of the server-specified versions");
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -7663,13 +7663,12 @@ ietf_full_conn_ci_packet_too_large (struct lsquic_conn *lconn,
 | 
			
		|||
    assert(packet_out->po_lflags & POL_HEADER_PROT);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    lsquic_senhist_add(&conn->ifc_send_ctl.sc_senhist, packet_out->po_packno);
 | 
			
		||||
    lsquic_send_ctl_sanity_check(&conn->ifc_send_ctl);
 | 
			
		||||
    if (packet_out->po_flags & PO_MTU_PROBE)
 | 
			
		||||
    {
 | 
			
		||||
        LSQ_DEBUG("%zu-byte MTU probe in packet %"PRIu64" is too large",
 | 
			
		||||
            lsquic_packet_out_sent_sz(&conn->ifc_conn, packet_out),
 | 
			
		||||
            packet_out->po_packno);
 | 
			
		||||
        lsquic_send_ctl_mtu_not_sent(&conn->ifc_send_ctl, packet_out);
 | 
			
		||||
        mtu_probe_too_large(conn, packet_out);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
| 
						 | 
				
			
			@ -9041,7 +9040,7 @@ on_goaway_server_27 (void *ctx, uint64_t stream_id)
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_goaway_client_28 (void *ctx, uint64_t stream_id)
 | 
			
		||||
on_goaway_client_27 (void *ctx, uint64_t stream_id)
 | 
			
		||||
{
 | 
			
		||||
    struct ietf_full_conn *const conn = ctx;
 | 
			
		||||
    struct lsquic_stream *stream;
 | 
			
		||||
| 
						 | 
				
			
			@ -9348,30 +9347,7 @@ static const struct hcsi_callbacks hcsi_callbacks_client_27 =
 | 
			
		|||
    .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,
 | 
			
		||||
    .on_priority_update     = on_priority_update_client,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static const struct hcsi_callbacks hcsi_callbacks_server_28 =
 | 
			
		||||
{
 | 
			
		||||
    .on_cancel_push         = on_cancel_push_server,
 | 
			
		||||
    .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,
 | 
			
		||||
    .on_priority_update     = on_priority_update_server,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct hcsi_callbacks hcsi_callbacks_client_28 =
 | 
			
		||||
{
 | 
			
		||||
    .on_cancel_push         = on_cancel_push_client,
 | 
			
		||||
    .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_goaway              = on_goaway_client_27,
 | 
			
		||||
    .on_unexpected_frame    = on_unexpected_frame,
 | 
			
		||||
    .on_priority_update     = on_priority_update_client,
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -9416,21 +9392,17 @@ hcsi_on_new (void *stream_if_ctx, struct lsquic_stream *stream)
 | 
			
		|||
        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:
 | 
			
		||||
        case (0 << 8) | LSQVER_ID32:
 | 
			
		||||
        case (0 << 8) | LSQVER_ID34:
 | 
			
		||||
        case (0 << 8) | LSQVER_I001:
 | 
			
		||||
            callbacks = &hcsi_callbacks_client_29;
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            assert(0);
 | 
			
		||||
            /* fallthru */
 | 
			
		||||
        case (1 << 8) | LSQVER_ID29:
 | 
			
		||||
        case (1 << 8) | LSQVER_ID32:
 | 
			
		||||
        case (1 << 8) | LSQVER_ID34:
 | 
			
		||||
        case (1 << 8) | LSQVER_I001:
 | 
			
		||||
            callbacks = &hcsi_callbacks_server_29;
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1963,13 +1963,12 @@ gen_rej1_data (struct lsquic_enc_session *enc_session, uint8_t *data,
 | 
			
		|||
    int len;
 | 
			
		||||
    EVP_PKEY * rsa_priv_key;
 | 
			
		||||
    SSL_CTX *ctx = enc_session->ssl_ctx;
 | 
			
		||||
    const struct lsquic_engine_settings *const settings =
 | 
			
		||||
                                        &enc_session->enpub->enp_settings;
 | 
			
		||||
    hs_ctx_t *const hs_ctx = &enc_session->hs_ctx;
 | 
			
		||||
    int scfg_len = enc_session->server_config->lsc_scfg->info.scfg_len;
 | 
			
		||||
    uint8_t *scfg_data = enc_session->server_config->lsc_scfg->scfg;
 | 
			
		||||
    size_t msg_len;
 | 
			
		||||
    struct message_writer mw;
 | 
			
		||||
    uint64_t sttl;
 | 
			
		||||
 | 
			
		||||
    rsa_priv_key = SSL_CTX_get0_privatekey(ctx);
 | 
			
		||||
    if (!rsa_priv_key)
 | 
			
		||||
| 
						 | 
				
			
			@ -2029,7 +2028,7 @@ gen_rej1_data (struct lsquic_enc_session *enc_session, uint8_t *data,
 | 
			
		|||
    MSG_LEN_ADD(msg_len, scfg_len);
 | 
			
		||||
    MSG_LEN_ADD(msg_len, STK_LENGTH);
 | 
			
		||||
    MSG_LEN_ADD(msg_len, SNO_LENGTH);
 | 
			
		||||
    MSG_LEN_ADD(msg_len, sizeof(settings->es_sttl));
 | 
			
		||||
    MSG_LEN_ADD(msg_len, sizeof(sttl));
 | 
			
		||||
    MSG_LEN_ADD(msg_len, lsquic_str_len(&hs_ctx->prof));
 | 
			
		||||
    if (hs_ctx->ccert)
 | 
			
		||||
        MSG_LEN_ADD(msg_len, hs_ctx->ccert->len);
 | 
			
		||||
| 
						 | 
				
			
			@ -2055,6 +2054,8 @@ gen_rej1_data (struct lsquic_enc_session *enc_session, uint8_t *data,
 | 
			
		|||
        lsquic_str_setlen(&enc_session->ssno, SNO_LENGTH);
 | 
			
		||||
    }
 | 
			
		||||
    RAND_bytes((uint8_t *) lsquic_str_buf(&enc_session->ssno), SNO_LENGTH);
 | 
			
		||||
    sttl = enc_session->enpub->enp_server_config->lsc_scfg->info.expy
 | 
			
		||||
                                                    - (uint64_t) time(NULL);
 | 
			
		||||
 | 
			
		||||
    MW_BEGIN(&mw, QTAG_REJ, 7, data);
 | 
			
		||||
    MW_WRITE_LS_STR(&mw, QTAG_STK, &enc_session->sstk);
 | 
			
		||||
| 
						 | 
				
			
			@ -2062,8 +2063,7 @@ gen_rej1_data (struct lsquic_enc_session *enc_session, uint8_t *data,
 | 
			
		|||
    MW_WRITE_LS_STR(&mw, QTAG_PROF, &hs_ctx->prof);
 | 
			
		||||
    MW_WRITE_BUFFER(&mw, QTAG_SCFG, scfg_data, scfg_len);
 | 
			
		||||
    MW_WRITE_BUFFER(&mw, QTAG_RREJ, &hs_ctx->rrej, sizeof(hs_ctx->rrej));
 | 
			
		||||
    MW_WRITE_BUFFER(&mw, QTAG_STTL, &settings->es_sttl,
 | 
			
		||||
                                                sizeof(settings->es_sttl));
 | 
			
		||||
    MW_WRITE_BUFFER(&mw, QTAG_STTL, &sttl, sizeof(sttl));
 | 
			
		||||
    if (hs_ctx->ccert)
 | 
			
		||||
        MW_WRITE_BUFFER(&mw, QTAG_CRT, hs_ctx->ccert->buf, hs_ctx->ccert->len);
 | 
			
		||||
    MW_END(&mw);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,9 +7,13 @@
 | 
			
		|||
                     "\xd2\x43\x2b\xb4\x63\x65\xbe\xf9\xf5\x02"
 | 
			
		||||
#define HSK_SALT_PRE29 ((unsigned char *) HSK_SALT_BUF)
 | 
			
		||||
/* [draft-ietf-quic-tls-29] Section 5.2 */
 | 
			
		||||
#define HSK_SALT ((unsigned char *) \
 | 
			
		||||
#define HSK_SALT_PRE33 ((unsigned char *) \
 | 
			
		||||
                     "\xaf\xbf\xec\x28\x99\x93\xd2\x4c\x9e\x97" \
 | 
			
		||||
                     "\x86\xf1\x9c\x61\x11\xe0\x43\x90\xa8\x99")
 | 
			
		||||
/* [draft-ietf-quic-tls-33] Section 5.2 */
 | 
			
		||||
#define HSK_SALT ((unsigned char *) \
 | 
			
		||||
                     "\x38\x76\x2c\xf7\xf5\x59\x34\xb3\x4d\x17" \
 | 
			
		||||
                     "\x9a\xe6\xa4\xc8\x0c\xad\xcc\xbb\x7f\x0a")
 | 
			
		||||
#define HSK_SALT_SZ (sizeof(HSK_SALT_BUF) - 1)
 | 
			
		||||
 | 
			
		||||
#define CLIENT_LABEL "client in"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -78,6 +78,7 @@ enum http_error_code
 | 
			
		|||
    HEC_REQUEST_REJECTED        =  0x10B,
 | 
			
		||||
    HEC_REQUEST_CANCELLED       =  0x10C,
 | 
			
		||||
    HEC_REQUEST_INCOMPLETE      =  0x10D,
 | 
			
		||||
    HEC_MESSAGE_ERROR           =  0x10E,
 | 
			
		||||
    HEC_CONNECT_ERROR           =  0x10F,
 | 
			
		||||
    HEC_VERSION_FALLBACK        =  0x110,
 | 
			
		||||
    HEC_QPACK_DECOMPRESSION_FAILED  = 0x200,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,7 @@
 | 
			
		|||
 | 
			
		||||
/* Things specific to the IETF version of QUIC that do not fit anywhere else */
 | 
			
		||||
 | 
			
		||||
/* [draft-ietf-quic-transport-31] Section 20 */
 | 
			
		||||
/* [draft-ietf-quic-transport-33] Section 20 */
 | 
			
		||||
enum trans_error_code
 | 
			
		||||
{
 | 
			
		||||
    TEC_NO_ERROR                   =  0x0,
 | 
			
		||||
| 
						 | 
				
			
			@ -23,6 +23,7 @@ enum trans_error_code
 | 
			
		|||
    TEC_CRYPTO_BUFFER_EXCEEDED     =  0xD,
 | 
			
		||||
    TEC_KEY_UPDATE_ERROR           =  0xE,
 | 
			
		||||
    TEC_AEAD_LIMIT_REACHED         =  0xF,
 | 
			
		||||
    TEC_NO_VIABLE_PATH             = 0x10,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Must be at least two */
 | 
			
		||||
| 
						 | 
				
			
			@ -32,9 +33,12 @@ enum trans_error_code
 | 
			
		|||
#define IETF_RETRY_KEY_SZ 16
 | 
			
		||||
#define IETF_RETRY_NONCE_SZ 12
 | 
			
		||||
 | 
			
		||||
#define N_IETF_RETRY_VERSIONS 2
 | 
			
		||||
#define N_IETF_RETRY_VERSIONS 3
 | 
			
		||||
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)
 | 
			
		||||
#define lsquic_version_2_retryver(ver_) (                       \
 | 
			
		||||
    (ver_) <= LSQVER_ID27 ? 0 :                                 \
 | 
			
		||||
    (ver_) <= LSQVER_ID34 ? 1 :                                 \
 | 
			
		||||
    2)
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1378,15 +1378,10 @@ imico_switch_to_trechist (struct ietf_mini_conn *conn)
 | 
			
		|||
        if (conn->imc_recvd_packnos.bitmasks[pns])
 | 
			
		||||
        {
 | 
			
		||||
            lsquic_imico_rechist_init(&iter, conn, pns);
 | 
			
		||||
            if (0 != lsquic_trechist_copy_ranges(&masks[pns],
 | 
			
		||||
            lsquic_trechist_copy_ranges(&masks[pns],
 | 
			
		||||
                                elems + TRECHIST_MAX_RANGES * pns, &iter,
 | 
			
		||||
                                lsquic_imico_rechist_first,
 | 
			
		||||
                                lsquic_imico_rechist_next))
 | 
			
		||||
            {
 | 
			
		||||
                LSQ_WARN("cannot copy ranges from bitmask to trechist");
 | 
			
		||||
                free(elems);
 | 
			
		||||
                return -1;
 | 
			
		||||
            }
 | 
			
		||||
                                lsquic_imico_rechist_next);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
            masks[pns] = 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -336,7 +336,7 @@ lsquic_dcid_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_ID32] = {
 | 
			
		||||
    [LSQVER_I001] = {
 | 
			
		||||
    [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
 | 
			
		||||
| 
						 | 
				
			
			@ -346,7 +346,37 @@ const enum quic_ft_bit lsquic_legal_frames_by_level[N_LSQVER][N_ENC_LEVS] =
 | 
			
		|||
                    | 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_DATAGRAM
 | 
			
		||||
                    | 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
 | 
			
		||||
                    | QUIC_FTBIT_DATAGRAM
 | 
			
		||||
                    ,
 | 
			
		||||
    },
 | 
			
		||||
    [LSQVER_ID34] = {
 | 
			
		||||
    [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_DATAGRAM
 | 
			
		||||
                    | QUIC_FTBIT_RETIRE_CONNECTION_ID,
 | 
			
		||||
    [ENC_LEV_INIT]  = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
 | 
			
		||||
| 
						 | 
				
			
			@ -396,34 +426,6 @@ const enum quic_ft_bit lsquic_legal_frames_by_level[N_LSQVER][N_ENC_LEVS] =
 | 
			
		|||
                    | QUIC_FTBIT_DATAGRAM
 | 
			
		||||
                    ,
 | 
			
		||||
    },
 | 
			
		||||
    [LSQVER_ID28] = {
 | 
			
		||||
    [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_ID27] = {
 | 
			
		||||
    [ENC_LEV_CLEAR] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
 | 
			
		||||
                    | QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -641,6 +641,10 @@ send_ctl_add_poison (struct lsquic_send_ctl *ctl)
 | 
			
		|||
{
 | 
			
		||||
    struct lsquic_packet_out *poison;
 | 
			
		||||
 | 
			
		||||
    /* XXX Allocating the poison packet out of the regular pool can fail.
 | 
			
		||||
     * This leads to a lot of error checking that could be skipped if we
 | 
			
		||||
     * did not have to allocate this packet at all.
 | 
			
		||||
     */
 | 
			
		||||
    poison = lsquic_malo_get(ctl->sc_conn_pub->packet_out_malo);
 | 
			
		||||
    if (!poison)
 | 
			
		||||
        return -1;
 | 
			
		||||
| 
						 | 
				
			
			@ -689,6 +693,33 @@ send_ctl_reschedule_poison (struct lsquic_send_ctl *ctl)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
send_ctl_update_poison_hist (struct lsquic_send_ctl *ctl,
 | 
			
		||||
                                                    lsquic_packno_t packno)
 | 
			
		||||
{
 | 
			
		||||
    if (packno == ctl->sc_gap + 1)
 | 
			
		||||
    {
 | 
			
		||||
        assert(!(ctl->sc_flags & SC_POISON));
 | 
			
		||||
        lsquic_senhist_add(&ctl->sc_senhist, ctl->sc_gap);
 | 
			
		||||
        if (0 != send_ctl_add_poison(ctl))
 | 
			
		||||
            return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
lsquic_send_ctl_mtu_not_sent (struct lsquic_send_ctl *ctl,
 | 
			
		||||
                                        struct lsquic_packet_out *packet_out)
 | 
			
		||||
{
 | 
			
		||||
    (void)  /* See comment in send_ctl_add_poison(): the plan is to make
 | 
			
		||||
    this code path always succeed. */
 | 
			
		||||
    send_ctl_update_poison_hist(ctl, packet_out->po_packno);
 | 
			
		||||
    lsquic_senhist_add(&ctl->sc_senhist, packet_out->po_packno);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
lsquic_send_ctl_sent_packet (lsquic_send_ctl_t *ctl,
 | 
			
		||||
                             struct lsquic_packet_out *packet_out)
 | 
			
		||||
| 
						 | 
				
			
			@ -699,13 +730,8 @@ lsquic_send_ctl_sent_packet (lsquic_send_ctl_t *ctl,
 | 
			
		|||
    assert(!(packet_out->po_flags & PO_ENCRYPTED));
 | 
			
		||||
    ctl->sc_last_sent_time = packet_out->po_sent;
 | 
			
		||||
    pns = lsquic_packet_out_pns(packet_out);
 | 
			
		||||
    if (packet_out->po_packno == ctl->sc_gap + 1)
 | 
			
		||||
    {
 | 
			
		||||
        assert(!(ctl->sc_flags & SC_POISON));
 | 
			
		||||
        lsquic_senhist_add(&ctl->sc_senhist, ctl->sc_gap);
 | 
			
		||||
        if (0 != send_ctl_add_poison(ctl))
 | 
			
		||||
            return -1;
 | 
			
		||||
    }
 | 
			
		||||
    if (0 != send_ctl_update_poison_hist(ctl, packet_out->po_packno))
 | 
			
		||||
        return -1;
 | 
			
		||||
    LSQ_DEBUG("packet %"PRIu64" has been sent (frame types: %s)",
 | 
			
		||||
        packet_out->po_packno, lsquic_frame_types_to_str(frames,
 | 
			
		||||
            sizeof(frames), packet_out->po_frame_types));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -155,6 +155,10 @@ lsquic_send_ctl_init (lsquic_send_ctl_t *, struct lsquic_alarmset *,
 | 
			
		|||
int
 | 
			
		||||
lsquic_send_ctl_sent_packet (lsquic_send_ctl_t *, struct lsquic_packet_out *);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
lsquic_send_ctl_mtu_not_sent (struct lsquic_send_ctl *ctl,
 | 
			
		||||
                                                    struct lsquic_packet_out *);
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
lsquic_send_ctl_got_ack (lsquic_send_ctl_t *, const struct ack_info *,
 | 
			
		||||
                                                lsquic_time_t, lsquic_time_t);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1473,7 +1473,7 @@ verify_cl_on_fin (struct lsquic_stream *stream)
 | 
			
		|||
    if (stream->sm_data_in != 0 && stream->sm_cont_len != stream->sm_data_in)
 | 
			
		||||
    {
 | 
			
		||||
        lconn = stream->conn_pub->lconn;
 | 
			
		||||
        lconn->cn_if->ci_abort_error(lconn, 1, HEC_GENERAL_PROTOCOL_ERROR,
 | 
			
		||||
        lconn->cn_if->ci_abort_error(lconn, 1, HEC_MESSAGE_ERROR,
 | 
			
		||||
            "number of bytes in DATA frames of stream %"PRIu64" is %llu, "
 | 
			
		||||
            "while content-length specified of %llu", stream->id,
 | 
			
		||||
            stream->sm_data_in, stream->sm_cont_len);
 | 
			
		||||
| 
						 | 
				
			
			@ -4811,7 +4811,7 @@ verify_cl_on_new_data_frame (struct lsquic_stream *stream,
 | 
			
		|||
    if (stream->sm_data_in > stream->sm_cont_len)
 | 
			
		||||
    {
 | 
			
		||||
        lconn = stream->conn_pub->lconn;
 | 
			
		||||
        lconn->cn_if->ci_abort_error(lconn, 1, HEC_GENERAL_PROTOCOL_ERROR,
 | 
			
		||||
        lconn->cn_if->ci_abort_error(lconn, 1, HEC_MESSAGE_ERROR,
 | 
			
		||||
            "number of bytes in DATA frames of stream %"PRIu64" exceeds "
 | 
			
		||||
            "content-length limit of %llu", stream->id, stream->sm_cont_len);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,12 +29,15 @@ find_free_slot (uint32_t slots)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Returns 0 on success, 1 if dup, -1 if out of elements */
 | 
			
		||||
/* When capacity is reached, smallest element is removed.  When the number
 | 
			
		||||
 * of elements in a single range cannot be represented by te_count, an
 | 
			
		||||
 * error is returned.  This is the only error this function returns.
 | 
			
		||||
 */
 | 
			
		||||
int
 | 
			
		||||
lsquic_trechist_insert (trechist_mask_t *mask, struct trechist_elem *elems,
 | 
			
		||||
                                                            uint32_t packno)
 | 
			
		||||
{
 | 
			
		||||
    struct trechist_elem *el, *prev;
 | 
			
		||||
    struct trechist_elem *el, *prev, *cur, *next;
 | 
			
		||||
    unsigned idx;
 | 
			
		||||
 | 
			
		||||
    if (*mask == 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -54,17 +57,22 @@ lsquic_trechist_insert (trechist_mask_t *mask, struct trechist_elem *elems,
 | 
			
		|||
            goto insert_before;
 | 
			
		||||
        if (packno == el->te_low - 1)
 | 
			
		||||
        {
 | 
			
		||||
            if (el->te_count == UCHAR_MAX)
 | 
			
		||||
                return -1;
 | 
			
		||||
            --el->te_low;
 | 
			
		||||
            ++el->te_count;
 | 
			
		||||
            if (el->te_next && el->te_low == TE_HIGH(&elems[el->te_next]) + 1)
 | 
			
		||||
            if (el->te_next && el->te_low == TE_HIGH(&elems[el->te_next]) + 2)
 | 
			
		||||
            {
 | 
			
		||||
                if (el->te_count + elems[el->te_next].te_count - 1 > UCHAR_MAX)
 | 
			
		||||
                    return -1;
 | 
			
		||||
                *mask &= ~(1u << el->te_next);
 | 
			
		||||
                el->te_count += elems[el->te_next].te_count;
 | 
			
		||||
                el->te_count += elems[el->te_next].te_count + 1;
 | 
			
		||||
                el->te_low    = elems[el->te_next].te_low;
 | 
			
		||||
                el->te_next   = elems[el->te_next].te_next;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                if (el->te_count == UCHAR_MAX)
 | 
			
		||||
                    return -1;
 | 
			
		||||
                --el->te_low;
 | 
			
		||||
                ++el->te_count;
 | 
			
		||||
            }
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        if (packno == TE_HIGH(el) + 1)
 | 
			
		||||
| 
						 | 
				
			
			@ -75,15 +83,18 @@ lsquic_trechist_insert (trechist_mask_t *mask, struct trechist_elem *elems,
 | 
			
		|||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        if (packno >= el->te_low && packno <= TE_HIGH(el))
 | 
			
		||||
            return 1;   /* Dup */
 | 
			
		||||
            return 0;   /* Dup */
 | 
			
		||||
        if (!el->te_next)
 | 
			
		||||
            break;  /* insert tail */
 | 
			
		||||
        prev = el;
 | 
			
		||||
        el = &elems[el->te_next];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (*mask == ((1u << TRECHIST_MAX_RANGES) - 1))
 | 
			
		||||
        return -1;
 | 
			
		||||
    if (*mask == TRECHIST_MAX_RANGES_MASK)
 | 
			
		||||
        /* No need to insert element smaller than the smallest element
 | 
			
		||||
         * already in our list.  The new element "overflows".
 | 
			
		||||
         */
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    idx = find_free_slot(*mask);
 | 
			
		||||
    elems[idx].te_low   = packno;
 | 
			
		||||
| 
						 | 
				
			
			@ -95,10 +106,17 @@ lsquic_trechist_insert (trechist_mask_t *mask, struct trechist_elem *elems,
 | 
			
		|||
 | 
			
		||||
  insert_before:
 | 
			
		||||
 | 
			
		||||
    if (*mask == ((1u << TRECHIST_MAX_RANGES) - 1))
 | 
			
		||||
        return -1;
 | 
			
		||||
    if (*mask != TRECHIST_MAX_RANGES_MASK)
 | 
			
		||||
        idx = find_free_slot(*mask);
 | 
			
		||||
    else
 | 
			
		||||
    {   /* Drop last element and reuse its slot */
 | 
			
		||||
        for (next = &elems[el->te_next], cur = el; next->te_next;
 | 
			
		||||
                                cur = next, next = &elems[cur->te_next])
 | 
			
		||||
            ;
 | 
			
		||||
        idx = cur->te_next;
 | 
			
		||||
        cur->te_next = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    idx = find_free_slot(*mask);
 | 
			
		||||
    *mask |= 1u << idx;;
 | 
			
		||||
    if (el == elems)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -159,7 +177,8 @@ lsquic_trechist_next (void *iter_p)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
/* First TRECHIST_MAX_RANGES ranges are copied */
 | 
			
		||||
void
 | 
			
		||||
lsquic_trechist_copy_ranges (trechist_mask_t *mask,
 | 
			
		||||
                    struct trechist_elem *elems, void *src_rechist,
 | 
			
		||||
                    const struct lsquic_packno_range * (*first) (void *),
 | 
			
		||||
| 
						 | 
				
			
			@ -182,19 +201,13 @@ lsquic_trechist_copy_ranges (trechist_mask_t *mask,
 | 
			
		|||
        el->te_next = i + 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!range && el)
 | 
			
		||||
    {
 | 
			
		||||
    if (el)
 | 
			
		||||
        el->te_next = 0;
 | 
			
		||||
 | 
			
		||||
    if (i < 32)
 | 
			
		||||
        *mask = (1u << i) - 1;
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    else if (!el)
 | 
			
		||||
    {
 | 
			
		||||
        *mask = 0;
 | 
			
		||||
        return 0;   /* Must have been an empty */
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
        return -1;
 | 
			
		||||
        *mask = UINT32_MAX;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,7 @@ struct lsquic_packno_range;
 | 
			
		|||
 * UCHAR_MAX, which is how many different values can fit into te_next.
 | 
			
		||||
 */
 | 
			
		||||
#define TRECHIST_MAX_RANGES 16
 | 
			
		||||
#define TRECHIST_MAX_RANGES_MASK ((1u << TRECHIST_MAX_RANGES) - 1)
 | 
			
		||||
 | 
			
		||||
struct trechist_elem
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -58,7 +59,7 @@ lsquic_trechist_first (void *iter);
 | 
			
		|||
const struct lsquic_packno_range *
 | 
			
		||||
lsquic_trechist_next (void *iter);
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
void
 | 
			
		||||
lsquic_trechist_copy_ranges (trechist_mask_t *mask /* This gets overwritten */,
 | 
			
		||||
                    struct trechist_elem *elems, void *src_rechist,
 | 
			
		||||
                    const struct lsquic_packno_range * (*first) (void *),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,9 +19,9 @@ static const unsigned char version_tags[N_LSQVER][4] =
 | 
			
		|||
    [LSQVER_098] = { 'Q', '0', '9', '8', },
 | 
			
		||||
#endif
 | 
			
		||||
    [LSQVER_ID27] = { 0xFF, 0, 0, 27, },
 | 
			
		||||
    [LSQVER_ID28] = { 0xFF, 0, 0, 28, },
 | 
			
		||||
    [LSQVER_ID29] = { 0xFF, 0, 0, 29, },
 | 
			
		||||
    [LSQVER_ID32] = { 0xFF, 0, 0, 32, },
 | 
			
		||||
    [LSQVER_ID34] = { 0xFF, 0, 0, 34, },
 | 
			
		||||
    [LSQVER_I001] = {    0, 0, 0, 1, },
 | 
			
		||||
    [LSQVER_VERNEG] = { 0xFA, 0xFA, 0xFA, 0xFA, },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -59,9 +59,9 @@ const char *const lsquic_ver2str[N_LSQVER] = {
 | 
			
		|||
    [LSQVER_098] = "Q098",
 | 
			
		||||
#endif
 | 
			
		||||
    [LSQVER_ID27] = "FF00001B",
 | 
			
		||||
    [LSQVER_ID28] = "FF00001C",
 | 
			
		||||
    [LSQVER_ID29] = "FF00001D",
 | 
			
		||||
    [LSQVER_ID32] = "FF000020",
 | 
			
		||||
    [LSQVER_ID34] = "FF000022",
 | 
			
		||||
    [LSQVER_I001] = "00000001",
 | 
			
		||||
    [LSQVER_VERNEG] = "FAFAFAFA",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1141,9 +1141,9 @@ fuzz_guided_pwritev_testing (const char *input)
 | 
			
		|||
    case 1: version = LSQVER_046; break;
 | 
			
		||||
    case 2: version = LSQVER_050; break;
 | 
			
		||||
    case 3: version = LSQVER_ID27; break;
 | 
			
		||||
    case 4: version = LSQVER_ID28; break;
 | 
			
		||||
    case 4: version = LSQVER_ID29; break;
 | 
			
		||||
    default:
 | 
			
		||||
    case 5: version = LSQVER_ID29; break;
 | 
			
		||||
    case 5: version = LSQVER_ID34; break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sched_immed = !!(buf[8] & 0x08);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,6 +16,32 @@
 | 
			
		|||
#include "lsquic_trechist.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct str_range_iter
 | 
			
		||||
{
 | 
			
		||||
    char                        *str;
 | 
			
		||||
    struct lsquic_packno_range   range;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static const struct lsquic_packno_range *
 | 
			
		||||
next_str_range (void *ctx)
 | 
			
		||||
{
 | 
			
		||||
    struct str_range_iter *const str_iter = ctx;
 | 
			
		||||
 | 
			
		||||
    if (str_iter->str && str_iter->str[0] == '[')
 | 
			
		||||
    {
 | 
			
		||||
        str_iter->range.high = strtoul(str_iter->str + 1, &str_iter->str, 10);
 | 
			
		||||
        assert('-' == *str_iter->str);
 | 
			
		||||
        str_iter->range.low = strtoul(str_iter->str + 1, &str_iter->str, 10);
 | 
			
		||||
        assert(']' == *str_iter->str);
 | 
			
		||||
        ++str_iter->str;
 | 
			
		||||
        return &str_iter->range;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
        return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
test_clone (trechist_mask_t src_mask, struct trechist_elem *src_elems)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -23,14 +49,12 @@ test_clone (trechist_mask_t src_mask, struct trechist_elem *src_elems)
 | 
			
		|||
    struct trechist_elem *hist_elems;
 | 
			
		||||
    const struct lsquic_packno_range *ranges[2];
 | 
			
		||||
    struct trechist_iter iters[2];
 | 
			
		||||
    int s;
 | 
			
		||||
 | 
			
		||||
    hist_elems = malloc(sizeof(hist_elems[0]) * TRECHIST_MAX_RANGES);
 | 
			
		||||
 | 
			
		||||
    lsquic_trechist_iter(&iters[0], src_mask, src_elems);
 | 
			
		||||
    s = lsquic_trechist_copy_ranges(&hist_mask, hist_elems, &iters[0],
 | 
			
		||||
    lsquic_trechist_copy_ranges(&hist_mask, hist_elems, &iters[0],
 | 
			
		||||
                        lsquic_trechist_first, lsquic_trechist_next);
 | 
			
		||||
    assert(s == 0);
 | 
			
		||||
 | 
			
		||||
    lsquic_trechist_iter(&iters[0], src_mask, src_elems);
 | 
			
		||||
    lsquic_trechist_iter(&iters[1], hist_mask, hist_elems);
 | 
			
		||||
| 
						 | 
				
			
			@ -254,10 +278,6 @@ basic_test (void)
 | 
			
		|||
    s = lsquic_trechist_insert(&hist_mask, hist_elems, 1);
 | 
			
		||||
    assert(("inserting packet number one is successful", 0 == s));
 | 
			
		||||
 | 
			
		||||
    s = lsquic_trechist_insert(&hist_mask, hist_elems, 1);
 | 
			
		||||
    assert(("inserting packet number one again results in duplicate error",
 | 
			
		||||
                                                            s == 1));
 | 
			
		||||
 | 
			
		||||
    lsquic_trechist_iter(&iter, hist_mask, hist_elems);
 | 
			
		||||
    range = lsquic_trechist_first(&iter);
 | 
			
		||||
    assert(("first range returned correctly", range));
 | 
			
		||||
| 
						 | 
				
			
			@ -338,18 +358,168 @@ test_limits (void)
 | 
			
		|||
    s = lsquic_trechist_insert(&hist_mask, hist_elems, i);
 | 
			
		||||
    assert(s == -1);    /* Overflow */
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < TRECHIST_MAX_RANGES - 1; ++i)
 | 
			
		||||
    /* Always successful inserting new entries: */
 | 
			
		||||
    for (i = 0; i < TRECHIST_MAX_RANGES * 2; ++i)
 | 
			
		||||
    {
 | 
			
		||||
        s = lsquic_trechist_insert(&hist_mask, hist_elems, 1000 + 2 * i);
 | 
			
		||||
        assert(s == 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    s = lsquic_trechist_insert(&hist_mask, hist_elems, 1000 + 2 * i);
 | 
			
		||||
    assert(s == -1);    /* Out of ranges */
 | 
			
		||||
    /* Always successful inserting new entries in descending order, too: */
 | 
			
		||||
    for (i = 0; i < TRECHIST_MAX_RANGES * 2; ++i)
 | 
			
		||||
    {
 | 
			
		||||
        s = lsquic_trechist_insert(&hist_mask, hist_elems, 10000 - 2 * i);
 | 
			
		||||
        assert(s == 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Test merge where count exceeds max: */
 | 
			
		||||
    hist_mask = 0;
 | 
			
		||||
    lsquic_trechist_copy_ranges(&hist_mask, hist_elems,
 | 
			
		||||
        & (struct str_range_iter) { .str = "[400-202][200-1]", },
 | 
			
		||||
        next_str_range, next_str_range);
 | 
			
		||||
    s = lsquic_trechist_insert(&hist_mask, hist_elems, 201);
 | 
			
		||||
    assert(s == -1);
 | 
			
		||||
 | 
			
		||||
    free(hist_elems);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
test_overflow (void)
 | 
			
		||||
{
 | 
			
		||||
    trechist_mask_t       mask;
 | 
			
		||||
    struct trechist_elem *elems;
 | 
			
		||||
    int s;
 | 
			
		||||
    char buf[0x1000];
 | 
			
		||||
 | 
			
		||||
    struct str_range_iter str_iter = { .str =
 | 
			
		||||
        "[395-390]"     /* 1 */
 | 
			
		||||
        "[385-380]"
 | 
			
		||||
        "[375-370]"
 | 
			
		||||
        "[365-360]"
 | 
			
		||||
        "[355-350]"     /* 5 */
 | 
			
		||||
        "[345-340]"
 | 
			
		||||
        "[335-330]"
 | 
			
		||||
        "[325-320]"
 | 
			
		||||
        "[315-310]"
 | 
			
		||||
        "[305-300]"     /* 10 */
 | 
			
		||||
        "[295-290]"
 | 
			
		||||
        "[285-280]"
 | 
			
		||||
        "[275-270]"
 | 
			
		||||
        "[265-260]"
 | 
			
		||||
        "[255-250]"     /* 15 */
 | 
			
		||||
        "[245-240]"     /* 16 */
 | 
			
		||||
        "[235-230]"     /* Overflow vvvvvv */
 | 
			
		||||
        "[225-220]"
 | 
			
		||||
        "[215-210]"
 | 
			
		||||
        "[205-200]"
 | 
			
		||||
        "[195-190]"
 | 
			
		||||
        "[185-180]" };
 | 
			
		||||
 | 
			
		||||
    elems = malloc(sizeof(elems[0]) * TRECHIST_MAX_RANGES);
 | 
			
		||||
    lsquic_trechist_copy_ranges(&mask, elems, &str_iter, next_str_range,
 | 
			
		||||
                                                         next_str_range);
 | 
			
		||||
 | 
			
		||||
    rechist2str(mask, elems, buf, sizeof(buf));
 | 
			
		||||
    assert(0 == strcmp(buf,
 | 
			
		||||
        "[395-390]"     /* 1 */
 | 
			
		||||
        "[385-380]"
 | 
			
		||||
        "[375-370]"
 | 
			
		||||
        "[365-360]"
 | 
			
		||||
        "[355-350]"     /* 5 */
 | 
			
		||||
        "[345-340]"
 | 
			
		||||
        "[335-330]"
 | 
			
		||||
        "[325-320]"
 | 
			
		||||
        "[315-310]"
 | 
			
		||||
        "[305-300]"     /* 10 */
 | 
			
		||||
        "[295-290]"
 | 
			
		||||
        "[285-280]"
 | 
			
		||||
        "[275-270]"
 | 
			
		||||
        "[265-260]"
 | 
			
		||||
        "[255-250]"     /* 15 */
 | 
			
		||||
        "[245-240]"     /* 16 */));
 | 
			
		||||
 | 
			
		||||
    s = lsquic_trechist_insert(&mask, elems, 400);
 | 
			
		||||
    assert(s == 0);
 | 
			
		||||
    rechist2str(mask, elems, buf, sizeof(buf));
 | 
			
		||||
    assert(0 == strcmp(buf,
 | 
			
		||||
        "[400-400]"
 | 
			
		||||
        "[395-390]"
 | 
			
		||||
        "[385-380]"
 | 
			
		||||
        "[375-370]"
 | 
			
		||||
        "[365-360]"
 | 
			
		||||
        "[355-350]"
 | 
			
		||||
        "[345-340]"
 | 
			
		||||
        "[335-330]"
 | 
			
		||||
        "[325-320]"
 | 
			
		||||
        "[315-310]"
 | 
			
		||||
        "[305-300]"
 | 
			
		||||
        "[295-290]"
 | 
			
		||||
        "[285-280]"
 | 
			
		||||
        "[275-270]"
 | 
			
		||||
        "[265-260]"
 | 
			
		||||
        "[255-250]"
 | 
			
		||||
    ));
 | 
			
		||||
 | 
			
		||||
    /* One more for a good measure */
 | 
			
		||||
    s = lsquic_trechist_insert(&mask, elems, 402);
 | 
			
		||||
    assert(s == 0);
 | 
			
		||||
    rechist2str(mask, elems, buf, sizeof(buf));
 | 
			
		||||
    assert(0 == strcmp(buf,
 | 
			
		||||
        "[402-402]"
 | 
			
		||||
        "[400-400]"
 | 
			
		||||
        "[395-390]"
 | 
			
		||||
        "[385-380]"
 | 
			
		||||
        "[375-370]"
 | 
			
		||||
        "[365-360]"
 | 
			
		||||
        "[355-350]"
 | 
			
		||||
        "[345-340]"
 | 
			
		||||
        "[335-330]"
 | 
			
		||||
        "[325-320]"
 | 
			
		||||
        "[315-310]"
 | 
			
		||||
        "[305-300]"
 | 
			
		||||
        "[295-290]"
 | 
			
		||||
        "[285-280]"
 | 
			
		||||
        "[275-270]"
 | 
			
		||||
        "[265-260]"
 | 
			
		||||
    ));
 | 
			
		||||
 | 
			
		||||
    s = lsquic_trechist_insert(&mask, elems, 401);
 | 
			
		||||
    assert(s == 0);
 | 
			
		||||
    s = lsquic_trechist_insert(&mask, elems, 500);
 | 
			
		||||
    assert(s == 0);
 | 
			
		||||
    s = lsquic_trechist_insert(&mask, elems, 200);
 | 
			
		||||
    assert(s == 0);
 | 
			
		||||
    s = lsquic_trechist_insert(&mask, elems, 267);
 | 
			
		||||
    assert(s == 0);
 | 
			
		||||
 | 
			
		||||
    /* One more for a good measure */
 | 
			
		||||
    s = lsquic_trechist_insert(&mask, elems, 402);
 | 
			
		||||
    assert(s == 0);
 | 
			
		||||
    rechist2str(mask, elems, buf, sizeof(buf));
 | 
			
		||||
    assert(0 == strcmp(buf,
 | 
			
		||||
        "[500-500]"
 | 
			
		||||
        "[402-400]"
 | 
			
		||||
        "[395-390]"
 | 
			
		||||
        "[385-380]"
 | 
			
		||||
        "[375-370]"
 | 
			
		||||
        "[365-360]"
 | 
			
		||||
        "[355-350]"
 | 
			
		||||
        "[345-340]"
 | 
			
		||||
        "[335-330]"
 | 
			
		||||
        "[325-320]"
 | 
			
		||||
        "[315-310]"
 | 
			
		||||
        "[305-300]"
 | 
			
		||||
        "[295-290]"
 | 
			
		||||
        "[285-280]"
 | 
			
		||||
        "[275-270]"
 | 
			
		||||
        "[267-267]"
 | 
			
		||||
    ));
 | 
			
		||||
 | 
			
		||||
    free(elems);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main (void)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -357,6 +527,7 @@ main (void)
 | 
			
		|||
    test4();
 | 
			
		||||
    test5();
 | 
			
		||||
    test_limits();
 | 
			
		||||
    test_overflow();
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue