mirror of
				https://gitea.invidious.io/iv-org/litespeed-quic.git
				synced 2024-08-15 00:53:43 +00:00 
			
		
		
		
	Release 2.15.0
- [FEATURE] QUIC and HTTP/3 Internet Draft 28 support. - [BUGFIX] Ignore Retry packets after other packets are decrypted successfully. - [BUGFIX] Transport parameter decoding: CID no longer has 4-byte length minimum. - http_client: fix and optimize lsxpack_header allocator. - Drop support for Internet Draft 25.
This commit is contained in:
		
							parent
							
								
									4d221313f7
								
							
						
					
					
						commit
						fb73393fef
					
				
					 33 changed files with 1124 additions and 631 deletions
				
			
		
							
								
								
									
										10
									
								
								CHANGELOG
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								CHANGELOG
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,3 +1,13 @@
 | 
			
		|||
2020-05-27
 | 
			
		||||
    - 2.15.0
 | 
			
		||||
    - [FEATURE] QUIC and HTTP/3 Internet Draft 28 support.
 | 
			
		||||
    - [BUGFIX] Ignore Retry packets after other packets are decrypted
 | 
			
		||||
      successfully.
 | 
			
		||||
    - [BUGFIX] Transport parameter decoding: CID no longer has 4-byte
 | 
			
		||||
      length minimum.
 | 
			
		||||
    - http_client: fix and optimize lsxpack_header allocator.
 | 
			
		||||
    - Drop support for Internet Draft 25.
 | 
			
		||||
 | 
			
		||||
2020-05-19
 | 
			
		||||
    - 2.14.8
 | 
			
		||||
    - Support Android.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -220,6 +220,7 @@ struct lsquic_conn_ctx {
 | 
			
		|||
struct hset_elem
 | 
			
		||||
{
 | 
			
		||||
    STAILQ_ENTRY(hset_elem)     next;
 | 
			
		||||
    size_t                      nalloc;
 | 
			
		||||
    struct lsxpack_header       xhdr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -999,16 +1000,19 @@ hset_prepare_decode (void *hset_p, struct lsxpack_header *xhdr,
 | 
			
		|||
        }
 | 
			
		||||
        STAILQ_INSERT_TAIL(hset, el, next);
 | 
			
		||||
        lsxpack_header_prepare_decode(&el->xhdr, buf, 0, req_space);
 | 
			
		||||
        el->nalloc = req_space;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        el = (struct hset_elem *) ((char *) xhdr
 | 
			
		||||
                                        - offsetof(struct hset_elem, xhdr));
 | 
			
		||||
        if (req_space <= xhdr->val_len)
 | 
			
		||||
        if (req_space <= el->nalloc)
 | 
			
		||||
        {
 | 
			
		||||
            LSQ_ERROR("requested space is smaller than already allocated");
 | 
			
		||||
            return NULL;
 | 
			
		||||
        }
 | 
			
		||||
        if (req_space < el->nalloc * 2)
 | 
			
		||||
            req_space = el->nalloc * 2;
 | 
			
		||||
        buf = realloc(el->xhdr.buf, req_space);
 | 
			
		||||
        if (!buf)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -1017,6 +1021,7 @@ hset_prepare_decode (void *hset_p, struct lsxpack_header *xhdr,
 | 
			
		|||
        }
 | 
			
		||||
        el->xhdr.buf = buf;
 | 
			
		||||
        el->xhdr.val_len = req_space;
 | 
			
		||||
        el->nalloc = req_space;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return &el->xhdr;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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-25\x5h3-27";
 | 
			
		||||
    const unsigned char alpn[] = "\x5h3-27\x5h3-28";
 | 
			
		||||
    int r;
 | 
			
		||||
 | 
			
		||||
    r = SSL_select_next_proto((unsigned char **) out, outlen, in, inlen,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1915,11 +1915,6 @@ set_engine_option (struct lsquic_engine_settings *settings,
 | 
			
		|||
            settings->es_qpack_dec_max_size = atoi(val);
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        if (0 == strncmp(name, "max_packet_size_rx", 18))
 | 
			
		||||
        {
 | 
			
		||||
            settings->es_max_packet_size_rx = atoi(val);
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case 20:
 | 
			
		||||
        if (0 == strncmp(name, "max_header_list_size", 20))
 | 
			
		||||
| 
						 | 
				
			
			@ -1945,6 +1940,13 @@ set_engine_option (struct lsquic_engine_settings *settings,
 | 
			
		|||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case 23:
 | 
			
		||||
        if (0 == strncmp(name, "max_udp_payload_size_rx", 18))
 | 
			
		||||
        {
 | 
			
		||||
            settings->es_max_udp_payload_size_rx = atoi(val);
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case 24:
 | 
			
		||||
        if (0 == strncmp(name, "init_max_stream_data_uni", 24))
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -693,7 +693,7 @@ settings structure:
 | 
			
		|||
 | 
			
		||||
       Default value is @ref LSQUIC_DF_TIMESTAMPS
 | 
			
		||||
 | 
			
		||||
    .. member:: unsigned short  es_max_packet_size_rx
 | 
			
		||||
    .. member:: unsigned short  es_max_udp_payload_size_rx
 | 
			
		||||
 | 
			
		||||
       Maximum packet size we are willing to receive.  This is sent to
 | 
			
		||||
       peer in transport parameters: the library does not enforce this
 | 
			
		||||
| 
						 | 
				
			
			@ -701,7 +701,7 @@ settings structure:
 | 
			
		|||
 | 
			
		||||
       If set to zero, limit is not set.
 | 
			
		||||
 | 
			
		||||
       Default value is :macro:`LSQUIC_DF_MAX_PACKET_SIZE_RX`
 | 
			
		||||
       Default value is :macro:`LSQUIC_DF_MAX_UDP_PAYLOAD_SIZE_RX`
 | 
			
		||||
 | 
			
		||||
To initialize the settings structure to library defaults, use the following
 | 
			
		||||
convenience function:
 | 
			
		||||
| 
						 | 
				
			
			@ -877,7 +877,7 @@ out of date.  Please check your :file:`lsquic.h` for actual values.*
 | 
			
		|||
 | 
			
		||||
    Delayed ACKs are off by default.
 | 
			
		||||
 | 
			
		||||
.. macro:: LSQUIC_DF_MAX_PACKET_SIZE_RX
 | 
			
		||||
.. macro:: LSQUIC_DF_MAX_UDP_PAYLOAD_SIZE_RX
 | 
			
		||||
 | 
			
		||||
    By default, incoming packet size is not limited.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1099,7 +1099,7 @@ callback.
 | 
			
		|||
 | 
			
		||||
In client mode, a new connection is created by
 | 
			
		||||
 | 
			
		||||
.. function:: lsquic_conn_t * lsquic_engine_connect (lsquic_engine_t *engine, enum lsquic_version version, const struct sockaddr *local_sa, const struct sockaddr *peer_sa, void *peer_ctx, lsquic_conn_ctx_t *conn_ctx, const char *sni, unsigned short max_packet_size, const unsigned char *zero_rtt, size_t zero_rtt_len, const unsigned char *token, size_t token_sz)
 | 
			
		||||
.. function:: lsquic_conn_t * lsquic_engine_connect (lsquic_engine_t *engine, enum lsquic_version version, const struct sockaddr *local_sa, const struct sockaddr *peer_sa, void *peer_ctx, lsquic_conn_ctx_t *conn_ctx, const char *sni, unsigned short max_udp_payload_size, const unsigned char *zero_rtt, size_t zero_rtt_len, const unsigned char *token, size_t token_sz)
 | 
			
		||||
 | 
			
		||||
    :param engine: Engine to use.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1132,7 +1132,7 @@ In client mode, a new connection is created by
 | 
			
		|||
        The SNI is required for Google QUIC connections; it is optional for
 | 
			
		||||
        IETF QUIC and may be set to NULL.
 | 
			
		||||
 | 
			
		||||
    :param max_packet_size:
 | 
			
		||||
    :param max_udp_payload_size:
 | 
			
		||||
 | 
			
		||||
        Maximum packet size.  If set to zero, it is inferred based on `peer_sa`
 | 
			
		||||
        and `version`.
 | 
			
		||||
| 
						 | 
				
			
			@ -1168,11 +1168,7 @@ Closing Connections
 | 
			
		|||
    Mark connection as going away: send GOAWAY frame and do not accept
 | 
			
		||||
    any more incoming streams, nor generate streams of our own.
 | 
			
		||||
 | 
			
		||||
    In the server mode, of course, we can call this function just fine in both
 | 
			
		||||
    Google and IETF QUIC.
 | 
			
		||||
 | 
			
		||||
    In client mode, calling this function in for an IETF QUIC connection does
 | 
			
		||||
    not do anything, as the client MUST NOT send GOAWAY frames.
 | 
			
		||||
    Only applicable to HTTP/3 and GQUIC connections.  Otherwise a no-op.
 | 
			
		||||
 | 
			
		||||
.. function:: void lsquic_conn_close (lsquic_conn_t *conn)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,9 +24,9 @@ copyright = u'2020, LiteSpeed Technologies'
 | 
			
		|||
author = u'LiteSpeed Technologies'
 | 
			
		||||
 | 
			
		||||
# The short X.Y version
 | 
			
		||||
version = u'2.14'
 | 
			
		||||
version = u'2.15'
 | 
			
		||||
# The full version, including alpha/beta/rc tags
 | 
			
		||||
release = u'2.14.8'
 | 
			
		||||
release = u'2.15.0'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# -- General configuration ---------------------------------------------------
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@ 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-25, and ID-27.
 | 
			
		||||
Currently supported QUIC versions are Q043, Q046, Q050, ID-27, and ID-28.
 | 
			
		||||
Support for newer versions will be added soon after they are released.
 | 
			
		||||
 | 
			
		||||
LSQUIC is licensed under the `MIT License`_; see LICENSE in the source
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,8 +24,8 @@ extern "C" {
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
#define LSQUIC_MAJOR_VERSION 2
 | 
			
		||||
#define LSQUIC_MINOR_VERSION 14
 | 
			
		||||
#define LSQUIC_PATCH_VERSION 8
 | 
			
		||||
#define LSQUIC_MINOR_VERSION 15
 | 
			
		||||
#define LSQUIC_PATCH_VERSION 0
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Engine flags:
 | 
			
		||||
| 
						 | 
				
			
			@ -76,16 +76,16 @@ enum lsquic_version
 | 
			
		|||
#define LSQUIC_EXPERIMENTAL_Q098 0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * IETF QUIC Draft-25
 | 
			
		||||
     */
 | 
			
		||||
    LSQVER_ID25,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * IETF QUIC Draft-27
 | 
			
		||||
     */
 | 
			
		||||
    LSQVER_ID27,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * IETF QUIC Draft-28
 | 
			
		||||
     */
 | 
			
		||||
    LSQVER_ID28,
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Special version to trigger version negotiation.
 | 
			
		||||
     * [draft-ietf-quic-transport-11], Section 3.
 | 
			
		||||
| 
						 | 
				
			
			@ -96,7 +96,7 @@ enum lsquic_version
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * We currently support versions 43, 46, 50, Draft-25, and Draft-27.
 | 
			
		||||
 * We currently support versions 43, 46, 50, Draft-27, and Draft-28.
 | 
			
		||||
 * @see lsquic_version
 | 
			
		||||
 */
 | 
			
		||||
#define LSQUIC_SUPPORTED_VERSIONS ((1 << N_LSQVER) - 1)
 | 
			
		||||
| 
						 | 
				
			
			@ -113,10 +113,10 @@ enum lsquic_version
 | 
			
		|||
 | 
			
		||||
#define LSQUIC_GQUIC_HEADER_VERSIONS (1 << LSQVER_043)
 | 
			
		||||
 | 
			
		||||
#define LSQUIC_IETF_VERSIONS ((1 << LSQVER_ID25) | (1 << LSQVER_ID27) \
 | 
			
		||||
#define LSQUIC_IETF_VERSIONS ((1 << LSQVER_ID27) | (1 << LSQVER_ID28) \
 | 
			
		||||
                                                    | (1 << LSQVER_VERNEG))
 | 
			
		||||
 | 
			
		||||
#define LSQUIC_IETF_DRAFT_VERSIONS ((1 << LSQVER_ID25) | (1 << LSQVER_ID27) \
 | 
			
		||||
#define LSQUIC_IETF_DRAFT_VERSIONS ((1 << LSQVER_ID27) | (1 << LSQVER_ID28) \
 | 
			
		||||
                                                    | (1 << LSQVER_VERNEG))
 | 
			
		||||
 | 
			
		||||
enum lsquic_hsk_status
 | 
			
		||||
| 
						 | 
				
			
			@ -341,7 +341,7 @@ typedef struct ssl_ctx_st * (*lsquic_lookup_cert_f)(
 | 
			
		|||
#define LSQUIC_DF_CC_ALGO 1
 | 
			
		||||
 | 
			
		||||
/** By default, incoming packet size is not limited. */
 | 
			
		||||
#define LSQUIC_DF_MAX_PACKET_SIZE_RX 0
 | 
			
		||||
#define LSQUIC_DF_MAX_UDP_PAYLOAD_SIZE_RX 0
 | 
			
		||||
 | 
			
		||||
struct lsquic_engine_settings {
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -749,9 +749,9 @@ struct lsquic_engine_settings {
 | 
			
		|||
     *
 | 
			
		||||
     * If set to zero, limit is not set.
 | 
			
		||||
     *
 | 
			
		||||
     * Default value is @ref LSQUIC_DF_MAX_PACKET_SIZE_RX
 | 
			
		||||
     * Default value is @ref LSQUIC_DF_MAX_UDP_PAYLOAD_SIZE_RX
 | 
			
		||||
     */
 | 
			
		||||
    unsigned short  es_max_packet_size_rx;
 | 
			
		||||
    unsigned short  es_max_udp_payload_size_rx;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Initialize `settings' to default values */
 | 
			
		||||
| 
						 | 
				
			
			@ -1078,7 +1078,7 @@ lsquic_engine_new (unsigned lsquic_engine_flags,
 | 
			
		|||
 * To let the engine specify QUIC version, use N_LSQVER.  If zero-rtt info
 | 
			
		||||
 * is supplied, version is picked from there instead.
 | 
			
		||||
 *
 | 
			
		||||
 * If `max_packet_size' is set to zero, it is inferred based on `peer_sa':
 | 
			
		||||
 * If `max_udp_payload_size' is set to zero, it is inferred based on `peer_sa':
 | 
			
		||||
 * 1350 for IPv6 and 1370 for IPv4.
 | 
			
		||||
 */
 | 
			
		||||
lsquic_conn_t *
 | 
			
		||||
| 
						 | 
				
			
			@ -1086,7 +1086,7 @@ lsquic_engine_connect (lsquic_engine_t *, enum lsquic_version,
 | 
			
		|||
                       const struct sockaddr *local_sa,
 | 
			
		||||
                       const struct sockaddr *peer_sa,
 | 
			
		||||
                       void *peer_ctx, lsquic_conn_ctx_t *conn_ctx,
 | 
			
		||||
                       const char *hostname, unsigned short max_packet_size,
 | 
			
		||||
                       const char *hostname, unsigned short max_udp_payload_size,
 | 
			
		||||
                       const unsigned char *zero_rtt, size_t zero_rtt_len,
 | 
			
		||||
                       /** Resumption token: optional */
 | 
			
		||||
                       const unsigned char *token, size_t token_sz);
 | 
			
		||||
| 
						 | 
				
			
			@ -1174,12 +1174,7 @@ lsquic_conn_cancel_pending_streams (lsquic_conn_t *, unsigned n);
 | 
			
		|||
 * Mark connection as going away: send GOAWAY frame and do not accept
 | 
			
		||||
 * any more incoming streams, nor generate streams of our own.
 | 
			
		||||
 *
 | 
			
		||||
 * In the server mode, of course, we can call this function just fine in both
 | 
			
		||||
 * Google and IETF QUIC.
 | 
			
		||||
 *
 | 
			
		||||
 * In client mode, calling this function in for an IETF QUIC connection does
 | 
			
		||||
 * not do anything, as the client MUST NOT send GOAWAY frames.
 | 
			
		||||
 * See [draft-ietf-quic-http-17] Section 4.2.7.
 | 
			
		||||
 * Only applicable to HTTP/3 and GQUIC connections.  Otherwise a no-op.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
lsquic_conn_going_away (lsquic_conn_t *);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,6 +33,8 @@ enum alarm_id {
 | 
			
		|||
    AL_PATH_CHAL,
 | 
			
		||||
    AL_PATH_CHAL_0 = AL_PATH_CHAL,
 | 
			
		||||
    AL_PATH_CHAL_1,
 | 
			
		||||
    AL_PATH_CHAL_2,
 | 
			
		||||
    AL_PATH_CHAL_3,
 | 
			
		||||
    AL_SESS_TICKET,
 | 
			
		||||
    AL_BLOCKED_KA,      /* Blocked Keep-Alive */
 | 
			
		||||
    MAX_LSQUIC_ALARMS
 | 
			
		||||
| 
						 | 
				
			
			@ -51,6 +53,8 @@ enum alarm_id_bit {
 | 
			
		|||
    ALBIT_CID_THROT = 1 << AL_CID_THROT,
 | 
			
		||||
    ALBIT_PATH_CHAL_0 = 1 << AL_PATH_CHAL_0,
 | 
			
		||||
    ALBIT_PATH_CHAL_1 = 1 << AL_PATH_CHAL_1,
 | 
			
		||||
    ALBIT_PATH_CHAL_2 = 1 << AL_PATH_CHAL_2,
 | 
			
		||||
    ALBIT_PATH_CHAL_3 = 1 << AL_PATH_CHAL_3,
 | 
			
		||||
    ALBIT_SESS_TICKET = 1 << AL_SESS_TICKET,
 | 
			
		||||
    ALBIT_BLOCKED_KA  = 1 << AL_BLOCKED_KA,
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -243,6 +243,10 @@ struct conn_iface
 | 
			
		|||
    /* Optional method.  Only used by the IETF client code. */
 | 
			
		||||
    void
 | 
			
		||||
    (*ci_drop_crypto_streams) (struct lsquic_conn *);
 | 
			
		||||
 | 
			
		||||
    /* Optional method.  Only used by IETF connections */
 | 
			
		||||
    void
 | 
			
		||||
    (*ci_count_garbage) (struct lsquic_conn *, size_t);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define LSCONN_CCE_BITS 3
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -276,6 +276,9 @@ struct enc_session_funcs_iquic
 | 
			
		|||
    (*esfi_reset_dcid) (enc_session_t *, const struct lsquic_cid *,
 | 
			
		||||
                                                const struct lsquic_cid *);
 | 
			
		||||
 | 
			
		||||
    void
 | 
			
		||||
    (*esfi_set_iscid) (enc_session_t *, const struct lsquic_packet_in *);
 | 
			
		||||
 | 
			
		||||
    int
 | 
			
		||||
    (*esfi_init_server) (enc_session_t *);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -288,7 +291,8 @@ struct enc_session_funcs_iquic
 | 
			
		|||
                                                    const struct lsquic_cid *,
 | 
			
		||||
                           void *(crypto_streams)[4],
 | 
			
		||||
                           const struct crypto_stream_if *,
 | 
			
		||||
                           const struct lsquic_cid *odcid);
 | 
			
		||||
                           const struct lsquic_cid *odcid,
 | 
			
		||||
                           const struct lsquic_cid *iscid );
 | 
			
		||||
 | 
			
		||||
    void
 | 
			
		||||
    (*esfi_shake_stream)(enc_session_t *, struct lsquic_stream *,
 | 
			
		||||
| 
						 | 
				
			
			@ -328,8 +332,8 @@ struct enc_session_funcs_gquic lsquic_enc_session_gquic_gquic_1;
 | 
			
		|||
extern const struct enc_session_funcs_iquic lsquic_enc_session_iquic_ietf_v1;
 | 
			
		||||
 | 
			
		||||
#define select_esf_common_by_ver(ver) ( \
 | 
			
		||||
    ver == LSQVER_ID25 ? &lsquic_enc_session_common_ietf_v1 : \
 | 
			
		||||
    ver == LSQVER_ID27 ? &lsquic_enc_session_common_ietf_v1 : \
 | 
			
		||||
    ver == LSQVER_ID28 ? &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 )
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -71,9 +71,9 @@ static const struct alpn_map {
 | 
			
		|||
    enum lsquic_version  version;
 | 
			
		||||
    const unsigned char *alpn;
 | 
			
		||||
} s_h3_alpns[] = {
 | 
			
		||||
    {   LSQVER_ID25, (unsigned char *) "\x05h3-25",     },
 | 
			
		||||
    {   LSQVER_ID27, (unsigned char *) "\x05h3-27",     },
 | 
			
		||||
    {   LSQVER_VERNEG, (unsigned char *) "\x05h3-27",     },
 | 
			
		||||
    {   LSQVER_ID28, (unsigned char *) "\x05h3-28",     },
 | 
			
		||||
    {   LSQVER_VERNEG, (unsigned char *) "\x05h3-28",     },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct enc_sess_iquic;
 | 
			
		||||
| 
						 | 
				
			
			@ -221,6 +221,8 @@ struct enc_sess_iquic
 | 
			
		|||
    struct header_prot  *esi_hsk_hps;
 | 
			
		||||
    lsquic_packno_t      esi_max_packno[N_PNS];
 | 
			
		||||
    lsquic_cid_t         esi_odcid;
 | 
			
		||||
    lsquic_cid_t         esi_rscid; /* Retry SCID */
 | 
			
		||||
    lsquic_cid_t         esi_iscid; /* Initial SCID */
 | 
			
		||||
    unsigned             esi_key_phase;
 | 
			
		||||
    enum {
 | 
			
		||||
        ESI_INITIALIZED  = 1 << 0,
 | 
			
		||||
| 
						 | 
				
			
			@ -237,6 +239,9 @@ struct enc_sess_iquic
 | 
			
		|||
        ESI_WANT_TICKET  = 1 << 11,
 | 
			
		||||
        ESI_RECV_QL_BITS = 1 << 12,
 | 
			
		||||
        ESI_SEND_QL_BITS = 1 << 13,
 | 
			
		||||
        ESI_RSCID        = 1 << 14,
 | 
			
		||||
        ESI_ISCID        = 1 << 15,
 | 
			
		||||
        ESI_RETRY        = 1 << 16, /* Connection was retried */
 | 
			
		||||
    }                    esi_flags;
 | 
			
		||||
    enum evp_aead_direction_t
 | 
			
		||||
                         esi_dir[2];        /* client, server */
 | 
			
		||||
| 
						 | 
				
			
			@ -429,9 +434,15 @@ gen_trans_params (struct enc_sess_iquic *enc_sess, unsigned char *buf,
 | 
			
		|||
    const struct lsquic_engine_settings *const settings =
 | 
			
		||||
                                    &enc_sess->esi_enpub->enp_settings;
 | 
			
		||||
    struct transport_params params;
 | 
			
		||||
    const enum lsquic_version version = enc_sess->esi_conn->cn_version;
 | 
			
		||||
    int len;
 | 
			
		||||
 | 
			
		||||
    memset(¶ms, 0, sizeof(params));
 | 
			
		||||
    if (version > LSQVER_ID27)
 | 
			
		||||
    {
 | 
			
		||||
        params.tp_initial_source_cid = *CN_SCID(enc_sess->esi_conn);
 | 
			
		||||
        params.tp_set |= 1 << TPI_INITIAL_SOURCE_CID;
 | 
			
		||||
    }
 | 
			
		||||
    if (enc_sess->esi_flags & ESI_SERVER)
 | 
			
		||||
    {
 | 
			
		||||
        const struct lsquic_conn *const lconn = enc_sess->esi_conn;
 | 
			
		||||
| 
						 | 
				
			
			@ -442,8 +453,8 @@ gen_trans_params (struct enc_sess_iquic *enc_sess, unsigned char *buf,
 | 
			
		|||
 | 
			
		||||
        if (enc_sess->esi_flags & ESI_ODCID)
 | 
			
		||||
        {
 | 
			
		||||
            params.tp_original_cid = enc_sess->esi_odcid;
 | 
			
		||||
            params.tp_set |= 1 << TPI_ORIGINAL_CONNECTION_ID;
 | 
			
		||||
            params.tp_original_dest_cid = enc_sess->esi_odcid;
 | 
			
		||||
            params.tp_set |= 1 << TPI_ORIGINAL_DEST_CID;
 | 
			
		||||
        }
 | 
			
		||||
#if LSQUIC_PREFERRED_ADDR
 | 
			
		||||
        char addr_buf[INET6_ADDRSTRLEN + 6 /* port */ + 1];
 | 
			
		||||
| 
						 | 
				
			
			@ -544,10 +555,10 @@ gen_trans_params (struct enc_sess_iquic *enc_sess, unsigned char *buf,
 | 
			
		|||
                  |  (1 << TPI_MAX_ACK_DELAY)
 | 
			
		||||
                  |  (1 << TPI_ACTIVE_CONNECTION_ID_LIMIT)
 | 
			
		||||
                  ;
 | 
			
		||||
    if (settings->es_max_packet_size_rx)
 | 
			
		||||
    if (settings->es_max_udp_payload_size_rx)
 | 
			
		||||
    {
 | 
			
		||||
        params.tp_max_packet_size = settings->es_max_packet_size_rx;
 | 
			
		||||
        params.tp_set |= 1 << TPI_MAX_PACKET_SIZE;
 | 
			
		||||
        params.tp_max_udp_payload_size = settings->es_max_udp_payload_size_rx;
 | 
			
		||||
        params.tp_set |= 1 << TPI_MAX_UDP_PAYLOAD_SIZE;
 | 
			
		||||
    }
 | 
			
		||||
    if (!settings->es_allow_migration)
 | 
			
		||||
        params.tp_set |= 1 << TPI_DISABLE_ACTIVE_MIGRATION;
 | 
			
		||||
| 
						 | 
				
			
			@ -564,10 +575,15 @@ gen_trans_params (struct enc_sess_iquic *enc_sess, unsigned char *buf,
 | 
			
		|||
    if (settings->es_timestamps)
 | 
			
		||||
        params.tp_set |= 1 << TPI_TIMESTAMPS;
 | 
			
		||||
 | 
			
		||||
    len = (enc_sess->esi_conn->cn_version == LSQVER_ID25 ? lsquic_tp_encode_id25 :
 | 
			
		||||
        lsquic_tp_encode)(¶ms, enc_sess->esi_flags & ESI_SERVER, buf, bufsz);
 | 
			
		||||
    len = (version == LSQVER_ID27 ? lsquic_tp_encode_27 : lsquic_tp_encode)(
 | 
			
		||||
                        ¶ms, enc_sess->esi_flags & ESI_SERVER, buf, bufsz);
 | 
			
		||||
    if (len >= 0)
 | 
			
		||||
    {
 | 
			
		||||
        char str[MAX_TP_STR_SZ];
 | 
			
		||||
        LSQ_DEBUG("generated transport parameters buffer of %d bytes", len);
 | 
			
		||||
        LSQ_DEBUG("%s", ((version == LSQVER_ID27 ? lsquic_tp_to_str_27
 | 
			
		||||
                        : lsquic_tp_to_str)(¶ms, str, sizeof(str)), str));
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
        LSQ_WARN("cannot generate transport parameters: %d", errno);
 | 
			
		||||
    return len;
 | 
			
		||||
| 
						 | 
				
			
			@ -726,6 +742,9 @@ iquic_esfi_create_client (const char *hostname,
 | 
			
		|||
    enc_sess->esi_dir[0] = evp_aead_seal;
 | 
			
		||||
    enc_sess->esi_dir[1] = evp_aead_open;
 | 
			
		||||
 | 
			
		||||
    enc_sess->esi_odcid = *dcid;
 | 
			
		||||
    enc_sess->esi_flags |= ESI_ODCID;
 | 
			
		||||
 | 
			
		||||
    LSQ_DEBUGC("created client, DCID: %"CID_FMT, CID_BITS(dcid));
 | 
			
		||||
    {
 | 
			
		||||
        const char *log;
 | 
			
		||||
| 
						 | 
				
			
			@ -793,7 +812,8 @@ iquic_esfi_create_server (struct lsquic_engine_public *enpub,
 | 
			
		|||
                    struct lsquic_conn *lconn, const lsquic_cid_t *first_dcid,
 | 
			
		||||
                    void *(crypto_streams)[4],
 | 
			
		||||
                    const struct crypto_stream_if *cryst_if,
 | 
			
		||||
                    const struct lsquic_cid *odcid)
 | 
			
		||||
                    const struct lsquic_cid *odcid,
 | 
			
		||||
                    const struct lsquic_cid *iscid )
 | 
			
		||||
{
 | 
			
		||||
    struct enc_sess_iquic *enc_sess;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -819,6 +839,8 @@ iquic_esfi_create_server (struct lsquic_engine_public *enpub,
 | 
			
		|||
        enc_sess->esi_odcid = *odcid;
 | 
			
		||||
        enc_sess->esi_flags |= ESI_ODCID;
 | 
			
		||||
    }
 | 
			
		||||
    enc_sess->esi_iscid = *iscid;
 | 
			
		||||
    enc_sess->esi_flags |= ESI_ISCID;
 | 
			
		||||
 | 
			
		||||
    init_frals(enc_sess);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1470,6 +1492,7 @@ get_peer_transport_params (struct enc_sess_iquic *enc_sess)
 | 
			
		|||
    const uint8_t *params_buf;
 | 
			
		||||
    size_t bufsz;
 | 
			
		||||
    char *params_str;
 | 
			
		||||
    const enum lsquic_version version = enc_sess->esi_conn->cn_version;
 | 
			
		||||
 | 
			
		||||
    SSL_get_peer_quic_transport_params(enc_sess->esi_ssl, ¶ms_buf, &bufsz);
 | 
			
		||||
    if (!params_buf)
 | 
			
		||||
| 
						 | 
				
			
			@ -1479,8 +1502,8 @@ get_peer_transport_params (struct enc_sess_iquic *enc_sess)
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    LSQ_DEBUG("have peer transport parameters (%zu bytes)", bufsz);
 | 
			
		||||
    if (0 > (enc_sess->esi_conn->cn_version == LSQVER_ID25
 | 
			
		||||
                ? lsquic_tp_decode_id25 : lsquic_tp_decode)(params_buf, bufsz,
 | 
			
		||||
    if (0 > (version == LSQVER_ID27 ? lsquic_tp_decode_27
 | 
			
		||||
                : lsquic_tp_decode)(params_buf, bufsz,
 | 
			
		||||
                            !(enc_sess->esi_flags & ESI_SERVER),
 | 
			
		||||
                                                trans_params))
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -1501,30 +1524,70 @@ get_peer_transport_params (struct enc_sess_iquic *enc_sess)
 | 
			
		|||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((enc_sess->esi_flags & (ESI_ODCID|ESI_SERVER)) == ESI_ODCID)
 | 
			
		||||
    const lsquic_cid_t *const cids[LAST_TPI + 1] = {
 | 
			
		||||
        [TP_CID_IDX(TPI_ORIGINAL_DEST_CID)]  = enc_sess->esi_flags & ESI_ODCID ? &enc_sess->esi_odcid : NULL,
 | 
			
		||||
        [TP_CID_IDX(TPI_RETRY_SOURCE_CID)]   = enc_sess->esi_flags & ESI_RSCID ? &enc_sess->esi_rscid : NULL,
 | 
			
		||||
        [TP_CID_IDX(TPI_INITIAL_SOURCE_CID)] = enc_sess->esi_flags & ESI_ISCID ? &enc_sess->esi_iscid : NULL,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    unsigned must_have, must_not_have = 0;
 | 
			
		||||
    if (version > LSQVER_ID27)
 | 
			
		||||
    {
 | 
			
		||||
        if (!(trans_params->tp_set & (1 << TPI_ORIGINAL_CONNECTION_ID)))
 | 
			
		||||
        must_have = 1 << TPI_INITIAL_SOURCE_CID;
 | 
			
		||||
        if (enc_sess->esi_flags & ESI_SERVER)
 | 
			
		||||
            must_not_have |= 1 << TPI_ORIGINAL_DEST_CID;
 | 
			
		||||
        else
 | 
			
		||||
            must_have |= 1 << TPI_ORIGINAL_DEST_CID;
 | 
			
		||||
        if ((enc_sess->esi_flags & (ESI_RETRY|ESI_SERVER)) == ESI_RETRY)
 | 
			
		||||
            must_have |= 1 << TPI_RETRY_SOURCE_CID;
 | 
			
		||||
        else
 | 
			
		||||
            must_not_have |= 1 << TPI_RETRY_SOURCE_CID;
 | 
			
		||||
    }
 | 
			
		||||
    else if ((enc_sess->esi_flags & (ESI_RETRY|ESI_SERVER)) == ESI_RETRY)
 | 
			
		||||
        must_have = 1 << TPI_ORIGINAL_DEST_CID;
 | 
			
		||||
 | 
			
		||||
    enum transport_param_id tpi;
 | 
			
		||||
    for (tpi = FIRST_TP_CID; tpi <= LAST_TP_CID; ++tpi)
 | 
			
		||||
    {
 | 
			
		||||
        if (!(must_have & (1 << tpi)))
 | 
			
		||||
            continue;
 | 
			
		||||
        if (!(trans_params->tp_set & (1 << tpi)))
 | 
			
		||||
        {
 | 
			
		||||
            LSQ_DEBUG("server did not produce original DCID (ODCID)");
 | 
			
		||||
            LSQ_DEBUG("server did not produce %s", lsquic_tpi2str[tpi]);
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
        if (LSQUIC_CIDS_EQ(&enc_sess->esi_odcid,
 | 
			
		||||
                                        &trans_params->tp_original_cid))
 | 
			
		||||
            LSQ_DEBUG("ODCID values match");
 | 
			
		||||
        if (!cids[TP_CID_IDX(tpi)])
 | 
			
		||||
        {
 | 
			
		||||
            LSQ_WARN("do not have CID %s for checking",
 | 
			
		||||
                                                    lsquic_tpi2str[tpi]);
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
        if (LSQUIC_CIDS_EQ(cids[TP_CID_IDX(tpi)],
 | 
			
		||||
                                &trans_params->tp_cids[TP_CID_IDX(tpi)]))
 | 
			
		||||
            LSQ_DEBUG("%s values match", lsquic_tpi2str[tpi]);
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            if (LSQ_LOG_ENABLED(LSQ_LOG_DEBUG))
 | 
			
		||||
            {
 | 
			
		||||
                char cidbuf[2][MAX_CID_LEN * 2 + 1];
 | 
			
		||||
                lsquic_cid2str(&enc_sess->esi_odcid, cidbuf[0]);
 | 
			
		||||
                lsquic_cid2str(&trans_params->tp_original_cid, cidbuf[1]);
 | 
			
		||||
                LSQ_DEBUG("server provided ODCID %s that does not match "
 | 
			
		||||
                    "our ODCID %s", cidbuf[1], cidbuf[0]);
 | 
			
		||||
                LSQ_DEBUG("server provided %s %"CID_FMT" that does not "
 | 
			
		||||
                    "match ours %"CID_FMT, lsquic_tpi2str[tpi],
 | 
			
		||||
                    CID_BITS_B(&trans_params->tp_cids[TP_CID_IDX(tpi)],
 | 
			
		||||
                                                            cidbuf[0]),
 | 
			
		||||
                    CID_BITS_B(cids[TP_CID_IDX(tpi)], cidbuf[1]));
 | 
			
		||||
            }
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (tpi = FIRST_TP_CID; tpi <= LAST_TP_CID; ++tpi)
 | 
			
		||||
        if (must_not_have & (1 << tpi) & trans_params->tp_set)
 | 
			
		||||
        {
 | 
			
		||||
            LSQ_DEBUG("server transport parameters unexpectedly contain %s",
 | 
			
		||||
                                        lsquic_tpi2str[tpi]);
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    if ((trans_params->tp_set & (1 << TPI_LOSS_BITS))
 | 
			
		||||
                            && enc_sess->esi_enpub->enp_settings.es_ql_bits)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -2239,6 +2302,21 @@ iquic_esf_zero_rtt_enabled (enc_session_t *enc_session_p)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
iquic_esfi_set_iscid (enc_session_t *enc_session_p,
 | 
			
		||||
                                    const struct lsquic_packet_in *packet_in)
 | 
			
		||||
{
 | 
			
		||||
    struct enc_sess_iquic *const enc_sess = enc_session_p;
 | 
			
		||||
 | 
			
		||||
    if (!(enc_sess->esi_flags & ESI_ISCID))
 | 
			
		||||
    {
 | 
			
		||||
        lsquic_scid_from_packet_in(packet_in, &enc_sess->esi_iscid);
 | 
			
		||||
        enc_sess->esi_flags |= ESI_ISCID;
 | 
			
		||||
        LSQ_DEBUGC("set ISCID to %"CID_FMT, CID_BITS(&enc_sess->esi_iscid));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
iquic_esfi_reset_dcid (enc_session_t *enc_session_p,
 | 
			
		||||
        const lsquic_cid_t *old_dcid, const lsquic_cid_t *new_dcid)
 | 
			
		||||
| 
						 | 
				
			
			@ -2247,7 +2325,8 @@ iquic_esfi_reset_dcid (enc_session_t *enc_session_p,
 | 
			
		|||
    struct crypto_ctx_pair *pair;
 | 
			
		||||
 | 
			
		||||
    enc_sess->esi_odcid = *old_dcid;
 | 
			
		||||
    enc_sess->esi_flags |= ESI_ODCID;
 | 
			
		||||
    enc_sess->esi_rscid = *new_dcid;
 | 
			
		||||
    enc_sess->esi_flags |= ESI_ODCID|ESI_RSCID|ESI_RETRY;
 | 
			
		||||
 | 
			
		||||
    /* Free previous handshake keys */
 | 
			
		||||
    assert(enc_sess->esi_hsk_pairs);
 | 
			
		||||
| 
						 | 
				
			
			@ -2340,6 +2419,7 @@ const struct enc_session_funcs_iquic lsquic_enc_session_iquic_ietf_v1 =
 | 
			
		|||
                         = iquic_esfi_get_peer_transport_params,
 | 
			
		||||
    .esfi_reset_dcid     = iquic_esfi_reset_dcid,
 | 
			
		||||
    .esfi_init_server    = iquic_esfi_init_server,
 | 
			
		||||
    .esfi_set_iscid      = iquic_esfi_set_iscid,
 | 
			
		||||
    .esfi_set_streams    = iquic_esfi_set_streams,
 | 
			
		||||
    .esfi_create_server  = iquic_esfi_create_server,
 | 
			
		||||
    .esfi_shake_stream   = iquic_esfi_shake_stream,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -223,6 +223,7 @@ struct lsquic_engine
 | 
			
		|||
    struct min_heap                    conns_out;
 | 
			
		||||
    struct eng_hist                    history;
 | 
			
		||||
    unsigned                           batch_size;
 | 
			
		||||
    struct lsquic_conn                *curr_conn;
 | 
			
		||||
    struct pr_queue                   *pr_queue;
 | 
			
		||||
    struct attq                       *attq;
 | 
			
		||||
    /* Track time last time a packet was sent to give new connections
 | 
			
		||||
| 
						 | 
				
			
			@ -1320,8 +1321,12 @@ process_packet_in (lsquic_engine_t *engine, lsquic_packet_in_t *packet_in,
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    if (engine->flags & ENG_SERVER)
 | 
			
		||||
    {
 | 
			
		||||
        conn = find_or_create_conn(engine, packet_in, ppstate, sa_local,
 | 
			
		||||
                                            sa_peer, peer_ctx, packet_in_size);
 | 
			
		||||
        if (!engine->curr_conn)
 | 
			
		||||
            engine->curr_conn = conn;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
        conn = find_conn(engine, packet_in, ppstate, sa_local);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2641,6 +2646,20 @@ process_connections (lsquic_engine_t *engine, conn_iter_f next_conn,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
maybe_count_garbage (struct lsquic_engine *engine, size_t garbage_sz)
 | 
			
		||||
{
 | 
			
		||||
    /* This is not very pretty (action at a distance via engine->curr_conn),
 | 
			
		||||
     * but it's the cheapest I can come up with to handle the "count garbage
 | 
			
		||||
     * toward amplification limit" requirement in
 | 
			
		||||
     * [draft-ietf-quic-transport-28] Section 8.1.
 | 
			
		||||
     */
 | 
			
		||||
    if (engine->curr_conn && engine->curr_conn->cn_if->ci_count_garbage)
 | 
			
		||||
        engine->curr_conn->cn_if->ci_count_garbage(engine->curr_conn,
 | 
			
		||||
                                                                garbage_sz);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Return 0 if packet is being processed by a real connection, 1 if the
 | 
			
		||||
 * packet was processed, but not by a connection, and -1 on error.
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -2692,6 +2711,7 @@ lsquic_engine_packet_in (lsquic_engine_t *engine,
 | 
			
		|||
    else
 | 
			
		||||
        parse_packet_in_begin = lsquic_parse_packet_in_begin;
 | 
			
		||||
 | 
			
		||||
    engine->curr_conn = NULL;
 | 
			
		||||
    n_zeroes = 0;
 | 
			
		||||
    is_ietf = 0;
 | 
			
		||||
    do
 | 
			
		||||
| 
						 | 
				
			
			@ -2709,6 +2729,7 @@ lsquic_engine_packet_in (lsquic_engine_t *engine,
 | 
			
		|||
                                engine->pub.enp_settings.es_scid_len, &ppstate))
 | 
			
		||||
        {
 | 
			
		||||
            LSQ_DEBUG("Cannot parse incoming packet's header");
 | 
			
		||||
            maybe_count_garbage(engine, packet_end - packet_in_data);
 | 
			
		||||
            lsquic_mm_put_packet_in(&engine->pub.enp_mm, packet_in);
 | 
			
		||||
            s = 1;
 | 
			
		||||
            break;
 | 
			
		||||
| 
						 | 
				
			
			@ -2724,6 +2745,7 @@ lsquic_engine_packet_in (lsquic_engine_t *engine,
 | 
			
		|||
                                && LSQUIC_CIDS_EQ(&packet_in->pi_dcid, &cid)))
 | 
			
		||||
            {
 | 
			
		||||
                packet_in_data += packet_in->pi_data_sz;
 | 
			
		||||
                maybe_count_garbage(engine, packet_in->pi_data_sz);
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -144,7 +144,7 @@ enum more_flags
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define N_PATHS 2
 | 
			
		||||
#define N_PATHS 4
 | 
			
		||||
 | 
			
		||||
enum send
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -154,9 +154,13 @@ enum send
 | 
			
		|||
    SEND_PATH_CHAL,
 | 
			
		||||
    SEND_PATH_CHAL_PATH_0 = SEND_PATH_CHAL + 0,
 | 
			
		||||
    SEND_PATH_CHAL_PATH_1 = SEND_PATH_CHAL + 1,
 | 
			
		||||
    SEND_PATH_CHAL_PATH_2 = SEND_PATH_CHAL + 2,
 | 
			
		||||
    SEND_PATH_CHAL_PATH_3 = SEND_PATH_CHAL + 3,
 | 
			
		||||
    SEND_PATH_RESP,
 | 
			
		||||
    SEND_PATH_RESP_PATH_0 = SEND_PATH_RESP + 0,
 | 
			
		||||
    SEND_PATH_RESP_PATH_1 = SEND_PATH_RESP + 1,
 | 
			
		||||
    SEND_PATH_RESP_PATH_2 = SEND_PATH_RESP + 2,
 | 
			
		||||
    SEND_PATH_RESP_PATH_3 = SEND_PATH_RESP + 3,
 | 
			
		||||
    SEND_MAX_DATA,
 | 
			
		||||
    SEND_PING,
 | 
			
		||||
    SEND_NEW_CID,
 | 
			
		||||
| 
						 | 
				
			
			@ -181,9 +185,13 @@ enum send_flags
 | 
			
		|||
    SF_SEND_PATH_CHAL               = 1 << SEND_PATH_CHAL,
 | 
			
		||||
    SF_SEND_PATH_CHAL_PATH_0        = 1 << SEND_PATH_CHAL_PATH_0,
 | 
			
		||||
    SF_SEND_PATH_CHAL_PATH_1        = 1 << SEND_PATH_CHAL_PATH_1,
 | 
			
		||||
    SF_SEND_PATH_CHAL_PATH_2        = 1 << SEND_PATH_CHAL_PATH_2,
 | 
			
		||||
    SF_SEND_PATH_CHAL_PATH_3        = 1 << SEND_PATH_CHAL_PATH_3,
 | 
			
		||||
    SF_SEND_PATH_RESP               = 1 << SEND_PATH_RESP,
 | 
			
		||||
    SF_SEND_PATH_RESP_PATH_0        = 1 << SEND_PATH_RESP_PATH_0,
 | 
			
		||||
    SF_SEND_PATH_RESP_PATH_1        = 1 << SEND_PATH_RESP_PATH_1,
 | 
			
		||||
    SF_SEND_PATH_RESP_PATH_2        = 1 << SEND_PATH_RESP_PATH_2,
 | 
			
		||||
    SF_SEND_PATH_RESP_PATH_3        = 1 << SEND_PATH_RESP_PATH_3,
 | 
			
		||||
    SF_SEND_NEW_CID                 = 1 << SEND_NEW_CID,
 | 
			
		||||
    SF_SEND_RETIRE_CID              = 1 << SEND_RETIRE_CID,
 | 
			
		||||
    SF_SEND_CONN_CLOSE              = 1 << SEND_CONN_CLOSE,
 | 
			
		||||
| 
						 | 
				
			
			@ -464,6 +472,10 @@ ietf_full_conn_ci_get_log_cid (const struct lsquic_conn *);
 | 
			
		|||
static void
 | 
			
		||||
ietf_full_conn_ci_destroy (struct lsquic_conn *);
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
insert_new_dcid (struct ietf_full_conn *, uint64_t seqno,
 | 
			
		||||
    const lsquic_cid_t *, const unsigned char *token, int update_cur_dcid);
 | 
			
		||||
 | 
			
		||||
static unsigned
 | 
			
		||||
highest_bit_set (unsigned sz)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -652,11 +664,11 @@ migra_begin (struct ietf_full_conn *conn, struct conn_path *copath,
 | 
			
		|||
        copath->cop_path.np_pack_size = IQUIC_MAX_IPv6_PACKET_SZ;
 | 
			
		||||
    else
 | 
			
		||||
        copath->cop_path.np_pack_size = IQUIC_MAX_IPv4_PACKET_SZ;
 | 
			
		||||
    if ((params->tp_set & (1 << TPI_MAX_PACKET_SIZE))
 | 
			
		||||
            && params->tp_numerics[TPI_MAX_PACKET_SIZE]
 | 
			
		||||
    if ((params->tp_set & (1 << TPI_MAX_UDP_PAYLOAD_SIZE))
 | 
			
		||||
            && params->tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE]
 | 
			
		||||
                                            < copath->cop_path.np_pack_size)
 | 
			
		||||
        copath->cop_path.np_pack_size
 | 
			
		||||
                                = params->tp_numerics[TPI_MAX_PACKET_SIZE];
 | 
			
		||||
                                = params->tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE];
 | 
			
		||||
    memcpy(&copath->cop_path.np_local_addr, NP_LOCAL_SA(CUR_NPATH(conn)),
 | 
			
		||||
                                    sizeof(copath->cop_path.np_local_addr));
 | 
			
		||||
    memcpy(&copath->cop_path.np_peer_addr, dest_sa,
 | 
			
		||||
| 
						 | 
				
			
			@ -1113,6 +1125,8 @@ ietf_full_conn_init (struct ietf_full_conn *conn,
 | 
			
		|||
    conn->ifc_max_ack_packno[PNS_APP] = IQUIC_INVALID_PACKNO;
 | 
			
		||||
    conn->ifc_paths[0].cop_path.np_path_id = 0;
 | 
			
		||||
    conn->ifc_paths[1].cop_path.np_path_id = 1;
 | 
			
		||||
    conn->ifc_paths[2].cop_path.np_path_id = 2;
 | 
			
		||||
    conn->ifc_paths[3].cop_path.np_path_id = 3;
 | 
			
		||||
#define valid_stream_id(v) ((v) <= VINT_MAX_VALUE)
 | 
			
		||||
    conn->ifc_max_req_id = VINT_MAX_VALUE + 1;
 | 
			
		||||
    conn->ifc_ping_unretx_thresh = 20;
 | 
			
		||||
| 
						 | 
				
			
			@ -2740,7 +2754,7 @@ ietf_full_conn_ci_going_away (struct lsquic_conn *lconn)
 | 
			
		|||
{
 | 
			
		||||
    struct ietf_full_conn *conn = (struct ietf_full_conn *) lconn;
 | 
			
		||||
 | 
			
		||||
    if ((conn->ifc_flags & (IFC_SERVER|IFC_HTTP)) == (IFC_SERVER|IFC_HTTP))
 | 
			
		||||
    if (conn->ifc_flags & IFC_HTTP)
 | 
			
		||||
    {
 | 
			
		||||
        if (!(conn->ifc_flags & (IFC_CLOSING|IFC_GOING_AWAY)))
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -2760,7 +2774,7 @@ ietf_full_conn_ci_going_away (struct lsquic_conn *lconn)
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
        LSQ_NOTICE("going away has no effect in IETF QUIC");
 | 
			
		||||
        LSQ_NOTICE("going away has no effect in non-HTTP mode");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2834,8 +2848,8 @@ retire_cid_from_tp (struct ietf_full_conn *conn,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
begin_migra_or_retire_cid (struct ietf_full_conn *conn,
 | 
			
		||||
static enum { BM_MIGRATING, BM_NOT_MIGRATING, BM_ERROR, }
 | 
			
		||||
try_to_begin_migration (struct ietf_full_conn *conn,
 | 
			
		||||
                                        const struct transport_params *params)
 | 
			
		||||
{
 | 
			
		||||
    struct conn_path *copath;
 | 
			
		||||
| 
						 | 
				
			
			@ -2853,8 +2867,7 @@ begin_migra_or_retire_cid (struct ietf_full_conn *conn,
 | 
			
		|||
            LSQ_DEBUG("TP disables migration: retire PreferredAddress CID");
 | 
			
		||||
        else
 | 
			
		||||
            LSQ_DEBUG("Migration not allowed: retire PreferredAddress CID");
 | 
			
		||||
        retire_cid_from_tp(conn, params);
 | 
			
		||||
        return 0;
 | 
			
		||||
        return BM_NOT_MIGRATING;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    is_ipv6 = NP_IS_IPv6(CUR_NPATH(conn));
 | 
			
		||||
| 
						 | 
				
			
			@ -2867,8 +2880,7 @@ begin_migra_or_retire_cid (struct ietf_full_conn *conn,
 | 
			
		|||
         */
 | 
			
		||||
        LSQ_DEBUG("Cannot migrate from IPv%u to IPv%u", is_ipv6 ? 6 : 4,
 | 
			
		||||
            is_ipv6 ? 4 : 6);
 | 
			
		||||
        retire_cid_from_tp(conn, params);
 | 
			
		||||
        return 0;
 | 
			
		||||
        return BM_NOT_MIGRATING;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (0 == params->tp_preferred_address.cid.len)
 | 
			
		||||
| 
						 | 
				
			
			@ -2877,15 +2889,14 @@ begin_migra_or_retire_cid (struct ietf_full_conn *conn,
 | 
			
		|||
         * DCID becomes available.
 | 
			
		||||
         */
 | 
			
		||||
        LSQ_DEBUG("Cannot migrate using zero-length DCID");
 | 
			
		||||
        retire_cid_from_tp(conn, params);
 | 
			
		||||
        return 0;
 | 
			
		||||
        return BM_NOT_MIGRATING;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    dce = get_new_dce(conn);
 | 
			
		||||
    if (!dce)
 | 
			
		||||
    {
 | 
			
		||||
        ABORT_WARN("cannot allocate DCE");
 | 
			
		||||
        return -1;
 | 
			
		||||
        return BM_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memset(dce, 0, sizeof(*dce));
 | 
			
		||||
| 
						 | 
				
			
			@ -2902,7 +2913,7 @@ begin_migra_or_retire_cid (struct ietf_full_conn *conn,
 | 
			
		|||
        {
 | 
			
		||||
            lsquic_malo_put(dce);
 | 
			
		||||
            ABORT_WARN("cannot insert DCE");
 | 
			
		||||
            return -1;
 | 
			
		||||
            return BM_ERROR;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2925,7 +2936,7 @@ begin_migra_or_retire_cid (struct ietf_full_conn *conn,
 | 
			
		|||
    assert(!(conn->ifc_used_paths & (1 << (copath - conn->ifc_paths))));
 | 
			
		||||
 | 
			
		||||
    migra_begin(conn, copath, dce, (struct sockaddr *) &sockaddr, params);
 | 
			
		||||
    return 0;
 | 
			
		||||
    return BM_MIGRATING;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2938,10 +2949,33 @@ maybe_start_migration (struct ietf_full_conn *conn)
 | 
			
		|||
    params = lconn->cn_esf.i->esfi_get_peer_transport_params(
 | 
			
		||||
                                                        lconn->cn_enc_session);
 | 
			
		||||
    if (params->tp_set & (1 << TPI_PREFERRED_ADDRESS))
 | 
			
		||||
    {
 | 
			
		||||
        if (0 != begin_migra_or_retire_cid(conn, params))
 | 
			
		||||
        switch (try_to_begin_migration(conn, params))
 | 
			
		||||
        {
 | 
			
		||||
        case BM_MIGRATING:
 | 
			
		||||
            break;
 | 
			
		||||
        case BM_NOT_MIGRATING:
 | 
			
		||||
            if (lconn->cn_version == LSQVER_ID27)
 | 
			
		||||
                retire_cid_from_tp(conn, params);
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
/*
 | 
			
		||||
 * [draft-ietf-quic-transport-28] Section 5.1.1:
 | 
			
		||||
 "                         Connection IDs that are issued and not
 | 
			
		||||
 " retired are considered active; any active connection ID is valid for
 | 
			
		||||
 " use with the current connection at any time, in any packet type.
 | 
			
		||||
 " This includes the connection ID issued by the server via the
 | 
			
		||||
 " preferred_address transport parameter.
 | 
			
		||||
 */
 | 
			
		||||
                LSQ_DEBUG("not migrating: save DCID from transport params");
 | 
			
		||||
                (void) insert_new_dcid(conn, 1,
 | 
			
		||||
                            ¶ms->tp_preferred_address.cid,
 | 
			
		||||
                            params->tp_preferred_address.srst, 0);
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case BM_ERROR:
 | 
			
		||||
            ABORT_QUIETLY(0, TEC_INTERNAL_ERROR, "error initiating migration");
 | 
			
		||||
    }
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2955,7 +2989,7 @@ handshake_ok (struct lsquic_conn *lconn)
 | 
			
		|||
    const struct transport_params *params;
 | 
			
		||||
    enum stream_id_type sit;
 | 
			
		||||
    uint64_t limit;
 | 
			
		||||
    char buf[0x200];
 | 
			
		||||
    char buf[MAX_TP_STR_SZ];
 | 
			
		||||
 | 
			
		||||
    fiu_return_on("full_conn_ietf/handshake_ok", -1);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2973,7 +3007,8 @@ handshake_ok (struct lsquic_conn *lconn)
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    LSQ_DEBUG("peer transport parameters: %s",
 | 
			
		||||
                        (lsquic_tp_to_str(params, buf, sizeof(buf)), buf));
 | 
			
		||||
                    ((lconn->cn_version == LSQVER_ID27 ? lsquic_tp_to_str_27
 | 
			
		||||
                    : lsquic_tp_to_str)(params, buf, sizeof(buf)), buf));
 | 
			
		||||
 | 
			
		||||
    if ((params->tp_set & (1 << TPI_LOSS_BITS))
 | 
			
		||||
                                    && conn->ifc_settings->es_ql_bits == 2)
 | 
			
		||||
| 
						 | 
				
			
			@ -3088,12 +3123,12 @@ handshake_ok (struct lsquic_conn *lconn)
 | 
			
		|||
 | 
			
		||||
    conn->ifc_max_peer_ack_usec = params->tp_max_ack_delay * 1000;
 | 
			
		||||
 | 
			
		||||
    if ((params->tp_set & (1 << TPI_MAX_PACKET_SIZE))
 | 
			
		||||
            && params->tp_numerics[TPI_MAX_PACKET_SIZE]
 | 
			
		||||
    if ((params->tp_set & (1 << TPI_MAX_UDP_PAYLOAD_SIZE))
 | 
			
		||||
            && params->tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE]
 | 
			
		||||
                                            < CUR_NPATH(conn)->np_pack_size)
 | 
			
		||||
    {
 | 
			
		||||
        CUR_NPATH(conn)->np_pack_size
 | 
			
		||||
                                = params->tp_numerics[TPI_MAX_PACKET_SIZE];
 | 
			
		||||
                                = params->tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE];
 | 
			
		||||
        LSQ_DEBUG("decrease packet size to %hu bytes",
 | 
			
		||||
                                                CUR_NPATH(conn)->np_pack_size);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -3937,6 +3972,20 @@ generate_path_chal_1 (struct ietf_full_conn *conn, lsquic_time_t now)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
generate_path_chal_2 (struct ietf_full_conn *conn, lsquic_time_t now)
 | 
			
		||||
{
 | 
			
		||||
    generate_path_chal_frame(conn, now, 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
generate_path_chal_3 (struct ietf_full_conn *conn, lsquic_time_t now)
 | 
			
		||||
{
 | 
			
		||||
    generate_path_chal_frame(conn, now, 3);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
generate_path_resp_frame (struct ietf_full_conn *conn, lsquic_time_t now,
 | 
			
		||||
                                                            unsigned path_id)
 | 
			
		||||
| 
						 | 
				
			
			@ -3986,6 +4035,20 @@ generate_path_resp_1 (struct ietf_full_conn *conn, lsquic_time_t now)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
generate_path_resp_2 (struct ietf_full_conn *conn, lsquic_time_t now)
 | 
			
		||||
{
 | 
			
		||||
    generate_path_resp_frame(conn, now, 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
generate_path_resp_3 (struct ietf_full_conn *conn, lsquic_time_t now)
 | 
			
		||||
{
 | 
			
		||||
    generate_path_resp_frame(conn, now, 3);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static struct lsquic_packet_out *
 | 
			
		||||
ietf_full_conn_ci_next_packet_to_send (struct lsquic_conn *lconn, size_t size)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -5140,17 +5203,91 @@ retire_dcids_prior_to (struct ietf_full_conn *conn, unsigned retire_prior_to)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
insert_new_dcid (struct ietf_full_conn *conn, uint64_t seqno,
 | 
			
		||||
    const lsquic_cid_t *cid, const unsigned char *token, int update_cur_dcid)
 | 
			
		||||
{
 | 
			
		||||
    struct dcid_elem **dce, **el;
 | 
			
		||||
    char tokstr[IQUIC_SRESET_TOKEN_SZ * 2 + 1];
 | 
			
		||||
 | 
			
		||||
    dce = NULL;
 | 
			
		||||
    for (el = conn->ifc_dces; el < conn->ifc_dces + sizeof(conn->ifc_dces)
 | 
			
		||||
                                            / sizeof(conn->ifc_dces[0]); ++el)
 | 
			
		||||
        if (*el)
 | 
			
		||||
        {
 | 
			
		||||
            if ((*el)->de_seqno == seqno)
 | 
			
		||||
            {
 | 
			
		||||
                if (!LSQUIC_CIDS_EQ(&(*el)->de_cid, cid))
 | 
			
		||||
                {
 | 
			
		||||
                    ABORT_QUIETLY(0, TEC_PROTOCOL_VIOLATION,
 | 
			
		||||
                        "NEW_CONNECTION_ID: already have CID seqno %"PRIu64
 | 
			
		||||
                        " but with a different CID", seqno);
 | 
			
		||||
                    return -1;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    LSQ_DEBUG("Ignore duplicate CID seqno %"PRIu64, seqno);
 | 
			
		||||
                    return 0;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else if (LSQUIC_CIDS_EQ(&(*el)->de_cid, cid))
 | 
			
		||||
            {
 | 
			
		||||
                ABORT_QUIETLY(0, TEC_PROTOCOL_VIOLATION,
 | 
			
		||||
                    "NEW_CONNECTION_ID: received the same CID with sequence "
 | 
			
		||||
                    "numbers %u and %"PRIu64, (*el)->de_seqno, seqno);
 | 
			
		||||
                return -1;
 | 
			
		||||
            }
 | 
			
		||||
            else if (((*el)->de_flags & DE_SRST)
 | 
			
		||||
                    && 0 == memcmp((*el)->de_srst, token,
 | 
			
		||||
                                                    IQUIC_SRESET_TOKEN_SZ))
 | 
			
		||||
            {
 | 
			
		||||
                ABORT_QUIETLY(0, TEC_PROTOCOL_VIOLATION,
 | 
			
		||||
                    "NEW_CONNECTION_ID: received second instance of reset "
 | 
			
		||||
                    "token %s in seqno %"PRIu64", same as in seqno %u",
 | 
			
		||||
                    (lsquic_hexstr(token, IQUIC_SRESET_TOKEN_SZ, tokstr,
 | 
			
		||||
                                                    sizeof(tokstr)), tokstr),
 | 
			
		||||
                    seqno, (*el)->de_seqno);
 | 
			
		||||
                return -1;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if (!dce)
 | 
			
		||||
            dce = el;
 | 
			
		||||
 | 
			
		||||
    if (!dce)
 | 
			
		||||
    {
 | 
			
		||||
        ABORT_QUIETLY(0, TEC_CONNECTION_ID_LIMIT_ERROR,
 | 
			
		||||
            "NEW_CONNECTION_ID: received connection ID that is going over the "
 | 
			
		||||
            "limit of %u CIDs", MAX_IETF_CONN_DCIDS);
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    *dce = lsquic_malo_get(conn->ifc_pub.mm->malo.dcid_elem);
 | 
			
		||||
    if (*dce)
 | 
			
		||||
    {
 | 
			
		||||
        memset(*dce, 0, sizeof(**dce));
 | 
			
		||||
        (*dce)->de_seqno = seqno;
 | 
			
		||||
        (*dce)->de_cid = *cid;
 | 
			
		||||
        memcpy((*dce)->de_srst, token, sizeof((*dce)->de_srst));
 | 
			
		||||
        (*dce)->de_flags |= DE_SRST;
 | 
			
		||||
        if (update_cur_dcid)
 | 
			
		||||
            *CUR_DCID(conn) = *cid;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
        LSQ_WARN("cannot allocate dce to insert DCID seqno %"PRIu64, seqno);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static unsigned
 | 
			
		||||
process_new_connection_id_frame (struct ietf_full_conn *conn,
 | 
			
		||||
        struct lsquic_packet_in *packet_in, const unsigned char *p, size_t len)
 | 
			
		||||
{
 | 
			
		||||
    struct dcid_elem **dce, **el;
 | 
			
		||||
    const unsigned char *token;
 | 
			
		||||
    const char *action_str;
 | 
			
		||||
    lsquic_cid_t cid;
 | 
			
		||||
    uint64_t seqno, retire_prior_to;
 | 
			
		||||
    int parsed_len, update_cur_dcid;
 | 
			
		||||
    char tokstr[IQUIC_SRESET_TOKEN_SZ * 2 + 1];
 | 
			
		||||
 | 
			
		||||
    parsed_len = conn->ifc_conn.cn_pf->pf_parse_new_conn_id(p, len,
 | 
			
		||||
                                        &seqno, &retire_prior_to, &cid, &token);
 | 
			
		||||
| 
						 | 
				
			
			@ -5194,71 +5331,9 @@ process_new_connection_id_frame (struct ietf_full_conn *conn,
 | 
			
		|||
    else
 | 
			
		||||
        update_cur_dcid = 0;
 | 
			
		||||
 | 
			
		||||
    dce = NULL;
 | 
			
		||||
    for (el = conn->ifc_dces; el < conn->ifc_dces + sizeof(conn->ifc_dces)
 | 
			
		||||
                                            / sizeof(conn->ifc_dces[0]); ++el)
 | 
			
		||||
        if (*el)
 | 
			
		||||
        {
 | 
			
		||||
            if ((*el)->de_seqno == seqno)
 | 
			
		||||
            {
 | 
			
		||||
                if (!LSQUIC_CIDS_EQ(&(*el)->de_cid, &cid))
 | 
			
		||||
                {
 | 
			
		||||
                    ABORT_QUIETLY(0, TEC_PROTOCOL_VIOLATION,
 | 
			
		||||
                        "NEW_CONNECTION_ID: already have CID seqno %"PRIu64
 | 
			
		||||
                        " but with a different CID", seqno);
 | 
			
		||||
                    return 0;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    LSQ_DEBUG("Ignore duplicate CID seqno %"PRIu64, seqno);
 | 
			
		||||
                    return parsed_len;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else if (LSQUIC_CIDS_EQ(&(*el)->de_cid, &cid))
 | 
			
		||||
            {
 | 
			
		||||
                ABORT_QUIETLY(0, TEC_PROTOCOL_VIOLATION,
 | 
			
		||||
                    "NEW_CONNECTION_ID: received the same CID with sequence "
 | 
			
		||||
                    "numbers %u and %"PRIu64, (*el)->de_seqno, seqno);
 | 
			
		||||
                return 0;
 | 
			
		||||
            }
 | 
			
		||||
            else if (((*el)->de_flags & DE_SRST)
 | 
			
		||||
                    && 0 == memcmp((*el)->de_srst, token,
 | 
			
		||||
                                                    IQUIC_SRESET_TOKEN_SZ))
 | 
			
		||||
            {
 | 
			
		||||
                ABORT_QUIETLY(0, TEC_PROTOCOL_VIOLATION,
 | 
			
		||||
                    "NEW_CONNECTION_ID: received second instance of reset "
 | 
			
		||||
                    "token %s in seqno %"PRIu64", same as in seqno %u",
 | 
			
		||||
                    (lsquic_hexstr(token, IQUIC_SRESET_TOKEN_SZ, tokstr,
 | 
			
		||||
                                                    sizeof(tokstr)), tokstr),
 | 
			
		||||
                    seqno, (*el)->de_seqno);
 | 
			
		||||
                return 0;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if (!dce)
 | 
			
		||||
            dce = el;
 | 
			
		||||
 | 
			
		||||
    if (!dce)
 | 
			
		||||
    {
 | 
			
		||||
        ABORT_QUIETLY(0, TEC_CONNECTION_ID_LIMIT_ERROR,
 | 
			
		||||
            "NEW_CONNECTION_ID: received connection ID that is going over the "
 | 
			
		||||
            "limit of %u CIDs", MAX_IETF_CONN_DCIDS);
 | 
			
		||||
    if (0 != insert_new_dcid(conn, seqno, &cid, token, update_cur_dcid))
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    *dce = lsquic_malo_get(conn->ifc_pub.mm->malo.dcid_elem);
 | 
			
		||||
    if (*dce)
 | 
			
		||||
    {
 | 
			
		||||
        memset(*dce, 0, sizeof(**dce));
 | 
			
		||||
        (*dce)->de_seqno = seqno;
 | 
			
		||||
        (*dce)->de_cid = cid;
 | 
			
		||||
        memcpy((*dce)->de_srst, token, sizeof((*dce)->de_srst));
 | 
			
		||||
        (*dce)->de_flags |= DE_SRST;
 | 
			
		||||
        action_str = "Saved";
 | 
			
		||||
        if (update_cur_dcid)
 | 
			
		||||
            *CUR_DCID(conn) = cid;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
        action_str = "Ignored (alloc failure)";
 | 
			
		||||
    action_str = "Saved";
 | 
			
		||||
 | 
			
		||||
  end:
 | 
			
		||||
    LSQ_DEBUGC("Got new connection ID from peer: seq=%"PRIu64"; "
 | 
			
		||||
| 
						 | 
				
			
			@ -5642,7 +5717,8 @@ process_packet_frame (struct ietf_full_conn *conn,
 | 
			
		|||
 | 
			
		||||
    enc_level = lsquic_packet_in_enc_level(packet_in);
 | 
			
		||||
    type = conn->ifc_conn.cn_pf->pf_parse_frame_type(p, len);
 | 
			
		||||
    if (lsquic_legal_frames_by_level[enc_level] & (1 << type))
 | 
			
		||||
    if (lsquic_legal_frames_by_level[conn->ifc_conn.cn_version][enc_level]
 | 
			
		||||
                                                                & (1 << type))
 | 
			
		||||
    {
 | 
			
		||||
        LSQ_DEBUG("about to process %s frame", frame_type_2_str[type]);
 | 
			
		||||
        packet_in->pi_frame_types |= 1 << type;
 | 
			
		||||
| 
						 | 
				
			
			@ -5724,11 +5800,11 @@ init_new_path (struct ietf_full_conn *conn, struct conn_path *path,
 | 
			
		|||
        path->cop_path.np_pack_size = IQUIC_MAX_IPv4_PACKET_SZ;
 | 
			
		||||
    params = lconn->cn_esf.i->esfi_get_peer_transport_params(
 | 
			
		||||
                                                        lconn->cn_enc_session);
 | 
			
		||||
    if (params && (params->tp_set & (1 << TPI_MAX_PACKET_SIZE))
 | 
			
		||||
            && params->tp_numerics[TPI_MAX_PACKET_SIZE]
 | 
			
		||||
    if (params && (params->tp_set & (1 << TPI_MAX_UDP_PAYLOAD_SIZE))
 | 
			
		||||
            && params->tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE]
 | 
			
		||||
                                            < path->cop_path.np_pack_size)
 | 
			
		||||
        path->cop_path.np_pack_size
 | 
			
		||||
                                = params->tp_numerics[TPI_MAX_PACKET_SIZE];
 | 
			
		||||
                                = params->tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE];
 | 
			
		||||
 | 
			
		||||
    LSQ_DEBUG("initialized path %u", (unsigned) (path - conn->ifc_paths));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -6158,6 +6234,9 @@ process_regular_packet (struct ietf_full_conn *conn,
 | 
			
		|||
        return process_retry_packet(conn, packet_in);
 | 
			
		||||
 | 
			
		||||
    pns = lsquic_hety2pns[ packet_in->pi_header_type ];
 | 
			
		||||
    if (pns == PNS_INIT)
 | 
			
		||||
        conn->ifc_conn.cn_esf.i->esfi_set_iscid(conn->ifc_conn.cn_enc_session,
 | 
			
		||||
                                                                    packet_in);
 | 
			
		||||
    if ((pns == PNS_INIT && (conn->ifc_flags & IFC_IGNORE_INIT))
 | 
			
		||||
                    || (pns == PNS_HSK  && (conn->ifc_flags & IFC_IGNORE_HSK)))
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -6241,6 +6320,10 @@ process_regular_packet (struct ietf_full_conn *conn,
 | 
			
		|||
                                    "decrypter reports protocol violation");
 | 
			
		||||
            return -1;
 | 
			
		||||
        case DECPI_OK:
 | 
			
		||||
            /* Receiving any other type of packet precludes subsequent retries.
 | 
			
		||||
             * We only set it if decryption is successful.
 | 
			
		||||
             */
 | 
			
		||||
            conn->ifc_flags |= IFC_RETRIED;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -6344,13 +6427,6 @@ process_incoming_packet_verneg (struct ietf_full_conn *conn,
 | 
			
		|||
 | 
			
		||||
    if (lsquic_packet_in_is_verneg(packet_in))
 | 
			
		||||
    {
 | 
			
		||||
        if (!verneg_ok(conn))
 | 
			
		||||
        {
 | 
			
		||||
            ABORT_ERROR("version negotiation not permitted in this version "
 | 
			
		||||
                                                                    "of QUIC");
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        LSQ_DEBUG("Processing version-negotiation packet");
 | 
			
		||||
 | 
			
		||||
        if (conn->ifc_u.cli.ifcli_ver_neg.vn_state != VN_START)
 | 
			
		||||
| 
						 | 
				
			
			@ -6383,10 +6459,26 @@ process_incoming_packet_verneg (struct ietf_full_conn *conn,
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* [draft-ietf-quic-transport-28] Section 6.2:
 | 
			
		||||
         " A client MUST discard a Version Negotiation packet that lists the
 | 
			
		||||
         " QUIC version selected by the client.
 | 
			
		||||
         */
 | 
			
		||||
        if (versions & (1 << conn->ifc_u.cli.ifcli_ver_neg.vn_ver))
 | 
			
		||||
        {
 | 
			
		||||
            ABORT_ERROR("server replied with version we support: %s",
 | 
			
		||||
            LSQ_DEBUG("server replied with version we sent, %s, ignore",
 | 
			
		||||
                        lsquic_ver2str[conn->ifc_u.cli.ifcli_ver_neg.vn_ver]);
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* [draft-ietf-quic-transport-28] Section 6.2:
 | 
			
		||||
         " A client that supports only this version of QUIC MUST abandon the
 | 
			
		||||
         " current connection attempt if it receives a Version Negotiation
 | 
			
		||||
         " packet [...]
 | 
			
		||||
         */
 | 
			
		||||
        if (!verneg_ok(conn))
 | 
			
		||||
        {
 | 
			
		||||
            ABORT_ERROR("version negotiation not permitted in this version "
 | 
			
		||||
                                                                    "of QUIC");
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -6530,8 +6622,12 @@ static void (*const send_funcs[N_SEND])(
 | 
			
		|||
    [SEND_STOP_SENDING] = generate_stop_sending_frames,
 | 
			
		||||
    [SEND_PATH_CHAL_PATH_0]    = generate_path_chal_0,
 | 
			
		||||
    [SEND_PATH_CHAL_PATH_1]    = generate_path_chal_1,
 | 
			
		||||
    [SEND_PATH_CHAL_PATH_2]    = generate_path_chal_2,
 | 
			
		||||
    [SEND_PATH_CHAL_PATH_3]    = generate_path_chal_3,
 | 
			
		||||
    [SEND_PATH_RESP_PATH_0]    = generate_path_resp_0,
 | 
			
		||||
    [SEND_PATH_RESP_PATH_1]    = generate_path_resp_1,
 | 
			
		||||
    [SEND_PATH_RESP_PATH_2]    = generate_path_resp_2,
 | 
			
		||||
    [SEND_PATH_RESP_PATH_3]    = generate_path_resp_3,
 | 
			
		||||
    [SEND_PING]                = generate_ping_frame,
 | 
			
		||||
    [SEND_HANDSHAKE_DONE]      = generate_handshake_done_frame,
 | 
			
		||||
    [SEND_ACK_FREQUENCY]       = generate_ack_frequency_frame,
 | 
			
		||||
| 
						 | 
				
			
			@ -6543,7 +6639,9 @@ static void (*const send_funcs[N_SEND])(
 | 
			
		|||
    |SF_SEND_STREAMS_BLOCKED_UNI|SF_SEND_STREAMS_BLOCKED_BIDI\
 | 
			
		||||
    |SF_SEND_MAX_STREAMS_UNI|SF_SEND_MAX_STREAMS_BIDI\
 | 
			
		||||
    |SF_SEND_PATH_CHAL_PATH_0|SF_SEND_PATH_CHAL_PATH_1\
 | 
			
		||||
    |SF_SEND_PATH_CHAL_PATH_2|SF_SEND_PATH_CHAL_PATH_3\
 | 
			
		||||
    |SF_SEND_PATH_RESP_PATH_0|SF_SEND_PATH_RESP_PATH_1\
 | 
			
		||||
    |SF_SEND_PATH_RESP_PATH_2|SF_SEND_PATH_RESP_PATH_3\
 | 
			
		||||
    |SF_SEND_PING|SF_SEND_HANDSHAKE_DONE\
 | 
			
		||||
    |SF_SEND_ACK_FREQUENCY\
 | 
			
		||||
    |SF_SEND_STOP_SENDING)
 | 
			
		||||
| 
						 | 
				
			
			@ -7119,6 +7217,17 @@ ietf_full_conn_ci_drop_crypto_streams (struct lsquic_conn *lconn)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
ietf_full_conn_ci_count_garbage (struct lsquic_conn *lconn, size_t garbage_sz)
 | 
			
		||||
{
 | 
			
		||||
    struct ietf_full_conn *conn = (struct ietf_full_conn *) lconn;
 | 
			
		||||
 | 
			
		||||
    conn->ifc_pub.bytes_in = garbage_sz;
 | 
			
		||||
    LSQ_DEBUG("count %zd bytes of garbage, new value: %u bytes", garbage_sz,
 | 
			
		||||
        conn->ifc_pub.bytes_in);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define IETF_FULL_CONN_FUNCS \
 | 
			
		||||
    .ci_abort                =  ietf_full_conn_ci_abort, \
 | 
			
		||||
    .ci_abort_error          =  ietf_full_conn_ci_abort_error, \
 | 
			
		||||
| 
						 | 
				
			
			@ -7127,6 +7236,7 @@ ietf_full_conn_ci_drop_crypto_streams (struct lsquic_conn *lconn)
 | 
			
		|||
    .ci_cancel_pending_streams =  ietf_full_conn_ci_cancel_pending_streams, \
 | 
			
		||||
    .ci_client_call_on_new   =  ietf_full_conn_ci_client_call_on_new, \
 | 
			
		||||
    .ci_close                =  ietf_full_conn_ci_close, \
 | 
			
		||||
    .ci_count_garbage        =  ietf_full_conn_ci_count_garbage, \
 | 
			
		||||
    .ci_destroy              =  ietf_full_conn_ci_destroy, \
 | 
			
		||||
    .ci_drain_time           =  ietf_full_conn_ci_drain_time, \
 | 
			
		||||
    .ci_drop_crypto_streams  =  ietf_full_conn_ci_drop_crypto_streams, \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,7 @@
 | 
			
		|||
 | 
			
		||||
/* Things specific to the IETF version of QUIC that do not fit anywhere else */
 | 
			
		||||
 | 
			
		||||
/* [draft-ietf-quic-transport-25] Section 22.4 */
 | 
			
		||||
/* [draft-ietf-quic-transport-28] Section 20 */
 | 
			
		||||
enum trans_error_code
 | 
			
		||||
{
 | 
			
		||||
    TEC_NO_ERROR                   =  0x0,
 | 
			
		||||
| 
						 | 
				
			
			@ -19,6 +19,7 @@ enum trans_error_code
 | 
			
		|||
    TEC_CONNECTION_ID_LIMIT_ERROR  =  0x9,
 | 
			
		||||
    TEC_PROTOCOL_VIOLATION         =  0xA,
 | 
			
		||||
    TEC_INVALID_TOKEN              =  0xB,
 | 
			
		||||
    TEC_APPLICATION_ERROR          =  0xC,
 | 
			
		||||
    TEC_CRYPTO_BUFFER_EXCEEDED     =  0xD,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -248,8 +248,10 @@ lsquic_logger_lopt (const char *optarg);
 | 
			
		|||
 | 
			
		||||
#define CID_FMT ".*s"
 | 
			
		||||
 | 
			
		||||
#define CID_BITS(cid) 2 * (int) (cid)->len, \
 | 
			
		||||
                                    (lsquic_cid2str(cid, cidbuf_), cidbuf_)
 | 
			
		||||
#define CID_BITS_B(cid, b) 2 * (int) (cid)->len, \
 | 
			
		||||
                                    (lsquic_cid2str(cid, b), b)
 | 
			
		||||
 | 
			
		||||
#define CID_BITS(cid) CID_BITS_B(cid, cidbuf_)
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
lsquic_cid2str (const struct lsquic_cid *, char *out);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -188,12 +188,12 @@ imico_maybe_process_params (struct ietf_mini_conn *conn)
 | 
			
		|||
        {
 | 
			
		||||
            conn->imc_flags |= IMC_HAVE_TP;
 | 
			
		||||
            conn->imc_ack_exp = params->tp_ack_delay_exponent;
 | 
			
		||||
            if (params->tp_set & (1 << TPI_MAX_PACKET_SIZE))
 | 
			
		||||
            if (params->tp_set & (1 << TPI_MAX_UDP_PAYLOAD_SIZE))
 | 
			
		||||
            {
 | 
			
		||||
                if (params->tp_numerics[TPI_MAX_PACKET_SIZE]
 | 
			
		||||
                if (params->tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE]
 | 
			
		||||
                                                < conn->imc_path.np_pack_size)
 | 
			
		||||
                    conn->imc_path.np_pack_size =
 | 
			
		||||
                                    params->tp_numerics[TPI_MAX_PACKET_SIZE];
 | 
			
		||||
                                params->tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE];
 | 
			
		||||
            }
 | 
			
		||||
            LSQ_DEBUG("read transport params, packet size is set to %hu bytes",
 | 
			
		||||
                                                conn->imc_path.np_pack_size);
 | 
			
		||||
| 
						 | 
				
			
			@ -493,6 +493,7 @@ lsquic_mini_conn_ietf_new (struct lsquic_engine_public *enpub,
 | 
			
		|||
    conn->imc_conn.cn_cur_cce_idx = 1;
 | 
			
		||||
 | 
			
		||||
    conn->imc_conn.cn_flags = LSCONN_MINI|LSCONN_IETF|LSCONN_SERVER;
 | 
			
		||||
    conn->imc_conn.cn_version = version;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < N_ENC_LEVS; ++i)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -503,7 +504,7 @@ lsquic_mini_conn_ietf_new (struct lsquic_engine_public *enpub,
 | 
			
		|||
    esfi = select_esf_iquic_by_ver(version);
 | 
			
		||||
    enc_sess = esfi->esfi_create_server(enpub, &conn->imc_conn,
 | 
			
		||||
                &packet_in->pi_dcid, conn->imc_stream_ps, &crypto_stream_if,
 | 
			
		||||
                odcid);
 | 
			
		||||
                &conn->imc_cces[0].cce_cid, &conn->imc_path.np_dcid);
 | 
			
		||||
    if (!enc_sess)
 | 
			
		||||
    {
 | 
			
		||||
        lsquic_malo_put(conn);
 | 
			
		||||
| 
						 | 
				
			
			@ -518,7 +519,6 @@ lsquic_mini_conn_ietf_new (struct lsquic_engine_public *enpub,
 | 
			
		|||
    if (getenv("LSQUIC_CN_PACK_SIZE"))
 | 
			
		||||
        conn->imc_path.np_pack_size = atoi(getenv("LSQUIC_CN_PACK_SIZE"));
 | 
			
		||||
#endif
 | 
			
		||||
    conn->imc_conn.cn_version = version;
 | 
			
		||||
    conn->imc_conn.cn_pf = select_pf_by_ver(version);
 | 
			
		||||
    conn->imc_conn.cn_esf.i = esfi;
 | 
			
		||||
    conn->imc_conn.cn_enc_session = enc_sess;
 | 
			
		||||
| 
						 | 
				
			
			@ -1099,7 +1099,8 @@ imico_process_packet_frame (struct ietf_mini_conn *conn,
 | 
			
		|||
 | 
			
		||||
    enc_level = lsquic_packet_in_enc_level(packet_in);
 | 
			
		||||
    type = conn->imc_conn.cn_pf->pf_parse_frame_type(p, len);
 | 
			
		||||
    if (lsquic_legal_frames_by_level[enc_level] & (1 << type))
 | 
			
		||||
    if (lsquic_legal_frames_by_level[conn->imc_conn.cn_version][enc_level]
 | 
			
		||||
                                                                & (1 << type))
 | 
			
		||||
    {
 | 
			
		||||
        packet_in->pi_frame_types |= 1 << type;
 | 
			
		||||
        return imico_process_frames[type](conn, packet_in, p, len);
 | 
			
		||||
| 
						 | 
				
			
			@ -1193,6 +1194,17 @@ ietf_mini_conn_ci_packet_in (struct lsquic_conn *lconn,
 | 
			
		|||
    enum dec_packin dec_packin;
 | 
			
		||||
    enum packnum_space pns;
 | 
			
		||||
 | 
			
		||||
    /* Update "bytes in" count as early as possible.  From
 | 
			
		||||
     * [draft-ietf-quic-transport-28] Section 8.1:
 | 
			
		||||
     "                                                 For the purposes of
 | 
			
		||||
     " avoiding amplification prior to address validation, servers MUST
 | 
			
		||||
     " count all of the payload bytes received in datagrams that are
 | 
			
		||||
     " uniquely attributed to a single connection.  This includes datagrams
 | 
			
		||||
     " that contain packets that are successfully processed and datagrams
 | 
			
		||||
     " that contain packets that are all discarded.
 | 
			
		||||
     */
 | 
			
		||||
    conn->imc_bytes_in += packet_in->pi_data_sz;
 | 
			
		||||
 | 
			
		||||
    if (conn->imc_flags & IMC_ERROR)
 | 
			
		||||
    {
 | 
			
		||||
        LSQ_DEBUG("ignore incoming packet: connection is in error state");
 | 
			
		||||
| 
						 | 
				
			
			@ -1216,7 +1228,6 @@ ietf_mini_conn_ci_packet_in (struct lsquic_conn *lconn,
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    EV_LOG_PACKET_IN(LSQUIC_LOG_CONN_ID, packet_in);
 | 
			
		||||
    conn->imc_bytes_in += packet_in->pi_data_sz + IQUIC_TAG_LEN;
 | 
			
		||||
 | 
			
		||||
    if (pns == PNS_APP)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -1580,7 +1591,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_NO_ERROR;
 | 
			
		||||
        error_code = TEC_PROTOCOL_VIOLATION;
 | 
			
		||||
        reason = "bad transport parameters";
 | 
			
		||||
        rlen = 24;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1607,7 +1618,7 @@ imico_generate_conn_close (struct ietf_mini_conn *conn)
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* [draft-ietf-quic-transport-23] Section 12.2:
 | 
			
		||||
/* [draft-ietf-quic-transport-28] Section 10.3.1:
 | 
			
		||||
 *
 | 
			
		||||
 " A client will always know whether the server has Handshake keys (see
 | 
			
		||||
 " Section 17.2.2.1), but it is possible that a server does not know
 | 
			
		||||
| 
						 | 
				
			
			@ -1615,7 +1626,25 @@ imico_generate_conn_close (struct ietf_mini_conn *conn)
 | 
			
		|||
 " server SHOULD send a CONNECTION_CLOSE frame in both Handshake and
 | 
			
		||||
 " Initial packets to ensure that at least one of them is processable by
 | 
			
		||||
 " the client.
 | 
			
		||||
--- 8< ---
 | 
			
		||||
 " Sending a CONNECTION_CLOSE of type 0x1d in an Initial or Handshake
 | 
			
		||||
 " packet could expose application state or be used to alter application
 | 
			
		||||
 " state.  A CONNECTION_CLOSE of type 0x1d MUST be replaced by a
 | 
			
		||||
 " CONNECTION_CLOSE of type 0x1c when sending the frame in Initial or
 | 
			
		||||
 " Handshake packets.  Otherwise, information about the application
 | 
			
		||||
 " state might be revealed.  Endpoints MUST clear the value of the
 | 
			
		||||
 " Reason Phrase field and SHOULD use the APPLICATION_ERROR code when
 | 
			
		||||
 " converting to a CONNECTION_CLOSE of type 0x1c.
 | 
			
		||||
 */
 | 
			
		||||
    LSQ_DEBUG("sending CONNECTION_CLOSE, is_app: %d, error code: %u, "
 | 
			
		||||
        "reason: %.*s", is_app, error_code, rlen, reason);
 | 
			
		||||
    if (is_app && conn->imc_conn.cn_version > LSQVER_ID27)
 | 
			
		||||
    {
 | 
			
		||||
        LSQ_DEBUG("convert to 0x1C, replace code and reason");
 | 
			
		||||
        is_app = 0;
 | 
			
		||||
        error_code = TEC_APPLICATION_ERROR;
 | 
			
		||||
        rlen = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pns = (conn->imc_flags >> IMCBIT_PNS_BIT_SHIFT) & 3;
 | 
			
		||||
    switch ((!!(conn->imc_flags & IMC_HSK_PACKET_SENT) << 1)
 | 
			
		||||
| 
						 | 
				
			
			@ -1844,9 +1873,21 @@ ietf_mini_conn_ci_record_addrs (struct lsquic_conn *lconn, void *peer_ctx,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
ietf_mini_conn_ci_count_garbage (struct lsquic_conn *lconn, size_t garbage_sz)
 | 
			
		||||
{
 | 
			
		||||
    struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn;
 | 
			
		||||
 | 
			
		||||
    conn->imc_bytes_in += garbage_sz;
 | 
			
		||||
    LSQ_DEBUG("count %zd bytes of garbage, new value: %u bytes", garbage_sz,
 | 
			
		||||
        conn->imc_bytes_in);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static const struct conn_iface mini_conn_ietf_iface = {
 | 
			
		||||
    .ci_abort_error          =  ietf_mini_conn_ci_abort_error,
 | 
			
		||||
    .ci_client_call_on_new   =  ietf_mini_conn_ci_client_call_on_new,
 | 
			
		||||
    .ci_count_garbage        =  ietf_mini_conn_ci_count_garbage,
 | 
			
		||||
    .ci_destroy              =  ietf_mini_conn_ci_destroy,
 | 
			
		||||
    .ci_get_engine           =  ietf_mini_conn_ci_get_engine,
 | 
			
		||||
    .ci_get_log_cid          =  ietf_mini_conn_ci_get_log_cid,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -238,6 +238,6 @@ extern const char *const lsquic_pns2str[];
 | 
			
		|||
    ALL_IQUIC_FRAMES & ~(QUIC_FTBIT_PADDING|QUIC_FTBIT_PATH_RESPONSE    \
 | 
			
		||||
            |QUIC_FTBIT_PATH_CHALLENGE|QUIC_FTBIT_ACK|QUIC_FTBIT_TIMESTAMP))
 | 
			
		||||
 | 
			
		||||
extern const enum quic_ft_bit lsquic_legal_frames_by_level[];
 | 
			
		||||
extern const enum quic_ft_bit lsquic_legal_frames_by_level[][4];
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -217,9 +217,38 @@ lsquic_cid_from_packet (const unsigned char *buf, size_t bufsz,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* See [draft-ietf-quic-transport-25], Section 12.4 (Table 3) */
 | 
			
		||||
const enum quic_ft_bit lsquic_legal_frames_by_level[N_ENC_LEVS] =
 | 
			
		||||
/* 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_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,
 | 
			
		||||
    [ENC_LEV_EARLY] = QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
 | 
			
		||||
| 
						 | 
				
			
			@ -246,4 +275,5 @@ const enum quic_ft_bit lsquic_legal_frames_by_level[N_ENC_LEVS] =
 | 
			
		|||
                    | QUIC_FTBIT_RETIRE_CONNECTION_ID | QUIC_FTBIT_NEW_TOKEN
 | 
			
		||||
                    | QUIC_FTBIT_TIMESTAMP
 | 
			
		||||
                    ,
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -355,7 +355,7 @@ lsquic_prq_new_req (struct pr_queue *prq, enum packet_req_type type,
 | 
			
		|||
        version = lsquic_tag2ver(ver_tag);
 | 
			
		||||
    }
 | 
			
		||||
    else /* Got to set it to something sensible... */
 | 
			
		||||
        version = LSQVER_ID25;
 | 
			
		||||
        version = LSQVER_ID27;
 | 
			
		||||
 | 
			
		||||
    lsquic_scid_from_packet_in(packet_in, &scid);
 | 
			
		||||
    return lsquic_prq_new_req_ext(prq, type, flags, version,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,7 +31,7 @@
 | 
			
		|||
#define STRINGIFY(x) #x
 | 
			
		||||
#define TOSTRING(x) STRINGIFY(x)
 | 
			
		||||
 | 
			
		||||
#define TOKGEN_VERSION 1
 | 
			
		||||
#define TOKGEN_VERSION 2
 | 
			
		||||
 | 
			
		||||
#define CRYPTER_KEY_SIZE        16
 | 
			
		||||
#define SRST_MAX_PRK_SIZE       EVP_MAX_MD_SIZE
 | 
			
		||||
| 
						 | 
				
			
			@ -65,6 +65,8 @@ struct crypter
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct token_generator
 | 
			
		||||
{
 | 
			
		||||
    /* We encrypt different token types using different keys. */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -18,7 +18,7 @@ enum transport_param_id
 | 
			
		|||
     * Numeric transport parameters that have default values:
 | 
			
		||||
     */
 | 
			
		||||
    TPI_MAX_IDLE_TIMEOUT,
 | 
			
		||||
    TPI_MAX_PACKET_SIZE,
 | 
			
		||||
    TPI_MAX_UDP_PAYLOAD_SIZE,
 | 
			
		||||
    TPI_INIT_MAX_DATA,
 | 
			
		||||
    TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL,
 | 
			
		||||
    TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE,
 | 
			
		||||
| 
						 | 
				
			
			@ -45,7 +45,12 @@ enum transport_param_id
 | 
			
		|||
     * Custom handlers:
 | 
			
		||||
     */
 | 
			
		||||
    TPI_PREFERRED_ADDRESS,
 | 
			
		||||
    TPI_ORIGINAL_CONNECTION_ID,
 | 
			
		||||
        /* CIDs must be in a contiguous range for tp_cids array to work */
 | 
			
		||||
#define FIRST_TP_CID TPI_ORIGINAL_DEST_CID
 | 
			
		||||
    TPI_ORIGINAL_DEST_CID,
 | 
			
		||||
    TPI_INITIAL_SOURCE_CID,
 | 
			
		||||
#define LAST_TP_CID TPI_RETRY_SOURCE_CID
 | 
			
		||||
    TPI_RETRY_SOURCE_CID,
 | 
			
		||||
#if LSQUIC_TEST_QUANTUM_READINESS
 | 
			
		||||
    /* https://github.com/quicwg/base-drafts/wiki/Quantum-Readiness-test */
 | 
			
		||||
#define QUANTUM_READY_SZ 1200
 | 
			
		||||
| 
						 | 
				
			
			@ -54,6 +59,8 @@ enum transport_param_id
 | 
			
		|||
    TPI_STATELESS_RESET_TOKEN,              LAST_TPI = TPI_STATELESS_RESET_TOKEN
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define TP_CID_IDX(tpi_) ((tpi_) - FIRST_TP_CID)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct transport_params
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -72,7 +79,7 @@ struct transport_params
 | 
			
		|||
#define tp_max_idle_timeout                 tp_numerics[TPI_MAX_IDLE_TIMEOUT]
 | 
			
		||||
#define tp_init_max_streams_bidi            tp_numerics[TPI_INIT_MAX_STREAMS_BIDI]
 | 
			
		||||
#define tp_init_max_streams_uni             tp_numerics[TPI_INIT_MAX_STREAMS_UNI]
 | 
			
		||||
#define tp_max_packet_size                  tp_numerics[TPI_MAX_PACKET_SIZE]
 | 
			
		||||
#define tp_max_udp_payload_size             tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE]
 | 
			
		||||
#define tp_ack_delay_exponent               tp_numerics[TPI_ACK_DELAY_EXPONENT]
 | 
			
		||||
#define tp_max_ack_delay                    tp_numerics[TPI_MAX_ACK_DELAY]
 | 
			
		||||
#define tp_active_connection_id_limit       tp_numerics[TPI_ACTIVE_CONNECTION_ID_LIMIT]
 | 
			
		||||
| 
						 | 
				
			
			@ -87,10 +94,20 @@ struct transport_params
 | 
			
		|||
        lsquic_cid_t    cid;
 | 
			
		||||
        uint8_t         srst[IQUIC_SRESET_TOKEN_SZ];
 | 
			
		||||
    }           tp_preferred_address;
 | 
			
		||||
    lsquic_cid_t    tp_original_cid;
 | 
			
		||||
    lsquic_cid_t    tp_cids[3];
 | 
			
		||||
#define tp_original_dest_cid tp_cids[TP_CID_IDX(TPI_ORIGINAL_DEST_CID)]
 | 
			
		||||
#define tp_initial_source_cid tp_cids[TP_CID_IDX(TPI_INITIAL_SOURCE_CID)]
 | 
			
		||||
#define tp_retry_source_cid tp_cids[TP_CID_IDX(TPI_RETRY_SOURCE_CID)]
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define TP_DEF_MAX_PACKET_SIZE 65527
 | 
			
		||||
#define MAX_TP_STR_SZ ((LAST_TPI + 1) *                                     \
 | 
			
		||||
    (34 /* longest entry in tt2str */ + 2 /* semicolon */ + 2 /* colon */)  \
 | 
			
		||||
  + INET_ADDRSTRLEN + INET6_ADDRSTRLEN + 5 /* Port */ * 2                   \
 | 
			
		||||
  + MAX_CID_LEN * 2 * 4 /* there are four CIDs */                           \
 | 
			
		||||
  + 11 * (MAX_NUMERIC_TPI + 1)                                              \
 | 
			
		||||
  + IQUIC_SRESET_TOKEN_SZ * 2 * 2 /* there are two reset tokens */)
 | 
			
		||||
 | 
			
		||||
#define TP_DEF_MAX_UDP_PAYLOAD_SIZE 65527
 | 
			
		||||
#define TP_DEF_ACK_DELAY_EXP 3
 | 
			
		||||
#define TP_DEF_INIT_MAX_STREAMS_UNI 0
 | 
			
		||||
#define TP_DEF_INIT_MAX_STREAMS_BIDI 0
 | 
			
		||||
| 
						 | 
				
			
			@ -111,7 +128,7 @@ struct transport_params
 | 
			
		|||
    .tp_active_connection_id_limit        =  TP_DEF_ACTIVE_CONNECTION_ID_LIMIT,       \
 | 
			
		||||
    .tp_max_idle_timeout                  =  TP_DEF_MAX_IDLE_TIMEOUT,                 \
 | 
			
		||||
    .tp_max_ack_delay                     =  TP_DEF_MAX_ACK_DELAY,                    \
 | 
			
		||||
    .tp_max_packet_size                   =  TP_DEF_MAX_PACKET_SIZE,                  \
 | 
			
		||||
    .tp_max_udp_payload_size              =  TP_DEF_MAX_UDP_PAYLOAD_SIZE,             \
 | 
			
		||||
    .tp_ack_delay_exponent                =  TP_DEF_ACK_DELAY_EXP,                    \
 | 
			
		||||
    .tp_init_max_streams_bidi             =  TP_DEF_INIT_MAX_STREAMS_BIDI,            \
 | 
			
		||||
    .tp_init_max_streams_uni              =  TP_DEF_INIT_MAX_STREAMS_UNI,             \
 | 
			
		||||
| 
						 | 
				
			
			@ -135,16 +152,20 @@ lsquic_tp_decode (const unsigned char *buf, size_t bufsz,
 | 
			
		|||
                  int is_server,
 | 
			
		||||
                  struct transport_params *);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
lsquic_tp_to_str (const struct transport_params *params, char *buf, size_t sz);
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
lsquic_tp_encode_id25 (const struct transport_params *, int is_server,
 | 
			
		||||
lsquic_tp_encode_27 (const struct transport_params *, int is_server,
 | 
			
		||||
                  unsigned char *buf, size_t bufsz);
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
lsquic_tp_decode_id25 (const unsigned char *buf, size_t bufsz,
 | 
			
		||||
                  int is_server, struct transport_params *);
 | 
			
		||||
lsquic_tp_decode_27 (const unsigned char *buf, size_t bufsz,
 | 
			
		||||
                  int is_server,
 | 
			
		||||
                  struct transport_params *);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
lsquic_tp_to_str (const struct transport_params *params, char *buf, size_t sz);
 | 
			
		||||
lsquic_tp_to_str_27 (const struct transport_params *params, char *buf, size_t sz);
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
lsquic_tp_has_pref_ipv4 (const struct transport_params *);
 | 
			
		||||
| 
						 | 
				
			
			@ -152,4 +173,6 @@ lsquic_tp_has_pref_ipv4 (const struct transport_params *);
 | 
			
		|||
int
 | 
			
		||||
lsquic_tp_has_pref_ipv6 (const struct transport_params *);
 | 
			
		||||
 | 
			
		||||
extern const char * const lsquic_tpi2str[LAST_TPI + 1];
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,8 +14,8 @@ static const unsigned char version_tags[N_LSQVER][4] =
 | 
			
		|||
#if LSQUIC_USE_Q098
 | 
			
		||||
    [LSQVER_098] = { 'Q', '0', '9', '8', },
 | 
			
		||||
#endif
 | 
			
		||||
    [LSQVER_ID25] = { 0xFF, 0, 0, 25, },
 | 
			
		||||
    [LSQVER_ID27] = { 0xFF, 0, 0, 27, },
 | 
			
		||||
    [LSQVER_ID28] = { 0xFF, 0, 0, 28, },
 | 
			
		||||
    [LSQVER_VERNEG] = { 0xFA, 0xFA, 0xFA, 0xFA, },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -52,8 +52,8 @@ const char *const lsquic_ver2str[N_LSQVER] = {
 | 
			
		|||
#if LSQUIC_USE_Q098
 | 
			
		||||
    [LSQVER_098] = "Q098",
 | 
			
		||||
#endif
 | 
			
		||||
    [LSQVER_ID25] = "FF000019",
 | 
			
		||||
    [LSQVER_ID27] = "FF00001B",
 | 
			
		||||
    [LSQVER_ID28] = "FF00001C",
 | 
			
		||||
    [LSQVER_VERNEG] = "FAFAFAFA",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -179,7 +179,7 @@ run_test (const struct test *test)
 | 
			
		|||
    size_t sz;
 | 
			
		||||
    unsigned char buf[0x1000];
 | 
			
		||||
 | 
			
		||||
    pf = select_pf_by_ver(LSQVER_ID25);
 | 
			
		||||
    pf = select_pf_by_ver(LSQVER_ID27);
 | 
			
		||||
    if (!test->skip_gen)
 | 
			
		||||
    {
 | 
			
		||||
        rechist.acki = &test->acki;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,7 +17,7 @@
 | 
			
		|||
 | 
			
		||||
static struct lsquic_conn lconn = LSCONN_INITIALIZER_CIDLEN(lconn, 0);
 | 
			
		||||
 | 
			
		||||
static const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_ID25);
 | 
			
		||||
static const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_ID27);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,7 +33,7 @@ struct test {
 | 
			
		|||
static const struct test tests[] = {
 | 
			
		||||
 | 
			
		||||
    {   .lineno     = __LINE__,
 | 
			
		||||
        .pf         = select_pf_by_ver(LSQVER_ID25),
 | 
			
		||||
        .pf         = select_pf_by_ver(LSQVER_ID27),
 | 
			
		||||
        .offset     = 0,
 | 
			
		||||
        .data_sz    = 10,
 | 
			
		||||
        .data       = "0123456789",
 | 
			
		||||
| 
						 | 
				
			
			@ -49,7 +49,7 @@ static const struct test tests[] = {
 | 
			
		|||
    },
 | 
			
		||||
 | 
			
		||||
    {   .lineno     = __LINE__,
 | 
			
		||||
        .pf         = select_pf_by_ver(LSQVER_ID25),
 | 
			
		||||
        .pf         = select_pf_by_ver(LSQVER_ID27),
 | 
			
		||||
        .offset     = 500,
 | 
			
		||||
        .data_sz    = 10,
 | 
			
		||||
        .data       = "0123456789",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -59,7 +59,7 @@
 | 
			
		|||
#include "lsquic_hq.h"
 | 
			
		||||
#include "lsquic_data_in_if.h"
 | 
			
		||||
 | 
			
		||||
static const struct parse_funcs *g_pf = select_pf_by_ver(LSQVER_ID25);
 | 
			
		||||
static const struct parse_funcs *g_pf = select_pf_by_ver(LSQVER_ID27);
 | 
			
		||||
 | 
			
		||||
struct test_ctl_settings
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -302,7 +302,7 @@ init_test_objs (struct test_objs *tobjs, unsigned initial_conn_window,
 | 
			
		|||
    memset(tobjs, 0, sizeof(*tobjs));
 | 
			
		||||
    LSCONN_INITIALIZE(&tobjs->lconn);
 | 
			
		||||
    tobjs->lconn.cn_pf = g_pf;
 | 
			
		||||
    tobjs->lconn.cn_version = LSQVER_ID25;
 | 
			
		||||
    tobjs->lconn.cn_version = LSQVER_ID27;
 | 
			
		||||
    tobjs->lconn.cn_esf_c = &lsquic_enc_session_common_ietf_v1;
 | 
			
		||||
    network_path.np_pack_size = packet_sz;
 | 
			
		||||
    tobjs->lconn.cn_if = &our_conn_if;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -161,8 +161,8 @@ init_test_objs (struct test_objs *tobjs, unsigned initial_conn_window,
 | 
			
		|||
    int s;
 | 
			
		||||
    memset(tobjs, 0, sizeof(*tobjs));
 | 
			
		||||
    LSCONN_INITIALIZE(&tobjs->lconn);
 | 
			
		||||
    tobjs->lconn.cn_pf = select_pf_by_ver(LSQVER_ID25);
 | 
			
		||||
    tobjs->lconn.cn_version = LSQVER_ID25;
 | 
			
		||||
    tobjs->lconn.cn_pf = select_pf_by_ver(LSQVER_ID27);
 | 
			
		||||
    tobjs->lconn.cn_version = LSQVER_ID27;
 | 
			
		||||
    tobjs->lconn.cn_esf_c = &lsquic_enc_session_common_ietf_v1;
 | 
			
		||||
    network_path.np_pack_size = IQUIC_MAX_IPv4_PACKET_SZ;
 | 
			
		||||
    tobjs->lconn.cn_if = &our_conn_if;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -325,7 +325,7 @@ init_test_objs (struct test_objs *tobjs, unsigned initial_conn_window,
 | 
			
		|||
    LSCONN_INITIALIZE(&tobjs->lconn);
 | 
			
		||||
    tobjs->lconn.cn_pf = pf ? pf : g_pf;
 | 
			
		||||
    tobjs->lconn.cn_version = tobjs->lconn.cn_pf == &lsquic_parse_funcs_ietf_v1 ?
 | 
			
		||||
        LSQVER_ID25 : LSQVER_043;
 | 
			
		||||
        LSQVER_ID27 : LSQVER_043;
 | 
			
		||||
    tobjs->lconn.cn_esf_c = &lsquic_enc_session_common_gquic_1;
 | 
			
		||||
    network_path.np_pack_size = 1370;
 | 
			
		||||
    tobjs->lconn.cn_if = &our_conn_if;
 | 
			
		||||
| 
						 | 
				
			
			@ -2243,7 +2243,7 @@ test_changing_pack_size (void)
 | 
			
		|||
    enum lsquic_version versions_to_test[3] =
 | 
			
		||||
    {
 | 
			
		||||
        LSQVER_046,
 | 
			
		||||
        LSQVER_ID25,
 | 
			
		||||
        LSQVER_ID27,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < 3; i++)
 | 
			
		||||
| 
						 | 
				
			
			@ -3173,7 +3173,7 @@ main (int argc, char **argv)
 | 
			
		|||
 | 
			
		||||
    /* Redo some tests using crypto streams and frames */
 | 
			
		||||
    g_use_crypto_ctor = 1;
 | 
			
		||||
    g_pf = select_pf_by_ver(LSQVER_ID25);
 | 
			
		||||
    g_pf = select_pf_by_ver(LSQVER_ID27);
 | 
			
		||||
    main_test_packetization();
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -279,7 +279,7 @@ static const struct test tests[] = {
 | 
			
		|||
     */
 | 
			
		||||
 | 
			
		||||
    {   .lineno     = __LINE__,
 | 
			
		||||
        .pf         = select_pf_by_ver(LSQVER_ID25),
 | 
			
		||||
        .pf         = select_pf_by_ver(LSQVER_ID27),
 | 
			
		||||
        .fin        = { 0, 1, },
 | 
			
		||||
        .offset     = 0x0807060504030201UL,
 | 
			
		||||
        .stream_id  = 0x210,
 | 
			
		||||
| 
						 | 
				
			
			@ -299,7 +299,7 @@ static const struct test tests[] = {
 | 
			
		|||
    },
 | 
			
		||||
 | 
			
		||||
    {   .lineno     = __LINE__,
 | 
			
		||||
        .pf         = select_pf_by_ver(LSQVER_ID25),
 | 
			
		||||
        .pf         = select_pf_by_ver(LSQVER_ID27),
 | 
			
		||||
        .fin        = { 0, 0, },
 | 
			
		||||
        .offset     = 0,
 | 
			
		||||
        .stream_id  = 0x210,
 | 
			
		||||
| 
						 | 
				
			
			@ -318,7 +318,7 @@ static const struct test tests[] = {
 | 
			
		|||
    },
 | 
			
		||||
 | 
			
		||||
    {   .lineno     = __LINE__,
 | 
			
		||||
        .pf         = select_pf_by_ver(LSQVER_ID25),
 | 
			
		||||
        .pf         = select_pf_by_ver(LSQVER_ID27),
 | 
			
		||||
        .fin        = { 0, 0, },
 | 
			
		||||
        .offset     = 0,
 | 
			
		||||
        .stream_id  = 0x21,
 | 
			
		||||
| 
						 | 
				
			
			@ -336,7 +336,7 @@ static const struct test tests[] = {
 | 
			
		|||
    },
 | 
			
		||||
 | 
			
		||||
    {   .lineno     = __LINE__,
 | 
			
		||||
        .pf         = select_pf_by_ver(LSQVER_ID25),
 | 
			
		||||
        .pf         = select_pf_by_ver(LSQVER_ID27),
 | 
			
		||||
        .fin        = { 0, 0, },
 | 
			
		||||
        .offset     = 0x0807060504030201UL,
 | 
			
		||||
        .stream_id  = 0x210,
 | 
			
		||||
| 
						 | 
				
			
			@ -356,7 +356,7 @@ static const struct test tests[] = {
 | 
			
		|||
    },
 | 
			
		||||
 | 
			
		||||
    {   .lineno     = __LINE__,
 | 
			
		||||
        .pf         = select_pf_by_ver(LSQVER_ID25),
 | 
			
		||||
        .pf         = select_pf_by_ver(LSQVER_ID27),
 | 
			
		||||
        .fin        = { 1, 0, },
 | 
			
		||||
        .offset     = 0x0807060504030201UL,
 | 
			
		||||
        .stream_id  = 0x210,
 | 
			
		||||
| 
						 | 
				
			
			@ -374,7 +374,7 @@ static const struct test tests[] = {
 | 
			
		|||
    },
 | 
			
		||||
 | 
			
		||||
    {   .lineno     = __LINE__,
 | 
			
		||||
        .pf         = select_pf_by_ver(LSQVER_ID25),
 | 
			
		||||
        .pf         = select_pf_by_ver(LSQVER_ID27),
 | 
			
		||||
        .fin        = { 1, 0, },
 | 
			
		||||
        .offset     = 0x0807060504030201UL,
 | 
			
		||||
        .stream_id  = 0x210,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -243,7 +243,7 @@ static const struct test tests[] = {
 | 
			
		|||
 | 
			
		||||
    {   "Balls to the wall: every possible bit is set",
 | 
			
		||||
        __LINE__,
 | 
			
		||||
        select_pf_by_ver(LSQVER_ID25),
 | 
			
		||||
        select_pf_by_ver(LSQVER_ID27),
 | 
			
		||||
      /*  TYPE   OFF    DLEN   FIN   */
 | 
			
		||||
        { 0x10 | 1<<2 | 1<<1 | 1<<0,
 | 
			
		||||
          0x41, 0x23,                                       /* Stream ID */
 | 
			
		||||
| 
						 | 
				
			
			@ -262,7 +262,7 @@ static const struct test tests[] = {
 | 
			
		|||
 | 
			
		||||
    {   "Balls to the wall #2: every possible bit is set except FIN",
 | 
			
		||||
        __LINE__,
 | 
			
		||||
        select_pf_by_ver(LSQVER_ID25),
 | 
			
		||||
        select_pf_by_ver(LSQVER_ID27),
 | 
			
		||||
      /*  TYPE   OFF    DLEN   FIN   */
 | 
			
		||||
        { 0x10 | 1<<2 | 1<<1 | 0<<0,
 | 
			
		||||
          0x81, 0x23, 0x00, 0xE4,                           /* Stream ID */
 | 
			
		||||
| 
						 | 
				
			
			@ -281,7 +281,7 @@ static const struct test tests[] = {
 | 
			
		|||
 | 
			
		||||
    {   "Data length is zero",
 | 
			
		||||
        __LINE__,
 | 
			
		||||
        select_pf_by_ver(LSQVER_ID25),
 | 
			
		||||
        select_pf_by_ver(LSQVER_ID27),
 | 
			
		||||
      /*  TYPE   OFF    DLEN   FIN   */
 | 
			
		||||
        { 0x10 | 1<<2 | 0<<1 | 0<<0,
 | 
			
		||||
          0x81, 0x23, 0x00, 0xE4,                           /* Stream ID */
 | 
			
		||||
| 
						 | 
				
			
			@ -299,7 +299,7 @@ static const struct test tests[] = {
 | 
			
		|||
 | 
			
		||||
    {   "Sanity check: what happens when data length is zero #1",
 | 
			
		||||
        __LINE__,
 | 
			
		||||
        select_pf_by_ver(LSQVER_ID25),
 | 
			
		||||
        select_pf_by_ver(LSQVER_ID27),
 | 
			
		||||
      /*  TYPE   OFF    DLEN   FIN   */
 | 
			
		||||
        { 0x10 | 1<<2 | 1<<1 | 0<<0,
 | 
			
		||||
          0x81, 0x23, 0x00, 0xE4,                           /* Stream ID */
 | 
			
		||||
| 
						 | 
				
			
			@ -318,7 +318,7 @@ static const struct test tests[] = {
 | 
			
		|||
 | 
			
		||||
    {   "Sanity check: what happens when data length is zero #2",
 | 
			
		||||
        __LINE__,
 | 
			
		||||
        select_pf_by_ver(LSQVER_ID25),
 | 
			
		||||
        select_pf_by_ver(LSQVER_ID27),
 | 
			
		||||
      /*  TYPE   OFF    DLEN   FIN   */
 | 
			
		||||
        { 0x10 | 1<<2 | 1<<1 | 0<<0,
 | 
			
		||||
          0x81, 0x23, 0x00, 0xE4,                           /* Stream ID */
 | 
			
		||||
| 
						 | 
				
			
			@ -337,7 +337,7 @@ static const struct test tests[] = {
 | 
			
		|||
 | 
			
		||||
    {   "Sanity check: what happens when data length is zero #3",
 | 
			
		||||
        __LINE__,
 | 
			
		||||
        select_pf_by_ver(LSQVER_ID25),
 | 
			
		||||
        select_pf_by_ver(LSQVER_ID27),
 | 
			
		||||
      /*  TYPE   OFF    DLEN   FIN   */
 | 
			
		||||
        { 0x10 | 0<<2 | 1<<1 | 0<<0,
 | 
			
		||||
          0x81, 0x23, 0x00, 0xE4,                           /* Stream ID */
 | 
			
		||||
| 
						 | 
				
			
			@ -355,7 +355,7 @@ static const struct test tests[] = {
 | 
			
		|||
 | 
			
		||||
    {   "Sanity check: what happens when data length is zero #3",
 | 
			
		||||
        __LINE__,
 | 
			
		||||
        select_pf_by_ver(LSQVER_ID25),
 | 
			
		||||
        select_pf_by_ver(LSQVER_ID27),
 | 
			
		||||
      /*  TYPE   OFF    DLEN   FIN   */
 | 
			
		||||
        { 0x10 | 1<<2 | 1<<1 | 1<<0,
 | 
			
		||||
          0x81, 0x23, 0x00, 0xE4,                           /* Stream ID */
 | 
			
		||||
| 
						 | 
				
			
			@ -374,7 +374,7 @@ static const struct test tests[] = {
 | 
			
		|||
 | 
			
		||||
    {   "Check data bounds #1",
 | 
			
		||||
        __LINE__,
 | 
			
		||||
        select_pf_by_ver(LSQVER_ID25),
 | 
			
		||||
        select_pf_by_ver(LSQVER_ID27),
 | 
			
		||||
      /*  TYPE   OFF    DLEN   FIN   */
 | 
			
		||||
        { 0x10 | 1<<2 | 1<<1 | 1<<0,
 | 
			
		||||
          0x81, 0x23, 0x00, 0xE4,                           /* Stream ID */
 | 
			
		||||
| 
						 | 
				
			
			@ -393,7 +393,7 @@ static const struct test tests[] = {
 | 
			
		|||
 | 
			
		||||
    {   "Check data bounds #2",
 | 
			
		||||
        __LINE__,
 | 
			
		||||
        select_pf_by_ver(LSQVER_ID25),
 | 
			
		||||
        select_pf_by_ver(LSQVER_ID27),
 | 
			
		||||
      /*  TYPE   OFF    DLEN   FIN   */
 | 
			
		||||
        { 0x10 | 1<<2 | 1<<1 | 1<<0,
 | 
			
		||||
          0x81, 0x23, 0x00, 0xE4,                           /* Stream ID */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,18 +58,20 @@ static const struct trapa_test tests[] =
 | 
			
		|||
                    | (1 << TPI_INIT_MAX_DATA)
 | 
			
		||||
                    | (1 << TPI_MAX_IDLE_TIMEOUT)
 | 
			
		||||
                    | (1 << TPI_MAX_ACK_DELAY)
 | 
			
		||||
                    | (1 << TPI_MAX_PACKET_SIZE)
 | 
			
		||||
                    | (1 << TPI_MAX_UDP_PAYLOAD_SIZE)
 | 
			
		||||
                    | (1 << TPI_ACK_DELAY_EXPONENT)
 | 
			
		||||
                    | (1 << TPI_INITIAL_SOURCE_CID)
 | 
			
		||||
                    | (1 << TPI_ACTIVE_CONNECTION_ID_LIMIT),
 | 
			
		||||
            .tp_init_max_stream_data_bidi_local = 0x12348877,
 | 
			
		||||
            .tp_init_max_data = 0xAABB,
 | 
			
		||||
            .tp_max_packet_size = 1213,
 | 
			
		||||
            .tp_max_udp_payload_size = 1213,
 | 
			
		||||
            .tp_max_idle_timeout = 10 * 1000,
 | 
			
		||||
            .tp_max_ack_delay = TP_DEF_MAX_ACK_DELAY,
 | 
			
		||||
            .tp_active_connection_id_limit = 7,
 | 
			
		||||
            .tp_initial_source_cid = { .len = 8, .u_cid.id = 0x0807060504030201ull, },
 | 
			
		||||
        },
 | 
			
		||||
        .is_server = 0,
 | 
			
		||||
        .enc_len = 26,
 | 
			
		||||
        .enc_len = 36,
 | 
			
		||||
        .encoded =
 | 
			
		||||
     /* Idle timeout */     "\x01\x02\x67\x10"
 | 
			
		||||
     /* Packet size */      "\x03\x02\x44\xBD"
 | 
			
		||||
| 
						 | 
				
			
			@ -77,6 +79,7 @@ static const struct trapa_test tests[] =
 | 
			
		|||
     /* Bidi local */       "\x05\x04\x92\x34\x88\x77"
 | 
			
		||||
     /* Ack delay exp */    "\x0A\x01\x00"
 | 
			
		||||
     /* Active CID limit */ "\x0E\x01\x07"
 | 
			
		||||
     /* Initial SCID */     "\x0F\x08\x01\x02\x03\x04\x05\x06\x07\x08"
 | 
			
		||||
    /* Trailer to make the end easily visible in gdb: */
 | 
			
		||||
    "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
 | 
			
		||||
    },
 | 
			
		||||
| 
						 | 
				
			
			@ -104,7 +107,7 @@ static const struct trapa_test tests[] =
 | 
			
		|||
            TP_DEFAULT_VALUES,
 | 
			
		||||
            .tp_init_max_data = 0x123456,
 | 
			
		||||
            .tp_init_max_stream_data_bidi_local = 0xABCDEF88,
 | 
			
		||||
            .tp_max_packet_size = 0x555,
 | 
			
		||||
            .tp_max_udp_payload_size = 0x555,
 | 
			
		||||
        },
 | 
			
		||||
        .is_server = 1,
 | 
			
		||||
        .addl_set = 1 << TPI_DISABLE_ACTIVE_MIGRATION,
 | 
			
		||||
| 
						 | 
				
			
			@ -125,7 +128,7 @@ static const struct trapa_test tests[] =
 | 
			
		|||
        .params = {
 | 
			
		||||
            TP_DEFAULT_VALUES,
 | 
			
		||||
            .tp_max_ack_delay = 25,
 | 
			
		||||
            .tp_max_packet_size = 0x555,
 | 
			
		||||
            .tp_max_udp_payload_size = 0x555,
 | 
			
		||||
            .tp_preferred_address = {
 | 
			
		||||
                .ipv4_addr = "\x01\x02\x03\x04",
 | 
			
		||||
                .ipv4_port = 0x1234,
 | 
			
		||||
| 
						 | 
				
			
			@ -172,8 +175,8 @@ params_are_equal (const struct transport_params *a,
 | 
			
		|||
        && a->tp_preferred_address.ipv4_port == b->tp_preferred_address.ipv4_port
 | 
			
		||||
        && a->tp_preferred_address.ipv6_port == b->tp_preferred_address.ipv6_port
 | 
			
		||||
        && a->tp_preferred_address.cid.len == b->tp_preferred_address.cid.len
 | 
			
		||||
        && MCMP(tp_original_cid.idbuf)
 | 
			
		||||
        && a->tp_original_cid.len == b->tp_original_cid.len
 | 
			
		||||
        && MCMP(tp_original_dest_cid.idbuf)
 | 
			
		||||
        && a->tp_original_dest_cid.len == b->tp_original_dest_cid.len
 | 
			
		||||
        ;
 | 
			
		||||
#undef MCMP
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue