summaryrefslogtreecommitdiff
path: root/chromium/net/third_party/quiche/src/quic
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-07-16 11:45:35 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-07-17 08:59:23 +0000
commit552906b0f222c5d5dd11b9fd73829d510980461a (patch)
tree3a11e6ed0538a81dd83b20cf3a4783e297f26d91 /chromium/net/third_party/quiche/src/quic
parent1b05827804eaf047779b597718c03e7d38344261 (diff)
downloadqtwebengine-chromium-552906b0f222c5d5dd11b9fd73829d510980461a.tar.gz
BASELINE: Update Chromium to 83.0.4103.122
Change-Id: Ie3a82f5bb0076eec2a7c6a6162326b4301ee291e Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/net/third_party/quiche/src/quic')
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/chlo_extractor.cc27
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/chlo_extractor_test.cc7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.cc301
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.h200
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler_test.cc313
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_drain.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_drain.h11
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.cc170
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.h94
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.cc163
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.h24
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_rtt.cc13
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_rtt.h9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.cc85
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.h24
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_simulator_test.cc406
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_startup.cc31
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_startup.h17
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.cc377
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.h68
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender_test.cc637
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/cubic_bytes.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/cubic_bytes_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm.cc129
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm.h45
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm_test.cc302
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/loss_detection_interface.h9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.cc30
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h30
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats_test.cc50
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.cc15
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h22
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_test.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.cc77
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.h56
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm_test.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/windowed_filter_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_decrypter.cc35
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_decrypter.h18
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_encrypter.cc37
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_encrypter.h22
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc46
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_encrypter_test.cc44
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_decrypter_test.cc53
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_encrypter_test.cc71
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aes_256_gcm_decrypter_test.cc54
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aes_256_gcm_encrypter_test.cc56
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_decrypter.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_decrypter.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_encrypter.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_encrypter.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/boring_utils.h29
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/cert_compressor.cc26
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/cert_compressor.h13
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/cert_compressor_test.cc55
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/certificate_view.cc246
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/certificate_view.h57
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/certificate_view_test.cc144
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_decrypter_test.cc34
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_encrypter_test.cc42
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_tls_decrypter_test.cc42
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_tls_encrypter_test.cc54
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_decrypter.cc12
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_decrypter.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_encrypter.cc12
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_encrypter.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/channel_id.cc13
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/channel_id.h14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/channel_id_test.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/common_cert_set.cc27
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/common_cert_set.h19
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/common_cert_set_test.cc24
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_framer.cc26
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_framer.h17
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_framer_test.cc57
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.cc26
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_message_parser.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_message_printer_bin.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h50
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer_test.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_server_test.cc119
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.cc205
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.h31
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils_test.cc23
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange.cc11
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange_test.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/key_exchange.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/key_exchange.h19
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/null_decrypter.cc30
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/null_decrypter.h23
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/null_decrypter_test.cc34
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/null_encrypter.cc23
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/null_encrypter.h21
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/null_encrypter_test.cc11
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/p256_key_exchange.cc15
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/p256_key_exchange.h9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/p256_key_exchange_test.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/proof_source.h14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/proof_verifier.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_compressed_certs_cache_test.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypter.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypter.h12
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.cc73
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h34
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config_test.cc66
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.cc145
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h35
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config_test.cc35
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_decrypter.cc18
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h16
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h13
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf.cc41
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf.h46
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf_test.cc15
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/server_proof_verifier.h42
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.cc57
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.h42
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.h12
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.cc645
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.h23
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters_test.cc489
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_blocked_frame.h10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_connection_close_frame.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_crypto_frame.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_crypto_frame.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.cc31
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_frames_test.cc14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_handshake_done_frame.cc25
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_handshake_done_frame.h33
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_max_streams_frame.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_message_frame.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_new_token_frame.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_new_token_frame.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_path_challenge_frame.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_path_response_frame.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_frame.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/handshaker_delegate_interface.h36
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/end_to_end_test.cc472
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_decoder.cc198
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_decoder.h62
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_decoder_test.cc604
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_encoder.cc168
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_encoder.h16
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_encoder_test.cc154
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_frames.h123
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_header_list.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_header_list.h14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream.cc15
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream_test.cc131
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.cc387
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.h50
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream_test.cc219
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream.cc96
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream.h23
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream_test.cc103
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.cc37
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.h11
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base_test.cc101
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.cc50
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.h14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_base.cc12
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_base.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_test.cc57
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream_test.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.cc428
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.h180
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session_test.cc777
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.cc311
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h48
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager.h10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager_test.cc13
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_test.cc636
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/spdy_server_push_utils.cc14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/spdy_server_push_utils.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/spdy_server_push_utils_test.cc10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.cc24
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/spdy_utils_test.cc50
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.cc62
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.h15
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager_test.cc196
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/packet_number_indexed_queue.h30
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/packet_number_indexed_queue_test.cc26
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_blocking_manager.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.cc13
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.h36
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator_test.cc61
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder.cc10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h13
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver_test.cc35
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender_test.cc49
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test.cc226
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder.cc21
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder.h17
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver.h15
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver_test.cc36
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.cc7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender_test.cc31
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test.cc165
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table.cc10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table.h9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table_test.cc20
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.cc20
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.h18
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder_test.cc34
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder_test.cc16
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instructions.cc14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h23
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_offline_decoder_bin.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.h13
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_receive_stream.cc11
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_receive_stream_test.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_required_insert_count_test.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_round_trip_test.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.cc24
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.h9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream_test.cc32
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_static_table.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_static_table_test.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_stream_receiver.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_stream_sender_delegate.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list.cc14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list_test.cc13
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_arena_scoped_ptr_test.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_bandwidth.cc14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_bandwidth.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_buffer_allocator.h24
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_circular_deque.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_circular_deque_test.cc28
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_clock.cc (renamed from chromium/net/third_party/quiche/src/quic/platform/api/quic_clock.cc)2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_clock.h (renamed from chromium/net/third_party/quiche/src/quic/platform/api/quic_clock.h)6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet.cc30
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet_test.cc14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_config.cc71
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_config.h55
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection.cc887
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection.h159
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_id.cc17
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_id.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_id_test.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_stats.h21
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_test.cc1318
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_constants.h14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.cc42
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.h11
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager_test.cc10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.cc176
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.h15
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker_test.cc35
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.cc25
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h60
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream_test.cc66
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_handshaker.cc480
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_handshaker.h237
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.cc449
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h344
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.cc51
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h92
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream_test.cc86
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.cc207
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.h45
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream_test.cc125
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_data_reader.cc208
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_data_reader.h131
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_data_writer.cc165
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_data_writer.h64
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_data_writer_test.cc199
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_datagram_queue.cc87
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_datagram_queue.h69
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_datagram_queue_test.cc169
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_default_packet_writer.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.cc128
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.h48
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_dispatcher_test.cc666
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_error_codes.cc30
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_error_codes.h84
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_flow_controller.cc11
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_flow_controller_test.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_framer.cc849
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_framer.h68
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_framer_test.cc1290
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector.cc109
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector.h103
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector_test.cc148
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_ietf_framer_test.cc1501
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_interval_deque.h391
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_interval_deque_test.cc360
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector.cc78
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector.h76
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector_test.cc121
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_one_block_arena.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_one_block_arena_test.cc10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.cc113
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.h21
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_creator_test.cc151
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_reader.cc254
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_reader.h63
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_writer.h30
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packets.cc44
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packets.h23
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packets_test.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager.cc20
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager_test.cc95
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.cc463
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h104
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager_test.cc1083
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_server_id.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_session.cc655
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_session.h187
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_session_test.cc489
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_socket_address_coder_test.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream.cc267
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream.h62
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.cc248
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.h95
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager_test.cc310
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.cc144
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.h11
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer_test.cc97
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer.cc84
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer.h21
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.cc54
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.h23
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer_test.cc52
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_test.cc90
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_test.cc346
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_tag.cc12
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_time.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.cc15
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor.cc7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor_test.cc18
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_types.cc183
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_types.h72
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_types_test.cc53
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_udp_socket.h248
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_udp_socket_posix.cc633
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_udp_socket_test.cc403
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.cc108
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.h27
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map_test.cc156
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_utils.cc84
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_utils.h89
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_utils_test.cc97
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_version_manager.cc55
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_version_manager.h22
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_version_manager_test.cc79
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_versions.cc354
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_versions.h249
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_versions_test.cc470
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/stream_delegate_interface.h54
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.cc146
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.h30
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_handshaker.cc72
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_handshaker.h51
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_handshaker_test.cc246
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.cc151
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.h66
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.cc75
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.h46
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager_test.cc322
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager.cc12
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/README.md4
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_client_bin.cc93
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_client_session.cc96
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_client_session.h99
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_client_tools.cc107
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_client_tools.h25
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_compression_engine.cc543
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_compression_engine.h126
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_dispatcher.cc86
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_dispatcher.h61
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_client_session.cc41
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_client_session.h58
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_epoll_client.cc125
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_epoll_client.h50
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.cc131
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.h57
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_epoll_server.cc31
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_epoll_server.h32
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_server_backend.cc139
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_server_backend.h68
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_server_bin.cc60
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_server_session.cc128
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_server_session.h77
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_utils.cc31
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_utils.h25
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_arraysize.h12
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_bbr2_sender.h16
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_cert_utils.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_containers.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_file_utils.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_file_utils.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_hostname_utils.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_hostname_utils.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_hostname_utils_test.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_logging.h40
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice.h14
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice_span.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_optional.h17
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_socket_address.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_str_cat.h28
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_str_cat_test.cc168
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_string_piece.h16
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_string_utils.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_string_utils_test.cc74
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_test.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_test_output.h31
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_text_utils.h126
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_text_utils_test.cc212
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_udp_socket_platform_api.h25
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable.cc17
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable_test.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/mock_packet_exchanger_stats_interface.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device.cc12
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger.cc25
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger.h13
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger_test.cc16
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_test.cc18
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/mock_qbone_client.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/mock_qbone_server_session.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/platform/icmp_packet.cc14
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/platform/icmp_packet.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/platform/icmp_packet_test.cc23
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/platform/ip_range.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/platform/ip_range.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/platform/mock_netlink.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/platform/netlink.cc48
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/platform/netlink.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/platform/netlink_interface.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/platform/netlink_test.cc13
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/platform/rtnetlink_message.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/platform/rtnetlink_message_test.cc19
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/platform/tcp_packet.cc7
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/platform/tcp_packet.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/platform/tcp_packet_test.cc24
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_client.cc13
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_client.h10
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_client_interface.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_client_session.cc17
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_client_session.h18
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_client_test.cc60
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_constants.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.cc15
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.h9
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_exchanger.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_exchanger.h10
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_exchanger_test.cc41
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor.cc59
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor.h34
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor_test.cc51
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor_test_tools.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor_test_tools.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_server_session.cc27
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_server_session.h18
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_session_base.cc26
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_session_base.h15
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_session_test.cc125
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_stream.cc20
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_stream.h9
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_stream_test.cc25
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_connection_helper.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.cc17
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.h22
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_dispatcher.cc11
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_dispatcher.h15
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint.h10
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint_test.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_factory.cc20
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_factory.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_fakes.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_multiplexer.cc10
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_multiplexer.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_multiplexer_test.cc29
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_session.cc44
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_session.h19
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_session_test.cc70
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_stream.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_stream.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_stream_test.cc75
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/simulated_packet_transport.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.cc61
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.h27
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session_test.cc18
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_integration_test.cc115
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_protocol.h20
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.cc68
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.h31
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session_test.cc93
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.cc63
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream_test.cc34
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.cc180
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h16
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils_test.cc56
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/failing_proof_source.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/failing_proof_source.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source.cc7
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/mock_clock.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_dispatcher.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_dispatcher.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_session_visitor.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/packet_dropping_test_writer.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/packet_dropping_test_writer.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_decoder_test_utils.cc11
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_decoder_test_utils.h28
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_test_utils.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_test_utils.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_offline_decoder.cc58
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_offline_decoder.h21
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_buffered_packet_store_peer.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.cc29
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.h15
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.cc39
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h15
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_crypto_server_config_peer.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_crypto_server_config_peer.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_framer_peer.cc256
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_framer_peer.h122
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_interval_deque_peer.h35
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.cc21
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.h9
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_server_session_base_peer.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.cc14
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_stream_peer.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_send_buffer_peer.cc23
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_send_buffer_peer.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.cc83
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.h14
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_server.cc19
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_server.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.cc218
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.h202
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_transport_test_tools.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/send_algorithm_test_result.proto15
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/send_algorithm_test_utils.cc62
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/send_algorithm_test_utils.h29
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/server_thread.cc23
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/server_thread.h10
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simple_data_producer.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simple_data_producer.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simple_quic_framer.cc17
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/actor.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/alarm_factory.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/link.cc12
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/link.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.cc7
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint_base.cc12
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/simulator.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/simulator.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/switch.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/switch.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/traffic_policer.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/fake_proof_verifier.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_backend_response.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client.cc22
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client_base.cc20
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client_base.h25
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client_epoll_network_helper.cc31
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client_interop_test_bin.cc240
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client_test.cc10
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_epoll_client_factory.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.cc151
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.h87
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend_test.cc45
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_packet_printer_bin.cc19
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_reject_reason_decoder_bin.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_server.cc22
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_server.h9
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_server_test.cc14
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_crypto_server_stream_helper.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session.cc16
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session_test.cc231
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream.cc22
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream_test.cc113
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.cc39
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.h20
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.cc73
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_toy_server.cc26
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.cc19
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.h14
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.cc35
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_url.cc14
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_url.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_url_test.cc1
639 files changed, 28805 insertions, 17401 deletions
diff --git a/chromium/net/third_party/quiche/src/quic/core/chlo_extractor.cc b/chromium/net/third_party/quiche/src/quic/core/chlo_extractor.cc
index 0430f8daf1d..b4907d4a020 100644
--- a/chromium/net/third_party/quiche/src/quic/core/chlo_extractor.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/chlo_extractor.cc
@@ -13,8 +13,8 @@
#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
#include "net/third_party/quiche/src/quic/core/quic_framer.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
@@ -38,7 +38,10 @@ class ChloFramerVisitor : public QuicFramerVisitorInterface,
const QuicVersionNegotiationPacket& /*packet*/) override {}
void OnRetryPacket(QuicConnectionId /*original_connection_id*/,
QuicConnectionId /*new_connection_id*/,
- QuicStringPiece /*retry_token*/) override {}
+ quiche::QuicheStringPiece /*retry_token*/,
+ quiche::QuicheStringPiece /*retry_integrity_tag*/,
+ quiche::QuicheStringPiece /*retry_without_tag*/) override {
+ }
bool OnUnauthenticatedPublicHeader(const QuicPacketHeader& header) override;
bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override;
void OnDecryptedPacket(EncryptionLevel /*level*/) override {}
@@ -73,6 +76,7 @@ class ChloFramerVisitor : public QuicFramerVisitorInterface,
bool OnBlockedFrame(const QuicBlockedFrame& frame) override;
bool OnPaddingFrame(const QuicPaddingFrame& frame) override;
bool OnMessageFrame(const QuicMessageFrame& frame) override;
+ bool OnHandshakeDoneFrame(const QuicHandshakeDoneFrame& frame) override;
void OnPacketComplete() override {}
bool IsValidStatelessResetToken(QuicUint128 token) const override;
void OnAuthenticatedIetfStatelessResetPacket(
@@ -83,7 +87,7 @@ class ChloFramerVisitor : public QuicFramerVisitorInterface,
void OnHandshakeMessage(const CryptoHandshakeMessage& message) override;
// Shared implementation between OnStreamFrame and OnCryptoFrame.
- bool OnHandshakeData(QuicStringPiece data);
+ bool OnHandshakeData(quiche::QuicheStringPiece data);
bool found_chlo() { return found_chlo_; }
bool chlo_contains_tags() { return chlo_contains_tags_; }
@@ -147,10 +151,10 @@ bool ChloFramerVisitor::OnStreamFrame(const QuicStreamFrame& frame) {
// CHLO will be sent in CRYPTO frames in v47 and above.
return false;
}
- QuicStringPiece data(frame.data_buffer, frame.data_length);
+ quiche::QuicheStringPiece data(frame.data_buffer, frame.data_length);
if (QuicUtils::IsCryptoStreamId(framer_->transport_version(),
frame.stream_id) &&
- frame.offset == 0 && QuicTextUtils::StartsWith(data, "CHLO")) {
+ frame.offset == 0 && quiche::QuicheTextUtils::StartsWith(data, "CHLO")) {
return OnHandshakeData(data);
}
return true;
@@ -161,14 +165,14 @@ bool ChloFramerVisitor::OnCryptoFrame(const QuicCryptoFrame& frame) {
// CHLO will be in stream frames before v47.
return false;
}
- QuicStringPiece data(frame.data_buffer, frame.data_length);
- if (frame.offset == 0 && QuicTextUtils::StartsWith(data, "CHLO")) {
+ quiche::QuicheStringPiece data(frame.data_buffer, frame.data_length);
+ if (frame.offset == 0 && quiche::QuicheTextUtils::StartsWith(data, "CHLO")) {
return OnHandshakeData(data);
}
return true;
}
-bool ChloFramerVisitor::OnHandshakeData(QuicStringPiece data) {
+bool ChloFramerVisitor::OnHandshakeData(quiche::QuicheStringPiece data) {
CryptoFramer crypto_framer;
crypto_framer.set_visitor(this);
if (!crypto_framer.ProcessInput(data)) {
@@ -280,6 +284,11 @@ bool ChloFramerVisitor::OnMessageFrame(const QuicMessageFrame& /*frame*/) {
return true;
}
+bool ChloFramerVisitor::OnHandshakeDoneFrame(
+ const QuicHandshakeDoneFrame& /*frame*/) {
+ return true;
+}
+
bool ChloFramerVisitor::IsValidStatelessResetToken(
QuicUint128 /*token*/) const {
return false;
diff --git a/chromium/net/third_party/quiche/src/quic/core/chlo_extractor_test.cc b/chromium/net/third_party/quiche/src/quic/core/chlo_extractor_test.cc
index aab0f65da3c..e293902faad 100644
--- a/chromium/net/third_party/quiche/src/quic/core/chlo_extractor_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/chlo_extractor_test.cc
@@ -10,10 +10,11 @@
#include "net/third_party/quiche/src/quic/core/quic_framer.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
@@ -60,7 +61,7 @@ class ChloExtractorTest : public QuicTest {
}
void MakePacket(ParsedQuicVersion version,
- QuicStringPiece data,
+ quiche::QuicheStringPiece data,
bool munge_offset,
bool munge_stream_id) {
QuicFrames frames;
@@ -89,7 +90,7 @@ class ChloExtractorTest : public QuicTest {
EXPECT_TRUE(packet != nullptr);
size_t encrypted_length =
framer.EncryptPayload(ENCRYPTION_INITIAL, header_.packet_number,
- *packet, buffer_, QUIC_ARRAYSIZE(buffer_));
+ *packet, buffer_, QUICHE_ARRAYSIZE(buffer_));
ASSERT_NE(0u, encrypted_length);
packet_ = std::make_unique<QuicEncryptedPacket>(buffer_, encrypted_length);
EXPECT_TRUE(packet_ != nullptr);
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.cc
index cc90cb00539..c929e8b55cc 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.cc
@@ -14,6 +14,15 @@
namespace quic {
+std::ostream& operator<<(std::ostream& os, const SendTimeState& s) {
+ os << "{valid:" << s.is_valid << ", app_limited:" << s.is_app_limited
+ << ", total_sent:" << s.total_bytes_sent
+ << ", total_acked:" << s.total_bytes_acked
+ << ", total_lost:" << s.total_bytes_lost
+ << ", inflight:" << s.bytes_in_flight << "}";
+ return os;
+}
+
QuicByteCount MaxAckHeightTracker::Update(QuicBandwidth bandwidth_estimate,
QuicRoundTripCount round_trip_count,
QuicTime ack_time,
@@ -32,8 +41,19 @@ QuicByteCount MaxAckHeightTracker::Update(QuicBandwidth bandwidth_estimate,
// Reset the current aggregation epoch as soon as the ack arrival rate is less
// than or equal to the max bandwidth.
if (aggregation_epoch_bytes_ <=
- GetQuicFlag(FLAGS_quic_ack_aggregation_bandwidth_threshold) *
- expected_bytes_acked) {
+ ack_aggregation_bandwidth_threshold_ * expected_bytes_acked) {
+ QUIC_DVLOG(3) << "Starting a new aggregation epoch because "
+ "aggregation_epoch_bytes_ "
+ << aggregation_epoch_bytes_
+ << " is smaller than expected. "
+ "ack_aggregation_bandwidth_threshold_:"
+ << ack_aggregation_bandwidth_threshold_
+ << ", expected_bytes_acked:" << expected_bytes_acked
+ << ", bandwidth_estimate:" << bandwidth_estimate
+ << ", aggregation_duration:"
+ << (ack_time - aggregation_epoch_start_time_)
+ << ", new_aggregation_epoch:" << ack_time
+ << ", new_aggregation_bytes_acked:" << bytes_acked;
// Reset to start measuring a new aggregation epoch.
aggregation_epoch_bytes_ = bytes_acked;
aggregation_epoch_start_time_ = ack_time;
@@ -46,6 +66,13 @@ QuicByteCount MaxAckHeightTracker::Update(QuicBandwidth bandwidth_estimate,
// Compute how many extra bytes were delivered vs max bandwidth.
QuicByteCount extra_bytes_acked =
aggregation_epoch_bytes_ - expected_bytes_acked;
+ QUIC_DVLOG(3) << "Updating MaxAckHeight. ack_time:" << ack_time
+ << ", round trip count:" << round_trip_count
+ << ", bandwidth_estimate:" << bandwidth_estimate
+ << ", bytes_acked:" << bytes_acked
+ << ", expected_bytes_acked:" << expected_bytes_acked
+ << ", aggregation_epoch_bytes_:" << aggregation_epoch_bytes_
+ << ", extra_bytes_acked:" << extra_bytes_acked;
max_ack_height_filter_.Update(extra_bytes_acked, round_trip_count);
return extra_bytes_acked;
}
@@ -56,15 +83,51 @@ BandwidthSampler::BandwidthSampler(
: total_bytes_sent_(0),
total_bytes_acked_(0),
total_bytes_lost_(0),
+ total_bytes_neutered_(0),
total_bytes_sent_at_last_acked_packet_(0),
last_acked_packet_sent_time_(QuicTime::Zero()),
last_acked_packet_ack_time_(QuicTime::Zero()),
- is_app_limited_(false),
+ is_app_limited_(started_as_app_limited_),
connection_state_map_(),
max_tracked_packets_(GetQuicFlag(FLAGS_quic_max_tracked_packet_count)),
unacked_packet_map_(unacked_packet_map),
max_ack_height_tracker_(max_height_tracker_window_length),
- total_bytes_acked_after_last_ack_event_(0) {}
+ total_bytes_acked_after_last_ack_event_(0),
+ overestimate_avoidance_(false) {}
+
+BandwidthSampler::BandwidthSampler(const BandwidthSampler& other)
+ : total_bytes_sent_(other.total_bytes_sent_),
+ total_bytes_acked_(other.total_bytes_acked_),
+ total_bytes_lost_(other.total_bytes_lost_),
+ total_bytes_neutered_(other.total_bytes_neutered_),
+ total_bytes_sent_at_last_acked_packet_(
+ other.total_bytes_sent_at_last_acked_packet_),
+ last_acked_packet_sent_time_(other.last_acked_packet_sent_time_),
+ last_acked_packet_ack_time_(other.last_acked_packet_ack_time_),
+ last_sent_packet_(other.last_sent_packet_),
+ started_as_app_limited_(other.started_as_app_limited_),
+ is_app_limited_(other.is_app_limited_),
+ end_of_app_limited_phase_(other.end_of_app_limited_phase_),
+ connection_state_map_(other.connection_state_map_),
+ recent_ack_points_(other.recent_ack_points_),
+ a0_candidates_(other.a0_candidates_),
+ max_tracked_packets_(other.max_tracked_packets_),
+ unacked_packet_map_(other.unacked_packet_map_),
+ max_ack_height_tracker_(other.max_ack_height_tracker_),
+ total_bytes_acked_after_last_ack_event_(
+ other.total_bytes_acked_after_last_ack_event_),
+ overestimate_avoidance_(other.overestimate_avoidance_) {}
+
+void BandwidthSampler::EnableOverestimateAvoidance() {
+ if (overestimate_avoidance_) {
+ return;
+ }
+
+ overestimate_avoidance_ = true;
+ // TODO(wub): Change the default value of
+ // --quic_ack_aggregation_bandwidth_threshold to 2.0.
+ max_ack_height_tracker_.SetAckAggregationBandwidthThreshold(2.0);
+}
BandwidthSampler::~BandwidthSampler() {}
@@ -90,6 +153,12 @@ void BandwidthSampler::OnPacketSent(
// importantly at the beginning of the connection.
if (bytes_in_flight == 0) {
last_acked_packet_ack_time_ = sent_time;
+ if (overestimate_avoidance_) {
+ recent_ack_points_.Clear();
+ recent_ack_points_.Update(sent_time, total_bytes_acked_);
+ a0_candidates_.clear();
+ a0_candidates_.push_back(recent_ack_points_.MostRecentPoint());
+ }
total_bytes_sent_at_last_acked_packet_ = total_bytes_sent_;
// In this situation ack compression is not a concern, set send rate to
@@ -115,13 +184,92 @@ void BandwidthSampler::OnPacketSent(
}
}
- bool success =
- connection_state_map_.Emplace(packet_number, sent_time, bytes, *this);
+ bool success = connection_state_map_.Emplace(packet_number, sent_time, bytes,
+ bytes_in_flight + bytes, *this);
QUIC_BUG_IF(!success) << "BandwidthSampler failed to insert the packet "
"into the map, most likely because it's already "
"in it.";
}
+void BandwidthSampler::OnPacketNeutered(QuicPacketNumber packet_number) {
+ connection_state_map_.Remove(
+ packet_number, [&](const ConnectionStateOnSentPacket& sent_packet) {
+ QUIC_CODE_COUNT(quic_bandwidth_sampler_packet_neutered);
+ total_bytes_neutered_ += sent_packet.size;
+ });
+}
+
+BandwidthSamplerInterface::CongestionEventSample
+BandwidthSampler::OnCongestionEvent(QuicTime ack_time,
+ const AckedPacketVector& acked_packets,
+ const LostPacketVector& lost_packets,
+ QuicBandwidth max_bandwidth,
+ QuicBandwidth est_bandwidth_upper_bound,
+ QuicRoundTripCount round_trip_count) {
+ CongestionEventSample event_sample;
+
+ SendTimeState last_lost_packet_send_state;
+
+ for (const LostPacket& packet : lost_packets) {
+ SendTimeState send_state =
+ OnPacketLost(packet.packet_number, packet.bytes_lost);
+ if (send_state.is_valid) {
+ last_lost_packet_send_state = send_state;
+ }
+ }
+
+ if (acked_packets.empty()) {
+ // Only populate send state for a loss-only event.
+ event_sample.last_packet_send_state = last_lost_packet_send_state;
+ return event_sample;
+ }
+
+ SendTimeState last_acked_packet_send_state;
+ for (const auto& packet : acked_packets) {
+ BandwidthSample sample =
+ OnPacketAcknowledged(ack_time, packet.packet_number);
+ if (!sample.state_at_send.is_valid) {
+ continue;
+ }
+
+ last_acked_packet_send_state = sample.state_at_send;
+
+ if (!sample.rtt.IsZero()) {
+ event_sample.sample_rtt = std::min(event_sample.sample_rtt, sample.rtt);
+ }
+ if (sample.bandwidth > event_sample.sample_max_bandwidth) {
+ event_sample.sample_max_bandwidth = sample.bandwidth;
+ event_sample.sample_is_app_limited = sample.state_at_send.is_app_limited;
+ }
+ const QuicByteCount inflight_sample =
+ total_bytes_acked() - last_acked_packet_send_state.total_bytes_acked;
+ if (inflight_sample > event_sample.sample_max_inflight) {
+ event_sample.sample_max_inflight = inflight_sample;
+ }
+ }
+
+ if (!last_lost_packet_send_state.is_valid) {
+ event_sample.last_packet_send_state = last_acked_packet_send_state;
+ } else if (!last_acked_packet_send_state.is_valid) {
+ event_sample.last_packet_send_state = last_lost_packet_send_state;
+ } else {
+ // If two packets are inflight and an alarm is armed to lose a packet and it
+ // wakes up late, then the first of two in flight packets could have been
+ // acknowledged before the wakeup, which re-evaluates loss detection, and
+ // could declare the later of the two lost.
+ event_sample.last_packet_send_state =
+ lost_packets.back().packet_number > acked_packets.back().packet_number
+ ? last_lost_packet_send_state
+ : last_acked_packet_send_state;
+ }
+
+ max_bandwidth = std::max(max_bandwidth, event_sample.sample_max_bandwidth);
+ event_sample.extra_acked = OnAckEventEnd(
+ std::min(est_bandwidth_upper_bound, max_bandwidth), round_trip_count);
+
+ return event_sample;
+}
+
QuicByteCount BandwidthSampler::OnAckEventEnd(
QuicBandwidth bandwidth_estimate,
QuicRoundTripCount round_trip_count) {
@@ -133,9 +281,17 @@ QuicByteCount BandwidthSampler::OnAckEventEnd(
}
total_bytes_acked_after_last_ack_event_ = total_bytes_acked_;
- return max_ack_height_tracker_.Update(bandwidth_estimate, round_trip_count,
- last_acked_packet_ack_time_,
- newly_acked_bytes);
+ QuicByteCount extra_acked = max_ack_height_tracker_.Update(
+ bandwidth_estimate, round_trip_count, last_acked_packet_ack_time_,
+ newly_acked_bytes);
+ // If |extra_acked| is zero, i.e. this ack event marks the start of a new ack
+ // aggregation epoch, save LessRecentPoint, which is the last ack point of the
+ // previous epoch, as a A0 candidate.
+ if (overestimate_avoidance_ && extra_acked == 0) {
+ a0_candidates_.push_back(recent_ack_points_.LessRecentPoint());
+ QUIC_DVLOG(1) << "New a0_candidate:" << a0_candidates_.back();
+ }
+ return extra_acked;
}
BandwidthSample BandwidthSampler::OnPacketAcknowledged(
@@ -149,7 +305,6 @@ BandwidthSample BandwidthSampler::OnPacketAcknowledged(
}
BandwidthSample sample =
OnPacketAcknowledgedInner(ack_time, packet_number, *sent_packet_pointer);
- connection_state_map_.Remove(packet_number);
return sample;
}
@@ -162,18 +317,37 @@ BandwidthSample BandwidthSampler::OnPacketAcknowledgedInner(
sent_packet.send_time_state.total_bytes_sent;
last_acked_packet_sent_time_ = sent_packet.sent_time;
last_acked_packet_ack_time_ = ack_time;
+ if (overestimate_avoidance_) {
+ recent_ack_points_.Update(ack_time, total_bytes_acked_);
+ }
- // Exit app-limited phase once a packet that was sent while the connection is
- // not app-limited is acknowledged.
- if (is_app_limited_ && end_of_app_limited_phase_.IsInitialized() &&
- packet_number > end_of_app_limited_phase_) {
- is_app_limited_ = false;
+ if (started_as_app_limited_) {
+ if (is_app_limited_) {
+ // Exit app-limited phase in two cases:
+ // (1) end_of_app_limited_phase_ is not initialized, i.e., so far all
+ // packets are sent while there are buffered packets or pending data.
+ // (2) The current acked packet is after the sent packet marked as the end
+ // of the app limit phase.
+ if (!end_of_app_limited_phase_.IsInitialized() ||
+ packet_number > end_of_app_limited_phase_) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_bw_sampler_app_limited_starting_value);
+ is_app_limited_ = false;
+ }
+ }
+ } else {
+ // Exit app-limited phase once a packet that was sent while the connection
+ // is not app-limited is acknowledged.
+ if (is_app_limited_ && end_of_app_limited_phase_.IsInitialized() &&
+ packet_number > end_of_app_limited_phase_) {
+ is_app_limited_ = false;
+ }
}
// There might have been no packets acknowledged at the moment when the
// current packet was sent. In that case, there is no bandwidth sample to
// make.
if (sent_packet.last_acked_packet_sent_time == QuicTime::Zero()) {
+ QUIC_BUG << "sent_packet.last_acked_packet_sent_time is zero";
return BandwidthSample();
}
@@ -187,28 +361,39 @@ BandwidthSample BandwidthSampler::OnPacketAcknowledgedInner(
sent_packet.sent_time - sent_packet.last_acked_packet_sent_time);
}
+ AckPoint a0;
+ if (overestimate_avoidance_ &&
+ ChooseA0Point(sent_packet.send_time_state.total_bytes_acked, &a0)) {
+ QUIC_DVLOG(2) << "Using a0 point: " << a0;
+ } else {
+ a0.ack_time = sent_packet.last_acked_packet_ack_time,
+ a0.total_bytes_acked = sent_packet.send_time_state.total_bytes_acked;
+ }
+
// During the slope calculation, ensure that ack time of the current packet is
// always larger than the time of the previous packet, otherwise division by
// zero or integer underflow can occur.
- if (ack_time <= sent_packet.last_acked_packet_ack_time) {
+ if (ack_time <= a0.ack_time) {
// TODO(wub): Compare this code count before and after fixing clock jitter
// issue.
- if (sent_packet.last_acked_packet_ack_time == sent_packet.sent_time) {
+ if (a0.ack_time == sent_packet.sent_time) {
// This is the 1st packet after quiescense.
QUIC_CODE_COUNT_N(quic_prev_ack_time_larger_than_current_ack_time, 1, 2);
} else {
QUIC_CODE_COUNT_N(quic_prev_ack_time_larger_than_current_ack_time, 2, 2);
}
- QUIC_LOG_EVERY_N_SEC(ERROR, 60)
- << "Time of the previously acked packet:"
- << sent_packet.last_acked_packet_ack_time.ToDebuggingValue()
- << " is larger than the ack time of the current packet:"
- << ack_time.ToDebuggingValue();
+ QUIC_BUG << "Time of the previously acked packet:"
+ << a0.ack_time.ToDebuggingValue()
+ << " is larger than the ack time of the current packet:"
+ << ack_time.ToDebuggingValue()
+ << ". acked packet number:" << packet_number
+ << ", total_bytes_acked_:" << total_bytes_acked_
+ << ", overestimate_avoidance_:" << overestimate_avoidance_
+ << ", sent_packet:" << sent_packet;
return BandwidthSample();
}
QuicBandwidth ack_rate = QuicBandwidth::FromBytesAndTimeDelta(
- total_bytes_acked_ - sent_packet.send_time_state.total_bytes_acked,
- ack_time - sent_packet.last_acked_packet_ack_time);
+ total_bytes_acked_ - a0.total_bytes_acked, ack_time - a0.ack_time);
BandwidthSample sample;
sample.bandwidth = std::min(send_rate, ack_rate);
@@ -217,19 +402,60 @@ BandwidthSample BandwidthSampler::OnPacketAcknowledgedInner(
// on low bandwidth connections.
sample.rtt = ack_time - sent_packet.sent_time;
SentPacketToSendTimeState(sent_packet, &sample.state_at_send);
+
+ QUIC_BUG_IF(sample.bandwidth.IsZero())
+ << "ack_rate: " << ack_rate << ", send_rate: " << send_rate
+ << ". acked packet number:" << packet_number
+ << ", overestimate_avoidance_:" << overestimate_avoidance_ << "a1:{"
+ << total_bytes_acked_ << "@" << ack_time << "}, a0:{"
+ << a0.total_bytes_acked << "@" << a0.ack_time
+ << "}, sent_packet:" << sent_packet;
return sample;
}
-SendTimeState BandwidthSampler::OnPacketLost(QuicPacketNumber packet_number) {
+bool BandwidthSampler::ChooseA0Point(QuicByteCount total_bytes_acked,
+ AckPoint* a0) {
+ if (a0_candidates_.empty()) {
+ QUIC_BUG << "No A0 point candicates. total_bytes_acked:"
+ << total_bytes_acked;
+ return false;
+ }
+
+ if (a0_candidates_.size() == 1) {
+ *a0 = a0_candidates_.front();
+ return true;
+ }
+
+ for (size_t i = 1; i < a0_candidates_.size(); ++i) {
+ if (a0_candidates_[i].total_bytes_acked > total_bytes_acked) {
+ *a0 = a0_candidates_[i - 1];
+ if (i > 1) {
+ a0_candidates_.pop_front_n(i - 1);
+ }
+ return true;
+ }
+ }
+
+ // All candidates' total_bytes_acked is <= |total_bytes_acked|.
+ *a0 = a0_candidates_.back();
+ a0_candidates_.pop_front_n(a0_candidates_.size() - 1);
+ return true;
+}
+
+SendTimeState BandwidthSampler::OnPacketLost(QuicPacketNumber packet_number,
+ QuicPacketLength bytes_lost) {
// TODO(vasilvv): see the comment for the case of missing packets in
// BandwidthSampler::OnPacketAcknowledged on why this does not raise a
// QUIC_BUG when removal fails.
SendTimeState send_time_state;
- send_time_state.is_valid = connection_state_map_.Remove(
- packet_number, [&](const ConnectionStateOnSentPacket& sent_packet) {
- total_bytes_lost_ += sent_packet.size;
- SentPacketToSendTimeState(sent_packet, &send_time_state);
- });
+
+ total_bytes_lost_ += bytes_lost;
+ ConnectionStateOnSentPacket* sent_packet_pointer =
+ connection_state_map_.GetEntry(packet_number);
+ if (sent_packet_pointer != nullptr) {
+ SentPacketToSendTimeState(*sent_packet_pointer, &send_time_state);
+ }
+
return send_time_state;
}
@@ -251,16 +477,7 @@ void BandwidthSampler::RemoveObsoletePackets(QuicPacketNumber least_unacked) {
// QuicSentPacketManager::RetransmitCryptoPackets retransmits a crypto packet,
// the packet is removed from QuicUnackedPacketMap's inflight, but is not
// marked as acked or lost in the BandwidthSampler.
- while (!connection_state_map_.IsEmpty() &&
- connection_state_map_.first_packet() < least_unacked) {
- connection_state_map_.Remove(
- connection_state_map_.first_packet(),
- [&](const ConnectionStateOnSentPacket& sent_packet) {
- // Obsoleted packets as either acked or lost but the sampler doesn't
- // know. We count them as acked here, since most packets are acked.
- total_bytes_acked_ += sent_packet.size;
- });
- }
+ connection_state_map_.RemoveUpTo(least_unacked);
}
QuicByteCount BandwidthSampler::total_bytes_sent() const {
@@ -275,6 +492,10 @@ QuicByteCount BandwidthSampler::total_bytes_lost() const {
return total_bytes_lost_;
}
+QuicByteCount BandwidthSampler::total_bytes_neutered() const {
+ return total_bytes_neutered_;
+}
+
bool BandwidthSampler::is_app_limited() const {
return is_app_limited_;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.h
index 51f5e870819..b3c07364705 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.h
@@ -9,11 +9,13 @@
#include "net/third_party/quiche/src/quic/core/congestion_control/windowed_filter.h"
#include "net/third_party/quiche/src/quic/core/packet_number_indexed_queue.h"
#include "net/third_party/quiche/src/quic/core/quic_bandwidth.h"
+#include "net/third_party/quiche/src/quic/core/quic_circular_deque.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_unacked_packet_map.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
namespace quic {
@@ -29,20 +31,26 @@ struct QUIC_EXPORT_PRIVATE SendTimeState {
is_app_limited(false),
total_bytes_sent(0),
total_bytes_acked(0),
- total_bytes_lost(0) {}
+ total_bytes_lost(0),
+ bytes_in_flight(0) {}
SendTimeState(bool is_app_limited,
QuicByteCount total_bytes_sent,
QuicByteCount total_bytes_acked,
- QuicByteCount total_bytes_lost)
+ QuicByteCount total_bytes_lost,
+ QuicByteCount bytes_in_flight)
: is_valid(true),
is_app_limited(is_app_limited),
total_bytes_sent(total_bytes_sent),
total_bytes_acked(total_bytes_acked),
- total_bytes_lost(total_bytes_lost) {}
+ total_bytes_lost(total_bytes_lost),
+ bytes_in_flight(bytes_in_flight) {}
SendTimeState(const SendTimeState& other) = default;
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
+ const SendTimeState& s);
+
// Whether other states in this object is valid.
bool is_valid;
@@ -60,6 +68,12 @@ struct QUIC_EXPORT_PRIVATE SendTimeState {
// Total number of lost bytes at the time the packet was sent.
QuicByteCount total_bytes_lost;
+
+ // Total number of inflight bytes at the time the packet was sent.
+ // Includes the packet itself.
+ // It should be equal to |total_bytes_sent| minus the sum of
+ // |total_bytes_acked|, |total_bytes_lost| and total neutered bytes.
+ QuicByteCount bytes_in_flight;
};
struct QUIC_EXPORT_PRIVATE BandwidthSample {
@@ -100,6 +114,14 @@ class QUIC_EXPORT_PRIVATE MaxAckHeightTracker {
max_ack_height_filter_.Reset(new_height, new_time);
}
+ void SetAckAggregationBandwidthThreshold(double threshold) {
+ ack_aggregation_bandwidth_threshold_ = threshold;
+ }
+
+ double ack_aggregation_bandwidth_threshold() const {
+ return ack_aggregation_bandwidth_threshold_;
+ }
+
uint64_t num_ack_aggregation_epochs() const {
return num_ack_aggregation_epochs_;
}
@@ -120,6 +142,8 @@ class QUIC_EXPORT_PRIVATE MaxAckHeightTracker {
// The number of ack aggregation epochs ever started, including the ongoing
// one. Stats only.
uint64_t num_ack_aggregation_epochs_ = 0;
+ double ack_aggregation_bandwidth_threshold_ =
+ GetQuicFlag(FLAGS_quic_ack_aggregation_bandwidth_threshold);
};
// An interface common to any class that can provide bandwidth samples from the
@@ -139,16 +163,42 @@ class QUIC_EXPORT_PRIVATE BandwidthSamplerInterface {
QuicByteCount bytes_in_flight,
HasRetransmittableData has_retransmittable_data) = 0;
- // Notifies the sampler that the |packet_number| is acknowledged. Returns a
- // bandwidth sample. If no bandwidth sample is available,
- // QuicBandwidth::Zero() is returned.
- virtual BandwidthSample OnPacketAcknowledged(
+ virtual void OnPacketNeutered(QuicPacketNumber packet_number) = 0;
+
+ struct QUIC_NO_EXPORT CongestionEventSample {
+ // The maximum bandwidth sample from all acked packets.
+ // QuicBandwidth::Zero() if no samples are available.
+ QuicBandwidth sample_max_bandwidth = QuicBandwidth::Zero();
+ // Whether |sample_max_bandwidth| is from a app-limited sample.
+ bool sample_is_app_limited = false;
+ // The minimum rtt sample from all acked packets.
+ // QuicTime::Delta::Infinite() if no samples are available.
+ QuicTime::Delta sample_rtt = QuicTime::Delta::Infinite();
+ // For each packet p in acked packets, this is the max value of INFLIGHT(p),
+ // where INFLIGHT(p) is the number of bytes acked while p is inflight.
+ QuicByteCount sample_max_inflight = 0;
+ // The send state of the largest packet in acked_packets, unless it is
+ // empty. If acked_packets is empty, it's the send state of the largest
+ // packet in lost_packets.
+ SendTimeState last_packet_send_state;
+ // The number of extra bytes acked from this ack event, compared to what is
+ // expected from the flow's bandwidth. Larger value means more ack
+ // aggregation.
+ QuicByteCount extra_acked = 0;
+ };
+ // Notifies the sampler that at |ack_time|, all packets in |acked_packets|
+ // have been acked, and all packets in |lost_packets| have been lost.
+ // See the comments in CongestionEventSample for the return value.
+ // |max_bandwidth| is the windowed maximum observed bandwidth.
+ // |est_bandwidth_upper_bound| is an upper bound of estimated bandwidth used
+ // to calculate extra_acked.
+ virtual CongestionEventSample OnCongestionEvent(
QuicTime ack_time,
- QuicPacketNumber packet_number) = 0;
-
- // Informs the sampler that a packet is considered lost and it should no
- // longer keep track of it.
- virtual SendTimeState OnPacketLost(QuicPacketNumber packet_number) = 0;
+ const AckedPacketVector& acked_packets,
+ const LostPacketVector& lost_packets,
+ QuicBandwidth max_bandwidth,
+ QuicBandwidth est_bandwidth_upper_bound,
+ QuicRoundTripCount round_trip_count) = 0;
// Informs the sampler that the connection is currently app-limited, causing
// the sampler to enter the app-limited phase. The phase will expire by
@@ -158,10 +208,11 @@ class QUIC_EXPORT_PRIVATE BandwidthSamplerInterface {
// Remove all the packets lower than the specified packet number.
virtual void RemoveObsoletePackets(QuicPacketNumber least_unacked) = 0;
- // Total number of bytes sent/acked/lost in the connection.
+ // Total number of bytes sent/acked/lost/neutered in the connection.
virtual QuicByteCount total_bytes_sent() const = 0;
virtual QuicByteCount total_bytes_acked() const = 0;
virtual QuicByteCount total_bytes_lost() const = 0;
+ virtual QuicByteCount total_bytes_neutered() const = 0;
// Application-limited information exported for debugging.
virtual bool is_app_limited() const = 0;
@@ -194,8 +245,8 @@ class QUIC_EXPORT_PRIVATE BandwidthSamplerInterface {
// For that purpose, BandwidthSampler always keeps track of the most recently
// acknowledged packet, and records it together with every outgoing packet.
// When a packet gets acknowledged (A_1), it has not only information about when
-// it itself was sent (S_1), but also the information about the latest
-// acknowledged packet right before it was sent (S_0 and A_0).
+// it itself was sent (S_1), but also the information about a previously
+// acknowledged packet before it was sent (S_0 and A_0).
//
// Based on that data, send and ack rate are estimated as:
// send_rate = (bytes(S_1) - bytes(S_0)) / (time(S_1) - time(S_0))
@@ -253,6 +304,10 @@ class QUIC_EXPORT_PRIVATE BandwidthSampler : public BandwidthSamplerInterface {
public:
BandwidthSampler(const QuicUnackedPacketMap* unacked_packet_map,
QuicRoundTripCount max_height_tracker_window_length);
+
+ // Copy states from |other|. This is useful when changing send algorithms in
+ // the middle of a connection.
+ BandwidthSampler(const BandwidthSampler& other);
~BandwidthSampler() override;
void OnPacketSent(QuicTime sent_time,
@@ -260,11 +315,17 @@ class QUIC_EXPORT_PRIVATE BandwidthSampler : public BandwidthSamplerInterface {
QuicByteCount bytes,
QuicByteCount bytes_in_flight,
HasRetransmittableData has_retransmittable_data) override;
- BandwidthSample OnPacketAcknowledged(QuicTime ack_time,
- QuicPacketNumber packet_number) override;
+ void OnPacketNeutered(QuicPacketNumber packet_number) override;
+
+ CongestionEventSample OnCongestionEvent(
+ QuicTime ack_time,
+ const AckedPacketVector& acked_packets,
+ const LostPacketVector& lost_packets,
+ QuicBandwidth max_bandwidth,
+ QuicBandwidth est_bandwidth_upper_bound,
+ QuicRoundTripCount round_trip_count) override;
QuicByteCount OnAckEventEnd(QuicBandwidth bandwidth_estimate,
QuicRoundTripCount round_trip_count);
- SendTimeState OnPacketLost(QuicPacketNumber packet_number) override;
void OnAppLimited() override;
@@ -273,6 +334,7 @@ class QUIC_EXPORT_PRIVATE BandwidthSampler : public BandwidthSamplerInterface {
QuicByteCount total_bytes_sent() const override;
QuicByteCount total_bytes_acked() const override;
QuicByteCount total_bytes_lost() const override;
+ QuicByteCount total_bytes_neutered() const override;
bool is_app_limited() const override;
@@ -293,6 +355,57 @@ class QUIC_EXPORT_PRIVATE BandwidthSampler : public BandwidthSamplerInterface {
max_ack_height_tracker_.Reset(new_height, new_time);
}
+ // AckPoint represents a point on the ack line.
+ struct QUIC_NO_EXPORT AckPoint {
+ QuicTime ack_time = QuicTime::Zero();
+ QuicByteCount total_bytes_acked = 0;
+
+ friend QUIC_NO_EXPORT std::ostream& operator<<(std::ostream& os,
+ const AckPoint& ack_point) {
+ return os << ack_point.ack_time << ":" << ack_point.total_bytes_acked;
+ }
+ };
+
+ // RecentAckPoints maintains the most recent 2 ack points at distinct times.
+ class QUIC_NO_EXPORT RecentAckPoints {
+ public:
+ void Update(QuicTime ack_time, QuicByteCount total_bytes_acked) {
+ DCHECK_GE(total_bytes_acked, ack_points_[1].total_bytes_acked);
+
+ if (ack_time < ack_points_[1].ack_time) {
+ // This can only happen when time goes backwards, we use the smaller
+ // timestamp for the most recent ack point in that case.
+ // TODO(wub): Add a QUIC_BUG if ack time stops going backwards.
+ ack_points_[1].ack_time = ack_time;
+ } else if (ack_time > ack_points_[1].ack_time) {
+ ack_points_[0] = ack_points_[1];
+ ack_points_[1].ack_time = ack_time;
+ }
+
+ ack_points_[1].total_bytes_acked = total_bytes_acked;
+ }
+
+ void Clear() { ack_points_[0] = ack_points_[1] = AckPoint(); }
+
+ const AckPoint& MostRecentPoint() const { return ack_points_[1]; }
+
+ const AckPoint& LessRecentPoint() const {
+ if (ack_points_[0].total_bytes_acked != 0) {
+ return ack_points_[0];
+ }
+
+ return ack_points_[1];
+ }
+
+ private:
+ AckPoint ack_points_[2];
+ };
+
+ void EnableOverestimateAvoidance();
+ bool IsOverestimateAvoidanceEnabled() const {
+ return overestimate_avoidance_;
+ }
+
private:
friend class test::BandwidthSamplerPeer;
@@ -325,8 +438,10 @@ class QUIC_EXPORT_PRIVATE BandwidthSampler : public BandwidthSamplerInterface {
// Snapshot constructor. Records the current state of the bandwidth
// sampler.
+ // |bytes_in_flight| is the bytes in flight right after the packet is sent.
ConnectionStateOnSentPacket(QuicTime sent_time,
QuicByteCount size,
+ QuicByteCount bytes_in_flight,
const BandwidthSampler& sampler)
: sent_time(sent_time),
size(size),
@@ -337,7 +452,8 @@ class QUIC_EXPORT_PRIVATE BandwidthSampler : public BandwidthSamplerInterface {
send_time_state(sampler.is_app_limited_,
sampler.total_bytes_sent_,
sampler.total_bytes_acked_,
- sampler.total_bytes_lost_) {}
+ sampler.total_bytes_lost_,
+ bytes_in_flight) {}
// Default constructor. Required to put this structure into
// PacketNumberIndexedQueue.
@@ -347,13 +463,45 @@ class QUIC_EXPORT_PRIVATE BandwidthSampler : public BandwidthSamplerInterface {
total_bytes_sent_at_last_acked_packet(0),
last_acked_packet_sent_time(QuicTime::Zero()),
last_acked_packet_ack_time(QuicTime::Zero()) {}
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const ConnectionStateOnSentPacket& p) {
+ os << "{sent_time:" << p.sent_time << ", size:" << p.size
+ << ", total_bytes_sent_at_last_acked_packet:"
+ << p.total_bytes_sent_at_last_acked_packet
+ << ", last_acked_packet_sent_time:" << p.last_acked_packet_sent_time
+ << ", last_acked_packet_ack_time:" << p.last_acked_packet_ack_time
+ << ", send_time_state:" << p.send_time_state << "}";
+ return os;
+ }
};
+ BandwidthSample OnPacketAcknowledged(QuicTime ack_time,
+ QuicPacketNumber packet_number);
+
+ SendTimeState OnPacketLost(QuicPacketNumber packet_number,
+ QuicPacketLength bytes_lost);
+
// Copy a subset of the (private) ConnectionStateOnSentPacket to the (public)
// SendTimeState. Always set send_time_state->is_valid to true.
void SentPacketToSendTimeState(const ConnectionStateOnSentPacket& sent_packet,
SendTimeState* send_time_state) const;
+ // Choose the best a0 from |a0_candidates_| to calculate the ack rate.
+ // |total_bytes_acked| is the total bytes acked when the packet being acked is
+ // sent. The best a0 is chosen as follows:
+ // - If there's only one candidate, use it.
+ // - If there are multiple candidates, let a[n] be the nth candidate, and
+ // a[n-1].total_bytes_acked <= |total_bytes_acked| < a[n].total_bytes_acked,
+ // use a[n-1].
+ // - If all candidates's total_bytes_acked is > |total_bytes_acked|, use a[0].
+ // This may happen when acks are received out of order, and ack[n] caused
+ // some candidates of ack[n-x] to be removed.
+ // - If all candidates's total_bytes_acked is <= |total_bytes_acked|, use
+ // a[a.size()-1].
+ bool ChooseA0Point(QuicByteCount total_bytes_acked, AckPoint* a0);
+
// The total number of congestion controlled bytes sent during the connection.
QuicByteCount total_bytes_sent_;
@@ -363,6 +511,9 @@ class QUIC_EXPORT_PRIVATE BandwidthSampler : public BandwidthSamplerInterface {
// The total number of congestion controlled bytes which were lost.
QuicByteCount total_bytes_lost_;
+ // The total number of congestion controlled bytes which have been neutered.
+ QuicByteCount total_bytes_neutered_;
+
// The value of |total_bytes_sent_| at the time the last acknowledged packet
// was sent. Valid only when |last_acked_packet_sent_time_| is valid.
QuicByteCount total_bytes_sent_at_last_acked_packet_;
@@ -377,6 +528,10 @@ class QUIC_EXPORT_PRIVATE BandwidthSampler : public BandwidthSamplerInterface {
// The most recently sent packet.
QuicPacketNumber last_sent_packet_;
+ // Indicates whether the bandwidth sampler is started in app-limited phase.
+ const bool started_as_app_limited_ =
+ GetQuicReloadableFlag(quic_bw_sampler_app_limited_starting_value);
+
// Indicates whether the bandwidth sampler is currently in an app-limited
// phase.
bool is_app_limited_;
@@ -389,6 +544,9 @@ class QUIC_EXPORT_PRIVATE BandwidthSampler : public BandwidthSamplerInterface {
// sent, indexed by the packet number.
PacketNumberIndexedQueue<ConnectionStateOnSentPacket> connection_state_map_;
+ RecentAckPoints recent_ack_points_;
+ QuicCircularDeque<AckPoint> a0_candidates_;
+
// Maximum number of tracked packets.
const QuicPacketCount max_tracked_packets_;
@@ -406,6 +564,10 @@ class QUIC_EXPORT_PRIVATE BandwidthSampler : public BandwidthSamplerInterface {
MaxAckHeightTracker max_ack_height_tracker_;
QuicByteCount total_bytes_acked_after_last_ack_event_;
+
+ // True if --quic_avoid_overestimate_bandwidth_with_aggregation=true and
+ // connection option 'BSAO' is set.
+ bool overestimate_avoidance_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler_test.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler_test.cc
index 59318a98590..5dda9986965 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler_test.cc
@@ -3,11 +3,14 @@
// found in the LICENSE file.
#include "net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.h"
+#include <cstdint>
+#include <set>
#include "net/third_party/quiche/src/quic/core/quic_bandwidth.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
@@ -36,14 +39,26 @@ class BandwidthSamplerTest : public QuicTest {
protected:
BandwidthSamplerTest()
: sampler_(nullptr, /*max_height_tracker_window_length=*/0),
- bytes_in_flight_(0) {
+ sampler_app_limited_at_start_(sampler_.is_app_limited()),
+ bytes_in_flight_(0),
+ max_bandwidth_(QuicBandwidth::Zero()),
+ est_bandwidth_upper_bound_(QuicBandwidth::Infinite()),
+ round_trip_count_(0) {
// Ensure that the clock does not start at zero.
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
+ if (GetQuicReloadableFlag(
+ quic_avoid_overestimate_bandwidth_with_aggregation)) {
+ sampler_.EnableOverestimateAvoidance();
+ }
}
MockClock clock_;
BandwidthSampler sampler_;
+ bool sampler_app_limited_at_start_;
QuicByteCount bytes_in_flight_;
+ QuicBandwidth max_bandwidth_; // Max observed bandwidth from acks.
+ QuicBandwidth est_bandwidth_upper_bound_;
+ QuicRoundTripCount round_trip_count_; // Needed to calculate extra_acked.
QuicByteCount PacketsToBytes(QuicPacketCount packet_count) {
return packet_count * kRegularPacketSize;
@@ -68,26 +83,72 @@ class BandwidthSamplerTest : public QuicTest {
QuicByteCount size = BandwidthSamplerPeer::GetPacketSize(
sampler_, QuicPacketNumber(packet_number));
bytes_in_flight_ -= size;
- return sampler_.OnPacketAcknowledged(clock_.Now(),
- QuicPacketNumber(packet_number));
+ BandwidthSampler::CongestionEventSample sample = sampler_.OnCongestionEvent(
+ clock_.Now(), {MakeAckedPacket(packet_number)}, {}, max_bandwidth_,
+ est_bandwidth_upper_bound_, round_trip_count_);
+ max_bandwidth_ = std::max(max_bandwidth_, sample.sample_max_bandwidth);
+ BandwidthSample bandwidth_sample;
+ bandwidth_sample.bandwidth = sample.sample_max_bandwidth;
+ bandwidth_sample.rtt = sample.sample_rtt;
+ bandwidth_sample.state_at_send = sample.last_packet_send_state;
+ EXPECT_TRUE(bandwidth_sample.state_at_send.is_valid);
+ return bandwidth_sample;
+ }
+
+ AckedPacket MakeAckedPacket(uint64_t packet_number) const {
+ QuicByteCount size = BandwidthSamplerPeer::GetPacketSize(
+ sampler_, QuicPacketNumber(packet_number));
+ return AckedPacket(QuicPacketNumber(packet_number), size, clock_.Now());
+ }
+
+ LostPacket MakeLostPacket(uint64_t packet_number) const {
+ return LostPacket(QuicPacketNumber(packet_number),
+ BandwidthSamplerPeer::GetPacketSize(
+ sampler_, QuicPacketNumber(packet_number)));
}
// Acknowledge receipt of a packet and expect it to be not app-limited.
QuicBandwidth AckPacket(uint64_t packet_number) {
BandwidthSample sample = AckPacketInner(packet_number);
- EXPECT_TRUE(sample.state_at_send.is_valid);
- EXPECT_FALSE(sample.state_at_send.is_app_limited);
return sample.bandwidth;
}
+ BandwidthSampler::CongestionEventSample OnCongestionEvent(
+ std::set<uint64_t> acked_packet_numbers,
+ std::set<uint64_t> lost_packet_numbers) {
+ AckedPacketVector acked_packets;
+ for (auto it = acked_packet_numbers.begin();
+ it != acked_packet_numbers.end(); ++it) {
+ acked_packets.push_back(MakeAckedPacket(*it));
+ bytes_in_flight_ -= acked_packets.back().bytes_acked;
+ }
+
+ LostPacketVector lost_packets;
+ for (auto it = lost_packet_numbers.begin(); it != lost_packet_numbers.end();
+ ++it) {
+ lost_packets.push_back(MakeLostPacket(*it));
+ bytes_in_flight_ -= lost_packets.back().bytes_lost;
+ }
+
+ BandwidthSampler::CongestionEventSample sample = sampler_.OnCongestionEvent(
+ clock_.Now(), acked_packets, lost_packets, max_bandwidth_,
+ est_bandwidth_upper_bound_, round_trip_count_);
+ max_bandwidth_ = std::max(max_bandwidth_, sample.sample_max_bandwidth);
+ return sample;
+ }
+
SendTimeState LosePacket(uint64_t packet_number) {
QuicByteCount size = BandwidthSamplerPeer::GetPacketSize(
sampler_, QuicPacketNumber(packet_number));
bytes_in_flight_ -= size;
- SendTimeState send_time_state =
- sampler_.OnPacketLost(QuicPacketNumber(packet_number));
- EXPECT_TRUE(send_time_state.is_valid);
- return send_time_state;
+ LostPacket lost_packet(QuicPacketNumber(packet_number), size);
+ BandwidthSampler::CongestionEventSample sample = sampler_.OnCongestionEvent(
+ clock_.Now(), {}, {lost_packet}, max_bandwidth_,
+ est_bandwidth_upper_bound_, round_trip_count_);
+ EXPECT_TRUE(sample.last_packet_send_state.is_valid);
+ EXPECT_EQ(sample.sample_max_bandwidth, QuicBandwidth::Zero());
+ EXPECT_EQ(sample.sample_rtt, QuicTime::Delta::Infinite());
+ return sample.last_packet_send_state;
}
// Sends one packet and acks it. Then, send 20 packets. Finally, send
@@ -133,6 +194,8 @@ TEST_F(BandwidthSamplerTest, SendAndWait) {
QuicBandwidth current_sample = AckPacket(i);
EXPECT_EQ(expected_bandwidth, current_sample);
}
+ sampler_.RemoveObsoletePackets(QuicPacketNumber(25));
+
EXPECT_EQ(0u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
EXPECT_EQ(0u, bytes_in_flight_);
}
@@ -190,6 +253,13 @@ TEST_F(BandwidthSamplerTest, SendTimeState) {
EXPECT_EQ(PacketsToBytes(1), send_time_state.total_bytes_acked);
EXPECT_EQ(PacketsToBytes(2), send_time_state.total_bytes_lost);
}
+
+ // This equation works because there is no neutered bytes.
+ EXPECT_EQ(send_time_state.total_bytes_sent -
+ send_time_state.total_bytes_acked -
+ send_time_state.total_bytes_lost,
+ send_time_state.bytes_in_flight);
+
clock_.AdvanceTime(time_between_packets);
}
}
@@ -208,9 +278,11 @@ TEST_F(BandwidthSamplerTest, SendPaced) {
QuicBandwidth last_bandwidth = QuicBandwidth::Zero();
for (int i = 21; i <= 40; i++) {
last_bandwidth = AckPacket(i);
- EXPECT_EQ(expected_bandwidth, last_bandwidth);
+ EXPECT_EQ(expected_bandwidth, last_bandwidth) << "i is " << i;
clock_.AdvanceTime(time_between_packets);
}
+ sampler_.RemoveObsoletePackets(QuicPacketNumber(41));
+
EXPECT_EQ(0u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
EXPECT_EQ(0u, bytes_in_flight_);
}
@@ -251,6 +323,8 @@ TEST_F(BandwidthSamplerTest, SendWithLosses) {
}
clock_.AdvanceTime(time_between_packets);
}
+ sampler_.RemoveObsoletePackets(QuicPacketNumber(41));
+
EXPECT_EQ(0u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
EXPECT_EQ(0u, bytes_in_flight_);
}
@@ -298,6 +372,7 @@ TEST_F(BandwidthSamplerTest, NotCongestionControlled) {
}
clock_.AdvanceTime(time_between_packets);
}
+ sampler_.RemoveObsoletePackets(QuicPacketNumber(41));
// Since only congestion controlled packets are entered into the map, it has
// to be empty at this point.
@@ -327,6 +402,9 @@ TEST_F(BandwidthSamplerTest, CompressedAck) {
clock_.AdvanceTime(ridiculously_small_time_delta);
}
EXPECT_EQ(expected_bandwidth, last_bandwidth);
+
+ sampler_.RemoveObsoletePackets(QuicPacketNumber(41));
+
EXPECT_EQ(0u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
EXPECT_EQ(0u, bytes_in_flight_);
}
@@ -356,6 +434,8 @@ TEST_F(BandwidthSamplerTest, ReorderedAck) {
EXPECT_EQ(expected_bandwidth, last_bandwidth);
clock_.AdvanceTime(time_between_packets);
}
+ sampler_.RemoveObsoletePackets(QuicPacketNumber(61));
+
EXPECT_EQ(0u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
EXPECT_EQ(0u, bytes_in_flight_);
}
@@ -367,14 +447,29 @@ TEST_F(BandwidthSamplerTest, AppLimited) {
QuicBandwidth expected_bandwidth =
QuicBandwidth::FromKBytesPerSecond(kRegularPacketSize);
- Send40PacketsAndAckFirst20(time_between_packets);
+ // Send 20 packets at a constant inter-packet time.
+ for (int i = 1; i <= 20; i++) {
+ SendPacket(i);
+ clock_.AdvanceTime(time_between_packets);
+ }
+
+ // Ack packets 1 to 20, while sending new packets at the same rate as
+ // before.
+ for (int i = 1; i <= 20; i++) {
+ BandwidthSample sample = AckPacketInner(i);
+ EXPECT_EQ(sample.state_at_send.is_app_limited,
+ sampler_app_limited_at_start_);
+ SendPacket(i + 20);
+ clock_.AdvanceTime(time_between_packets);
+ }
// We are now app-limited. Ack 21 to 40 as usual, but do not send anything for
// now.
sampler_.OnAppLimited();
for (int i = 21; i <= 40; i++) {
- QuicBandwidth current_sample = AckPacket(i);
- EXPECT_EQ(expected_bandwidth, current_sample);
+ BandwidthSample sample = AckPacketInner(i);
+ EXPECT_FALSE(sample.state_at_send.is_app_limited);
+ EXPECT_EQ(expected_bandwidth, sample.bandwidth);
clock_.AdvanceTime(time_between_packets);
}
@@ -401,10 +496,12 @@ TEST_F(BandwidthSamplerTest, AppLimited) {
// Run out of packets, and then ack packet 61 to 80, all of which should have
// correct non-app-limited samples.
for (int i = 61; i <= 80; i++) {
- QuicBandwidth last_bandwidth = AckPacket(i);
- EXPECT_EQ(expected_bandwidth, last_bandwidth);
+ BandwidthSample sample = AckPacketInner(i);
+ EXPECT_FALSE(sample.state_at_send.is_app_limited);
+ EXPECT_EQ(sample.bandwidth, expected_bandwidth);
clock_.AdvanceTime(time_between_packets);
}
+ sampler_.RemoveObsoletePackets(QuicPacketNumber(81));
EXPECT_EQ(0u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
EXPECT_EQ(0u, bytes_in_flight_);
@@ -458,15 +555,149 @@ TEST_F(BandwidthSamplerTest, RemoveObsoletePackets) {
EXPECT_EQ(5u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
sampler_.RemoveObsoletePackets(QuicPacketNumber(4));
EXPECT_EQ(2u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
- sampler_.OnPacketLost(QuicPacketNumber(4));
+ LosePacket(4);
+ sampler_.RemoveObsoletePackets(QuicPacketNumber(5));
+
EXPECT_EQ(1u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
AckPacket(5);
+
+ sampler_.RemoveObsoletePackets(QuicPacketNumber(6));
+
EXPECT_EQ(0u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
}
+TEST_F(BandwidthSamplerTest, NeuterPacket) {
+ SendPacket(1);
+ EXPECT_EQ(0u, sampler_.total_bytes_neutered());
+
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+ sampler_.OnPacketNeutered(QuicPacketNumber(1));
+ EXPECT_LT(0u, sampler_.total_bytes_neutered());
+ EXPECT_EQ(0u, sampler_.total_bytes_acked());
+
+ // If packet 1 is acked it should not produce a bandwidth sample.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+ BandwidthSampler::CongestionEventSample sample = sampler_.OnCongestionEvent(
+ clock_.Now(),
+ {AckedPacket(QuicPacketNumber(1), kRegularPacketSize, clock_.Now())}, {},
+ max_bandwidth_, est_bandwidth_upper_bound_, round_trip_count_);
+ EXPECT_EQ(0u, sampler_.total_bytes_acked());
+ EXPECT_EQ(QuicBandwidth::Zero(), sample.sample_max_bandwidth);
+ EXPECT_FALSE(sample.sample_is_app_limited);
+ EXPECT_EQ(QuicTime::Delta::Infinite(), sample.sample_rtt);
+ EXPECT_EQ(0u, sample.sample_max_inflight);
+ EXPECT_EQ(0u, sample.extra_acked);
+}
+
+TEST_F(BandwidthSamplerTest, CongestionEventSampleDefaultValues) {
+ // Make sure a default constructed CongestionEventSample has the correct
+ // initial values for BandwidthSampler::OnCongestionEvent() to work.
+ BandwidthSampler::CongestionEventSample sample;
+
+ EXPECT_EQ(QuicBandwidth::Zero(), sample.sample_max_bandwidth);
+ EXPECT_FALSE(sample.sample_is_app_limited);
+ EXPECT_EQ(QuicTime::Delta::Infinite(), sample.sample_rtt);
+ EXPECT_EQ(0u, sample.sample_max_inflight);
+ EXPECT_EQ(0u, sample.extra_acked);
+}
+
+// 1) Send 2 packets, 2) Ack both in 1 event, 3) Repeat.
+TEST_F(BandwidthSamplerTest, TwoAckedPacketsPerEvent) {
+ QuicTime::Delta time_between_packets = QuicTime::Delta::FromMilliseconds(10);
+ QuicBandwidth sending_rate = QuicBandwidth::FromBytesAndTimeDelta(
+ kRegularPacketSize, time_between_packets);
+
+ for (uint64_t i = 1; i < 21; i++) {
+ SendPacket(i);
+ clock_.AdvanceTime(time_between_packets);
+ if (i % 2 != 0) {
+ continue;
+ }
+
+ BandwidthSampler::CongestionEventSample sample =
+ OnCongestionEvent({i - 1, i}, {});
+ EXPECT_EQ(sending_rate, sample.sample_max_bandwidth);
+ EXPECT_EQ(time_between_packets, sample.sample_rtt);
+ EXPECT_EQ(2 * kRegularPacketSize, sample.sample_max_inflight);
+ EXPECT_TRUE(sample.last_packet_send_state.is_valid);
+ EXPECT_EQ(2 * kRegularPacketSize,
+ sample.last_packet_send_state.bytes_in_flight);
+ EXPECT_EQ(i * kRegularPacketSize,
+ sample.last_packet_send_state.total_bytes_sent);
+ EXPECT_EQ((i - 2) * kRegularPacketSize,
+ sample.last_packet_send_state.total_bytes_acked);
+ EXPECT_EQ(0u, sample.last_packet_send_state.total_bytes_lost);
+ sampler_.RemoveObsoletePackets(QuicPacketNumber(i - 2));
+ }
+}
+
+TEST_F(BandwidthSamplerTest, LoseEveryOtherPacket) {
+ QuicTime::Delta time_between_packets = QuicTime::Delta::FromMilliseconds(10);
+ QuicBandwidth sending_rate = QuicBandwidth::FromBytesAndTimeDelta(
+ kRegularPacketSize, time_between_packets);
+
+ for (uint64_t i = 1; i < 21; i++) {
+ SendPacket(i);
+ clock_.AdvanceTime(time_between_packets);
+ if (i % 2 != 0) {
+ continue;
+ }
+
+ // Ack packet i and lose i-1.
+ BandwidthSampler::CongestionEventSample sample =
+ OnCongestionEvent({i}, {i - 1});
+ // Losing 50% packets means sending rate is twice the bandwidth.
+ EXPECT_EQ(sending_rate, sample.sample_max_bandwidth * 2);
+ EXPECT_EQ(time_between_packets, sample.sample_rtt);
+ EXPECT_EQ(kRegularPacketSize, sample.sample_max_inflight);
+ EXPECT_TRUE(sample.last_packet_send_state.is_valid);
+ EXPECT_EQ(2 * kRegularPacketSize,
+ sample.last_packet_send_state.bytes_in_flight);
+ EXPECT_EQ(i * kRegularPacketSize,
+ sample.last_packet_send_state.total_bytes_sent);
+ EXPECT_EQ((i - 2) * kRegularPacketSize / 2,
+ sample.last_packet_send_state.total_bytes_acked);
+ EXPECT_EQ((i - 2) * kRegularPacketSize / 2,
+ sample.last_packet_send_state.total_bytes_lost);
+ sampler_.RemoveObsoletePackets(QuicPacketNumber(i - 2));
+ }
+}
+
+TEST_F(BandwidthSamplerTest, AckHeightRespectBandwidthEstimateUpperBound) {
+ QuicTime::Delta time_between_packets = QuicTime::Delta::FromMilliseconds(10);
+ QuicBandwidth first_packet_sending_rate =
+ QuicBandwidth::FromBytesAndTimeDelta(kRegularPacketSize,
+ time_between_packets);
+
+ // Send and ack packet 1.
+ SendPacket(1);
+ clock_.AdvanceTime(time_between_packets);
+ BandwidthSampler::CongestionEventSample sample = OnCongestionEvent({1}, {});
+ EXPECT_EQ(first_packet_sending_rate, sample.sample_max_bandwidth);
+ EXPECT_EQ(first_packet_sending_rate, max_bandwidth_);
+
+ // Send and ack packet 2, 3 and 4.
+ round_trip_count_++;
+ est_bandwidth_upper_bound_ = first_packet_sending_rate * 0.3;
+ SendPacket(2);
+ SendPacket(3);
+ SendPacket(4);
+ clock_.AdvanceTime(time_between_packets);
+ sample = OnCongestionEvent({2, 3, 4}, {});
+ EXPECT_EQ(first_packet_sending_rate * 3, sample.sample_max_bandwidth);
+ EXPECT_EQ(max_bandwidth_, sample.sample_max_bandwidth);
+
+ EXPECT_LT(2 * kRegularPacketSize, sample.extra_acked);
+}
+
class MaxAckHeightTrackerTest : public QuicTest {
protected:
- MaxAckHeightTrackerTest() : tracker_(/*initial_filter_window=*/10) {}
+ MaxAckHeightTrackerTest() : tracker_(/*initial_filter_window=*/10) {
+ if (GetQuicReloadableFlag(
+ quic_avoid_overestimate_bandwidth_with_aggregation)) {
+ tracker_.SetAckAggregationBandwidthThreshold(1.8);
+ }
+ }
// Run a full aggregation episode, which is one or more aggregated acks,
// followed by a quiet period in which no ack happens.
@@ -549,9 +780,15 @@ TEST_F(MaxAckHeightTrackerTest, VeryAggregatedLargeAck) {
1200, true);
now_ = now_ - QuicTime::Delta::FromMilliseconds(1);
- AggregationEpisode(bandwidth_ * 20, QuicTime::Delta::FromMilliseconds(6),
- 1200, false);
- EXPECT_EQ(2u, tracker_.num_ack_aggregation_epochs());
+ if (tracker_.ack_aggregation_bandwidth_threshold() > 1.1) {
+ AggregationEpisode(bandwidth_ * 20, QuicTime::Delta::FromMilliseconds(6),
+ 1200, true);
+ EXPECT_EQ(3u, tracker_.num_ack_aggregation_epochs());
+ } else {
+ AggregationEpisode(bandwidth_ * 20, QuicTime::Delta::FromMilliseconds(6),
+ 1200, false);
+ EXPECT_EQ(2u, tracker_.num_ack_aggregation_epochs());
+ }
}
TEST_F(MaxAckHeightTrackerTest, VeryAggregatedSmallAcks) {
@@ -561,9 +798,15 @@ TEST_F(MaxAckHeightTrackerTest, VeryAggregatedSmallAcks) {
true);
now_ = now_ - QuicTime::Delta::FromMilliseconds(1);
- AggregationEpisode(bandwidth_ * 20, QuicTime::Delta::FromMilliseconds(6), 300,
- false);
- EXPECT_EQ(2u, tracker_.num_ack_aggregation_epochs());
+ if (tracker_.ack_aggregation_bandwidth_threshold() > 1.1) {
+ AggregationEpisode(bandwidth_ * 20, QuicTime::Delta::FromMilliseconds(6),
+ 300, true);
+ EXPECT_EQ(3u, tracker_.num_ack_aggregation_epochs());
+ } else {
+ AggregationEpisode(bandwidth_ * 20, QuicTime::Delta::FromMilliseconds(6),
+ 300, false);
+ EXPECT_EQ(2u, tracker_.num_ack_aggregation_epochs());
+ }
}
TEST_F(MaxAckHeightTrackerTest, SomewhatAggregatedLargeAck) {
@@ -573,9 +816,15 @@ TEST_F(MaxAckHeightTrackerTest, SomewhatAggregatedLargeAck) {
1000, true);
now_ = now_ - QuicTime::Delta::FromMilliseconds(1);
- AggregationEpisode(bandwidth_ * 2, QuicTime::Delta::FromMilliseconds(50),
- 1000, false);
- EXPECT_EQ(2u, tracker_.num_ack_aggregation_epochs());
+ if (tracker_.ack_aggregation_bandwidth_threshold() > 1.1) {
+ AggregationEpisode(bandwidth_ * 2, QuicTime::Delta::FromMilliseconds(50),
+ 1000, true);
+ EXPECT_EQ(3u, tracker_.num_ack_aggregation_epochs());
+ } else {
+ AggregationEpisode(bandwidth_ * 2, QuicTime::Delta::FromMilliseconds(50),
+ 1000, false);
+ EXPECT_EQ(2u, tracker_.num_ack_aggregation_epochs());
+ }
}
TEST_F(MaxAckHeightTrackerTest, SomewhatAggregatedSmallAcks) {
@@ -585,9 +834,15 @@ TEST_F(MaxAckHeightTrackerTest, SomewhatAggregatedSmallAcks) {
true);
now_ = now_ - QuicTime::Delta::FromMilliseconds(1);
- AggregationEpisode(bandwidth_ * 2, QuicTime::Delta::FromMilliseconds(50), 100,
- false);
- EXPECT_EQ(2u, tracker_.num_ack_aggregation_epochs());
+ if (tracker_.ack_aggregation_bandwidth_threshold() > 1.1) {
+ AggregationEpisode(bandwidth_ * 2, QuicTime::Delta::FromMilliseconds(50),
+ 100, true);
+ EXPECT_EQ(3u, tracker_.num_ack_aggregation_epochs());
+ } else {
+ AggregationEpisode(bandwidth_ * 2, QuicTime::Delta::FromMilliseconds(50),
+ 100, false);
+ EXPECT_EQ(2u, tracker_.num_ack_aggregation_epochs());
+ }
}
TEST_F(MaxAckHeightTrackerTest, NotAggregated) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_drain.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_drain.cc
index a4247a41c12..60226392d57 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_drain.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_drain.cc
@@ -5,11 +5,10 @@
#include "net/third_party/quiche/src/quic/core/congestion_control/bbr2_drain.h"
#include "net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
namespace quic {
-void Bbr2DrainMode::Enter(const Bbr2CongestionEvent& /*congestion_event*/) {}
-
Bbr2Mode Bbr2DrainMode::OnCongestionEvent(
QuicByteCount /*prior_in_flight*/,
QuicTime /*event_time*/,
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_drain.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_drain.h
index e083aeb655b..548db8b07d4 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_drain.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_drain.h
@@ -17,8 +17,10 @@ class QUIC_EXPORT_PRIVATE Bbr2DrainMode final : public Bbr2ModeBase {
public:
using Bbr2ModeBase::Bbr2ModeBase;
- void Enter(const Bbr2CongestionEvent& congestion_event) override;
- void Leave(const Bbr2CongestionEvent& /*congestion_event*/) override {}
+ void Enter(QuicTime /*now*/,
+ const Bbr2CongestionEvent* /*congestion_event*/) override {}
+ void Leave(QuicTime /*now*/,
+ const Bbr2CongestionEvent* /*congestion_event*/) override {}
Bbr2Mode OnCongestionEvent(
QuicByteCount prior_in_flight,
@@ -33,6 +35,11 @@ class QUIC_EXPORT_PRIVATE Bbr2DrainMode final : public Bbr2ModeBase {
bool IsProbingForBandwidth() const override { return false; }
+ Bbr2Mode OnExitQuiescence(QuicTime /*now*/,
+ QuicTime /*quiescence_start_time*/) override {
+ return Bbr2Mode::DRAIN;
+ }
+
struct QUIC_EXPORT_PRIVATE DebugState {
QuicByteCount drain_target;
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.cc
index a527417a19d..5a3046794be 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.cc
@@ -8,15 +8,10 @@
#include "net/third_party/quiche/src/quic/core/quic_bandwidth.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
namespace quic {
-namespace {
-// Sensitivity in response to losses. 0 means no loss response.
-// 0.3 is also used by TCP bbr and cubic.
-const float kBeta = 0.3;
-} // namespace
-
RoundTripCounter::RoundTripCounter() : round_trip_count_(0) {}
void RoundTripCounter::OnPacketSent(QuicPacketNumber packet_number) {
@@ -56,34 +51,23 @@ void MinRttFilter::ForceUpdate(QuicTime::Delta sample_rtt, QuicTime now) {
min_rtt_timestamp_ = now;
}
-const SendTimeState& SendStateOfLargestPacket(
- const Bbr2CongestionEvent& congestion_event) {
- const auto& last_acked_sample = congestion_event.last_acked_sample;
- const auto& last_lost_sample = congestion_event.last_lost_sample;
-
- if (!last_lost_sample.packet_number.IsInitialized()) {
- return last_acked_sample.bandwidth_sample.state_at_send;
- }
-
- if (!last_acked_sample.packet_number.IsInitialized()) {
- return last_lost_sample.send_time_state;
- }
-
- DCHECK_NE(last_acked_sample.packet_number, last_lost_sample.packet_number);
-
- if (last_acked_sample.packet_number < last_lost_sample.packet_number) {
- return last_lost_sample.send_time_state;
- }
- return last_acked_sample.bandwidth_sample.state_at_send;
-}
-
Bbr2NetworkModel::Bbr2NetworkModel(const Bbr2Params* params,
QuicTime::Delta initial_rtt,
QuicTime initial_rtt_timestamp,
float cwnd_gain,
- float pacing_gain)
+ float pacing_gain,
+ const BandwidthSampler* old_sampler)
: params_(params),
- bandwidth_sampler_(nullptr, params->initial_max_ack_height_filter_window),
+ bandwidth_sampler_([](QuicRoundTripCount max_height_tracker_window_length,
+ const BandwidthSampler* old_sampler) {
+ if (GetQuicReloadableFlag(quic_bbr_copy_sampler_state_from_v1_to_v2) &&
+ old_sampler != nullptr) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_bbr_copy_sampler_state_from_v1_to_v2);
+ return BandwidthSampler(*old_sampler);
+ }
+ return BandwidthSampler(/*unacked_packet_map=*/nullptr,
+ max_height_tracker_window_length);
+ }(params->initial_max_ack_height_filter_window, old_sampler)),
min_rtt_filter_(initial_rtt, initial_rtt_timestamp),
cwnd_gain_(cwnd_gain),
pacing_gain_(pacing_gain) {}
@@ -113,64 +97,77 @@ void Bbr2NetworkModel::OnCongestionEventStart(
: round_trip_counter_.OnPacketsAcked(
acked_packets.rbegin()->packet_number);
- for (const auto& packet : acked_packets) {
- const BandwidthSample bandwidth_sample =
- bandwidth_sampler_.OnPacketAcknowledged(event_time,
- packet.packet_number);
- if (!bandwidth_sample.state_at_send.is_valid) {
- // From the sampler's perspective, the packet has never been sent, or
- // the packet has been acked or marked as lost previously.
- continue;
- }
+ BandwidthSamplerInterface::CongestionEventSample sample =
+ bandwidth_sampler_.OnCongestionEvent(event_time, acked_packets,
+ lost_packets, MaxBandwidth(),
+ bandwidth_lo(), RoundTripCount());
+ if (sample.last_packet_send_state.is_valid) {
+ congestion_event->last_packet_send_state = sample.last_packet_send_state;
congestion_event->last_sample_is_app_limited =
- bandwidth_sample.state_at_send.is_app_limited;
- if (!bandwidth_sample.rtt.IsZero()) {
- congestion_event->sample_min_rtt =
- std::min(congestion_event->sample_min_rtt, bandwidth_sample.rtt);
- }
- if (!bandwidth_sample.state_at_send.is_app_limited ||
- bandwidth_sample.bandwidth > MaxBandwidth()) {
- congestion_event->sample_max_bandwidth = std::max(
- congestion_event->sample_max_bandwidth, bandwidth_sample.bandwidth);
- }
+ sample.last_packet_send_state.is_app_limited;
+ }
- if (bandwidth_sample.bandwidth > bandwidth_latest_) {
- bandwidth_latest_ = bandwidth_sample.bandwidth;
+ // Avoid updating |max_bandwidth_filter_| if a) this is a loss-only event, or
+ // b) all packets in |acked_packets| did not generate valid samples. (e.g. ack
+ // of ack-only packets). In both cases, total_bytes_acked() will not change.
+ if (!fix_zero_bw_on_loss_only_event_ ||
+ (prior_bytes_acked != total_bytes_acked())) {
+ QUIC_BUG_IF((prior_bytes_acked != total_bytes_acked()) &&
+ sample.sample_max_bandwidth.IsZero())
+ << total_bytes_acked() - prior_bytes_acked << " bytes from "
+ << acked_packets.size()
+ << " packets have been acked, but sample_max_bandwidth is zero.";
+ if (!sample.sample_is_app_limited ||
+ sample.sample_max_bandwidth > MaxBandwidth()) {
+ congestion_event->sample_max_bandwidth = sample.sample_max_bandwidth;
+ max_bandwidth_filter_.Update(congestion_event->sample_max_bandwidth);
}
-
- // |inflight_sample| is the total bytes acked while |packet| is inflight.
- QuicByteCount inflight_sample =
- total_bytes_acked() - bandwidth_sample.state_at_send.total_bytes_acked;
- if (inflight_sample > inflight_latest_) {
- inflight_latest_ = inflight_sample;
+ } else {
+ if (acked_packets.empty()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr_fix_zero_bw_on_loss_only_event, 3,
+ 4);
+ } else {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr_fix_zero_bw_on_loss_only_event, 4,
+ 4);
}
-
- congestion_event->last_acked_sample = {packet.packet_number,
- bandwidth_sample, inflight_sample};
}
- min_rtt_filter_.Update(congestion_event->sample_min_rtt, event_time);
- if (!congestion_event->sample_max_bandwidth.IsZero()) {
- max_bandwidth_filter_.Update(congestion_event->sample_max_bandwidth);
+ if (!sample.sample_rtt.IsInfinite()) {
+ congestion_event->sample_min_rtt = sample.sample_rtt;
+ min_rtt_filter_.Update(congestion_event->sample_min_rtt, event_time);
}
- for (const LostPacket& packet : lost_packets) {
- const SendTimeState send_time_state =
- bandwidth_sampler_.OnPacketLost(packet.packet_number);
- if (send_time_state.is_valid) {
- congestion_event->last_lost_sample = {packet.packet_number,
- send_time_state};
- }
+ congestion_event->bytes_acked = total_bytes_acked() - prior_bytes_acked;
+ congestion_event->bytes_lost = total_bytes_lost() - prior_bytes_lost;
+
+ if (congestion_event->prior_bytes_in_flight >=
+ congestion_event->bytes_acked + congestion_event->bytes_lost) {
+ congestion_event->bytes_in_flight =
+ congestion_event->prior_bytes_in_flight -
+ congestion_event->bytes_acked - congestion_event->bytes_lost;
+ } else {
+ QUIC_LOG_FIRST_N(ERROR, 1)
+ << "prior_bytes_in_flight:" << congestion_event->prior_bytes_in_flight
+ << " is smaller than the sum of bytes_acked:"
+ << congestion_event->bytes_acked
+ << " and bytes_lost:" << congestion_event->bytes_lost;
+ congestion_event->bytes_in_flight = 0;
}
- congestion_event->bytes_in_flight = bytes_in_flight();
+ if (congestion_event->bytes_lost > 0) {
+ bytes_lost_in_round_ += congestion_event->bytes_lost;
+ loss_events_in_round_++;
+ }
- congestion_event->bytes_acked = total_bytes_acked() - prior_bytes_acked;
- congestion_event->bytes_lost = total_bytes_lost() - prior_bytes_lost;
- bytes_lost_in_round_ += congestion_event->bytes_lost;
+ // |bandwidth_latest_| and |inflight_latest_| only increased within a round.
+ if (sample.sample_max_bandwidth > bandwidth_latest_) {
+ bandwidth_latest_ = sample.sample_max_bandwidth;
+ }
- bandwidth_sampler_.OnAckEventEnd(BandwidthEstimate(), RoundTripCount());
+ if (sample.sample_max_inflight > inflight_latest_) {
+ inflight_latest_ = sample.sample_max_inflight;
+ }
if (!congestion_event->end_of_round_trip) {
return;
@@ -178,6 +175,14 @@ void Bbr2NetworkModel::OnCongestionEventStart(
// Per round-trip updates.
AdaptLowerBounds(*congestion_event);
+
+ if (!sample.sample_max_bandwidth.IsZero()) {
+ bandwidth_latest_ = sample.sample_max_bandwidth;
+ }
+
+ if (sample.sample_max_inflight > 0) {
+ inflight_latest_ = sample.sample_max_inflight;
+ }
}
void Bbr2NetworkModel::AdaptLowerBounds(
@@ -195,12 +200,13 @@ void Bbr2NetworkModel::AdaptLowerBounds(
inflight_lo_ = congestion_event.prior_cwnd;
}
- bandwidth_lo_ = std::max(bandwidth_latest_, bandwidth_lo_ * (1.0 - kBeta));
+ bandwidth_lo_ =
+ std::max(bandwidth_latest_, bandwidth_lo_ * (1.0 - Params().beta));
QUIC_DVLOG(3) << "bandwidth_lo_ updated to " << bandwidth_lo_
<< ", bandwidth_latest_ is " << bandwidth_latest_;
- inflight_lo_ =
- std::max<QuicByteCount>(inflight_latest_, inflight_lo_ * (1.0 - kBeta));
+ inflight_lo_ = std::max<QuicByteCount>(
+ inflight_latest_, inflight_lo_ * (1.0 - Params().beta));
}
}
@@ -208,13 +214,8 @@ void Bbr2NetworkModel::OnCongestionEventFinish(
QuicPacketNumber least_unacked_packet,
const Bbr2CongestionEvent& congestion_event) {
if (congestion_event.end_of_round_trip) {
- const auto& last_acked_sample = congestion_event.last_acked_sample;
- if (last_acked_sample.bandwidth_sample.state_at_send.is_valid) {
- bandwidth_latest_ = last_acked_sample.bandwidth_sample.bandwidth;
- inflight_latest_ = last_acked_sample.inflight_sample;
- }
-
bytes_lost_in_round_ = 0;
+ loss_events_in_round_ = 0;
}
bandwidth_sampler_.RemoveObsoletePackets(least_unacked_packet);
@@ -258,7 +259,7 @@ bool Bbr2NetworkModel::IsCongestionWindowLimited(
bool Bbr2NetworkModel::IsInflightTooHigh(
const Bbr2CongestionEvent& congestion_event) const {
- const SendTimeState& send_state = SendStateOfLargestPacket(congestion_event);
+ const SendTimeState& send_state = congestion_event.last_packet_send_state;
if (!send_state.is_valid) {
// Not enough information.
return false;
@@ -287,6 +288,7 @@ bool Bbr2NetworkModel::IsInflightTooHigh(
void Bbr2NetworkModel::RestartRound() {
bytes_lost_in_round_ = 0;
+ loss_events_in_round_ = 0;
round_trip_counter_.RestartRound();
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.h
index 8f08a58c6fc..63a11e14681 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.h
@@ -119,6 +119,10 @@ struct QUIC_EXPORT_PRIVATE Bbr2Params {
QuicTime::Delta::FromMilliseconds(
GetQuicFlag(FLAGS_quic_bbr2_default_probe_bw_max_rand_duration_ms));
+ // The minimum number of loss marking events to exit the PROBE_UP phase.
+ int64_t probe_bw_full_loss_count =
+ GetQuicFlag(FLAGS_quic_bbr2_default_probe_bw_full_loss_count);
+
// Multiplier to get target inflight (as multiple of BDP) for PROBE_UP phase.
float probe_bw_probe_inflight_gain = 1.25;
@@ -142,7 +146,8 @@ struct QUIC_EXPORT_PRIVATE Bbr2Params {
*/
// The initial value of the max ack height filter's window length.
- QuicRoundTripCount initial_max_ack_height_filter_window = 10;
+ QuicRoundTripCount initial_max_ack_height_filter_window =
+ GetQuicFlag(FLAGS_quic_bbr2_default_initial_ack_height_filter_window);
// Fraction of unutilized headroom to try to leave in path upon high loss.
float inflight_hi_headroom =
@@ -151,7 +156,27 @@ struct QUIC_EXPORT_PRIVATE Bbr2Params {
// Estimate startup/bw probing has gone too far if loss rate exceeds this.
float loss_threshold = GetQuicFlag(FLAGS_quic_bbr2_default_loss_threshold);
+ // A common factor for multiplicative decreases. Used for adjusting
+ // bandwidth_lo, inflight_lo and inflight_hi upon losses.
+ float beta = 0.3;
+
Limits<QuicByteCount> cwnd_limits;
+
+ /*
+ * Experimental flags from QuicConfig.
+ */
+
+ // Indicates app-limited calls should be ignored as long as there's
+ // enough data inflight to see more bandwidth when necessary.
+ bool flexible_app_limited = false;
+
+ // Can be disabled by connection option 'B2NA'.
+ bool add_ack_height_to_queueing_threshold =
+ GetQuicReloadableFlag(quic_bbr2_add_ack_height_to_queueing_threshold);
+
+ // Can be disabled by connection option 'B2RP'.
+ bool avoid_unnecessary_probe_rtt =
+ GetQuicReloadableFlag(quic_bbr2_avoid_unnecessary_probe_rtt);
};
class QUIC_EXPORT_PRIVATE RoundTripCounter {
@@ -228,6 +253,9 @@ struct QUIC_EXPORT_PRIVATE Bbr2CongestionEvent {
// The congestion window prior to the processing of the ack/loss events.
QuicByteCount prior_cwnd;
+ // Total bytes inflight before the processing of the ack/loss events.
+ QuicByteCount prior_bytes_in_flight = 0;
+
// Total bytes inflight after the processing of the ack/loss events.
QuicByteCount bytes_in_flight = 0;
@@ -240,6 +268,8 @@ struct QUIC_EXPORT_PRIVATE Bbr2CongestionEvent {
// Whether acked_packets indicates the end of a round trip.
bool end_of_round_trip = false;
+ // TODO(wub): After deprecating --quic_one_bw_sample_per_ack_event, use
+ // last_packet_send_state.is_app_limited instead of this field.
// Whether the last bandwidth sample from acked_packets is app limited.
// false if acked_packets is empty.
bool last_sample_is_app_limited = false;
@@ -254,24 +284,12 @@ struct QUIC_EXPORT_PRIVATE Bbr2CongestionEvent {
// Maximum bandwidth of all bandwidth samples from acked_packets.
QuicBandwidth sample_max_bandwidth = QuicBandwidth::Zero();
- // Send time state of the largest-numbered packet in this event.
- // SendTimeState send_time_state;
- struct {
- QuicPacketNumber packet_number;
- BandwidthSample bandwidth_sample;
- // Total bytes acked while |packet| is inflight.
- QuicByteCount inflight_sample;
- } last_acked_sample;
-
- struct {
- QuicPacketNumber packet_number;
- SendTimeState send_time_state;
- } last_lost_sample;
+ // The send state of the largest packet in acked_packets, unless it is empty.
+ // If acked_packets is empty, it's the send state of the largest packet in
+ // lost_packets.
+ SendTimeState last_packet_send_state;
};
-QUIC_EXPORT_PRIVATE const SendTimeState& SendStateOfLargestPacket(
- const Bbr2CongestionEvent& congestion_event);
-
// Bbr2NetworkModel takes low level congestion signals(packets sent/acked/lost)
// as input and produces BBRv2 model parameters like inflight_(hi|lo),
// bandwidth_(hi|lo), bandwidth and rtt estimates, etc.
@@ -281,7 +299,8 @@ class QUIC_EXPORT_PRIVATE Bbr2NetworkModel {
QuicTime::Delta initial_rtt,
QuicTime initial_rtt_timestamp,
float cwnd_gain,
- float pacing_gain);
+ float pacing_gain,
+ const BandwidthSampler* old_sampler);
void OnPacketSent(QuicTime sent_time,
QuicByteCount bytes_in_flight,
@@ -325,12 +344,26 @@ class QUIC_EXPORT_PRIVATE Bbr2NetworkModel {
QuicTime MinRttTimestamp() const { return min_rtt_filter_.GetTimestamp(); }
+ // TODO(wub): If we do this too frequently, we can potentailly postpone
+ // PROBE_RTT indefinitely. Observe how it works in production and improve it.
+ void PostponeMinRttTimestamp(QuicTime::Delta duration) {
+ min_rtt_filter_.ForceUpdate(MinRtt(), MinRttTimestamp() + duration);
+ }
+
QuicBandwidth MaxBandwidth() const { return max_bandwidth_filter_.Get(); }
QuicByteCount MaxAckHeight() const {
return bandwidth_sampler_.max_ack_height();
}
+ void EnableOverestimateAvoidance() {
+ bandwidth_sampler_.EnableOverestimateAvoidance();
+ }
+
+ void OnPacketNeutered(QuicPacketNumber packet_number) {
+ bandwidth_sampler_.OnPacketNeutered(packet_number);
+ }
+
uint64_t num_ack_aggregation_epochs() const {
return bandwidth_sampler_.num_ack_aggregation_epochs();
}
@@ -348,6 +381,8 @@ class QUIC_EXPORT_PRIVATE Bbr2NetworkModel {
bool IsCongestionWindowLimited(
const Bbr2CongestionEvent& congestion_event) const;
+ // TODO(wub): Replace this by a new version which takes two thresholds, one
+ // is the number of loss events, the other is the percentage of bytes lost.
bool IsInflightTooHigh(const Bbr2CongestionEvent& congestion_event) const;
QuicPacketNumber last_sent_packet() const {
@@ -366,9 +401,7 @@ class QUIC_EXPORT_PRIVATE Bbr2NetworkModel {
return bandwidth_sampler_.total_bytes_sent();
}
- QuicByteCount bytes_in_flight() const {
- return total_bytes_sent() - total_bytes_acked() - total_bytes_lost();
- }
+ int64_t loss_events_in_round() const { return loss_events_in_round_; }
QuicPacketNumber end_of_app_limited_phase() const {
return bandwidth_sampler_.end_of_app_limited_phase();
@@ -423,6 +456,8 @@ class QUIC_EXPORT_PRIVATE Bbr2NetworkModel {
// Bytes lost in the current round. Updated once per congestion event.
QuicByteCount bytes_lost_in_round_ = 0;
+ // Number of loss marking events in the current round.
+ int64_t loss_events_in_round_ = 0;
// Max bandwidth in the current round. Updated once per congestion event.
QuicBandwidth bandwidth_latest_ = QuicBandwidth::Zero();
@@ -437,6 +472,9 @@ class QUIC_EXPORT_PRIVATE Bbr2NetworkModel {
float cwnd_gain_;
float pacing_gain_;
+
+ const bool fix_zero_bw_on_loss_only_event_ =
+ GetQuicReloadableFlag(quic_bbr_fix_zero_bw_on_loss_only_event);
};
enum class Bbr2Mode : uint8_t {
@@ -478,8 +516,12 @@ class QUIC_EXPORT_PRIVATE Bbr2ModeBase {
virtual ~Bbr2ModeBase() = default;
// Called when entering/leaving this mode.
- virtual void Enter(const Bbr2CongestionEvent& congestion_event) = 0;
- virtual void Leave(const Bbr2CongestionEvent& congestion_event) = 0;
+ // congestion_event != nullptr means BBRv2 is switching modes in the context
+ // of a ack and/or loss.
+ virtual void Enter(QuicTime now,
+ const Bbr2CongestionEvent* congestion_event) = 0;
+ virtual void Leave(QuicTime now,
+ const Bbr2CongestionEvent* congestion_event) = 0;
virtual Bbr2Mode OnCongestionEvent(
QuicByteCount prior_in_flight,
@@ -492,6 +534,9 @@ class QUIC_EXPORT_PRIVATE Bbr2ModeBase {
virtual bool IsProbingForBandwidth() const = 0;
+ virtual Bbr2Mode OnExitQuiescence(QuicTime now,
+ QuicTime quiescence_start_time) = 0;
+
protected:
const Bbr2Sender* const sender_;
Bbr2NetworkModel* model_;
@@ -500,6 +545,9 @@ class QUIC_EXPORT_PRIVATE Bbr2ModeBase {
QUIC_EXPORT_PRIVATE inline QuicByteCount BytesInFlight(
const SendTimeState& send_state) {
DCHECK(send_state.is_valid);
+ if (send_state.bytes_in_flight != 0) {
+ return send_state.bytes_in_flight;
+ }
return send_state.total_bytes_sent - send_state.total_bytes_acked -
send_state.total_bytes_lost;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.cc
index 4487cbf879b..1a7a7193a16 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.cc
@@ -9,24 +9,27 @@
#include "net/third_party/quiche/src/quic/core/quic_bandwidth.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
namespace quic {
-void Bbr2ProbeBwMode::Enter(const Bbr2CongestionEvent& congestion_event) {
+void Bbr2ProbeBwMode::Enter(QuicTime now,
+ const Bbr2CongestionEvent* /*congestion_event*/) {
if (cycle_.phase == CyclePhase::PROBE_NOT_STARTED) {
// First time entering PROBE_BW. Start a new probing cycle.
EnterProbeDown(/*probed_too_high=*/false, /*stopped_risky_probe=*/false,
- congestion_event);
+ now);
} else {
// Transitioning from PROBE_RTT to PROBE_BW. Re-enter the last phase before
// PROBE_RTT.
DCHECK(cycle_.phase == CyclePhase::PROBE_CRUISE ||
cycle_.phase == CyclePhase::PROBE_REFILL);
- cycle_.cycle_start_time = congestion_event.event_time;
+ cycle_.cycle_start_time = now;
if (cycle_.phase == CyclePhase::PROBE_CRUISE) {
- EnterProbeCruise(congestion_event);
+ EnterProbeCruise(now);
} else if (cycle_.phase == CyclePhase::PROBE_REFILL) {
- EnterProbeRefill(cycle_.probe_up_rounds, congestion_event);
+ EnterProbeRefill(cycle_.probe_up_rounds, now);
}
}
}
@@ -89,6 +92,15 @@ bool Bbr2ProbeBwMode::IsProbingForBandwidth() const {
cycle_.phase == CyclePhase::PROBE_UP;
}
+Bbr2Mode Bbr2ProbeBwMode::OnExitQuiescence(QuicTime now,
+ QuicTime quiescence_start_time) {
+ QUIC_DVLOG(3) << sender_ << " Postponing min_rtt_timestamp("
+ << model_->MinRttTimestamp() << ") by "
+ << now - quiescence_start_time;
+ model_->PostponeMinRttTimestamp(now - quiescence_start_time);
+ return Bbr2Mode::PROBE_BW;
+}
+
void Bbr2ProbeBwMode::UpdateProbeDown(
QuicByteCount prior_in_flight,
const Bbr2CongestionEvent& congestion_event) {
@@ -106,7 +118,7 @@ void Bbr2ProbeBwMode::UpdateProbeDown(
}
if (last_cycle_stopped_risky_probe_ && !last_cycle_probed_too_high_) {
- EnterProbeRefill(/*probe_up_rounds=*/0, congestion_event);
+ EnterProbeRefill(/*probe_up_rounds=*/0, congestion_event.event_time);
return;
}
}
@@ -114,13 +126,13 @@ void Bbr2ProbeBwMode::UpdateProbeDown(
MaybeAdaptUpperBounds(congestion_event);
if (IsTimeToProbeBandwidth(congestion_event)) {
- EnterProbeRefill(/*probe_up_rounds=*/0, congestion_event);
+ EnterProbeRefill(/*probe_up_rounds=*/0, congestion_event.event_time);
return;
}
if (HasStayedLongEnoughInProbeDown(congestion_event)) {
QUIC_DVLOG(3) << sender_ << " Proportional time based PROBE_DOWN exit";
- EnterProbeCruise(congestion_event);
+ EnterProbeCruise(congestion_event.event_time);
return;
}
@@ -141,26 +153,39 @@ void Bbr2ProbeBwMode::UpdateProbeDown(
QUIC_DVLOG(3) << sender_ << " Checking if drained to target. prior_in_flight:"
<< prior_in_flight << ", bdp:" << bdp;
if (prior_in_flight < bdp) {
- EnterProbeCruise(congestion_event);
+ EnterProbeCruise(congestion_event.event_time);
}
}
Bbr2ProbeBwMode::AdaptUpperBoundsResult Bbr2ProbeBwMode::MaybeAdaptUpperBounds(
const Bbr2CongestionEvent& congestion_event) {
- const SendTimeState& send_state = SendStateOfLargestPacket(congestion_event);
+ const SendTimeState& send_state = congestion_event.last_packet_send_state;
if (!send_state.is_valid) {
QUIC_DVLOG(3) << sender_ << " " << cycle_.phase
<< ": NOT_ADAPTED_INVALID_SAMPLE";
return NOT_ADAPTED_INVALID_SAMPLE;
}
- if (model_->IsInflightTooHigh(congestion_event)) {
+ const bool has_enough_loss_events =
+ model_->loss_events_in_round() >= Params().probe_bw_full_loss_count;
+
+ if (has_enough_loss_events && model_->IsInflightTooHigh(congestion_event)) {
if (cycle_.is_sample_from_probing) {
cycle_.is_sample_from_probing = false;
if (!send_state.is_app_limited) {
QuicByteCount inflight_at_send = BytesInFlight(send_state);
- model_->set_inflight_hi(inflight_at_send);
+
+ QuicByteCount inflight_target =
+ sender_->GetTargetBytesInflight() * (1.0 - Params().beta);
+ if (inflight_at_send >= inflight_target) {
+ // The new code does not change behavior.
+ QUIC_CODE_COUNT(quic_bbr2_cut_inflight_hi_gradually_noop);
+ } else {
+ // The new code actually cuts inflight_hi slower than before.
+ QUIC_CODE_COUNT(quic_bbr2_cut_inflight_hi_gradually_in_effect);
+ }
+ model_->set_inflight_hi(std::max(inflight_at_send, inflight_target));
}
QUIC_DVLOG(3) << sender_ << " " << cycle_.phase
@@ -192,28 +217,26 @@ Bbr2ProbeBwMode::AdaptUpperBoundsResult Bbr2ProbeBwMode::MaybeAdaptUpperBounds(
bool Bbr2ProbeBwMode::IsTimeToProbeBandwidth(
const Bbr2CongestionEvent& congestion_event) const {
- return HasCycleLasted(cycle_.probe_wait_time, congestion_event) ||
- IsTimeToProbeForRenoCoexistence(1.0, congestion_event);
+ if (HasCycleLasted(cycle_.probe_wait_time, congestion_event)) {
+ return true;
+ }
+
+ if (IsTimeToProbeForRenoCoexistence(1.0, congestion_event)) {
+ ++sender_->connection_stats_->bbr_num_short_cycles_for_reno_coexistence;
+ return true;
+ }
+ return false;
}
// QUIC only. Used to prevent a Bbr2 flow from staying in PROBE_DOWN for too
// long, as seen in some multi-sender simulator tests.
bool Bbr2ProbeBwMode::HasStayedLongEnoughInProbeDown(
const Bbr2CongestionEvent& congestion_event) const {
- if (exit_probe_down_after_one_rtt_) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_bbr2_exit_probe_bw_down_after_one_rtt);
- // Stay in PROBE_DOWN for at most the time of a min rtt, as it is done in
- // BBRv1. The intention here is to figure out whether the performance
- // regression in BBRv2 is because it stays in PROBE_DOWN for too long.
- // TODO(wub): Consider exit after a full round instead, which typically
- // indicates most(if not all) packets sent during PROBE_UP have been acked.
- return HasPhaseLasted(model_->MinRtt(), congestion_event);
- }
- // The amount of time to stay in PROBE_DOWN, as a fraction of probe wait time.
- const double kProbeWaitFraction = 0.2;
- return HasCycleLasted(cycle_.probe_wait_time * kProbeWaitFraction,
- congestion_event) ||
- IsTimeToProbeForRenoCoexistence(kProbeWaitFraction, congestion_event);
+ // Stay in PROBE_DOWN for at most the time of a min rtt, as it is done in
+ // BBRv1.
+ // TODO(wub): Consider exit after a full round instead, which typically
+ // indicates most(if not all) packets sent during PROBE_UP have been acked.
+ return HasPhaseLasted(model_->MinRtt(), congestion_event);
}
bool Bbr2ProbeBwMode::HasCycleLasted(
@@ -245,11 +268,9 @@ bool Bbr2ProbeBwMode::IsTimeToProbeForRenoCoexistence(
const Bbr2CongestionEvent& /*congestion_event*/) const {
uint64_t rounds = Params().probe_bw_probe_max_rounds;
if (Params().probe_bw_probe_reno_gain > 0.0) {
- QuicByteCount bdp = model_->BDP(model_->BandwidthEstimate());
- QuicByteCount inflight_bytes =
- std::min(bdp, sender_->GetCongestionWindow());
- uint64_t reno_rounds =
- Params().probe_bw_probe_reno_gain * inflight_bytes / kDefaultTCPMSS;
+ QuicByteCount target_bytes_inflight = sender_->GetTargetBytesInflight();
+ uint64_t reno_rounds = Params().probe_bw_probe_reno_gain *
+ target_bytes_inflight / kDefaultTCPMSS;
rounds = std::min(rounds, reno_rounds);
}
bool result = cycle_.rounds_since_probe >= (rounds * probe_wait_fraction);
@@ -327,7 +348,7 @@ void Bbr2ProbeBwMode::UpdateProbeCruise(
DCHECK(!cycle_.is_sample_from_probing);
if (IsTimeToProbeBandwidth(congestion_event)) {
- EnterProbeRefill(/*probe_up_rounds=*/0, congestion_event);
+ EnterProbeRefill(/*probe_up_rounds=*/0, congestion_event.event_time);
return;
}
}
@@ -339,7 +360,7 @@ void Bbr2ProbeBwMode::UpdateProbeRefill(
DCHECK(!cycle_.is_sample_from_probing);
if (cycle_.rounds_in_phase > 0 && congestion_event.end_of_round_trip) {
- EnterProbeUp(congestion_event);
+ EnterProbeUp(congestion_event.event_time);
return;
}
}
@@ -350,7 +371,7 @@ void Bbr2ProbeBwMode::UpdateProbeUp(
DCHECK_EQ(cycle_.phase, CyclePhase::PROBE_UP);
if (MaybeAdaptUpperBounds(congestion_event) == ADAPTED_PROBED_TOO_HIGH) {
EnterProbeDown(/*probed_too_high=*/true, /*stopped_risky_probe=*/false,
- congestion_event);
+ congestion_event.event_time);
return;
}
@@ -370,9 +391,16 @@ void Bbr2ProbeBwMode::UpdateProbeUp(
// TCP uses min_rtt instead of a full round:
// HasPhaseLasted(model_->MinRtt(), congestion_event)
} else if (cycle_.rounds_in_phase > 0) {
- QuicByteCount bdp = model_->BDP(model_->MaxBandwidth());
+ const QuicByteCount bdp = model_->BDP(model_->MaxBandwidth());
+ QuicByteCount queuing_threshold_extra_bytes = 2 * kDefaultTCPMSS;
+ if (Params().add_ack_height_to_queueing_threshold) {
+ QUIC_RELOADABLE_FLAG_COUNT(
+ quic_bbr2_add_ack_height_to_queueing_threshold);
+ queuing_threshold_extra_bytes += model_->MaxAckHeight();
+ }
QuicByteCount queuing_threshold =
- (Params().probe_bw_probe_inflight_gain * bdp) + 2 * kDefaultTCPMSS;
+ (Params().probe_bw_probe_inflight_gain * bdp) +
+ queuing_threshold_extra_bytes;
is_queuing = prior_in_flight >= queuing_threshold;
QUIC_DVLOG(3) << sender_
<< " Checking if building up a queue. prior_in_flight:"
@@ -384,28 +412,28 @@ void Bbr2ProbeBwMode::UpdateProbeUp(
if (is_risky || is_queuing) {
EnterProbeDown(/*probed_too_high=*/false, /*stopped_risky_probe=*/is_risky,
- congestion_event);
+ congestion_event.event_time);
}
}
-void Bbr2ProbeBwMode::EnterProbeDown(
- bool probed_too_high,
- bool stopped_risky_probe,
- const Bbr2CongestionEvent& congestion_event) {
+void Bbr2ProbeBwMode::EnterProbeDown(bool probed_too_high,
+ bool stopped_risky_probe,
+ QuicTime now) {
QUIC_DVLOG(2) << sender_ << " Phase change: " << cycle_.phase << " ==> "
<< CyclePhase::PROBE_DOWN << " after "
- << congestion_event.event_time - cycle_.phase_start_time
- << ", or " << cycle_.rounds_in_phase
+ << now - cycle_.phase_start_time << ", or "
+ << cycle_.rounds_in_phase
<< " rounds. probed_too_high:" << probed_too_high
<< ", stopped_risky_probe:" << stopped_risky_probe << " @ "
- << congestion_event.event_time;
+ << now;
last_cycle_probed_too_high_ = probed_too_high;
last_cycle_stopped_risky_probe_ = stopped_risky_probe;
- cycle_.cycle_start_time = congestion_event.event_time;
+ cycle_.cycle_start_time = now;
cycle_.phase = CyclePhase::PROBE_DOWN;
cycle_.rounds_in_phase = 0;
- cycle_.phase_start_time = congestion_event.event_time;
+ cycle_.phase_start_time = now;
+ ++sender_->connection_stats_->bbr_num_cycles;
// Pick probe wait time.
cycle_.rounds_since_probe =
@@ -420,39 +448,35 @@ void Bbr2ProbeBwMode::EnterProbeDown(
model_->RestartRound();
}
-void Bbr2ProbeBwMode::EnterProbeCruise(
- const Bbr2CongestionEvent& congestion_event) {
+void Bbr2ProbeBwMode::EnterProbeCruise(QuicTime now) {
if (cycle_.phase == CyclePhase::PROBE_DOWN) {
- ExitProbeDown(congestion_event);
+ ExitProbeDown();
}
QUIC_DVLOG(2) << sender_ << " Phase change: " << cycle_.phase << " ==> "
<< CyclePhase::PROBE_CRUISE << " after "
- << congestion_event.event_time - cycle_.phase_start_time
- << ", or " << cycle_.rounds_in_phase << " rounds. @ "
- << congestion_event.event_time;
+ << now - cycle_.phase_start_time << ", or "
+ << cycle_.rounds_in_phase << " rounds. @ " << now;
model_->cap_inflight_lo(model_->inflight_hi());
cycle_.phase = CyclePhase::PROBE_CRUISE;
cycle_.rounds_in_phase = 0;
- cycle_.phase_start_time = congestion_event.event_time;
+ cycle_.phase_start_time = now;
cycle_.is_sample_from_probing = false;
}
-void Bbr2ProbeBwMode::EnterProbeRefill(
- uint64_t probe_up_rounds,
- const Bbr2CongestionEvent& congestion_event) {
+void Bbr2ProbeBwMode::EnterProbeRefill(uint64_t probe_up_rounds, QuicTime now) {
if (cycle_.phase == CyclePhase::PROBE_DOWN) {
- ExitProbeDown(congestion_event);
+ ExitProbeDown();
}
QUIC_DVLOG(2) << sender_ << " Phase change: " << cycle_.phase << " ==> "
<< CyclePhase::PROBE_REFILL << " after "
- << congestion_event.event_time - cycle_.phase_start_time
- << ", or " << cycle_.rounds_in_phase
+ << now - cycle_.phase_start_time << ", or "
+ << cycle_.rounds_in_phase
<< " rounds. probe_up_rounds:" << probe_up_rounds << " @ "
- << congestion_event.event_time;
+ << now;
cycle_.phase = CyclePhase::PROBE_REFILL;
cycle_.rounds_in_phase = 0;
- cycle_.phase_start_time = congestion_event.event_time;
+ cycle_.phase_start_time = now;
cycle_.is_sample_from_probing = false;
last_cycle_stopped_risky_probe_ = false;
@@ -463,25 +487,22 @@ void Bbr2ProbeBwMode::EnterProbeRefill(
model_->RestartRound();
}
-void Bbr2ProbeBwMode::EnterProbeUp(
- const Bbr2CongestionEvent& congestion_event) {
+void Bbr2ProbeBwMode::EnterProbeUp(QuicTime now) {
DCHECK_EQ(cycle_.phase, CyclePhase::PROBE_REFILL);
QUIC_DVLOG(2) << sender_ << " Phase change: " << cycle_.phase << " ==> "
<< CyclePhase::PROBE_UP << " after "
- << congestion_event.event_time - cycle_.phase_start_time
- << ", or " << cycle_.rounds_in_phase << " rounds. @ "
- << congestion_event.event_time;
+ << now - cycle_.phase_start_time << ", or "
+ << cycle_.rounds_in_phase << " rounds. @ " << now;
cycle_.phase = CyclePhase::PROBE_UP;
cycle_.rounds_in_phase = 0;
- cycle_.phase_start_time = congestion_event.event_time;
+ cycle_.phase_start_time = now;
cycle_.is_sample_from_probing = true;
RaiseInflightHighSlope();
model_->RestartRound();
}
-void Bbr2ProbeBwMode::ExitProbeDown(
- const Bbr2CongestionEvent& /*congestion_event*/) {
+void Bbr2ProbeBwMode::ExitProbeDown() {
DCHECK_EQ(cycle_.phase, CyclePhase::PROBE_DOWN);
if (!cycle_.has_advanced_max_bw) {
QUIC_DVLOG(2) << sender_ << " Advancing max bw filter at end of cycle.";
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.h
index 45b5a73835e..5c0224ff974 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.h
@@ -20,8 +20,10 @@ class QUIC_EXPORT_PRIVATE Bbr2ProbeBwMode final : public Bbr2ModeBase {
public:
using Bbr2ModeBase::Bbr2ModeBase;
- void Enter(const Bbr2CongestionEvent& congestion_event) override;
- void Leave(const Bbr2CongestionEvent& /*congestion_event*/) override {}
+ void Enter(QuicTime now,
+ const Bbr2CongestionEvent* congestion_event) override;
+ void Leave(QuicTime /*now*/,
+ const Bbr2CongestionEvent* /*congestion_event*/) override {}
Bbr2Mode OnCongestionEvent(
QuicByteCount prior_in_flight,
@@ -34,6 +36,9 @@ class QUIC_EXPORT_PRIVATE Bbr2ProbeBwMode final : public Bbr2ModeBase {
bool IsProbingForBandwidth() const override;
+ Bbr2Mode OnExitQuiescence(QuicTime now,
+ QuicTime quiescence_start_time) override;
+
enum class CyclePhase : uint8_t {
PROBE_NOT_STARTED,
PROBE_UP,
@@ -77,14 +82,13 @@ class QUIC_EXPORT_PRIVATE Bbr2ProbeBwMode final : public Bbr2ModeBase {
void EnterProbeDown(bool probed_too_high,
bool stopped_risky_probe,
- const Bbr2CongestionEvent& congestion_event);
- void EnterProbeCruise(const Bbr2CongestionEvent& congestion_event);
- void EnterProbeRefill(uint64_t probe_up_rounds,
- const Bbr2CongestionEvent& congestion_event);
- void EnterProbeUp(const Bbr2CongestionEvent& congestion_event);
+ QuicTime now);
+ void EnterProbeCruise(QuicTime now);
+ void EnterProbeRefill(uint64_t probe_up_rounds, QuicTime now);
+ void EnterProbeUp(QuicTime now);
// Call right before the exit of PROBE_DOWN.
- void ExitProbeDown(const Bbr2CongestionEvent& congestion_event);
+ void ExitProbeDown();
float PercentTimeElapsedToProbeBandwidth(
const Bbr2CongestionEvent& congestion_event) const;
@@ -122,10 +126,6 @@ class QUIC_EXPORT_PRIVATE Bbr2ProbeBwMode final : public Bbr2ModeBase {
bool last_cycle_probed_too_high_;
bool last_cycle_stopped_risky_probe_;
-
- // Latched value of --quic_bbr2_exit_probe_bw_down_after_one_rtt.
- const bool exit_probe_down_after_one_rtt_ =
- GetQuicReloadableFlag(quic_bbr2_exit_probe_bw_down_after_one_rtt);
};
QUIC_EXPORT_PRIVATE std::ostream& operator<<(
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_rtt.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_rtt.cc
index f9c77097324..ec5cf7c700d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_rtt.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_rtt.cc
@@ -6,10 +6,12 @@
#include "net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
namespace quic {
-void Bbr2ProbeRttMode::Enter(const Bbr2CongestionEvent& /*congestion_event*/) {
+void Bbr2ProbeRttMode::Enter(QuicTime /*now*/,
+ const Bbr2CongestionEvent* /*congestion_event*/) {
model_->set_pacing_gain(1.0);
model_->set_cwnd_gain(1.0);
exit_time_ = QuicTime::Zero();
@@ -51,6 +53,15 @@ Limits<QuicByteCount> Bbr2ProbeRttMode::GetCwndLimits() const {
return NoGreaterThan(std::min(inflight_upper_bound, InflightTarget()));
}
+Bbr2Mode Bbr2ProbeRttMode::OnExitQuiescence(
+ QuicTime now,
+ QuicTime /*quiescence_start_time*/) {
+ if (now > exit_time_) {
+ return Bbr2Mode::PROBE_BW;
+ }
+ return Bbr2Mode::PROBE_RTT;
+}
+
Bbr2ProbeRttMode::DebugState Bbr2ProbeRttMode::ExportDebugState() const {
DebugState s;
s.inflight_target = InflightTarget();
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_rtt.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_rtt.h
index 80a9d93d423..156fda52fd6 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_rtt.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_rtt.h
@@ -17,8 +17,10 @@ class QUIC_EXPORT_PRIVATE Bbr2ProbeRttMode final : public Bbr2ModeBase {
public:
using Bbr2ModeBase::Bbr2ModeBase;
- void Enter(const Bbr2CongestionEvent& congestion_event) override;
- void Leave(const Bbr2CongestionEvent& /*congestion_event*/) override {}
+ void Enter(QuicTime now,
+ const Bbr2CongestionEvent* congestion_event) override;
+ void Leave(QuicTime /*now*/,
+ const Bbr2CongestionEvent* /*congestion_event*/) override {}
Bbr2Mode OnCongestionEvent(
QuicByteCount prior_in_flight,
@@ -31,6 +33,9 @@ class QUIC_EXPORT_PRIVATE Bbr2ProbeRttMode final : public Bbr2ModeBase {
bool IsProbingForBandwidth() const override { return false; }
+ Bbr2Mode OnExitQuiescence(QuicTime now,
+ QuicTime quiescence_start_time) override;
+
struct QUIC_EXPORT_PRIVATE DebugState {
QuicByteCount inflight_target;
QuicTime exit_time = QuicTime::Zero();
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.cc
index 31bf29946e5..4d794432ec4 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.cc
@@ -12,6 +12,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
#include "net/third_party/quiche/src/quic/core/quic_bandwidth.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
namespace quic {
@@ -57,7 +58,8 @@ Bbr2Sender::Bbr2Sender(QuicTime now,
QuicPacketCount initial_cwnd_in_packets,
QuicPacketCount max_cwnd_in_packets,
QuicRandom* random,
- QuicConnectionStats* stats)
+ QuicConnectionStats* stats,
+ BbrSender* old_sender)
: mode_(Bbr2Mode::STARTUP),
rtt_stats_(rtt_stats),
unacked_packets_(unacked_packets),
@@ -69,7 +71,8 @@ Bbr2Sender::Bbr2Sender(QuicTime now,
rtt_stats->SmoothedOrInitialRtt(),
rtt_stats->last_update_time(),
/*cwnd_gain=*/1.0,
- /*pacing_gain=*/kInitialPacingGain),
+ /*pacing_gain=*/kInitialPacingGain,
+ old_sender ? &old_sender->sampler_ : nullptr),
initial_cwnd_(
cwnd_limits().ApplyLimits(initial_cwnd_in_packets * kDefaultTCPMSS)),
cwnd_(initial_cwnd_),
@@ -80,7 +83,6 @@ Bbr2Sender::Bbr2Sender(QuicTime now,
drain_(this, &model_),
probe_bw_(this, &model_),
probe_rtt_(this, &model_),
- flexible_app_limited_(false),
last_sample_is_app_limited_(false) {
QUIC_DVLOG(2) << this << " Initializing Bbr2Sender. mode:" << mode_
<< ", PacingRate:" << pacing_rate_ << ", Cwnd:" << cwnd_
@@ -91,7 +93,20 @@ Bbr2Sender::Bbr2Sender(QuicTime now,
void Bbr2Sender::SetFromConfig(const QuicConfig& config,
Perspective perspective) {
if (config.HasClientRequestedIndependentOption(kBBR9, perspective)) {
- flexible_app_limited_ = true;
+ params_.flexible_app_limited = true;
+ }
+ if (GetQuicReloadableFlag(
+ quic_avoid_overestimate_bandwidth_with_aggregation) &&
+ config.HasClientRequestedIndependentOption(kBSAO, perspective)) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(
+ quic_avoid_overestimate_bandwidth_with_aggregation, 4, 4);
+ model_.EnableOverestimateAvoidance();
+ }
+ if (config.HasClientRequestedIndependentOption(kB2NA, perspective)) {
+ params_.add_ack_height_to_queueing_threshold = false;
+ }
+ if (config.HasClientRequestedIndependentOption(kB2RP, perspective)) {
+ params_.avoid_unnecessary_probe_rtt = false;
}
}
@@ -112,7 +127,7 @@ Limits<QuicByteCount> Bbr2Sender::GetCwndLimitsByMode() const {
}
const Limits<QuicByteCount>& Bbr2Sender::cwnd_limits() const {
- return params_.cwnd_limits;
+ return params().cwnd_limits;
}
void Bbr2Sender::AdjustNetworkParameters(const NetworkParams& params) {
@@ -150,6 +165,7 @@ void Bbr2Sender::OnCongestionEvent(bool /*rtt_updated*/,
<< " prior_cwnd:" << cwnd_ << " @ " << event_time;
Bbr2CongestionEvent congestion_event;
congestion_event.prior_cwnd = cwnd_;
+ congestion_event.prior_bytes_in_flight = prior_in_flight;
congestion_event.is_probing_for_bandwidth =
BBR2_MODE_DISPATCH(IsProbingForBandwidth());
@@ -169,9 +185,9 @@ void Bbr2Sender::OnCongestionEvent(bool /*rtt_updated*/,
QUIC_DVLOG(2) << this << " Mode change: " << mode_ << " ==> " << next_mode
<< " @ " << event_time;
- BBR2_MODE_DISPATCH(Leave(congestion_event));
+ BBR2_MODE_DISPATCH(Leave(event_time, &congestion_event));
mode_ = next_mode;
- BBR2_MODE_DISPATCH(Enter(congestion_event));
+ BBR2_MODE_DISPATCH(Enter(event_time, &congestion_event));
--mode_changes_allowed;
if (mode_changes_allowed < 0) {
QUIC_BUG << "Exceeded max number of mode changes per congestion event.";
@@ -188,12 +204,17 @@ void Bbr2Sender::OnCongestionEvent(bool /*rtt_updated*/,
model_.OnCongestionEventFinish(unacked_packets_->GetLeastUnacked(),
congestion_event);
last_sample_is_app_limited_ = congestion_event.last_sample_is_app_limited;
+ if (congestion_event.bytes_in_flight == 0 &&
+ params().avoid_unnecessary_probe_rtt) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_avoid_unnecessary_probe_rtt, 2, 2);
+ OnEnterQuiescence(event_time);
+ }
QUIC_DVLOG(3)
<< this << " END CongestionEvent(acked:" << acked_packets
<< ", lost:" << lost_packets.size() << ") "
<< ", Mode:" << mode_ << ", RttCount:" << model_.RoundTripCount()
- << ", BytesInFlight:" << model_.bytes_in_flight()
+ << ", BytesInFlight:" << congestion_event.bytes_in_flight
<< ", PacingRate:" << PacingRate(0) << ", CWND:" << GetCongestionWindow()
<< ", PacingGain:" << model_.pacing_gain()
<< ", CwndGain:" << model_.cwnd_gain()
@@ -274,15 +295,23 @@ void Bbr2Sender::OnPacketSent(QuicTime sent_time,
HasRetransmittableData is_retransmittable) {
QUIC_DVLOG(3) << this << " OnPacketSent: pkn:" << packet_number
<< ", bytes:" << bytes << ", cwnd:" << cwnd_
- << ", inflight:" << model_.bytes_in_flight() + bytes
+ << ", inflight:" << bytes_in_flight + bytes
<< ", total_sent:" << model_.total_bytes_sent() + bytes
<< ", total_acked:" << model_.total_bytes_acked()
<< ", total_lost:" << model_.total_bytes_lost() << " @ "
<< sent_time;
+ if (bytes_in_flight == 0 && params().avoid_unnecessary_probe_rtt) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_avoid_unnecessary_probe_rtt, 1, 2);
+ OnExitQuiescence(sent_time);
+ }
model_.OnPacketSent(sent_time, bytes_in_flight, packet_number, bytes,
is_retransmittable);
}
+void Bbr2Sender::OnPacketNeutered(QuicPacketNumber packet_number) {
+ model_.OnPacketNeutered(packet_number);
+}
+
bool Bbr2Sender::CanSend(QuicByteCount bytes_in_flight) {
const bool result = bytes_in_flight < GetCongestionWindow();
return result;
@@ -301,7 +330,7 @@ void Bbr2Sender::OnApplicationLimited(QuicByteCount bytes_in_flight) {
if (bytes_in_flight >= GetCongestionWindow()) {
return;
}
- if (flexible_app_limited_ && IsPipeSufficientlyFull()) {
+ if (params().flexible_app_limited && IsPipeSufficientlyFull()) {
return;
}
@@ -311,10 +340,32 @@ void Bbr2Sender::OnApplicationLimited(QuicByteCount bytes_in_flight) {
<< ", CWND: " << GetCongestionWindow();
}
+QuicByteCount Bbr2Sender::GetTargetBytesInflight() const {
+ QuicByteCount bdp = model_.BDP(model_.BandwidthEstimate());
+ return std::min(bdp, GetCongestionWindow());
+}
+
void Bbr2Sender::PopulateConnectionStats(QuicConnectionStats* stats) const {
stats->num_ack_aggregation_epochs = model_.num_ack_aggregation_epochs();
}
+void Bbr2Sender::OnEnterQuiescence(QuicTime now) {
+ last_quiescence_start_ = now;
+}
+
+void Bbr2Sender::OnExitQuiescence(QuicTime now) {
+ if (last_quiescence_start_ != QuicTime::Zero()) {
+ Bbr2Mode next_mode = BBR2_MODE_DISPATCH(
+ OnExitQuiescence(now, std::min(now, last_quiescence_start_)));
+ if (next_mode != mode_) {
+ BBR2_MODE_DISPATCH(Leave(now, nullptr));
+ mode_ = next_mode;
+ BBR2_MODE_DISPATCH(Enter(now, nullptr));
+ }
+ last_quiescence_start_ = QuicTime::Zero();
+ }
+}
+
bool Bbr2Sender::ShouldSendProbingPacket() const {
// TODO(wub): Implement ShouldSendProbingPacket properly.
if (!BBR2_MODE_DISPATCH(IsProbingForBandwidth())) {
@@ -324,12 +375,12 @@ bool Bbr2Sender::ShouldSendProbingPacket() const {
// TODO(b/77975811): If the pipe is highly under-utilized, consider not
// sending a probing transmission, because the extra bandwidth is not needed.
// If flexible_app_limited is enabled, check if the pipe is sufficiently full.
- if (flexible_app_limited_) {
+ if (params().flexible_app_limited) {
const bool is_pipe_sufficiently_full = IsPipeSufficientlyFull();
QUIC_DVLOG(3) << this << " CWND: " << GetCongestionWindow()
- << ", inflight: " << model_.bytes_in_flight()
+ << ", inflight: " << unacked_packets_->bytes_in_flight()
<< ", pacing_rate: " << PacingRate(0)
- << ", flexible_app_limited_: true, ShouldSendProbingPacket: "
+ << ", flexible_app_limited: true, ShouldSendProbingPacket: "
<< !is_pipe_sufficiently_full;
return !is_pipe_sufficiently_full;
} else {
@@ -338,20 +389,20 @@ bool Bbr2Sender::ShouldSendProbingPacket() const {
}
bool Bbr2Sender::IsPipeSufficientlyFull() const {
+ QuicByteCount bytes_in_flight = unacked_packets_->bytes_in_flight();
// See if we need more bytes in flight to see more bandwidth.
if (mode_ == Bbr2Mode::STARTUP) {
// STARTUP exits if it doesn't observe a 25% bandwidth increase, so the CWND
// must be more than 25% above the target.
- return model_.bytes_in_flight() >= GetTargetCongestionWindow(1.5);
+ return bytes_in_flight >= GetTargetCongestionWindow(1.5);
}
if (model_.pacing_gain() > 1) {
// Super-unity PROBE_BW doesn't exit until 1.25 * BDP is achieved.
- return model_.bytes_in_flight() >=
- GetTargetCongestionWindow(model_.pacing_gain());
+ return bytes_in_flight >= GetTargetCongestionWindow(model_.pacing_gain());
}
// If bytes_in_flight are above the target congestion window, it should be
// possible to observe the same or more bandwidth if it's available.
- return model_.bytes_in_flight() >= GetTargetCongestionWindow(1.1);
+ return bytes_in_flight >= GetTargetCongestionWindow(1.1);
}
std::string Bbr2Sender::GetDebugState() const {
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.h
index 4cfd34c74c7..d68a6a13265 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.h
@@ -13,12 +13,14 @@
#include "net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.h"
#include "net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_rtt.h"
#include "net/third_party/quiche/src/quic/core/congestion_control/bbr2_startup.h"
+#include "net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.h"
#include "net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h"
#include "net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h"
#include "net/third_party/quiche/src/quic/core/congestion_control/windowed_filter.h"
#include "net/third_party/quiche/src/quic/core/quic_bandwidth.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
namespace quic {
@@ -30,7 +32,8 @@ class QUIC_EXPORT_PRIVATE Bbr2Sender final : public SendAlgorithmInterface {
QuicPacketCount initial_cwnd_in_packets,
QuicPacketCount max_cwnd_in_packets,
QuicRandom* random,
- QuicConnectionStats* stats);
+ QuicConnectionStats* stats,
+ BbrSender* old_sender);
~Bbr2Sender() override = default;
@@ -64,6 +67,8 @@ class QUIC_EXPORT_PRIVATE Bbr2Sender final : public SendAlgorithmInterface {
QuicByteCount bytes,
HasRetransmittableData is_retransmittable) override;
+ void OnPacketNeutered(QuicPacketNumber packet_number) override;
+
void OnRetransmissionTimeout(bool /*packets_retransmitted*/) override {}
void OnConnectionMigration() override {}
@@ -97,6 +102,9 @@ class QUIC_EXPORT_PRIVATE Bbr2Sender final : public SendAlgorithmInterface {
return cwnd_limits().Min();
}
+ // Returns the min of BDP and congestion window.
+ QuicByteCount GetTargetBytesInflight() const;
+
struct QUIC_EXPORT_PRIVATE DebugState {
Bbr2Mode mode;
@@ -128,6 +136,8 @@ class QUIC_EXPORT_PRIVATE Bbr2Sender final : public SendAlgorithmInterface {
void UpdatePacingRate(QuicByteCount bytes_acked);
void UpdateCongestionWindow(QuicByteCount bytes_acked);
QuicByteCount GetTargetCongestionWindow(float gain) const;
+ void OnEnterQuiescence(QuicTime now);
+ void OnExitQuiescence(QuicTime now);
// Helper function for BBR2_MODE_DISPATCH.
Bbr2ProbeRttMode& probe_rtt_or_die() {
@@ -154,6 +164,8 @@ class QUIC_EXPORT_PRIVATE Bbr2Sender final : public SendAlgorithmInterface {
// Cwnd limits imposed by caller.
const Limits<QuicByteCount>& cwnd_limits() const;
+ const Bbr2Params& params() const { return params_; }
+
Bbr2Mode mode_;
const RttStats* const rtt_stats_;
@@ -161,7 +173,9 @@ class QUIC_EXPORT_PRIVATE Bbr2Sender final : public SendAlgorithmInterface {
QuicRandom* random_;
QuicConnectionStats* connection_stats_;
- const Bbr2Params params_;
+ // Don't use it directly outside of SetFromConfig. Instead, use params() to
+ // get read-only access.
+ Bbr2Params params_;
Bbr2NetworkModel model_;
@@ -171,15 +185,13 @@ class QUIC_EXPORT_PRIVATE Bbr2Sender final : public SendAlgorithmInterface {
QuicByteCount cwnd_;
QuicBandwidth pacing_rate_;
+ QuicTime last_quiescence_start_ = QuicTime::Zero();
+
Bbr2StartupMode startup_;
Bbr2DrainMode drain_;
Bbr2ProbeBwMode probe_bw_;
Bbr2ProbeRttMode probe_rtt_;
- // Indicates app-limited calls should be ignored as long as there's
- // enough data inflight to see more bandwidth when necessary.
- bool flexible_app_limited_;
-
// Debug only.
bool last_sample_is_app_limited_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_simulator_test.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_simulator_test.cc
index 005e11deae7..949b2834e89 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_simulator_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_simulator_test.cc
@@ -11,23 +11,37 @@
#include "net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.h"
#include "net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.h"
#include "net/third_party/quiche/src/quic/core/quic_bandwidth.h"
+#include "net/third_party/quiche/src/quic/core/quic_packet_number.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_optional.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/send_algorithm_test_result.pb.h"
+#include "net/third_party/quiche/src/quic/test_tools/send_algorithm_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/link.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/switch.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/traffic_policer.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_optional.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
using testing::AllOf;
using testing::Ge;
using testing::Le;
+DEFINE_QUIC_COMMAND_LINE_FLAG(
+ std::string,
+ quic_bbr2_test_regression_mode,
+ "",
+ "One of a) 'record' to record test result (one file per test), or "
+ "b) 'regress' to regress against recorded results, or "
+ "c) <anything else> for non-regression mode.");
+
namespace quic {
using CyclePhase = Bbr2ProbeBwMode::CyclePhase;
@@ -77,7 +91,7 @@ class DefaultTopologyParams {
// Network switch queue capacity, in number of BDPs.
float switch_queue_capacity_in_bdp = 2;
- QuicOptional<TrafficPolicerParams> sender_policer_params;
+ quiche::QuicheOptional<TrafficPolicerParams> sender_policer_params;
QuicBandwidth BottleneckBandwidth() const {
return std::min(local_link.bandwidth, test_link.bandwidth);
@@ -107,11 +121,42 @@ class DefaultTopologyParams {
class Bbr2SimulatorTest : public QuicTest {
protected:
- Bbr2SimulatorTest() {
+ Bbr2SimulatorTest() : simulator_(&random_) {
// Disable Ack Decimation by default, because it can significantly increase
// srtt. Individual test can enable it via QuicConnectionPeer::SetAckMode().
SetQuicReloadableFlag(quic_enable_ack_decimation, false);
}
+
+ void SetUp() override {
+ if (GetQuicFlag(FLAGS_quic_bbr2_test_regression_mode) == "regress") {
+ SendAlgorithmTestResult expected;
+ ASSERT_TRUE(LoadSendAlgorithmTestResult(&expected));
+ random_seed_ = expected.random_seed();
+ } else {
+ random_seed_ = QuicRandom::GetInstance()->RandUint64();
+ }
+ random_.set_seed(random_seed_);
+ QUIC_LOG(INFO) << "Using random seed: " << random_seed_;
+ }
+
+ ~Bbr2SimulatorTest() override {
+ const std::string regression_mode =
+ GetQuicFlag(FLAGS_quic_bbr2_test_regression_mode);
+ const QuicTime::Delta simulated_duration =
+ SimulatedNow() - QuicTime::Zero();
+ if (regression_mode == "record") {
+ RecordSendAlgorithmTestResult(random_seed_,
+ simulated_duration.ToMicroseconds());
+ } else if (regression_mode == "regress") {
+ CompareSendAlgorithmTestResult(simulated_duration.ToMicroseconds());
+ }
+ }
+
+ QuicTime SimulatedNow() const { return simulator_.GetClock()->Now(); }
+
+ uint64_t random_seed_;
+ SimpleRandom random_;
+ simulator::Simulator simulator_;
};
class Bbr2DefaultTopologyTest : public Bbr2SimulatorTest {
@@ -127,13 +172,7 @@ class Bbr2DefaultTopologyTest : public Bbr2SimulatorTest {
"Sender",
Perspective::IS_SERVER,
TestConnectionId(42)) {
- sender_ = SetupBbr2Sender(&sender_endpoint_);
-
- uint64_t seed = QuicRandom::GetInstance()->RandUint64();
- random_.set_seed(seed);
- QUIC_LOG(INFO) << "Bbr2DefaultTopologyTest set up. Seed: " << seed;
-
- simulator_.set_random_generator(&random_);
+ sender_ = SetupBbr2Sender(&sender_endpoint_, /*old_sender=*/nullptr);
}
~Bbr2DefaultTopologyTest() {
@@ -148,16 +187,20 @@ class Bbr2DefaultTopologyTest : public Bbr2SimulatorTest {
<< "%, bw_hi:" << debug_state.bandwidth_hi;
}
- Bbr2Sender* SetupBbr2Sender(simulator::QuicEndpoint* endpoint) {
+ QuicUnackedPacketMap* GetUnackedMap(QuicConnection* connection) {
+ return QuicSentPacketManagerPeer::GetUnackedPacketMap(
+ QuicConnectionPeer::GetSentPacketManager(connection));
+ }
+
+ Bbr2Sender* SetupBbr2Sender(simulator::QuicEndpoint* endpoint,
+ BbrSender* old_sender) {
// Ownership of the sender will be overtaken by the endpoint.
Bbr2Sender* sender = new Bbr2Sender(
endpoint->connection()->clock()->Now(),
endpoint->connection()->sent_packet_manager().GetRttStats(),
- QuicSentPacketManagerPeer::GetUnackedPacketMap(
- QuicConnectionPeer::GetSentPacketManager(endpoint->connection())),
- kDefaultInitialCwndPackets,
+ GetUnackedMap(endpoint->connection()), kDefaultInitialCwndPackets,
GetQuicFlag(FLAGS_quic_max_congestion_window), &random_,
- QuicConnectionPeer::GetStats(endpoint->connection()));
+ QuicConnectionPeer::GetStats(endpoint->connection()), old_sender);
QuicConnectionPeer::SetSendAlgorithm(endpoint->connection(), sender);
endpoint->RecordTrace();
return sender;
@@ -264,6 +307,14 @@ class Bbr2DefaultTopologyTest : public Bbr2SimulatorTest {
aggregation_timeout);
}
+ void SetConnectionOption(QuicTag option) {
+ QuicConfig config;
+ QuicTagVector options;
+ options.push_back(option);
+ QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+ sender_->SetFromConfig(config, Perspective::IS_SERVER);
+ }
+
bool Bbr2ModeIsOneOf(const std::vector<Bbr2Mode>& expected_modes) const {
const Bbr2Mode mode = sender_->ExportDebugState().mode;
for (Bbr2Mode expected_mode : expected_modes) {
@@ -274,8 +325,6 @@ class Bbr2DefaultTopologyTest : public Bbr2SimulatorTest {
return false;
}
- QuicTime SimulatedNow() const { return simulator_.GetClock()->Now(); }
-
const RttStats* rtt_stats() {
return sender_endpoint_.connection()->sent_packet_manager().GetRttStats();
}
@@ -286,16 +335,18 @@ class Bbr2DefaultTopologyTest : public Bbr2SimulatorTest {
return sender_connection()->GetStats();
}
+ QuicUnackedPacketMap* sender_unacked_map() {
+ return GetUnackedMap(sender_connection());
+ }
+
float sender_loss_rate_in_packets() {
return static_cast<float>(sender_connection_stats().packets_lost) /
sender_connection_stats().packets_sent;
}
- simulator::Simulator simulator_;
simulator::QuicEndpoint sender_endpoint_;
simulator::QuicEndpoint receiver_endpoint_;
Bbr2Sender* sender_;
- SimpleRandom random_;
std::unique_ptr<simulator::Switch> switch_;
std::unique_ptr<simulator::TrafficPolicer> sender_policer_;
@@ -359,7 +410,7 @@ TEST_F(Bbr2DefaultTopologyTest, SimpleTransfer) {
// The margin here is quite high, since there exists a possibility that the
// connection just exited high gain cycle.
- EXPECT_APPROX_EQ(params.RTT(), rtt_stats()->smoothed_rtt(), 0.2f);
+ EXPECT_APPROX_EQ(params.RTT(), rtt_stats()->smoothed_rtt(), 1.0f);
}
TEST_F(Bbr2DefaultTopologyTest, SimpleTransferSmallBuffer) {
@@ -376,6 +427,10 @@ TEST_F(Bbr2DefaultTopologyTest, SimpleTransferSmallBuffer) {
}
TEST_F(Bbr2DefaultTopologyTest, SimpleTransfer2RTTAggregationBytes) {
+ if (GetQuicReloadableFlag(
+ quic_avoid_overestimate_bandwidth_with_aggregation)) {
+ SetConnectionOption(kBSAO);
+ }
DefaultTopologyParams params;
CreateNetwork(params);
// 2 RTTs of aggregation, with a max of 10kb.
@@ -385,11 +440,17 @@ TEST_F(Bbr2DefaultTopologyTest, SimpleTransfer2RTTAggregationBytes) {
DoSimpleTransfer(12 * 1024 * 1024, QuicTime::Delta::FromSeconds(35));
EXPECT_TRUE(Bbr2ModeIsOneOf({Bbr2Mode::PROBE_BW, Bbr2Mode::PROBE_RTT}));
- EXPECT_LE(params.BottleneckBandwidth() * 0.99f,
- sender_->ExportDebugState().bandwidth_hi);
- // TODO(b/36022633): Bandwidth sampler overestimates with aggregation.
- EXPECT_GE(params.BottleneckBandwidth() * 1.5f,
- sender_->ExportDebugState().bandwidth_hi);
+ if (GetQuicReloadableFlag(
+ quic_avoid_overestimate_bandwidth_with_aggregation)) {
+ EXPECT_APPROX_EQ(params.BottleneckBandwidth(),
+ sender_->ExportDebugState().bandwidth_hi, 0.01f);
+ } else {
+ EXPECT_LE(params.BottleneckBandwidth() * 0.99f,
+ sender_->ExportDebugState().bandwidth_hi);
+ // TODO(b/36022633): Bandwidth sampler overestimates with aggregation.
+ EXPECT_GE(params.BottleneckBandwidth() * 1.5f,
+ sender_->ExportDebugState().bandwidth_hi);
+ }
EXPECT_LE(sender_loss_rate_in_packets(), 0.05);
// The margin here is high, because the aggregation greatly increases
// smoothed rtt.
@@ -398,6 +459,10 @@ TEST_F(Bbr2DefaultTopologyTest, SimpleTransfer2RTTAggregationBytes) {
}
TEST_F(Bbr2DefaultTopologyTest, SimpleTransferAckDecimation) {
+ if (GetQuicReloadableFlag(
+ quic_avoid_overestimate_bandwidth_with_aggregation)) {
+ SetConnectionOption(kBSAO);
+ }
// Enable Ack Decimation on the receiver.
QuicConnectionPeer::SetAckMode(receiver_endpoint_.connection(),
AckMode::ACK_DECIMATION);
@@ -408,16 +473,22 @@ TEST_F(Bbr2DefaultTopologyTest, SimpleTransferAckDecimation) {
DoSimpleTransfer(12 * 1024 * 1024, QuicTime::Delta::FromSeconds(35));
EXPECT_TRUE(Bbr2ModeIsOneOf({Bbr2Mode::PROBE_BW, Bbr2Mode::PROBE_RTT}));
- EXPECT_LE(params.BottleneckBandwidth() * 0.99f,
- sender_->ExportDebugState().bandwidth_hi);
- // TODO(b/36022633): Bandwidth sampler overestimates with aggregation.
- EXPECT_GE(params.BottleneckBandwidth() * 1.1f,
- sender_->ExportDebugState().bandwidth_hi);
+ if (GetQuicReloadableFlag(
+ quic_avoid_overestimate_bandwidth_with_aggregation)) {
+ EXPECT_APPROX_EQ(params.BottleneckBandwidth(),
+ sender_->ExportDebugState().bandwidth_hi, 0.01f);
+ } else {
+ EXPECT_LE(params.BottleneckBandwidth() * 0.99f,
+ sender_->ExportDebugState().bandwidth_hi);
+ // TODO(b/36022633): Bandwidth sampler overestimates with aggregation.
+ EXPECT_GE(params.BottleneckBandwidth() * 1.1f,
+ sender_->ExportDebugState().bandwidth_hi);
+ }
EXPECT_LE(sender_loss_rate_in_packets(), 0.001);
EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
// The margin here is high, because the aggregation greatly increases
// smoothed rtt.
- EXPECT_GE(params.RTT() * 2, rtt_stats()->smoothed_rtt());
+ EXPECT_GE(params.RTT() * 3, rtt_stats()->smoothed_rtt());
EXPECT_APPROX_EQ(params.RTT(), rtt_stats()->min_rtt(), 0.1f);
}
@@ -699,16 +770,265 @@ TEST_F(Bbr2DefaultTopologyTest, StartupStats) {
->GetSlowStartDuration());
}
+TEST_F(Bbr2DefaultTopologyTest, ProbeUpAdaptInflightHiGradually) {
+ DefaultTopologyParams params;
+ CreateNetwork(params);
+
+ DriveOutOfStartup(params);
+
+ AckedPacketVector acked_packets;
+ QuicPacketNumber acked_packet_number =
+ sender_unacked_map()->GetLeastUnacked();
+ for (auto& info : *sender_unacked_map()) {
+ acked_packets.emplace_back(acked_packet_number++, info.bytes_sent,
+ SimulatedNow());
+ }
+
+ // Advance time significantly so the OnCongestionEvent enters PROBE_REFILL.
+ QuicTime now = SimulatedNow() + QuicTime::Delta::FromSeconds(5);
+ auto next_packet_number = sender_unacked_map()->largest_sent_packet() + 1;
+ sender_->OnCongestionEvent(
+ /*rtt_updated=*/true, sender_unacked_map()->bytes_in_flight(), now,
+ acked_packets, {});
+ ASSERT_EQ(CyclePhase::PROBE_REFILL,
+ sender_->ExportDebugState().probe_bw.phase);
+
+ // Send and Ack one packet to exit app limited and enter PROBE_UP.
+ sender_->OnPacketSent(now, /*bytes_in_flight=*/0, next_packet_number++,
+ kDefaultMaxPacketSize, HAS_RETRANSMITTABLE_DATA);
+ now = now + params.RTT();
+ sender_->OnCongestionEvent(
+ /*rtt_updated=*/true, kDefaultMaxPacketSize, now,
+ {AckedPacket(next_packet_number - 1, kDefaultMaxPacketSize, now)}, {});
+ ASSERT_EQ(CyclePhase::PROBE_UP, sender_->ExportDebugState().probe_bw.phase);
+
+ // Send 2 packets and lose the first one(50% loss) to exit PROBE_UP.
+ for (uint64_t i = 0; i < 2; ++i) {
+ sender_->OnPacketSent(now, /*bytes_in_flight=*/i * kDefaultMaxPacketSize,
+ next_packet_number++, kDefaultMaxPacketSize,
+ HAS_RETRANSMITTABLE_DATA);
+ }
+ now = now + params.RTT();
+ sender_->OnCongestionEvent(
+ /*rtt_updated=*/true, kDefaultMaxPacketSize, now,
+ {AckedPacket(next_packet_number - 1, kDefaultMaxPacketSize, now)},
+ {LostPacket(next_packet_number - 2, kDefaultMaxPacketSize)});
+
+ QuicByteCount inflight_hi = sender_->ExportDebugState().inflight_hi;
+ EXPECT_LT(2 * kDefaultMaxPacketSize, inflight_hi);
+}
+
+// Ensures bandwidth estimate does not change after a loss only event.
+TEST_F(Bbr2DefaultTopologyTest, LossOnlyCongestionEvent) {
+ DefaultTopologyParams params;
+ CreateNetwork(params);
+
+ DriveOutOfStartup(params);
+ EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
+
+ // Send some bursts, each burst increments round count by 1, since it only
+ // generates small, app-limited samples, the max_bandwidth_filter_ will not be
+ // updated.
+ SendBursts(params, 20, 512, QuicTime::Delta::FromSeconds(3));
+
+ // Run until we have something in flight.
+ sender_endpoint_.AddBytesToTransfer(50 * 1024 * 1024);
+ bool simulator_result = simulator_.RunUntilOrTimeout(
+ [&]() { return sender_unacked_map()->bytes_in_flight() > 0; },
+ QuicTime::Delta::FromSeconds(5));
+ ASSERT_TRUE(simulator_result);
+
+ const QuicBandwidth prior_bandwidth_estimate = sender_->BandwidthEstimate();
+ EXPECT_APPROX_EQ(params.BottleneckBandwidth(), prior_bandwidth_estimate,
+ 0.01f);
+
+ // Lose the least unacked packet.
+ LostPacketVector lost_packets;
+ lost_packets.emplace_back(
+ sender_connection()->sent_packet_manager().GetLeastUnacked(),
+ kDefaultMaxPacketSize);
+
+ QuicTime now = simulator_.GetClock()->Now() + params.RTT() * 0.25;
+ sender_->OnCongestionEvent(false, sender_unacked_map()->bytes_in_flight(),
+ now, {}, lost_packets);
+
+ // Bandwidth estimate should not change for the loss only event.
+ EXPECT_EQ(prior_bandwidth_estimate, sender_->BandwidthEstimate());
+}
+
+// After quiescence, if the sender is in PROBE_RTT, it should transition to
+// PROBE_BW immediately on the first sent packet after quiescence.
+TEST_F(Bbr2DefaultTopologyTest, ProbeRttAfterQuiescenceImmediatelyExits) {
+ DefaultTopologyParams params;
+ CreateNetwork(params);
+
+ DriveOutOfStartup(params);
+
+ const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(15);
+ bool simulator_result;
+
+ // Keep sending until reach PROBE_RTT.
+ simulator_result = SendUntilOrTimeout(
+ [this]() {
+ return sender_->ExportDebugState().mode == Bbr2Mode::PROBE_RTT;
+ },
+ timeout);
+ ASSERT_TRUE(simulator_result);
+
+ // Wait for entering a quiescence of 5 seconds.
+ ASSERT_TRUE(simulator_.RunUntilOrTimeout(
+ [this]() {
+ return sender_unacked_map()->bytes_in_flight() == 0 &&
+ sender_->ExportDebugState().mode == Bbr2Mode::PROBE_RTT;
+ },
+ timeout));
+
+ simulator_.RunFor(QuicTime::Delta::FromSeconds(5));
+
+ // Send one packet to exit quiescence.
+ EXPECT_EQ(sender_->ExportDebugState().mode, Bbr2Mode::PROBE_RTT);
+ sender_->OnPacketSent(SimulatedNow(), /*bytes_in_flight=*/0,
+ sender_unacked_map()->largest_sent_packet() + 1,
+ kDefaultMaxPacketSize, HAS_RETRANSMITTABLE_DATA);
+ if (GetQuicReloadableFlag(quic_bbr2_avoid_unnecessary_probe_rtt)) {
+ EXPECT_EQ(sender_->ExportDebugState().mode, Bbr2Mode::PROBE_BW);
+ } else {
+ EXPECT_EQ(sender_->ExportDebugState().mode, Bbr2Mode::PROBE_RTT);
+ }
+}
+
+TEST_F(Bbr2DefaultTopologyTest, ProbeBwAfterQuiescencePostponeMinRttTimestamp) {
+ DefaultTopologyParams params;
+ CreateNetwork(params);
+
+ DriveOutOfStartup(params);
+
+ const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(5);
+ bool simulator_result;
+
+ // Keep sending until reach PROBE_REFILL.
+ simulator_result = SendUntilOrTimeout(
+ [this]() {
+ return sender_->ExportDebugState().probe_bw.phase ==
+ CyclePhase::PROBE_REFILL;
+ },
+ timeout);
+ ASSERT_TRUE(simulator_result);
+
+ const QuicTime min_rtt_timestamp_before_idle =
+ sender_->ExportDebugState().min_rtt_timestamp;
+
+ // Wait for entering a quiescence of 15 seconds.
+ ASSERT_TRUE(simulator_.RunUntilOrTimeout(
+ [this]() { return sender_unacked_map()->bytes_in_flight() == 0; },
+ params.RTT()));
+
+ simulator_.RunFor(QuicTime::Delta::FromSeconds(15));
+
+ // Send some data to exit quiescence.
+ SendBursts(params, 1, kDefaultTCPMSS, QuicTime::Delta::Zero());
+ const QuicTime min_rtt_timestamp_after_idle =
+ sender_->ExportDebugState().min_rtt_timestamp;
+ if (GetQuicReloadableFlag(quic_bbr2_avoid_unnecessary_probe_rtt)) {
+ EXPECT_LT(min_rtt_timestamp_before_idle + QuicTime::Delta::FromSeconds(14),
+ min_rtt_timestamp_after_idle);
+ } else {
+ EXPECT_EQ(min_rtt_timestamp_before_idle, min_rtt_timestamp_after_idle);
+ }
+}
+
+// Regression test for http://shortn/_Jt1QWtshAM.
+TEST_F(Bbr2DefaultTopologyTest, SwitchToBbr2MidConnection) {
+ if (!GetQuicReloadableFlag(quic_bbr_copy_sampler_state_from_v1_to_v2)) {
+ return;
+ }
+ QuicTime now = QuicTime::Zero();
+ BbrSender old_sender(sender_connection()->clock()->Now(),
+ sender_connection()->sent_packet_manager().GetRttStats(),
+ GetUnackedMap(sender_connection()),
+ kDefaultInitialCwndPackets,
+ GetQuicFlag(FLAGS_quic_max_congestion_window), &random_,
+ QuicConnectionPeer::GetStats(sender_connection()));
+
+ QuicPacketNumber next_packet_number(1);
+
+ // Send packets 1-4.
+ while (next_packet_number < QuicPacketNumber(5)) {
+ now = now + QuicTime::Delta::FromMilliseconds(10);
+
+ old_sender.OnPacketSent(now, /*bytes_in_flight=*/0, next_packet_number++,
+ /*bytes=*/1350, HAS_RETRANSMITTABLE_DATA);
+ }
+
+ // Switch from |old_sender| to |sender_|.
+ sender_ = SetupBbr2Sender(&sender_endpoint_, &old_sender);
+
+ // Send packets 5-7.
+ now = now + QuicTime::Delta::FromMilliseconds(10);
+ sender_->OnPacketSent(now, /*bytes_in_flight=*/1350, next_packet_number++,
+ /*bytes=*/23, NO_RETRANSMITTABLE_DATA);
+
+ now = now + QuicTime::Delta::FromMilliseconds(10);
+ sender_->OnPacketSent(now, /*bytes_in_flight=*/1350, next_packet_number++,
+ /*bytes=*/767, HAS_RETRANSMITTABLE_DATA);
+
+ QuicByteCount bytes_in_flight = 767;
+ while (next_packet_number < QuicPacketNumber(30)) {
+ now = now + QuicTime::Delta::FromMilliseconds(10);
+ bytes_in_flight += 1350;
+ sender_->OnPacketSent(now, bytes_in_flight, next_packet_number++,
+ /*bytes=*/1350, HAS_RETRANSMITTABLE_DATA);
+ }
+
+ // Ack 1 & 2.
+ AckedPacketVector acked = {
+ AckedPacket(QuicPacketNumber(1), /*bytes_acked=*/0, QuicTime::Zero()),
+ AckedPacket(QuicPacketNumber(2), /*bytes_acked=*/0, QuicTime::Zero()),
+ };
+ now = now + QuicTime::Delta::FromMilliseconds(2000);
+ sender_->OnCongestionEvent(true, bytes_in_flight, now, acked, {});
+
+ // Send 30-41.
+ while (next_packet_number < QuicPacketNumber(42)) {
+ now = now + QuicTime::Delta::FromMilliseconds(10);
+ bytes_in_flight += 1350;
+ sender_->OnPacketSent(now, bytes_in_flight, next_packet_number++,
+ /*bytes=*/1350, HAS_RETRANSMITTABLE_DATA);
+ }
+
+ // Ack 3.
+ acked = {
+ AckedPacket(QuicPacketNumber(3), /*bytes_acked=*/0, QuicTime::Zero()),
+ };
+ now = now + QuicTime::Delta::FromMilliseconds(2000);
+ sender_->OnCongestionEvent(true, bytes_in_flight, now, acked, {});
+
+ // Send 42.
+ now = now + QuicTime::Delta::FromMilliseconds(10);
+ bytes_in_flight += 1350;
+ sender_->OnPacketSent(now, bytes_in_flight, next_packet_number++,
+ /*bytes=*/1350, HAS_RETRANSMITTABLE_DATA);
+
+ // Ack 4-7.
+ acked = {
+ AckedPacket(QuicPacketNumber(4), /*bytes_acked=*/0, QuicTime::Zero()),
+ AckedPacket(QuicPacketNumber(5), /*bytes_acked=*/0, QuicTime::Zero()),
+ AckedPacket(QuicPacketNumber(6), /*bytes_acked=*/767, QuicTime::Zero()),
+ AckedPacket(QuicPacketNumber(7), /*bytes_acked=*/1350, QuicTime::Zero()),
+ };
+ now = now + QuicTime::Delta::FromMilliseconds(2000);
+ sender_->OnCongestionEvent(true, bytes_in_flight, now, acked, {});
+ EXPECT_FALSE(sender_->BandwidthEstimate().IsZero());
+}
+
// All Bbr2MultiSenderTests uses the following network topology:
//
// Sender 0 (A Bbr2Sender)
// |
// | <-- local_links[0]
// |
-// | Sender N (1 <= N < kNumLocalLinks) (May or may not be a Bbr2Sender)
-// | |
-// | | <-- local_links[N]
-// | |
+// | Sender N (1 <= N < kNumLocalLinks) (May or may not be a
+// Bbr2Sender) | | | | <-- local_links[N] | |
// Network switch
// * <-- the bottleneck queue in the direction
// | of the receiver
@@ -771,8 +1091,8 @@ class Bbr2MultiSenderTest : public Bbr2SimulatorTest {
uint64_t first_connection_id = 42;
std::vector<simulator::QuicEndpointBase*> receiver_endpoint_pointers;
for (size_t i = 0; i < MultiSenderTopologyParams::kNumLocalLinks; ++i) {
- std::string sender_name = QuicStrCat("Sender", i + 1);
- std::string receiver_name = QuicStrCat("Receiver", i + 1);
+ std::string sender_name = quiche::QuicheStrCat("Sender", i + 1);
+ std::string receiver_name = quiche::QuicheStrCat("Receiver", i + 1);
sender_endpoints_.push_back(std::make_unique<simulator::QuicEndpoint>(
&simulator_, sender_name, receiver_name, Perspective::IS_CLIENT,
TestConnectionId(first_connection_id + i)));
@@ -785,12 +1105,6 @@ class Bbr2MultiSenderTest : public Bbr2SimulatorTest {
std::make_unique<simulator::QuicEndpointMultiplexer>(
"Receiver multiplexer", receiver_endpoint_pointers);
sender_1_ = SetupBbr2Sender(sender_endpoints_[0].get());
-
- uint64_t seed = QuicRandom::GetInstance()->RandUint64();
- random_.set_seed(seed);
- QUIC_LOG(INFO) << "Bbr2MultiSenderTest set up. Seed: " << seed;
-
- simulator_.set_random_generator(&random_);
}
~Bbr2MultiSenderTest() {
@@ -820,7 +1134,7 @@ class Bbr2MultiSenderTest : public Bbr2SimulatorTest {
QuicConnectionPeer::GetSentPacketManager(endpoint->connection())),
kDefaultInitialCwndPackets,
GetQuicFlag(FLAGS_quic_max_congestion_window), &random_,
- QuicConnectionPeer::GetStats(endpoint->connection()));
+ QuicConnectionPeer::GetStats(endpoint->connection()), nullptr);
QuicConnectionPeer::SetSendAlgorithm(endpoint->connection(), sender);
endpoint->RecordTrace();
return sender;
@@ -873,8 +1187,6 @@ class Bbr2MultiSenderTest : public Bbr2SimulatorTest {
}
}
- QuicTime SimulatedNow() const { return simulator_.GetClock()->Now(); }
-
QuicConnection* sender_connection(size_t which) {
return sender_endpoints_[which]->connection();
}
@@ -888,12 +1200,10 @@ class Bbr2MultiSenderTest : public Bbr2SimulatorTest {
sender_connection_stats(which).packets_sent;
}
- simulator::Simulator simulator_;
std::vector<std::unique_ptr<simulator::QuicEndpoint>> sender_endpoints_;
std::vector<std::unique_ptr<simulator::QuicEndpoint>> receiver_endpoints_;
std::unique_ptr<simulator::QuicEndpointMultiplexer> receiver_multiplexer_;
Bbr2Sender* sender_1_;
- SimpleRandom random_;
std::unique_ptr<simulator::Switch> switch_;
std::vector<std::unique_ptr<simulator::SymmetricLink>> network_links_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_startup.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_startup.cc
index 187b349b327..8514d2accbc 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_startup.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_startup.cc
@@ -8,6 +8,7 @@
#include "net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.h"
#include "net/third_party/quiche/src/quic/core/quic_bandwidth.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
namespace quic {
@@ -17,8 +18,7 @@ Bbr2StartupMode::Bbr2StartupMode(const Bbr2Sender* sender,
: Bbr2ModeBase(sender, model),
full_bandwidth_reached_(false),
full_bandwidth_baseline_(QuicBandwidth::Zero()),
- rounds_without_bandwidth_growth_(0),
- loss_events_in_round_(0) {
+ rounds_without_bandwidth_growth_(0) {
// Clear some startup stats if |sender_->connection_stats_| has been used by
// another sender, which happens e.g. when QuicConnection switch send
// algorithms.
@@ -27,24 +27,25 @@ Bbr2StartupMode::Bbr2StartupMode(const Bbr2Sender* sender,
sender_->connection_stats_->slowstart_duration.Start(now);
}
-void Bbr2StartupMode::Enter(const Bbr2CongestionEvent& /*congestion_event*/) {
+void Bbr2StartupMode::Enter(QuicTime /*now*/,
+ const Bbr2CongestionEvent* /*congestion_event*/) {
QUIC_BUG << "Bbr2StartupMode::Enter should not be called";
}
-void Bbr2StartupMode::Leave(const Bbr2CongestionEvent& congestion_event) {
- sender_->connection_stats_->slowstart_duration.Stop(
- congestion_event.event_time);
+void Bbr2StartupMode::Leave(QuicTime now,
+ const Bbr2CongestionEvent* /*congestion_event*/) {
+ sender_->connection_stats_->slowstart_duration.Stop(now);
}
Bbr2Mode Bbr2StartupMode::OnCongestionEvent(
QuicByteCount /*prior_in_flight*/,
QuicTime /*event_time*/,
const AckedPacketVector& /*acked_packets*/,
- const LostPacketVector& lost_packets,
+ const LostPacketVector& /*lost_packets*/,
const Bbr2CongestionEvent& congestion_event) {
CheckFullBandwidthReached(congestion_event);
- CheckExcessiveLosses(lost_packets, congestion_event);
+ CheckExcessiveLosses(congestion_event);
model_->set_pacing_gain(Params().startup_gain);
model_->set_cwnd_gain(Params().startup_gain);
@@ -87,15 +88,12 @@ void Bbr2StartupMode::CheckFullBandwidthReached(
}
void Bbr2StartupMode::CheckExcessiveLosses(
- const LostPacketVector& lost_packets,
const Bbr2CongestionEvent& congestion_event) {
if (full_bandwidth_reached_) {
return;
}
- if (!lost_packets.empty()) {
- ++loss_events_in_round_;
- }
+ const int64_t loss_events_in_round = model_->loss_events_in_round();
// TODO(wub): In TCP, loss based exit only happens at end of a loss round, in
// QUIC we use the end of the normal round here. It is possible to exit after
@@ -106,13 +104,13 @@ void Bbr2StartupMode::CheckExcessiveLosses(
QUIC_DVLOG(3)
<< sender_
- << " CheckExcessiveLosses at end of round. loss_events_in_round_:"
- << loss_events_in_round_
+ << " CheckExcessiveLosses at end of round. loss_events_in_round:"
+ << loss_events_in_round
<< ", threshold:" << Params().startup_full_loss_count << " @ "
<< congestion_event.event_time;
// At the end of a round trip. Check if loss is too high in this round.
- if (loss_events_in_round_ >= Params().startup_full_loss_count &&
+ if (loss_events_in_round >= Params().startup_full_loss_count &&
model_->IsInflightTooHigh(congestion_event)) {
const QuicByteCount bdp = model_->BDP(model_->MaxBandwidth());
QUIC_DVLOG(3) << sender_
@@ -120,9 +118,8 @@ void Bbr2StartupMode::CheckExcessiveLosses(
model_->set_inflight_hi(bdp);
full_bandwidth_reached_ = true;
+ sender_->connection_stats_->bbr_exit_startup_due_to_loss = true;
}
-
- loss_events_in_round_ = 0;
}
Bbr2StartupMode::DebugState Bbr2StartupMode::ExportDebugState() const {
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_startup.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_startup.h
index 80539d9a108..e8f37ff9b81 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_startup.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_startup.h
@@ -20,8 +20,10 @@ class QUIC_EXPORT_PRIVATE Bbr2StartupMode final : public Bbr2ModeBase {
Bbr2NetworkModel* model,
QuicTime now);
- void Enter(const Bbr2CongestionEvent& congestion_event) override;
- void Leave(const Bbr2CongestionEvent& congestion_event) override;
+ void Enter(QuicTime now,
+ const Bbr2CongestionEvent* congestion_event) override;
+ void Leave(QuicTime now,
+ const Bbr2CongestionEvent* congestion_event) override;
Bbr2Mode OnCongestionEvent(
QuicByteCount prior_in_flight,
@@ -36,6 +38,11 @@ class QUIC_EXPORT_PRIVATE Bbr2StartupMode final : public Bbr2ModeBase {
bool IsProbingForBandwidth() const override { return true; }
+ Bbr2Mode OnExitQuiescence(QuicTime /*now*/,
+ QuicTime /*quiescence_start_time*/) override {
+ return Bbr2Mode::STARTUP;
+ }
+
bool FullBandwidthReached() const { return full_bandwidth_reached_; }
struct QUIC_EXPORT_PRIVATE DebugState {
@@ -51,15 +58,11 @@ class QUIC_EXPORT_PRIVATE Bbr2StartupMode final : public Bbr2ModeBase {
void CheckFullBandwidthReached(const Bbr2CongestionEvent& congestion_event);
- void CheckExcessiveLosses(const LostPacketVector& lost_packets,
- const Bbr2CongestionEvent& congestion_event);
+ void CheckExcessiveLosses(const Bbr2CongestionEvent& congestion_event);
bool full_bandwidth_reached_;
QuicBandwidth full_bandwidth_baseline_;
QuicRoundTripCount rounds_without_bandwidth_growth_;
-
- // Number of loss events in the current round trip.
- int64_t loss_events_in_round_;
};
QUIC_EXPORT_PRIVATE std::ostream& operator<<(
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.cc
index 0096ca5b095..8331611252d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.cc
@@ -53,12 +53,6 @@ const QuicTime::Delta kProbeRttTime = QuicTime::Delta::FromMilliseconds(200);
// will exit the STARTUP mode.
const float kStartupGrowthTarget = 1.25;
const QuicRoundTripCount kRoundTripsWithoutGrowthBeforeExitingStartup = 3;
-// Coefficient of target congestion window to use when basing PROBE_RTT on BDP.
-const float kModerateProbeRttMultiplier = 0.75;
-// Coefficient to determine if a new RTT is sufficiently similar to min_rtt that
-// we don't need to enter PROBE_RTT.
-const float kSimilarMinRttThreshold = 1.125;
-
} // namespace
BbrSender::DebugState::DebugState(const BbrSender& sender)
@@ -93,6 +87,8 @@ BbrSender::BbrSender(QuicTime now,
mode_(STARTUP),
sampler_(unacked_packets, kBandwidthWindowSize),
round_trip_count_(0),
+ num_loss_events_in_round_(0),
+ bytes_lost_in_round_(0),
max_bandwidth_(kBandwidthWindowSize, QuicBandwidth::Zero(), 0),
min_rtt_(QuicTime::Delta::Zero()),
min_rtt_timestamp_(QuicTime::Zero()),
@@ -110,7 +106,8 @@ BbrSender::BbrSender(QuicTime now,
congestion_window_gain_constant_(
static_cast<float>(GetQuicFlag(FLAGS_quic_bbr_cwnd_gain))),
num_startup_rtts_(kRoundTripsWithoutGrowthBeforeExitingStartup),
- exit_startup_on_loss_(false),
+ exit_startup_on_loss_(
+ GetQuicReloadableFlag(quic_bbr_default_exit_startup_on_loss)),
cycle_current_offset_(0),
last_cycle_start_(QuicTime::Zero()),
is_at_full_bandwidth_(false),
@@ -126,16 +123,14 @@ BbrSender::BbrSender(QuicTime now,
recovery_window_(max_congestion_window_),
slower_startup_(false),
rate_based_startup_(false),
- startup_rate_reduction_multiplier_(0),
- startup_bytes_lost_(0),
enable_ack_aggregation_during_startup_(false),
expire_ack_aggregation_in_startup_(false),
drain_to_target_(false),
- probe_rtt_based_on_bdp_(false),
- probe_rtt_skipped_if_similar_rtt_(false),
- probe_rtt_disabled_if_app_limited_(false),
- app_limited_since_last_probe_rtt_(false),
- min_rtt_since_last_probe_rtt_(QuicTime::Delta::Infinite()) {
+ network_parameters_adjusted_(false),
+ bytes_lost_with_network_parameters_adjusted_(0),
+ bytes_lost_multiplier_with_network_parameters_adjusted_(2),
+ max_congestion_window_with_network_parameters_adjusted_(
+ kMaxInitialCongestionWindow * kDefaultTCPMSS) {
if (stats_) {
// Clear some startup stats if |stats_| has been used by another sender,
// which happens e.g. when QuicConnection switch send algorithms.
@@ -143,6 +138,10 @@ BbrSender::BbrSender(QuicTime now,
stats_->slowstart_duration = QuicTimeAccumulator();
}
EnterStartupMode(now);
+ if (exit_startup_on_loss_) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_bbr_default_exit_startup_on_loss);
+ set_high_cwnd_gain(kDerivedHighCWNDGain);
+ }
}
BbrSender::~BbrSender() {}
@@ -179,6 +178,10 @@ void BbrSender::OnPacketSent(QuicTime sent_time,
is_retransmittable);
}
+void BbrSender::OnPacketNeutered(QuicPacketNumber packet_number) {
+ sampler_.OnPacketNeutered(packet_number);
+}
+
bool BbrSender::CanSend(QuicByteCount bytes_in_flight) {
return bytes_in_flight < GetCongestionWindow();
}
@@ -200,8 +203,14 @@ QuicByteCount BbrSender::GetCongestionWindow() const {
return ProbeRttCongestionWindow();
}
- if (InRecovery() && !(rate_based_startup_ && mode_ == STARTUP)) {
- return std::min(congestion_window_, recovery_window_);
+ if (exit_startup_on_loss_) {
+ if (InRecovery()) {
+ return std::min(congestion_window_, recovery_window_);
+ }
+ } else {
+ if (InRecovery() && !(rate_based_startup_ && mode_ == STARTUP)) {
+ return std::min(congestion_window_, recovery_window_);
+ }
}
return congestion_window_;
@@ -259,26 +268,24 @@ void BbrSender::SetFromConfig(const QuicConfig& config,
if (config.HasClientRequestedIndependentOption(k2RTT, perspective)) {
num_startup_rtts_ = 2;
}
- if (config.HasClientRequestedIndependentOption(kBBRS, perspective)) {
+ if (!exit_startup_on_loss_ &&
+ config.HasClientRequestedIndependentOption(kBBRS, perspective)) {
slower_startup_ = true;
}
if (config.HasClientRequestedIndependentOption(kBBR3, perspective)) {
drain_to_target_ = true;
}
- if (config.HasClientRequestedIndependentOption(kBBS1, perspective)) {
- rate_based_startup_ = true;
- }
- if (GetQuicReloadableFlag(quic_bbr_startup_rate_reduction) &&
- config.HasClientRequestedIndependentOption(kBBS4, perspective)) {
+ if (!exit_startup_on_loss_ &&
+ config.HasClientRequestedIndependentOption(kBBS1, perspective)) {
rate_based_startup_ = true;
- // Hits 1.25x pacing multiplier when ~2/3 CWND is lost.
- startup_rate_reduction_multiplier_ = 1;
}
- if (GetQuicReloadableFlag(quic_bbr_startup_rate_reduction) &&
- config.HasClientRequestedIndependentOption(kBBS5, perspective)) {
- rate_based_startup_ = true;
- // Hits 1.25x pacing multiplier when ~1/3 CWND is lost.
- startup_rate_reduction_multiplier_ = 2;
+ if (GetQuicReloadableFlag(quic_bbr_mitigate_overly_large_bandwidth_sample)) {
+ if (config.HasClientRequestedIndependentOption(kBWM3, perspective)) {
+ bytes_lost_multiplier_with_network_parameters_adjusted_ = 3;
+ }
+ if (config.HasClientRequestedIndependentOption(kBWM4, perspective)) {
+ bytes_lost_multiplier_with_network_parameters_adjusted_ = 4;
+ }
}
if (config.HasClientRequestedIndependentOption(kBBR4, perspective)) {
sampler_.SetMaxAckHeightTrackerWindowLength(2 * kBandwidthWindowSize);
@@ -286,21 +293,6 @@ void BbrSender::SetFromConfig(const QuicConfig& config,
if (config.HasClientRequestedIndependentOption(kBBR5, perspective)) {
sampler_.SetMaxAckHeightTrackerWindowLength(4 * kBandwidthWindowSize);
}
- if (GetQuicReloadableFlag(quic_bbr_less_probe_rtt) &&
- config.HasClientRequestedIndependentOption(kBBR6, perspective)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr_less_probe_rtt, 1, 3);
- probe_rtt_based_on_bdp_ = true;
- }
- if (GetQuicReloadableFlag(quic_bbr_less_probe_rtt) &&
- config.HasClientRequestedIndependentOption(kBBR7, perspective)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr_less_probe_rtt, 2, 3);
- probe_rtt_skipped_if_similar_rtt_ = true;
- }
- if (GetQuicReloadableFlag(quic_bbr_less_probe_rtt) &&
- config.HasClientRequestedIndependentOption(kBBR8, perspective)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr_less_probe_rtt, 3, 3);
- probe_rtt_disabled_if_app_limited_ = true;
- }
if (GetQuicReloadableFlag(quic_bbr_flexible_app_limited) &&
config.HasClientRequestedIndependentOption(kBBR9, perspective)) {
QUIC_RELOADABLE_FLAG_COUNT(quic_bbr_flexible_app_limited);
@@ -311,27 +303,37 @@ void BbrSender::SetFromConfig(const QuicConfig& config,
set_high_cwnd_gain(kDerivedHighGain);
set_drain_gain(1.f / kDerivedHighGain);
}
- if (config.HasClientRequestedIndependentOption(kBBQ2, perspective)) {
+ if (!exit_startup_on_loss_ &&
+ config.HasClientRequestedIndependentOption(kBBQ2, perspective)) {
set_high_cwnd_gain(kDerivedHighCWNDGain);
}
if (config.HasClientRequestedIndependentOption(kBBQ3, perspective)) {
enable_ack_aggregation_during_startup_ = true;
}
- if (GetQuicReloadableFlag(quic_bbr_slower_startup4) &&
- config.HasClientRequestedIndependentOption(kBBQ5, perspective)) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_bbr_slower_startup4);
+ if (config.HasClientRequestedIndependentOption(kBBQ5, perspective)) {
expire_ack_aggregation_in_startup_ = true;
}
if (config.HasClientRequestedIndependentOption(kMIN1, perspective)) {
min_congestion_window_ = kMaxSegmentSize;
}
+ if (config.HasClientRequestedIndependentOption(kICW1, perspective)) {
+ max_congestion_window_with_network_parameters_adjusted_ =
+ 100 * kDefaultTCPMSS;
+ }
+ if (GetQuicReloadableFlag(
+ quic_avoid_overestimate_bandwidth_with_aggregation) &&
+ config.HasClientRequestedIndependentOption(kBSAO, perspective)) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(
+ quic_avoid_overestimate_bandwidth_with_aggregation, 3, 4);
+ sampler_.EnableOverestimateAvoidance();
+ }
}
void BbrSender::AdjustNetworkParameters(const NetworkParams& params) {
const QuicBandwidth& bandwidth = params.bandwidth;
const QuicTime::Delta& rtt = params.rtt;
- if (GetQuicReloadableFlag(quic_bbr_donot_inject_bandwidth)) {
+ if (params.quic_bbr_donot_inject_bandwidth) {
QUIC_RELOADABLE_FLAG_COUNT(quic_bbr_donot_inject_bandwidth);
} else if (!bandwidth.IsZero()) {
max_bandwidth_.Update(bandwidth, round_trip_count_);
@@ -347,11 +349,10 @@ void BbrSender::AdjustNetworkParameters(const NetworkParams& params) {
}
const QuicByteCount new_cwnd = std::max(
kMinInitialCongestionWindow * kDefaultTCPMSS,
- std::min(
- kMaxInitialCongestionWindow * kDefaultTCPMSS,
- bandwidth * (GetQuicReloadableFlag(quic_bbr_donot_inject_bandwidth)
- ? GetMinRtt()
- : rtt_stats_->SmoothedOrInitialRtt())));
+ std::min(max_congestion_window_with_network_parameters_adjusted_,
+ bandwidth * (params.quic_bbr_donot_inject_bandwidth
+ ? GetMinRtt()
+ : rtt_stats_->SmoothedOrInitialRtt())));
if (!rtt_stats_->smoothed_rtt().IsZero()) {
QUIC_CODE_COUNT(quic_smoothed_rtt_available);
} else if (rtt_stats_->initial_rtt() !=
@@ -377,6 +378,12 @@ void BbrSender::AdjustNetworkParameters(const NetworkParams& params) {
QuicBandwidth new_pacing_rate =
QuicBandwidth::FromBytesAndTimeDelta(congestion_window_, GetMinRtt());
pacing_rate_ = std::max(pacing_rate_, new_pacing_rate);
+ if (GetQuicReloadableFlag(
+ quic_bbr_mitigate_overly_large_bandwidth_sample)) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(
+ quic_bbr_mitigate_overly_large_bandwidth_sample, 1, 4);
+ network_parameters_adjusted_ = true;
+ }
}
}
}
@@ -387,23 +394,76 @@ void BbrSender::OnCongestionEvent(bool /*rtt_updated*/,
const AckedPacketVector& acked_packets,
const LostPacketVector& lost_packets) {
const QuicByteCount total_bytes_acked_before = sampler_.total_bytes_acked();
+ const QuicByteCount total_bytes_lost_before = sampler_.total_bytes_lost();
bool is_round_start = false;
bool min_rtt_expired = false;
+ QuicByteCount excess_acked = 0;
+ QuicByteCount bytes_lost = 0;
- DiscardLostPackets(lost_packets);
+ // The send state of the largest packet in acked_packets, unless it is
+ // empty. If acked_packets is empty, it's the send state of the largest
+ // packet in lost_packets.
+ SendTimeState last_packet_send_state;
- // Input the new data into the BBR model of the connection.
- QuicByteCount excess_acked = 0;
if (!acked_packets.empty()) {
QuicPacketNumber last_acked_packet = acked_packets.rbegin()->packet_number;
is_round_start = UpdateRoundTripCounter(last_acked_packet);
- min_rtt_expired = UpdateBandwidthAndMinRtt(event_time, acked_packets);
UpdateRecoveryState(last_acked_packet, !lost_packets.empty(),
is_round_start);
+ }
- excess_acked =
- sampler_.OnAckEventEnd(max_bandwidth_.GetBest(), round_trip_count_);
+ BandwidthSamplerInterface::CongestionEventSample sample =
+ sampler_.OnCongestionEvent(event_time, acked_packets, lost_packets,
+ max_bandwidth_.GetBest(),
+ QuicBandwidth::Infinite(), round_trip_count_);
+ if (sample.last_packet_send_state.is_valid) {
+ last_sample_is_app_limited_ = sample.last_packet_send_state.is_app_limited;
+ has_non_app_limited_sample_ |= !last_sample_is_app_limited_;
+ if (stats_) {
+ stats_->has_non_app_limited_sample = has_non_app_limited_sample_;
+ }
+ }
+ // Avoid updating |max_bandwidth_| if a) this is a loss-only event, or b) all
+ // packets in |acked_packets| did not generate valid samples. (e.g. ack of
+ // ack-only packets). In both cases, sampler_.total_bytes_acked() will not
+ // change.
+ if (!fix_zero_bw_on_loss_only_event_ ||
+ (total_bytes_acked_before != sampler_.total_bytes_acked())) {
+ QUIC_BUG_IF((total_bytes_acked_before != sampler_.total_bytes_acked()) &&
+ sample.sample_max_bandwidth.IsZero())
+ << sampler_.total_bytes_acked() - total_bytes_acked_before
+ << " bytes from " << acked_packets.size()
+ << " packets have been acked, but sample_max_bandwidth is zero.";
+ if (!sample.sample_is_app_limited ||
+ sample.sample_max_bandwidth > max_bandwidth_.GetBest()) {
+ max_bandwidth_.Update(sample.sample_max_bandwidth, round_trip_count_);
+ }
+ } else {
+ if (acked_packets.empty()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr_fix_zero_bw_on_loss_only_event, 1,
+ 4);
+ } else {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr_fix_zero_bw_on_loss_only_event, 2,
+ 4);
+ }
+ }
+ if (!sample.sample_rtt.IsInfinite()) {
+ min_rtt_expired = MaybeUpdateMinRtt(event_time, sample.sample_rtt);
+ }
+ bytes_lost = sampler_.total_bytes_lost() - total_bytes_lost_before;
+ if (mode_ == STARTUP) {
+ if (stats_) {
+ stats_->slowstart_packets_lost += lost_packets.size();
+ stats_->slowstart_bytes_lost += bytes_lost;
+ }
+ }
+ excess_acked = sample.extra_acked;
+ last_packet_send_state = sample.last_packet_send_state;
+
+ if (!lost_packets.empty()) {
+ ++num_loss_events_in_round_;
+ bytes_lost_in_round_ += bytes_lost;
}
// Handle logic specific to PROBE_BW mode.
@@ -413,7 +473,7 @@ void BbrSender::OnCongestionEvent(bool /*rtt_updated*/,
// Handle logic specific to STARTUP and DRAIN modes.
if (is_round_start && !is_at_full_bandwidth_) {
- CheckIfFullBandwidthReached();
+ CheckIfFullBandwidthReached(last_packet_send_state);
}
MaybeExitStartupOrDrain(event_time);
@@ -423,19 +483,19 @@ void BbrSender::OnCongestionEvent(bool /*rtt_updated*/,
// Calculate number of packets acked and lost.
QuicByteCount bytes_acked =
sampler_.total_bytes_acked() - total_bytes_acked_before;
- QuicByteCount bytes_lost = 0;
- for (const auto& packet : lost_packets) {
- bytes_lost += packet.bytes_lost;
- }
// After the model is updated, recalculate the pacing rate and congestion
// window.
- CalculatePacingRate();
+ CalculatePacingRate(bytes_lost);
CalculateCongestionWindow(bytes_acked, excess_acked);
CalculateRecoveryWindow(bytes_acked, bytes_lost);
// Cleanup internal state.
sampler_.RemoveObsoletePackets(unacked_packets_->GetLeastUnacked());
+ if (is_round_start) {
+ num_loss_events_in_round_ = 0;
+ bytes_lost_in_round_ = 0;
+ }
}
CongestionControlType BbrSender::GetCongestionControlType() const {
@@ -459,9 +519,6 @@ QuicByteCount BbrSender::GetTargetCongestionWindow(float gain) const {
}
QuicByteCount BbrSender::ProbeRttCongestionWindow() const {
- if (probe_rtt_based_on_bdp_) {
- return GetTargetCongestionWindow(kModerateProbeRttMultiplier);
- }
return min_congestion_window_;
}
@@ -491,21 +548,6 @@ void BbrSender::EnterProbeBandwidthMode(QuicTime now) {
pacing_gain_ = kPacingGain[cycle_current_offset_];
}
-void BbrSender::DiscardLostPackets(const LostPacketVector& lost_packets) {
- for (const LostPacket& packet : lost_packets) {
- sampler_.OnPacketLost(packet.packet_number);
- if (mode_ == STARTUP) {
- if (stats_) {
- ++stats_->slowstart_packets_lost;
- stats_->slowstart_bytes_lost += packet.bytes_lost;
- }
- if (startup_rate_reduction_multiplier_ != 0) {
- startup_bytes_lost_ += packet.bytes_lost;
- }
- }
- }
-}
-
bool BbrSender::UpdateRoundTripCounter(QuicPacketNumber last_acked_packet) {
if (!current_round_trip_end_.IsInitialized() ||
last_acked_packet > current_round_trip_end_) {
@@ -520,39 +562,8 @@ bool BbrSender::UpdateRoundTripCounter(QuicPacketNumber last_acked_packet) {
return false;
}
-bool BbrSender::UpdateBandwidthAndMinRtt(
- QuicTime now,
- const AckedPacketVector& acked_packets) {
- QuicTime::Delta sample_min_rtt = QuicTime::Delta::Infinite();
- for (const auto& packet : acked_packets) {
- BandwidthSample bandwidth_sample =
- sampler_.OnPacketAcknowledged(now, packet.packet_number);
- if (!bandwidth_sample.state_at_send.is_valid) {
- // From the sampler's perspective, the packet has never been sent, or the
- // packet has been acked or marked as lost previously.
- continue;
- }
-
- last_sample_is_app_limited_ = bandwidth_sample.state_at_send.is_app_limited;
- has_non_app_limited_sample_ |=
- !bandwidth_sample.state_at_send.is_app_limited;
- if (!bandwidth_sample.rtt.IsZero()) {
- sample_min_rtt = std::min(sample_min_rtt, bandwidth_sample.rtt);
- }
-
- if (!bandwidth_sample.state_at_send.is_app_limited ||
- bandwidth_sample.bandwidth > BandwidthEstimate()) {
- max_bandwidth_.Update(bandwidth_sample.bandwidth, round_trip_count_);
- }
- }
-
- // If none of the RTT samples are valid, return immediately.
- if (sample_min_rtt.IsInfinite()) {
- return false;
- }
- min_rtt_since_last_probe_rtt_ =
- std::min(min_rtt_since_last_probe_rtt_, sample_min_rtt);
-
+bool BbrSender::MaybeUpdateMinRtt(QuicTime now,
+ QuicTime::Delta sample_min_rtt) {
// Do not expire min_rtt if none was ever available.
bool min_rtt_expired =
!min_rtt_.IsZero() && (now > (min_rtt_timestamp_ + kMinRttExpiry));
@@ -562,38 +573,14 @@ bool BbrSender::UpdateBandwidthAndMinRtt(
<< ", new value: " << sample_min_rtt
<< ", current time: " << now.ToDebuggingValue();
- if (min_rtt_expired && ShouldExtendMinRttExpiry()) {
- min_rtt_expired = false;
- } else {
- min_rtt_ = sample_min_rtt;
- }
+ min_rtt_ = sample_min_rtt;
min_rtt_timestamp_ = now;
- // Reset since_last_probe_rtt fields.
- min_rtt_since_last_probe_rtt_ = QuicTime::Delta::Infinite();
- app_limited_since_last_probe_rtt_ = false;
}
DCHECK(!min_rtt_.IsZero());
return min_rtt_expired;
}
-bool BbrSender::ShouldExtendMinRttExpiry() const {
- if (probe_rtt_disabled_if_app_limited_ && app_limited_since_last_probe_rtt_) {
- // Extend the current min_rtt if we've been app limited recently.
- return true;
- }
- const bool min_rtt_increased_since_last_probe =
- min_rtt_since_last_probe_rtt_ > min_rtt_ * kSimilarMinRttThreshold;
- if (probe_rtt_skipped_if_similar_rtt_ && app_limited_since_last_probe_rtt_ &&
- !min_rtt_increased_since_last_probe) {
- // Extend the current min_rtt if we've been app limited recently and an rtt
- // has been measured in that time that's less than 12.5% more than the
- // current min_rtt.
- return true;
- }
- return false;
-}
-
void BbrSender::UpdateGainCyclePhase(QuicTime now,
QuicByteCount prior_in_flight,
bool has_losses) {
@@ -621,6 +608,9 @@ void BbrSender::UpdateGainCyclePhase(QuicTime now,
if (should_advance_gain_cycling) {
cycle_current_offset_ = (cycle_current_offset_ + 1) % kGainCycleLength;
+ if (cycle_current_offset_ == 0) {
+ ++stats_->bbr_num_cycles;
+ }
last_cycle_start_ = now;
// Stay in low gain mode until the target BDP is hit.
// Low gain mode will be exited immediately when the target BDP is achieved.
@@ -633,7 +623,8 @@ void BbrSender::UpdateGainCyclePhase(QuicTime now,
}
}
-void BbrSender::CheckIfFullBandwidthReached() {
+void BbrSender::CheckIfFullBandwidthReached(
+ const SendTimeState& last_packet_send_state) {
if (last_sample_is_app_limited_) {
return;
}
@@ -651,7 +642,7 @@ void BbrSender::CheckIfFullBandwidthReached() {
rounds_without_bandwidth_gain_++;
if ((rounds_without_bandwidth_gain_ >= num_startup_rtts_) ||
- (exit_startup_on_loss_ && InRecovery())) {
+ ShouldExitStartupDueToLoss(last_packet_send_state)) {
DCHECK(has_non_app_limited_sample_);
is_at_full_bandwidth_ = true;
}
@@ -677,6 +668,33 @@ void BbrSender::OnExitStartup(QuicTime now) {
}
}
+bool BbrSender::ShouldExitStartupDueToLoss(
+ const SendTimeState& last_packet_send_state) const {
+ if (!exit_startup_on_loss_) {
+ return false;
+ }
+
+ if (num_loss_events_in_round_ <
+ GetQuicFlag(FLAGS_quic_bbr2_default_startup_full_loss_count) ||
+ !last_packet_send_state.is_valid) {
+ return false;
+ }
+
+ const QuicByteCount inflight_at_send = last_packet_send_state.bytes_in_flight;
+
+ if (inflight_at_send > 0 && bytes_lost_in_round_ > 0) {
+ if (bytes_lost_in_round_ >
+ inflight_at_send *
+ GetQuicFlag(FLAGS_quic_bbr2_default_loss_threshold)) {
+ stats_->bbr_exit_startup_due_to_loss = true;
+ return true;
+ }
+ return false;
+ }
+
+ return false;
+}
+
void BbrSender::MaybeEnterOrExitProbeRtt(QuicTime now,
bool is_round_start,
bool min_rtt_expired) {
@@ -725,6 +743,11 @@ void BbrSender::MaybeEnterOrExitProbeRtt(QuicTime now,
void BbrSender::UpdateRecoveryState(QuicPacketNumber last_acked_packet,
bool has_losses,
bool is_round_start) {
+ // Disable recovery in startup, if loss-based exit is enabled.
+ if (exit_startup_on_loss_ && !is_at_full_bandwidth_) {
+ return;
+ }
+
// Exit recovery when there are no losses for a round.
if (has_losses) {
end_recovery_at_ = last_sent_packet_;
@@ -760,7 +783,7 @@ void BbrSender::UpdateRecoveryState(QuicPacketNumber last_acked_packet,
}
}
-void BbrSender::CalculatePacingRate() {
+void BbrSender::CalculatePacingRate(QuicByteCount bytes_lost) {
if (BandwidthEstimate().IsZero()) {
return;
}
@@ -778,26 +801,51 @@ void BbrSender::CalculatePacingRate() {
initial_congestion_window_, rtt_stats_->min_rtt());
return;
}
- // Slow the pacing rate in STARTUP once loss has ever been detected.
- const bool has_ever_detected_loss = end_recovery_at_.IsInitialized();
- if (slower_startup_ && has_ever_detected_loss &&
- has_non_app_limited_sample_) {
- pacing_rate_ = kStartupAfterLossGain * BandwidthEstimate();
- return;
+
+ if (network_parameters_adjusted_) {
+ bytes_lost_with_network_parameters_adjusted_ += bytes_lost;
+ // Check for overshooting with network parameters adjusted when pacing rate
+ // > target_rate and loss has been detected.
+ if (pacing_rate_ > target_rate &&
+ bytes_lost_with_network_parameters_adjusted_ > 0) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(
+ quic_bbr_mitigate_overly_large_bandwidth_sample, 2, 4);
+ if (has_non_app_limited_sample_ ||
+ bytes_lost_with_network_parameters_adjusted_ *
+ bytes_lost_multiplier_with_network_parameters_adjusted_ >
+ initial_congestion_window_) {
+ // We are fairly sure overshoot happens if 1) there is at least one
+ // non app-limited bw sample or 2) half of IW gets lost. Slow pacing
+ // rate.
+ if (has_non_app_limited_sample_) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(
+ quic_bbr_mitigate_overly_large_bandwidth_sample, 3, 4);
+ } else {
+ QUIC_RELOADABLE_FLAG_COUNT_N(
+ quic_bbr_mitigate_overly_large_bandwidth_sample, 4, 4);
+ }
+ // Do not let the pacing rate drop below the connection's initial pacing
+ // rate.
+ pacing_rate_ =
+ std::max(target_rate, QuicBandwidth::FromBytesAndTimeDelta(
+ initial_congestion_window_, GetMinRtt()));
+ if (stats_) {
+ stats_->overshooting_detected_with_network_parameters_adjusted = true;
+ }
+ bytes_lost_with_network_parameters_adjusted_ = 0;
+ network_parameters_adjusted_ = false;
+ }
+ }
}
- // Slow the pacing rate in STARTUP by the bytes_lost / CWND.
- if (startup_rate_reduction_multiplier_ != 0 && has_ever_detected_loss &&
- has_non_app_limited_sample_) {
- pacing_rate_ =
- (1 - (startup_bytes_lost_ * startup_rate_reduction_multiplier_ * 1.0f /
- congestion_window_)) *
- target_rate;
- // Ensure the pacing rate doesn't drop below the startup growth target times
- // the bandwidth estimate.
- pacing_rate_ =
- std::max(pacing_rate_, kStartupGrowthTarget * BandwidthEstimate());
- return;
+ if (!exit_startup_on_loss_) {
+ // Slow the pacing rate in STARTUP once loss has ever been detected.
+ const bool has_ever_detected_loss = end_recovery_at_.IsInitialized();
+ if (slower_startup_ && has_ever_detected_loss &&
+ has_non_app_limited_sample_) {
+ pacing_rate_ = kStartupAfterLossGain * BandwidthEstimate();
+ return;
+ }
}
// Do not decrease the pacing rate during startup.
@@ -845,7 +893,7 @@ void BbrSender::CalculateCongestionWindow(QuicByteCount bytes_acked,
void BbrSender::CalculateRecoveryWindow(QuicByteCount bytes_acked,
QuicByteCount bytes_lost) {
- if (rate_based_startup_ && mode_ == STARTUP) {
+ if (!exit_startup_on_loss_ && rate_based_startup_ && mode_ == STARTUP) {
return;
}
@@ -899,7 +947,6 @@ void BbrSender::OnApplicationLimited(QuicByteCount bytes_in_flight) {
return;
}
- app_limited_since_last_probe_rtt_ = true;
sampler_.OnAppLimited();
QUIC_DVLOG(2) << "Becoming application limited. Last sent packet: "
<< last_sent_packet_ << ", CWND: " << GetCongestionWindow();
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.h
index dc512cf59be..ab5d8197419 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.h
@@ -16,10 +16,12 @@
#include "net/third_party/quiche/src/quic/core/congestion_control/windowed_filter.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
#include "net/third_party/quiche/src/quic/core/quic_bandwidth.h"
+#include "net/third_party/quiche/src/quic/core/quic_packet_number.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
#include "net/third_party/quiche/src/quic/core/quic_unacked_packet_map.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
namespace quic {
@@ -118,6 +120,7 @@ class QUIC_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface {
QuicPacketNumber packet_number,
QuicByteCount bytes,
HasRetransmittableData is_retransmittable) override;
+ void OnPacketNeutered(QuicPacketNumber packet_number) override;
void OnRetransmissionTimeout(bool /*packets_retransmitted*/) override {}
void OnConnectionMigration() override {}
bool CanSend(QuicByteCount bytes_in_flight) override;
@@ -168,6 +171,9 @@ class QUIC_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface {
DebugState ExportDebugState() const;
private:
+ // For switching send algorithm mid connection.
+ friend class Bbr2Sender;
+
typedef WindowedFilter<QuicBandwidth,
MaxFilter<QuicBandwidth>,
QuicRoundTripCount,
@@ -190,28 +196,24 @@ class QUIC_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface {
// Returns true if the current min_rtt should be kept and we should not enter
// PROBE_RTT immediately.
bool ShouldExtendMinRttExpiry() const;
+ bool MaybeUpdateMinRtt(QuicTime now, QuicTime::Delta sample_min_rtt);
// Enters the STARTUP mode.
void EnterStartupMode(QuicTime now);
// Enters the PROBE_BW mode.
void EnterProbeBandwidthMode(QuicTime now);
- // Discards the lost packets from BandwidthSampler state.
- void DiscardLostPackets(const LostPacketVector& lost_packets);
// Updates the round-trip counter if a round-trip has passed. Returns true if
// the counter has been advanced.
bool UpdateRoundTripCounter(QuicPacketNumber last_acked_packet);
- // Updates the current bandwidth and min_rtt estimate based on the samples for
- // the received acknowledgements. Returns true if min_rtt has expired.
- bool UpdateBandwidthAndMinRtt(QuicTime now,
- const AckedPacketVector& acked_packets);
+
// Updates the current gain used in PROBE_BW mode.
void UpdateGainCyclePhase(QuicTime now,
QuicByteCount prior_in_flight,
bool has_losses);
// Tracks for how many round-trips the bandwidth has not increased
// significantly.
- void CheckIfFullBandwidthReached();
+ void CheckIfFullBandwidthReached(const SendTimeState& last_packet_send_state);
// Transitions from STARTUP to DRAIN and from DRAIN to PROBE_BW if
// appropriate.
void MaybeExitStartupOrDrain(QuicTime now);
@@ -232,7 +234,7 @@ class QUIC_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface {
QuicByteCount newly_acked_bytes);
// Determines the appropriate pacing rate for the connection.
- void CalculatePacingRate();
+ void CalculatePacingRate(QuicByteCount bytes_lost);
// Determines the appropriate congestion window for the connection.
void CalculateCongestionWindow(QuicByteCount bytes_acked,
QuicByteCount excess_acked);
@@ -248,6 +250,10 @@ class QUIC_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface {
// Called right before exiting STARTUP.
void OnExitStartup(QuicTime now);
+ // Return whether we should exit STARTUP due to excessive loss.
+ bool ShouldExitStartupDueToLoss(
+ const SendTimeState& last_packet_send_state) const;
+
const RttStats* rtt_stats_;
const QuicUnackedPacketMap* unacked_packets_;
QuicRandom* random_;
@@ -268,6 +274,12 @@ class QUIC_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface {
// the round trip counter to advance.
QuicPacketNumber current_round_trip_end_;
+ // Number of congestion events with some losses, in the current round.
+ int64_t num_loss_events_in_round_;
+
+ // Number of total bytes lost in the current round.
+ QuicByteCount bytes_lost_in_round_;
+
// The filter that tracks the maximum bandwidth over the multiple recent
// round-trips.
MaxBandwidthFilter max_bandwidth_;
@@ -312,8 +324,12 @@ class QUIC_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface {
const float congestion_window_gain_constant_;
// The number of RTTs to stay in STARTUP mode. Defaults to 3.
QuicRoundTripCount num_startup_rtts_;
- // If true, exit startup if 1RTT has passed with no bandwidth increase and
- // the connection is in recovery.
+
+ // Latched value of --quic_bbr_default_exit_startup_on_loss.
+ // If true, exit startup if all of the following conditions are met:
+ // - 1RTT has passed with no bandwidth increase,
+ // - Some number of congestion events happened with loss, in the last round.
+ // - Some amount of inflight bytes (at the start of the last round) are lost.
bool exit_startup_on_loss_;
// Number of round-trips in PROBE_BW mode, used for determining the current
@@ -363,11 +379,6 @@ class QUIC_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface {
bool slower_startup_;
// When true, disables packet conservation in STARTUP.
bool rate_based_startup_;
- // When non-zero, decreases the rate in STARTUP by the total number of bytes
- // lost in STARTUP divided by CWND.
- uint8_t startup_rate_reduction_multiplier_;
- // Sum of bytes lost in STARTUP.
- QuicByteCount startup_bytes_lost_;
// When true, add the most recent ack aggregation measurement during STARTUP.
bool enable_ack_aggregation_during_startup_;
@@ -379,18 +390,21 @@ class QUIC_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface {
// or it's time for high gain mode.
bool drain_to_target_;
- // If true, use a CWND of 0.75*BDP during probe_rtt instead of 4 packets.
- bool probe_rtt_based_on_bdp_;
- // If true, skip probe_rtt and update the timestamp of the existing min_rtt to
- // now if min_rtt over the last cycle is within 12.5% of the current min_rtt.
- // Even if the min_rtt is 12.5% too low, the 25% gain cycling and 2x CWND gain
- // should overcome an overly small min_rtt.
- bool probe_rtt_skipped_if_similar_rtt_;
- // If true, disable PROBE_RTT entirely as long as the connection was recently
- // app limited.
- bool probe_rtt_disabled_if_app_limited_;
- bool app_limited_since_last_probe_rtt_;
- QuicTime::Delta min_rtt_since_last_probe_rtt_;
+ const bool fix_zero_bw_on_loss_only_event_ =
+ GetQuicReloadableFlag(quic_bbr_fix_zero_bw_on_loss_only_event);
+
+ // True if network parameters are adjusted, and this will be reset if
+ // overshooting is detected and pacing rate gets slowed.
+ bool network_parameters_adjusted_;
+ // Bytes lost after network parameters gets adjusted.
+ QuicByteCount bytes_lost_with_network_parameters_adjusted_;
+ // Decrease pacing rate after parameters adjusted if
+ // bytes_lost_with_network_parameters_adjusted_ *
+ // bytes_lost_multiplier_with_network_parameters_adjusted_ > IW.
+ uint8_t bytes_lost_multiplier_with_network_parameters_adjusted_;
+
+ // Max congestion window when adjusting network parameters.
+ QuicByteCount max_congestion_window_with_network_parameters_adjusted_;
};
QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender_test.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender_test.cc
index 6acfe80519a..e07931b8c79 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender_test.cc
@@ -10,7 +10,9 @@
#include <utility>
#include "net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h"
+#include "net/third_party/quiche/src/quic/core/quic_bandwidth.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
@@ -20,6 +22,8 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/send_algorithm_test_result.pb.h"
+#include "net/third_party/quiche/src/quic/test_tools/send_algorithm_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/switch.h"
@@ -28,6 +32,14 @@ using testing::AllOf;
using testing::Ge;
using testing::Le;
+DEFINE_QUIC_COMMAND_LINE_FLAG(
+ std::string,
+ quic_bbr_test_regression_mode,
+ "",
+ "One of a) 'record' to record test result (one file per test), or "
+ "b) 'regress' to regress against recorded results, or "
+ "c) <anything else> for non-regression mode.");
+
namespace quic {
namespace test {
@@ -73,7 +85,7 @@ const QuicByteCount kTestBdp = kTestRtt * kTestLinkBandwidth;
class BbrSenderTest : public QuicTest {
protected:
BbrSenderTest()
- : simulator_(),
+ : simulator_(&random_),
bbr_sender_(&simulator_,
"BBR sender",
"Receiver",
@@ -100,13 +112,34 @@ class BbrSenderTest : public QuicTest {
sender_ = SetupBbrSender(&bbr_sender_);
clock_ = simulator_.GetClock();
- simulator_.set_random_generator(&random_);
+ }
- uint64_t seed = QuicRandom::GetInstance()->RandUint64();
- random_.set_seed(seed);
- QUIC_LOG(INFO) << "BbrSenderTest simulator set up. Seed: " << seed;
+ void SetUp() override {
+ if (GetQuicFlag(FLAGS_quic_bbr_test_regression_mode) == "regress") {
+ SendAlgorithmTestResult expected;
+ ASSERT_TRUE(LoadSendAlgorithmTestResult(&expected));
+ random_seed_ = expected.random_seed();
+ } else {
+ random_seed_ = QuicRandom::GetInstance()->RandUint64();
+ }
+ random_.set_seed(random_seed_);
+ QUIC_LOG(INFO) << "BbrSenderTest simulator set up. Seed: " << random_seed_;
}
+ ~BbrSenderTest() {
+ const std::string regression_mode =
+ GetQuicFlag(FLAGS_quic_bbr_test_regression_mode);
+ const QuicTime::Delta simulated_duration = clock_->Now() - QuicTime::Zero();
+ if (regression_mode == "record") {
+ RecordSendAlgorithmTestResult(random_seed_,
+ simulated_duration.ToMicroseconds());
+ } else if (regression_mode == "regress") {
+ CompareSendAlgorithmTestResult(simulated_duration.ToMicroseconds());
+ }
+ }
+
+ uint64_t random_seed_;
+ SimpleRandom random_;
simulator::Simulator simulator_;
simulator::QuicEndpoint bbr_sender_;
simulator::QuicEndpoint competing_sender_;
@@ -118,8 +151,6 @@ class BbrSenderTest : public QuicTest {
std::unique_ptr<simulator::SymmetricLink> competing_sender_link_;
std::unique_ptr<simulator::SymmetricLink> receiver_link_;
- SimpleRandom random_;
-
// Owned by different components of the connection.
const QuicClock* clock_;
const RttStats* rtt_stats_;
@@ -309,71 +340,94 @@ TEST_F(BbrSenderTest, SimpleTransferSmallBuffer) {
EXPECT_APPROX_EQ(kTestRtt, sender_->GetMinRtt(), 0.2f);
}
-TEST_F(BbrSenderTest, SimpleTransferEarlyPacketLoss) {
- SetQuicReloadableFlag(quic_bbr_no_bytes_acked_in_startup_recovery, true);
- // Enable rate based startup so the recovery window doesn't hide the true
- // congestion_window_ in GetCongestionWindow().
- SetConnectionOption(kBBS1);
+TEST_F(BbrSenderTest, RemoveBytesLostInRecovery) {
+ SetQuicReloadableFlag(quic_bbr_one_mss_conservation, false);
// Disable Ack Decimation on the receiver, because it can increase srtt.
QuicConnectionPeer::SetAckMode(receiver_.connection(), AckMode::TCP_ACKING);
CreateDefaultSetup();
- // At startup make sure we are at the default.
- EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
- // Verify that Sender is in slow start.
- EXPECT_TRUE(sender_->InSlowStart());
- // At startup make sure we can send.
- EXPECT_TRUE(sender_->CanSend(0));
- // And that window is un-affected.
- EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
+ DriveOutOfStartup();
- // Transfer 12MB.
- bbr_sender_.AddBytesToTransfer(12 * 1024 * 1024);
- // Drop the first packet.
+ // Drop a packet to enter recovery.
receiver_.DropNextIncomingPacket();
- bool simulator_result = simulator_.RunUntilOrTimeout(
- [this]() {
- if (sender_->InRecovery()) {
- // Two packets are acked before the first is declared lost.
- EXPECT_LE(sender_->GetCongestionWindow(),
- (kDefaultWindowTCP + 2 * kDefaultTCPMSS));
- }
- return bbr_sender_.bytes_to_transfer() == 0 || !sender_->InSlowStart();
- },
- QuicTime::Delta::FromSeconds(30));
- EXPECT_TRUE(simulator_result) << "Simple transfer failed. Bytes remaining: "
- << bbr_sender_.bytes_to_transfer();
- EXPECT_EQ(BbrSender::DRAIN, sender_->ExportDebugState().mode);
- EXPECT_EQ(1u, bbr_sender_.connection()->GetStats().packets_lost);
- EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
+ ASSERT_TRUE(
+ simulator_.RunUntilOrTimeout([this]() { return sender_->InRecovery(); },
+ QuicTime::Delta::FromSeconds(30)));
+
+ QuicUnackedPacketMap* unacked_packets =
+ QuicSentPacketManagerPeer::GetUnackedPacketMap(
+ QuicConnectionPeer::GetSentPacketManager(bbr_sender_.connection()));
+ QuicPacketNumber largest_sent =
+ bbr_sender_.connection()->sent_packet_manager().GetLargestSentPacket();
+ // least_inflight is the smallest inflight packet.
+ QuicPacketNumber least_inflight =
+ bbr_sender_.connection()->sent_packet_manager().GetLeastUnacked();
+ while (!unacked_packets->GetTransmissionInfo(least_inflight).in_flight) {
+ ASSERT_LE(least_inflight, largest_sent);
+ least_inflight++;
+ }
+ QuicPacketLength least_inflight_packet_size =
+ unacked_packets->GetTransmissionInfo(least_inflight).bytes_sent;
+ QuicByteCount prior_recovery_window =
+ sender_->ExportDebugState().recovery_window;
+ QuicByteCount prior_inflight = unacked_packets->bytes_in_flight();
+ QUIC_LOG(INFO) << "Recovery window:" << prior_recovery_window
+ << ", least_inflight_packet_size:"
+ << least_inflight_packet_size
+ << ", bytes_in_flight:" << prior_inflight;
+ ASSERT_GT(prior_recovery_window, least_inflight_packet_size);
+
+ // Lose the least inflight packet and expect the recovery window to drop.
+ unacked_packets->RemoveFromInFlight(least_inflight);
+ LostPacketVector lost_packets;
+ lost_packets.emplace_back(least_inflight, least_inflight_packet_size);
+ sender_->OnCongestionEvent(false, prior_inflight, clock_->Now(), {},
+ lost_packets);
+ EXPECT_EQ(sender_->ExportDebugState().recovery_window,
+ prior_inflight - least_inflight_packet_size);
+ EXPECT_LT(sender_->ExportDebugState().recovery_window, prior_recovery_window);
}
// Test a simple long data transfer with 2 rtts of aggregation.
TEST_F(BbrSenderTest, SimpleTransfer2RTTAggregationBytes) {
+ if (GetQuicReloadableFlag(
+ quic_avoid_overestimate_bandwidth_with_aggregation)) {
+ SetConnectionOption(kBSAO);
+ }
CreateDefaultSetup();
// 2 RTTs of aggregation, with a max of 10kb.
EnableAggregation(10 * 1024, 2 * kTestRtt);
// Transfer 12MB.
DoSimpleTransfer(12 * 1024 * 1024, QuicTime::Delta::FromSeconds(35));
- EXPECT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
- // It's possible to read a bandwidth as much as 50% too high with aggregation.
- EXPECT_LE(kTestLinkBandwidth * 0.99f,
- sender_->ExportDebugState().max_bandwidth);
- // TODO(ianswett): Tighten this bound once we understand why BBR is
- // overestimating bandwidth with aggregation. b/36022633
- EXPECT_GE(kTestLinkBandwidth * 1.5f,
- sender_->ExportDebugState().max_bandwidth);
- // TODO(ianswett): Expect 0 packets are lost once BBR no longer measures
- // bandwidth higher than the link rate.
+ EXPECT_TRUE(sender_->ExportDebugState().mode == BbrSender::PROBE_BW ||
+ sender_->ExportDebugState().mode == BbrSender::PROBE_RTT);
+ if (GetQuicReloadableFlag(
+ quic_avoid_overestimate_bandwidth_with_aggregation)) {
+ EXPECT_APPROX_EQ(kTestLinkBandwidth,
+ sender_->ExportDebugState().max_bandwidth, 0.01f);
+ } else {
+ // It's possible to read a bandwidth as much as 50% too high with
+ // aggregation.
+ EXPECT_LE(kTestLinkBandwidth * 0.93f,
+ sender_->ExportDebugState().max_bandwidth);
+ // TODO(ianswett): Tighten this bound once we understand why BBR is
+ // overestimating bandwidth with aggregation. b/36022633
+ EXPECT_GE(kTestLinkBandwidth * 1.5f,
+ sender_->ExportDebugState().max_bandwidth);
+ }
// The margin here is high, because the aggregation greatly increases
// smoothed rtt.
EXPECT_GE(kTestRtt * 4, rtt_stats_->smoothed_rtt());
- EXPECT_APPROX_EQ(kTestRtt, rtt_stats_->min_rtt(), 0.2f);
+ EXPECT_APPROX_EQ(kTestRtt, rtt_stats_->min_rtt(), 0.5f);
}
// Test a simple long data transfer with 2 rtts of aggregation.
TEST_F(BbrSenderTest, SimpleTransferAckDecimation) {
+ if (GetQuicReloadableFlag(
+ quic_avoid_overestimate_bandwidth_with_aggregation)) {
+ SetConnectionOption(kBSAO);
+ }
// Decrease the CWND gain so extra CWND is required with stretch acks.
SetQuicFlag(FLAGS_quic_bbr_cwnd_gain, 1.0);
sender_ = new BbrSender(
@@ -392,13 +446,21 @@ TEST_F(BbrSenderTest, SimpleTransferAckDecimation) {
// Transfer 12MB.
DoSimpleTransfer(12 * 1024 * 1024, QuicTime::Delta::FromSeconds(35));
EXPECT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
- // It's possible to read a bandwidth as much as 50% too high with aggregation.
- EXPECT_LE(kTestLinkBandwidth * 0.99f,
- sender_->ExportDebugState().max_bandwidth);
- // TODO(ianswett): Tighten this bound once we understand why BBR is
- // overestimating bandwidth with aggregation. b/36022633
- EXPECT_GE(kTestLinkBandwidth * 1.5f,
- sender_->ExportDebugState().max_bandwidth);
+
+ if (GetQuicReloadableFlag(
+ quic_avoid_overestimate_bandwidth_with_aggregation)) {
+ EXPECT_APPROX_EQ(kTestLinkBandwidth,
+ sender_->ExportDebugState().max_bandwidth, 0.01f);
+ } else {
+ // It's possible to read a bandwidth as much as 50% too high with
+ // aggregation.
+ EXPECT_LE(kTestLinkBandwidth * 0.93f,
+ sender_->ExportDebugState().max_bandwidth);
+ // TODO(ianswett): Tighten this bound once we understand why BBR is
+ // overestimating bandwidth with aggregation. b/36022633
+ EXPECT_GE(kTestLinkBandwidth * 1.5f,
+ sender_->ExportDebugState().max_bandwidth);
+ }
// TODO(ianswett): Expect 0 packets are lost once BBR no longer measures
// bandwidth higher than the link rate.
EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
@@ -410,6 +472,10 @@ TEST_F(BbrSenderTest, SimpleTransferAckDecimation) {
// Test a simple long data transfer with 2 rtts of aggregation.
TEST_F(BbrSenderTest, SimpleTransfer2RTTAggregationBytes20RTTWindow) {
+ if (GetQuicReloadableFlag(
+ quic_avoid_overestimate_bandwidth_with_aggregation)) {
+ SetConnectionOption(kBSAO);
+ }
// Disable Ack Decimation on the receiver, because it can increase srtt.
QuicConnectionPeer::SetAckMode(receiver_.connection(), AckMode::TCP_ACKING);
CreateDefaultSetup();
@@ -421,13 +487,20 @@ TEST_F(BbrSenderTest, SimpleTransfer2RTTAggregationBytes20RTTWindow) {
DoSimpleTransfer(12 * 1024 * 1024, QuicTime::Delta::FromSeconds(35));
EXPECT_TRUE(sender_->ExportDebugState().mode == BbrSender::PROBE_BW ||
sender_->ExportDebugState().mode == BbrSender::PROBE_RTT);
- // It's possible to read a bandwidth as much as 50% too high with aggregation.
- EXPECT_LE(kTestLinkBandwidth * 0.99f,
- sender_->ExportDebugState().max_bandwidth);
- // TODO(ianswett): Tighten this bound once we understand why BBR is
- // overestimating bandwidth with aggregation. b/36022633
- EXPECT_GE(kTestLinkBandwidth * 1.5f,
- sender_->ExportDebugState().max_bandwidth);
+ if (GetQuicReloadableFlag(
+ quic_avoid_overestimate_bandwidth_with_aggregation)) {
+ EXPECT_APPROX_EQ(kTestLinkBandwidth,
+ sender_->ExportDebugState().max_bandwidth, 0.01f);
+ } else {
+ // It's possible to read a bandwidth as much as 50% too high with
+ // aggregation.
+ EXPECT_LE(kTestLinkBandwidth * 0.93f,
+ sender_->ExportDebugState().max_bandwidth);
+ // TODO(ianswett): Tighten this bound once we understand why BBR is
+ // overestimating bandwidth with aggregation. b/36022633
+ EXPECT_GE(kTestLinkBandwidth * 1.5f,
+ sender_->ExportDebugState().max_bandwidth);
+ }
// TODO(ianswett): Expect 0 packets are lost once BBR no longer measures
// bandwidth higher than the link rate.
// The margin here is high, because the aggregation greatly increases
@@ -438,6 +511,10 @@ TEST_F(BbrSenderTest, SimpleTransfer2RTTAggregationBytes20RTTWindow) {
// Test a simple long data transfer with 2 rtts of aggregation.
TEST_F(BbrSenderTest, SimpleTransfer2RTTAggregationBytes40RTTWindow) {
+ if (GetQuicReloadableFlag(
+ quic_avoid_overestimate_bandwidth_with_aggregation)) {
+ SetConnectionOption(kBSAO);
+ }
// Disable Ack Decimation on the receiver, because it can increase srtt.
QuicConnectionPeer::SetAckMode(receiver_.connection(), AckMode::TCP_ACKING);
CreateDefaultSetup();
@@ -449,13 +526,20 @@ TEST_F(BbrSenderTest, SimpleTransfer2RTTAggregationBytes40RTTWindow) {
DoSimpleTransfer(12 * 1024 * 1024, QuicTime::Delta::FromSeconds(35));
EXPECT_TRUE(sender_->ExportDebugState().mode == BbrSender::PROBE_BW ||
sender_->ExportDebugState().mode == BbrSender::PROBE_RTT);
- // It's possible to read a bandwidth as much as 50% too high with aggregation.
- EXPECT_LE(kTestLinkBandwidth * 0.99f,
- sender_->ExportDebugState().max_bandwidth);
- // TODO(ianswett): Tighten this bound once we understand why BBR is
- // overestimating bandwidth with aggregation. b/36022633
- EXPECT_GE(kTestLinkBandwidth * 1.5f,
- sender_->ExportDebugState().max_bandwidth);
+ if (GetQuicReloadableFlag(
+ quic_avoid_overestimate_bandwidth_with_aggregation)) {
+ EXPECT_APPROX_EQ(kTestLinkBandwidth,
+ sender_->ExportDebugState().max_bandwidth, 0.01f);
+ } else {
+ // It's possible to read a bandwidth as much as 50% too high with
+ // aggregation.
+ EXPECT_LE(kTestLinkBandwidth * 0.93f,
+ sender_->ExportDebugState().max_bandwidth);
+ // TODO(ianswett): Tighten this bound once we understand why BBR is
+ // overestimating bandwidth with aggregation. b/36022633
+ EXPECT_GE(kTestLinkBandwidth * 1.5f,
+ sender_->ExportDebugState().max_bandwidth);
+ }
// TODO(ianswett): Expect 0 packets are lost once BBR no longer measures
// bandwidth higher than the link rate.
// The margin here is high, because the aggregation greatly increases
@@ -583,10 +667,18 @@ TEST_F(BbrSenderTest, Drain) {
ASSERT_EQ(BbrSender::DRAIN, sender_->ExportDebugState().mode);
EXPECT_APPROX_EQ(sender_->BandwidthEstimate() * (1 / 2.885f),
sender_->PacingRate(0), 0.01f);
- // BBR uses CWND gain of 2.88 during STARTUP, hence it will fill the buffer
- // with approximately 1.88 BDPs. Here, we use 1.5 to give some margin for
- // error.
- EXPECT_GE(queue->bytes_queued(), 1.5 * kTestBdp);
+
+ if (!GetQuicReloadableFlag(quic_bbr_default_exit_startup_on_loss)) {
+ // BBR uses CWND gain of 2.88 during STARTUP, hence it will fill the buffer
+ // with approximately 1.88 BDPs. Here, we use 1.5 to give some margin for
+ // error.
+ EXPECT_GE(queue->bytes_queued(), 1.5 * kTestBdp);
+ } else {
+ // BBR uses CWND gain of 2 during STARTUP, hence it will fill the buffer
+ // with approximately 1 BDP. Here, we use 0.8 to give some margin for
+ // error.
+ EXPECT_GE(queue->bytes_queued(), 0.8 * kTestBdp);
+ }
// Observe increased RTT due to bufferbloat.
const QuicTime::Delta queueing_delay =
@@ -710,77 +802,6 @@ TEST_F(BbrSenderTest, ProbeRtt) {
EXPECT_GE(sender_->ExportDebugState().min_rtt_timestamp, probe_rtt_start);
}
-// Verify that the connection enters and exits PROBE_RTT correctly.
-TEST_F(BbrSenderTest, ProbeRttBDPBasedCWNDTarget) {
- CreateDefaultSetup();
- SetQuicReloadableFlag(quic_bbr_less_probe_rtt, true);
- SetConnectionOption(kBBR6);
- DriveOutOfStartup();
-
- // We have no intention of ever finishing this transfer.
- bbr_sender_.AddBytesToTransfer(100 * 1024 * 1024);
-
- // Wait until the connection enters PROBE_RTT.
- const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(12);
- bool simulator_result = simulator_.RunUntilOrTimeout(
- [this]() {
- return sender_->ExportDebugState().mode == BbrSender::PROBE_RTT;
- },
- timeout);
- ASSERT_TRUE(simulator_result);
- ASSERT_EQ(BbrSender::PROBE_RTT, sender_->ExportDebugState().mode);
-
- // Exit PROBE_RTT.
- const QuicTime probe_rtt_start = clock_->Now();
- const QuicTime::Delta time_to_exit_probe_rtt =
- kTestRtt + QuicTime::Delta::FromMilliseconds(200);
- simulator_.RunFor(1.5 * time_to_exit_probe_rtt);
- EXPECT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
- EXPECT_GE(sender_->ExportDebugState().min_rtt_timestamp, probe_rtt_start);
-}
-
-// Verify that the connection enters does not enter PROBE_RTT.
-TEST_F(BbrSenderTest, ProbeRttSkippedAfterAppLimitedAndStableRtt) {
- CreateDefaultSetup();
- SetQuicReloadableFlag(quic_bbr_less_probe_rtt, true);
- SetConnectionOption(kBBR7);
- DriveOutOfStartup();
-
- // We have no intention of ever finishing this transfer.
- bbr_sender_.AddBytesToTransfer(100 * 1024 * 1024);
-
- // Wait until the connection enters PROBE_RTT.
- const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(12);
- bool simulator_result = simulator_.RunUntilOrTimeout(
- [this]() {
- return sender_->ExportDebugState().mode == BbrSender::PROBE_RTT;
- },
- timeout);
- ASSERT_FALSE(simulator_result);
- ASSERT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
-}
-
-// Verify that the connection enters does not enter PROBE_RTT.
-TEST_F(BbrSenderTest, ProbeRttSkippedAfterAppLimited) {
- CreateDefaultSetup();
- SetQuicReloadableFlag(quic_bbr_less_probe_rtt, true);
- SetConnectionOption(kBBR8);
- DriveOutOfStartup();
-
- // We have no intention of ever finishing this transfer.
- bbr_sender_.AddBytesToTransfer(100 * 1024 * 1024);
-
- // Wait until the connection enters PROBE_RTT.
- const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(12);
- bool simulator_result = simulator_.RunUntilOrTimeout(
- [this]() {
- return sender_->ExportDebugState().mode == BbrSender::PROBE_RTT;
- },
- timeout);
- ASSERT_FALSE(simulator_result);
- ASSERT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
-}
-
// Ensure that a connection that is app-limited and is at sufficiently low
// bandwidth will not exit high gain phase, and similarly ensure that the
// connection will exit low gain early if the number of bytes in flight is low.
@@ -791,12 +812,12 @@ TEST_F(BbrSenderTest, InFlightAwareGainCycling) {
DriveOutOfStartup();
const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(5);
- bool simulator_result;
-
- // Start a few cycles prior to the high gain one.
- simulator_result = simulator_.RunUntilOrTimeout(
- [this]() { return sender_->ExportDebugState().gain_cycle_index == 6; },
- timeout);
+ while (!(sender_->ExportDebugState().gain_cycle_index >= 4 &&
+ bbr_sender_.bytes_to_transfer() == 0)) {
+ bbr_sender_.AddBytesToTransfer(kTestLinkBandwidth.ToBytesPerSecond());
+ ASSERT_TRUE(simulator_.RunUntilOrTimeout(
+ [this]() { return bbr_sender_.bytes_to_transfer() == 0; }, timeout));
+ }
// Send at 10% of available rate. Run for 3 seconds, checking in the middle
// and at the end. The pacing gain should be high throughout.
@@ -815,10 +836,10 @@ TEST_F(BbrSenderTest, InFlightAwareGainCycling) {
// PROBE_BW mode to enter low gain cycle, and exit it earlier than one min_rtt
// due to running out of data to send.
bbr_sender_.AddBytesToTransfer(1.3 * kTestBdp);
- simulator_result = simulator_.RunUntilOrTimeout(
+ ASSERT_TRUE(simulator_.RunUntilOrTimeout(
[this]() { return sender_->ExportDebugState().gain_cycle_index == 1; },
- timeout);
- ASSERT_TRUE(simulator_result);
+ timeout));
+
simulator_.RunFor(0.75 * sender_->ExportDebugState().min_rtt);
EXPECT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
EXPECT_EQ(2, sender_->ExportDebugState().gain_cycle_index);
@@ -911,11 +932,13 @@ TEST_F(BbrSenderTest, SimpleTransfer2RTTStartup) {
EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
}
-// Test exiting STARTUP earlier upon loss due to the LRTT connection option.
-TEST_F(BbrSenderTest, SimpleTransferLRTTStartup) {
+// Test exiting STARTUP earlier upon loss.
+TEST_F(BbrSenderTest, SimpleTransferExitStartupOnLoss) {
CreateDefaultSetup();
- SetConnectionOption(kLRTT);
+ if (!GetQuicReloadableFlag(quic_bbr_default_exit_startup_on_loss)) {
+ SetConnectionOption(kLRTT);
+ }
EXPECT_EQ(3u, sender_->num_startup_rtts());
// Run until the full bandwidth is reached and check how many rounds it was.
@@ -939,11 +962,13 @@ TEST_F(BbrSenderTest, SimpleTransferLRTTStartup) {
EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
}
-// Test exiting STARTUP earlier upon loss due to the LRTT connection option.
-TEST_F(BbrSenderTest, SimpleTransferLRTTStartupSmallBuffer) {
+// Test exiting STARTUP earlier upon loss with a small buffer.
+TEST_F(BbrSenderTest, SimpleTransferExitStartupOnLossSmallBuffer) {
CreateSmallBufferSetup();
- SetConnectionOption(kLRTT);
+ if (!GetQuicReloadableFlag(quic_bbr_default_exit_startup_on_loss)) {
+ SetConnectionOption(kLRTT);
+ }
EXPECT_EQ(3u, sender_->num_startup_rtts());
// Run until the full bandwidth is reached and check how many rounds it was.
@@ -967,170 +992,6 @@ TEST_F(BbrSenderTest, SimpleTransferLRTTStartupSmallBuffer) {
EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
}
-// Test slower pacing after loss in STARTUP due to the BBRS connection option.
-TEST_F(BbrSenderTest, SimpleTransferSlowerStartup) {
- CreateSmallBufferSetup();
-
- SetConnectionOption(kBBRS);
- EXPECT_EQ(3u, sender_->num_startup_rtts());
-
- // Run until the full bandwidth is reached and check how many rounds it was.
- bbr_sender_.AddBytesToTransfer(12 * 1024 * 1024);
- QuicRoundTripCount max_bw_round = 0;
- QuicBandwidth max_bw(QuicBandwidth::Zero());
- bool simulator_result = simulator_.RunUntilOrTimeout(
- [this, &max_bw, &max_bw_round]() {
- if (max_bw < sender_->ExportDebugState().max_bandwidth) {
- max_bw = sender_->ExportDebugState().max_bandwidth;
- max_bw_round = sender_->ExportDebugState().round_trip_count;
- }
- // Expect the pacing rate in STARTUP to decrease once packet loss
- // is observed, but the CWND does not.
- if (bbr_sender_.connection()->GetStats().packets_lost > 0 &&
- !sender_->ExportDebugState().is_at_full_bandwidth &&
- sender_->has_non_app_limited_sample()) {
- EXPECT_EQ(1.5f * max_bw, sender_->PacingRate(0));
- }
- return sender_->ExportDebugState().is_at_full_bandwidth;
- },
- QuicTime::Delta::FromSeconds(5));
- ASSERT_TRUE(simulator_result);
- EXPECT_EQ(BbrSender::DRAIN, sender_->ExportDebugState().mode);
- EXPECT_GE(3u, sender_->ExportDebugState().round_trip_count - max_bw_round);
- EXPECT_EQ(3u, sender_->ExportDebugState().rounds_without_bandwidth_gain);
- EXPECT_NE(0u, bbr_sender_.connection()->GetStats().packets_lost);
- EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
-}
-
-// Ensures no change in congestion window in STARTUP after loss.
-TEST_F(BbrSenderTest, SimpleTransferNoConservationInStartup) {
- CreateSmallBufferSetup();
-
- SetConnectionOption(kBBS1);
-
- // Run until the full bandwidth is reached and check how many rounds it was.
- bbr_sender_.AddBytesToTransfer(12 * 1024 * 1024);
- bool used_conservation_cwnd = false;
- bool simulator_result = simulator_.RunUntilOrTimeout(
- [this, &used_conservation_cwnd]() {
- if (!sender_->ExportDebugState().is_at_full_bandwidth &&
- sender_->GetCongestionWindow() <
- sender_->ExportDebugState().congestion_window) {
- used_conservation_cwnd = true;
- }
- return sender_->ExportDebugState().is_at_full_bandwidth;
- },
- QuicTime::Delta::FromSeconds(5));
- ASSERT_TRUE(simulator_result);
- EXPECT_FALSE(used_conservation_cwnd);
- EXPECT_EQ(BbrSender::DRAIN, sender_->ExportDebugState().mode);
- EXPECT_EQ(3u, sender_->ExportDebugState().rounds_without_bandwidth_gain);
- EXPECT_NE(0u, bbr_sender_.connection()->GetStats().packets_lost);
- EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
-}
-
-// Ensures no change in congestion window in STARTUP after loss, but that the
-// rate decreases.
-TEST_F(BbrSenderTest, SimpleTransferStartupRateReduction) {
- SetQuicReloadableFlag(quic_bbr_startup_rate_reduction, true);
- CreateSmallBufferSetup();
-
- SetConnectionOption(kBBS4);
-
- // Run until the full bandwidth is reached and check how many rounds it was.
- bbr_sender_.AddBytesToTransfer(12 * 1024 * 1024);
- bool used_conservation_cwnd = false;
- bool simulator_result = simulator_.RunUntilOrTimeout(
- [this, &used_conservation_cwnd]() {
- if (!sender_->ExportDebugState().is_at_full_bandwidth &&
- sender_->GetCongestionWindow() <
- sender_->ExportDebugState().congestion_window) {
- used_conservation_cwnd = true;
- }
- // Exit once a loss is hit.
- return bbr_sender_.connection()->GetStats().packets_lost > 0 ||
- sender_->ExportDebugState().is_at_full_bandwidth;
- },
- QuicTime::Delta::FromSeconds(5));
- ASSERT_TRUE(simulator_result);
- EXPECT_TRUE(sender_->InRecovery());
- EXPECT_FALSE(used_conservation_cwnd);
- EXPECT_EQ(BbrSender::STARTUP, sender_->ExportDebugState().mode);
- EXPECT_NE(0u, bbr_sender_.connection()->GetStats().packets_lost);
-
- // Lose each outstanding packet and the pacing rate decreases.
- const QuicBandwidth original_pacing_rate = sender_->PacingRate(0);
- QuicBandwidth pacing_rate = original_pacing_rate;
- const QuicByteCount original_cwnd = sender_->GetCongestionWindow();
- LostPacketVector lost_packets;
- lost_packets.push_back(
- LostPacket(QuicPacketNumber(), kMaxOutgoingPacketSize));
- QuicPacketNumber largest_sent =
- bbr_sender_.connection()->sent_packet_manager().GetLargestSentPacket();
- for (QuicPacketNumber packet_number =
- bbr_sender_.connection()->sent_packet_manager().GetLeastUnacked();
- packet_number <= largest_sent; ++packet_number) {
- lost_packets[0].packet_number = packet_number;
- sender_->OnCongestionEvent(false, 0, clock_->Now(), {}, lost_packets);
- EXPECT_EQ(original_cwnd, sender_->GetCongestionWindow());
- EXPECT_GT(original_pacing_rate, sender_->PacingRate(0));
- EXPECT_GE(pacing_rate, sender_->PacingRate(0));
- EXPECT_LE(1.25 * sender_->BandwidthEstimate(), sender_->PacingRate(0));
- pacing_rate = sender_->PacingRate(0);
- }
-}
-
-// Ensures no change in congestion window in STARTUP after loss, but that the
-// rate decreases twice as fast as BBS4.
-TEST_F(BbrSenderTest, SimpleTransferDoubleStartupRateReduction) {
- SetQuicReloadableFlag(quic_bbr_startup_rate_reduction, true);
- CreateSmallBufferSetup();
-
- SetConnectionOption(kBBS5);
-
- // Run until the full bandwidth is reached and check how many rounds it was.
- bbr_sender_.AddBytesToTransfer(12 * 1024 * 1024);
- bool used_conservation_cwnd = false;
- bool simulator_result = simulator_.RunUntilOrTimeout(
- [this, &used_conservation_cwnd]() {
- if (!sender_->ExportDebugState().is_at_full_bandwidth &&
- sender_->GetCongestionWindow() <
- sender_->ExportDebugState().congestion_window) {
- used_conservation_cwnd = true;
- }
- // Exit once a loss is hit.
- return bbr_sender_.connection()->GetStats().packets_lost > 0 ||
- sender_->ExportDebugState().is_at_full_bandwidth;
- },
- QuicTime::Delta::FromSeconds(5));
- ASSERT_TRUE(simulator_result);
- EXPECT_TRUE(sender_->InRecovery());
- EXPECT_FALSE(used_conservation_cwnd);
- EXPECT_EQ(BbrSender::STARTUP, sender_->ExportDebugState().mode);
- EXPECT_NE(0u, bbr_sender_.connection()->GetStats().packets_lost);
-
- // Lose each outstanding packet and the pacing rate decreases.
- const QuicBandwidth original_pacing_rate = sender_->PacingRate(0);
- QuicBandwidth pacing_rate = original_pacing_rate;
- const QuicByteCount original_cwnd = sender_->GetCongestionWindow();
- LostPacketVector lost_packets;
- lost_packets.push_back(
- LostPacket(QuicPacketNumber(), kMaxOutgoingPacketSize));
- QuicPacketNumber largest_sent =
- bbr_sender_.connection()->sent_packet_manager().GetLargestSentPacket();
- for (QuicPacketNumber packet_number =
- bbr_sender_.connection()->sent_packet_manager().GetLeastUnacked();
- packet_number <= largest_sent; ++packet_number) {
- lost_packets[0].packet_number = packet_number;
- sender_->OnCongestionEvent(false, 0, clock_->Now(), {}, lost_packets);
- EXPECT_EQ(original_cwnd, sender_->GetCongestionWindow());
- EXPECT_GT(original_pacing_rate, sender_->PacingRate(0));
- EXPECT_GE(pacing_rate, sender_->PacingRate(0));
- EXPECT_LE(1.25 * sender_->BandwidthEstimate(), sender_->PacingRate(0));
- pacing_rate = sender_->PacingRate(0);
- }
-}
-
TEST_F(BbrSenderTest, DerivedPacingGainStartup) {
CreateDefaultSetup();
@@ -1161,7 +1022,9 @@ TEST_F(BbrSenderTest, DerivedPacingGainStartup) {
TEST_F(BbrSenderTest, DerivedCWNDGainStartup) {
CreateSmallBufferSetup();
- SetConnectionOption(kBBQ2);
+ if (!GetQuicReloadableFlag(quic_bbr_default_exit_startup_on_loss)) {
+ SetConnectionOption(kBBQ2);
+ }
EXPECT_EQ(3u, sender_->num_startup_rtts());
// Verify that Sender is in slow start.
EXPECT_TRUE(sender_->InSlowStart());
@@ -1178,7 +1041,9 @@ TEST_F(BbrSenderTest, DerivedCWNDGainStartup) {
QuicTime::Delta::FromSeconds(5));
ASSERT_TRUE(simulator_result);
EXPECT_EQ(BbrSender::DRAIN, sender_->ExportDebugState().mode);
- EXPECT_EQ(3u, sender_->ExportDebugState().rounds_without_bandwidth_gain);
+ if (!bbr_sender_.connection()->GetStats().bbr_exit_startup_due_to_loss) {
+ EXPECT_EQ(3u, sender_->ExportDebugState().rounds_without_bandwidth_gain);
+ }
EXPECT_APPROX_EQ(kTestLinkBandwidth,
sender_->ExportDebugState().max_bandwidth, 0.01f);
float loss_rate =
@@ -1392,5 +1257,125 @@ TEST_F(BbrSenderTest, RecalculatePacingRateOnCwndChange0RTT) {
}
}
+TEST_F(BbrSenderTest, MitigateCwndBootstrappingOvershoot) {
+ SetQuicReloadableFlag(quic_bbr_mitigate_overly_large_bandwidth_sample, true);
+ CreateDefaultSetup();
+ bbr_sender_.AddBytesToTransfer(1 * 1024 * 1024);
+
+ // Wait until an ACK comes back.
+ const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(5);
+ bool simulator_result = simulator_.RunUntilOrTimeout(
+ [this]() { return !sender_->ExportDebugState().min_rtt.IsZero(); },
+ timeout);
+ ASSERT_TRUE(simulator_result);
+
+ // Bootstrap cwnd by a overly large bandwidth sample.
+ bbr_sender_.connection()->AdjustNetworkParameters(
+ SendAlgorithmInterface::NetworkParams(8 * kTestLinkBandwidth,
+ QuicTime::Delta::Zero(), false));
+ QuicBandwidth pacing_rate = sender_->PacingRate(0);
+ EXPECT_EQ(8 * kTestLinkBandwidth, pacing_rate);
+
+ // Wait until pacing_rate decreases.
+ simulator_result = simulator_.RunUntilOrTimeout(
+ [this, pacing_rate]() { return sender_->PacingRate(0) < pacing_rate; },
+ timeout);
+ ASSERT_TRUE(simulator_result);
+ EXPECT_EQ(BbrSender::STARTUP, sender_->ExportDebugState().mode);
+ if (GetQuicReloadableFlag(quic_conservative_cwnd_and_pacing_gains)) {
+ EXPECT_APPROX_EQ(2.0f * sender_->BandwidthEstimate(),
+ sender_->PacingRate(0), 0.01f);
+ } else {
+ EXPECT_APPROX_EQ(2.885f * sender_->BandwidthEstimate(),
+ sender_->PacingRate(0), 0.01f);
+ }
+}
+
+TEST_F(BbrSenderTest, 200InitialCongestionWindowWithNetworkParameterAdjusted) {
+ CreateDefaultSetup();
+
+ bbr_sender_.AddBytesToTransfer(1 * 1024 * 1024);
+ // Wait until an ACK comes back.
+ const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(5);
+ bool simulator_result = simulator_.RunUntilOrTimeout(
+ [this]() { return !sender_->ExportDebugState().min_rtt.IsZero(); },
+ timeout);
+ ASSERT_TRUE(simulator_result);
+
+ // Bootstrap cwnd by a overly large bandwidth sample.
+ bbr_sender_.connection()->AdjustNetworkParameters(
+ SendAlgorithmInterface::NetworkParams(1024 * kTestLinkBandwidth,
+ QuicTime::Delta::Zero(), false));
+ // Verify cwnd is capped at 200.
+ EXPECT_EQ(200 * kDefaultTCPMSS,
+ sender_->ExportDebugState().congestion_window);
+ EXPECT_GT(1024 * kTestLinkBandwidth, sender_->PacingRate(0));
+}
+
+TEST_F(BbrSenderTest, 100InitialCongestionWindowWithNetworkParameterAdjusted) {
+ SetConnectionOption(kICW1);
+ CreateDefaultSetup();
+
+ bbr_sender_.AddBytesToTransfer(1 * 1024 * 1024);
+ // Wait until an ACK comes back.
+ const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(5);
+ bool simulator_result = simulator_.RunUntilOrTimeout(
+ [this]() { return !sender_->ExportDebugState().min_rtt.IsZero(); },
+ timeout);
+ ASSERT_TRUE(simulator_result);
+
+ // Bootstrap cwnd by a overly large bandwidth sample.
+ bbr_sender_.connection()->AdjustNetworkParameters(
+ SendAlgorithmInterface::NetworkParams(1024 * kTestLinkBandwidth,
+ QuicTime::Delta::Zero(), false));
+ // Verify cwnd is capped at 100.
+ EXPECT_EQ(100 * kDefaultTCPMSS,
+ sender_->ExportDebugState().congestion_window);
+ EXPECT_GT(1024 * kTestLinkBandwidth, sender_->PacingRate(0));
+}
+
+// Ensures bandwidth estimate does not change after a loss only event.
+// Regression test for b/151239871.
+TEST_F(BbrSenderTest, LossOnlyCongestionEvent) {
+ CreateDefaultSetup();
+
+ DriveOutOfStartup();
+ EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
+
+ // Send some bursts, each burst increments round count by 1, since it only
+ // generates small, app-limited samples, the max_bandwidth_ will not be
+ // updated. At the end of all bursts, all estimates in max_bandwidth_ will
+ // look very old such that any Update() will reset all estimates.
+ SendBursts(20, 512, QuicTime::Delta::FromSeconds(3));
+
+ QuicUnackedPacketMap* unacked_packets =
+ QuicSentPacketManagerPeer::GetUnackedPacketMap(
+ QuicConnectionPeer::GetSentPacketManager(bbr_sender_.connection()));
+ // Run until we have something in flight.
+ bbr_sender_.AddBytesToTransfer(50 * 1024 * 1024);
+ bool simulator_result = simulator_.RunUntilOrTimeout(
+ [&]() { return unacked_packets->bytes_in_flight() > 0; },
+ QuicTime::Delta::FromSeconds(5));
+ ASSERT_TRUE(simulator_result);
+
+ const QuicBandwidth prior_bandwidth_estimate = sender_->BandwidthEstimate();
+ EXPECT_APPROX_EQ(kTestLinkBandwidth, prior_bandwidth_estimate, 0.01f);
+
+ // Lose the least unacked packet.
+ LostPacketVector lost_packets;
+ lost_packets.emplace_back(
+ bbr_sender_.connection()->sent_packet_manager().GetLeastUnacked(),
+ kDefaultMaxPacketSize);
+
+ QuicTime now = simulator_.GetClock()->Now() + kTestRtt * 0.25;
+ sender_->OnCongestionEvent(false, unacked_packets->bytes_in_flight(), now, {},
+ lost_packets);
+
+ // Bandwidth estimate should not change for the loss only event.
+ if (GetQuicReloadableFlag(quic_bbr_fix_zero_bw_on_loss_only_event)) {
+ EXPECT_EQ(prior_bandwidth_estimate, sender_->BandwidthEstimate());
+ }
+}
+
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/cubic_bytes.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/cubic_bytes.h
index 2bbd04c6573..0e174a84af4 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/cubic_bytes.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/cubic_bytes.h
@@ -11,9 +11,9 @@
#include <cstdint>
#include "net/third_party/quiche/src/quic/core/quic_bandwidth.h"
+#include "net/third_party/quiche/src/quic/core/quic_clock.h"
#include "net/third_party/quiche/src/quic/core/quic_connection_stats.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/cubic_bytes_test.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/cubic_bytes_test.cc
index 4f3e9b1044a..7a48ddf9165 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/cubic_bytes_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/cubic_bytes_test.cc
@@ -7,7 +7,6 @@
#include <cstdint>
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm.cc
index 8798322eb76..6c090136c1a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm.cc
@@ -12,48 +12,15 @@
namespace quic {
-namespace {
-
-// The minimum delay before a packet will be considered lost,
-// regardless of SRTT. Half of the minimum TLP, since the loss algorithm only
-// triggers when a nack has been receieved for the packet.
-static const size_t kMinLossDelayMs = 5;
-
-// Default fraction (1/8) of an RTT when doing IETF loss detection.
-static const int kDefaultIetfLossDelayShift = 3;
-// Default fraction (1/16) of an RTT when doing adaptive loss detection.
-static const int kDefaultAdaptiveLossDelayShift = 4;
-
-} // namespace
-
-GeneralLossAlgorithm::GeneralLossAlgorithm() : GeneralLossAlgorithm(kNack) {}
-
-GeneralLossAlgorithm::GeneralLossAlgorithm(LossDetectionType loss_type)
+GeneralLossAlgorithm::GeneralLossAlgorithm()
: loss_detection_timeout_(QuicTime::Zero()),
+ reordering_shift_(kDefaultLossDelayShift),
reordering_threshold_(kNumberOfNacksBeforeRetransmission),
- use_adaptive_reordering_threshold_(false),
+ use_adaptive_reordering_threshold_(true),
use_adaptive_time_threshold_(false),
+ use_packet_threshold_for_runt_packets_(true),
least_in_flight_(1),
- packet_number_space_(NUM_PACKET_NUMBER_SPACES) {
- SetLossDetectionType(loss_type);
-}
-
-void GeneralLossAlgorithm::SetLossDetectionType(LossDetectionType loss_type) {
- loss_detection_timeout_ = QuicTime::Zero();
- loss_type_ = loss_type;
- if (loss_type == kAdaptiveTime) {
- reordering_shift_ = kDefaultAdaptiveLossDelayShift;
- } else if (loss_type == kIetfLossDetection) {
- reordering_shift_ = kDefaultIetfLossDelayShift;
- } else {
- reordering_shift_ = kDefaultLossDelayShift;
- }
- largest_previously_acked_.Clear();
-}
-
-LossDetectionType GeneralLossAlgorithm::GetLossDetectionType() const {
- return loss_type_;
-}
+ packet_number_space_(NUM_PACKET_NUMBER_SPACES) {}
// Uses nack counts to decide when packets are lost.
void GeneralLossAlgorithm::DetectLosses(
@@ -73,7 +40,6 @@ void GeneralLossAlgorithm::DetectLosses(
// do not use this optimization if largest_newly_acked is not the largest
// packet in packets_acked.
least_in_flight_ = largest_newly_acked + 1;
- largest_previously_acked_ = largest_newly_acked;
return;
}
// There is hole in acked_packets, increment least_in_flight_ if possible.
@@ -86,14 +52,8 @@ void GeneralLossAlgorithm::DetectLosses(
}
QuicTime::Delta max_rtt =
std::max(rtt_stats.previous_srtt(), rtt_stats.latest_rtt());
- if (loss_type_ == kIetfLossDetection) {
- max_rtt = std::max(QuicTime::Delta::FromMilliseconds(1), max_rtt);
- }
+ max_rtt = std::max(kAlarmGranularity, max_rtt);
QuicTime::Delta loss_delay = max_rtt + (max_rtt >> reordering_shift_);
- if (loss_type_ != kIetfLossDetection) {
- loss_delay = std::max(QuicTime::Delta::FromMilliseconds(kMinLossDelayMs),
- loss_delay);
- }
QuicPacketNumber packet_number = unacked_packets.GetLeastUnacked();
auto it = unacked_packets.begin();
if (least_in_flight_.IsInitialized() && least_in_flight_ >= packet_number) {
@@ -120,65 +80,38 @@ void GeneralLossAlgorithm::DetectLosses(
if (!it->in_flight) {
continue;
}
-
- if (loss_type_ == kNack || loss_type_ == kIetfLossDetection) {
- // Packet threshold loss detection.
- if (largest_newly_acked - packet_number >= reordering_threshold_) {
- packets_lost->push_back(LostPacket(packet_number, it->bytes_sent));
- continue;
- }
- } else if (loss_type_ == kLazyFack) {
- // Require two in order acks to invoke FACK, which avoids spuriously
- // retransmitting packets when one packet is reordered by a large amount.
- if (largest_previously_acked_.IsInitialized() &&
- largest_newly_acked > largest_previously_acked_ &&
- largest_previously_acked_ > packet_number &&
- largest_previously_acked_ - packet_number >=
- (kNumberOfNacksBeforeRetransmission - 1)) {
- packets_lost->push_back(LostPacket(packet_number, it->bytes_sent));
- continue;
- }
+ // Packet threshold loss detection.
+ // Skip packet threshold loss detection if largest_newly_acked is a runt.
+ const bool skip_packet_threshold_detection =
+ !use_packet_threshold_for_runt_packets_ &&
+ it->bytes_sent >
+ unacked_packets.GetTransmissionInfo(largest_newly_acked).bytes_sent;
+ if (skip_packet_threshold_detection) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(
+ quic_skip_packet_threshold_loss_detection_with_runt, 2, 2);
}
-
- // Time threshold loss detection. Also implements early retransmit(RFC5827)
- // when time threshold is not used and the last packet gets acked.
- QuicPacketNumber largest_sent_retransmittable_packet =
- unacked_packets.GetLargestSentRetransmittableOfPacketNumberSpace(
- packet_number_space_);
- if (largest_sent_retransmittable_packet <= largest_newly_acked ||
- loss_type_ == kTime || loss_type_ == kAdaptiveTime ||
- loss_type_ == kIetfLossDetection) {
- QuicTime when_lost = it->sent_time + loss_delay;
- if (time < when_lost) {
- loss_detection_timeout_ = when_lost;
- if (!least_in_flight_.IsInitialized()) {
- // At this point, packet_number is in flight and not detected as lost.
- least_in_flight_ = packet_number;
- }
- break;
- }
+ if (!skip_packet_threshold_detection &&
+ largest_newly_acked - packet_number >= reordering_threshold_) {
packets_lost->push_back(LostPacket(packet_number, it->bytes_sent));
continue;
}
- // NACK-based loss detection allows for a max reordering window of 1 RTT.
- if (loss_type_ != kIetfLossDetection &&
- it->sent_time + rtt_stats.smoothed_rtt() <
- unacked_packets.GetTransmissionInfo(largest_newly_acked)
- .sent_time) {
- packets_lost->push_back(LostPacket(packet_number, it->bytes_sent));
- continue;
- }
- if (!least_in_flight_.IsInitialized()) {
- // At this point, packet_number is in flight and not detected as lost.
- least_in_flight_ = packet_number;
+ // Time threshold loss detection.
+ QuicTime when_lost = it->sent_time + loss_delay;
+ if (time < when_lost) {
+ loss_detection_timeout_ = when_lost;
+ if (!least_in_flight_.IsInitialized()) {
+ // At this point, packet_number is in flight and not detected as lost.
+ least_in_flight_ = packet_number;
+ }
+ break;
}
+ packets_lost->push_back(LostPacket(packet_number, it->bytes_sent));
}
if (!least_in_flight_.IsInitialized()) {
// There is no in flight packet.
least_in_flight_ = largest_newly_acked + 1;
}
- largest_previously_acked_ = largest_newly_acked;
}
QuicTime GeneralLossAlgorithm::GetLossTimeout() const {
@@ -191,8 +124,7 @@ void GeneralLossAlgorithm::SpuriousLossDetected(
QuicTime ack_receive_time,
QuicPacketNumber packet_number,
QuicPacketNumber previous_largest_acked) {
- if ((loss_type_ == kAdaptiveTime || use_adaptive_time_threshold_) &&
- reordering_shift_ > 0) {
+ if (use_adaptive_time_threshold_ && reordering_shift_ > 0) {
// Increase reordering fraction such that the packet would not have been
// declared lost.
QuicTime::Delta time_needed =
@@ -225,4 +157,9 @@ void GeneralLossAlgorithm::SetPacketNumberSpace(
packet_number_space_ = packet_number_space;
}
+void GeneralLossAlgorithm::Reset() {
+ loss_detection_timeout_ = QuicTime::Zero();
+ least_in_flight_.Clear();
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm.h
index fb85523c63e..7ab0d536eb7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm.h
@@ -25,17 +25,10 @@ class QUIC_EXPORT_PRIVATE GeneralLossAlgorithm : public LossDetectionInterface {
static const QuicPacketCount kNumberOfNacksBeforeRetransmission = 3;
GeneralLossAlgorithm();
- explicit GeneralLossAlgorithm(LossDetectionType loss_type);
GeneralLossAlgorithm(const GeneralLossAlgorithm&) = delete;
GeneralLossAlgorithm& operator=(const GeneralLossAlgorithm&) = delete;
~GeneralLossAlgorithm() override {}
- LossDetectionType GetLossDetectionType() const override;
-
- // Switches the loss detection type to |loss_type| and resets the loss
- // algorithm.
- void SetLossDetectionType(LossDetectionType loss_type);
-
// Uses |largest_acked| and time to decide when packets are lost.
void DetectLosses(const QuicUnackedPacketMap& unacked_packets,
QuicTime time,
@@ -54,20 +47,41 @@ class QUIC_EXPORT_PRIVATE GeneralLossAlgorithm : public LossDetectionInterface {
QuicPacketNumber packet_number,
QuicPacketNumber previous_largest_acked) override;
+ void OnConfigNegotiated() override {
+ DCHECK(false)
+ << "Unexpected call to GeneralLossAlgorithm::OnConfigNegotiated";
+ }
+
+ void OnMinRttAvailable() override {
+ DCHECK(false)
+ << "Unexpected call to GeneralLossAlgorithm::OnMinRttAvailable";
+ }
+
+ void OnConnectionClosed() override {
+ DCHECK(false)
+ << "Unexpected call to GeneralLossAlgorithm::OnConnectionClosed";
+ }
+
void SetPacketNumberSpace(PacketNumberSpace packet_number_space);
+ void Reset();
+
int reordering_shift() const { return reordering_shift_; }
void set_reordering_shift(int reordering_shift) {
reordering_shift_ = reordering_shift;
}
+ void set_reordering_threshold(QuicPacketCount reordering_threshold) {
+ reordering_threshold_ = reordering_threshold;
+ }
+
bool use_adaptive_reordering_threshold() const {
return use_adaptive_reordering_threshold_;
}
- void enable_adaptive_reordering_threshold() {
- use_adaptive_reordering_threshold_ = true;
+ void set_use_adaptive_reordering_threshold(bool value) {
+ use_adaptive_reordering_threshold_ = value;
}
bool use_adaptive_time_threshold() const {
@@ -76,9 +90,16 @@ class QUIC_EXPORT_PRIVATE GeneralLossAlgorithm : public LossDetectionInterface {
void enable_adaptive_time_threshold() { use_adaptive_time_threshold_ = true; }
+ bool use_packet_threshold_for_runt_packets() const {
+ return use_packet_threshold_for_runt_packets_;
+ }
+
+ void disable_packet_threshold_for_runt_packets() {
+ use_packet_threshold_for_runt_packets_ = false;
+ }
+
private:
QuicTime loss_detection_timeout_;
- LossDetectionType loss_type_;
// Fraction of a max(SRTT, latest_rtt) to permit reordering before declaring
// loss. Fraction calculated by shifting max(SRTT, latest_rtt) to the right
// by reordering_shift.
@@ -89,8 +110,8 @@ class QUIC_EXPORT_PRIVATE GeneralLossAlgorithm : public LossDetectionInterface {
bool use_adaptive_reordering_threshold_;
// If true, uses adaptive time threshold for time based loss detection.
bool use_adaptive_time_threshold_;
- // The largest newly acked from the previous call to DetectLosses.
- QuicPacketNumber largest_previously_acked_;
+ // If true, uses packet threshold when largest acked is a runt packet.
+ bool use_packet_threshold_for_runt_packets_;
// The least in flight packet. Loss detection should start from this. Please
// note, least_in_flight_ could be largest packet ever sent + 1.
QuicPacketNumber least_in_flight_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm_test.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm_test.cc
index aaf9c7c32bc..7bef933b93f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm_test.cc
@@ -32,19 +32,24 @@ class GeneralLossAlgorithmTest : public QuicTest {
~GeneralLossAlgorithmTest() override {}
- void SendDataPacket(uint64_t packet_number) {
+ void SendDataPacket(uint64_t packet_number,
+ QuicPacketLength encrypted_length) {
QuicStreamFrame frame;
frame.stream_id = QuicUtils::GetFirstBidirectionalStreamId(
CurrentSupportedVersions()[0].transport_version,
Perspective::IS_CLIENT);
SerializedPacket packet(QuicPacketNumber(packet_number),
- PACKET_1BYTE_PACKET_NUMBER, nullptr, kDefaultLength,
- false, false);
+ PACKET_1BYTE_PACKET_NUMBER, nullptr,
+ encrypted_length, false, false);
packet.retransmittable_frames.push_back(QuicFrame(frame));
unacked_packets_.AddSentPacket(&packet, NOT_RETRANSMISSION, clock_.Now(),
true);
}
+ void SendDataPacket(uint64_t packet_number) {
+ SendDataPacket(packet_number, kDefaultLength);
+ }
+
void SendAckPacket(uint64_t packet_number) {
SerializedPacket packet(QuicPacketNumber(packet_number),
PACKET_1BYTE_PACKET_NUMBER, nullptr, kDefaultLength,
@@ -138,7 +143,8 @@ TEST_F(GeneralLossAlgorithmTest, NackRetransmit1PacketSingleAck) {
packets_acked.push_back(AckedPacket(
QuicPacketNumber(4), kMaxOutgoingPacketSize, QuicTime::Zero()));
VerifyLosses(4, packets_acked, {1});
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
+ EXPECT_EQ(clock_.Now() + 1.25 * rtt_stats_.smoothed_rtt(),
+ loss_algorithm_.GetLossTimeout());
}
TEST_F(GeneralLossAlgorithmTest, EarlyRetransmit1Packet) {
@@ -262,266 +268,7 @@ TEST_F(GeneralLossAlgorithmTest, AlwaysLosePacketSent1RTTEarlier) {
VerifyLosses(2, packets_acked, {1});
}
-// NoFack loss detection tests.
-TEST_F(GeneralLossAlgorithmTest, LazyFackNackRetransmit1Packet) {
- loss_algorithm_.SetLossDetectionType(kLazyFack);
- const size_t kNumSentPackets = 5;
- // Transmit 5 packets.
- for (size_t i = 1; i <= kNumSentPackets; ++i) {
- SendDataPacket(i);
- }
- AckedPacketVector packets_acked;
- // No loss on one ack.
- unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2));
- packets_acked.push_back(AckedPacket(
- QuicPacketNumber(2), kMaxOutgoingPacketSize, QuicTime::Zero()));
- VerifyLosses(2, packets_acked, std::vector<uint64_t>{});
- packets_acked.clear();
- // No loss on two acks.
- unacked_packets_.RemoveFromInFlight(QuicPacketNumber(3));
- packets_acked.push_back(AckedPacket(
- QuicPacketNumber(3), kMaxOutgoingPacketSize, QuicTime::Zero()));
- VerifyLosses(3, packets_acked, std::vector<uint64_t>{});
- packets_acked.clear();
- // Loss on three acks.
- unacked_packets_.RemoveFromInFlight(QuicPacketNumber(4));
- packets_acked.push_back(AckedPacket(
- QuicPacketNumber(4), kMaxOutgoingPacketSize, QuicTime::Zero()));
- VerifyLosses(4, packets_acked, {1});
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
-}
-
-// A stretch ack is an ack that covers more than 1 packet of previously
-// unacknowledged data.
-TEST_F(GeneralLossAlgorithmTest,
- LazyFackNoNackRetransmit1PacketWith1StretchAck) {
- loss_algorithm_.SetLossDetectionType(kLazyFack);
- const size_t kNumSentPackets = 10;
- // Transmit 10 packets.
- for (size_t i = 1; i <= kNumSentPackets; ++i) {
- SendDataPacket(i);
- }
- AckedPacketVector packets_acked;
- // Nack the first packet 3 times in a single StretchAck.
- unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2));
- packets_acked.push_back(AckedPacket(
- QuicPacketNumber(2), kMaxOutgoingPacketSize, QuicTime::Zero()));
- unacked_packets_.RemoveFromInFlight(QuicPacketNumber(3));
- packets_acked.push_back(AckedPacket(
- QuicPacketNumber(3), kMaxOutgoingPacketSize, QuicTime::Zero()));
- unacked_packets_.RemoveFromInFlight(QuicPacketNumber(4));
- packets_acked.push_back(AckedPacket(
- QuicPacketNumber(4), kMaxOutgoingPacketSize, QuicTime::Zero()));
- VerifyLosses(4, packets_acked, std::vector<uint64_t>{});
- packets_acked.clear();
- // The timer isn't set because we expect more acks.
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
- // Process another ack and then packet 1 will be lost.
- unacked_packets_.RemoveFromInFlight(QuicPacketNumber(5));
- packets_acked.push_back(AckedPacket(
- QuicPacketNumber(5), kMaxOutgoingPacketSize, QuicTime::Zero()));
- VerifyLosses(5, packets_acked, {1});
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
-}
-
-// Ack a packet 3 packets ahead does not cause a retransmit.
-TEST_F(GeneralLossAlgorithmTest, LazyFackNackRetransmit1PacketSingleAck) {
- loss_algorithm_.SetLossDetectionType(kLazyFack);
- const size_t kNumSentPackets = 10;
- // Transmit 10 packets.
- for (size_t i = 1; i <= kNumSentPackets; ++i) {
- SendDataPacket(i);
- }
- AckedPacketVector packets_acked;
- // Nack the first packet 3 times in an AckFrame with three missing packets.
- unacked_packets_.RemoveFromInFlight(QuicPacketNumber(4));
- packets_acked.push_back(AckedPacket(
- QuicPacketNumber(4), kMaxOutgoingPacketSize, QuicTime::Zero()));
- VerifyLosses(4, packets_acked, std::vector<uint64_t>{});
- packets_acked.clear();
- // The timer isn't set because we expect more acks.
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
- // Process another ack and then packet 1 and 2 will be lost.
- unacked_packets_.RemoveFromInFlight(QuicPacketNumber(5));
- packets_acked.push_back(AckedPacket(
- QuicPacketNumber(5), kMaxOutgoingPacketSize, QuicTime::Zero()));
- VerifyLosses(5, packets_acked, {1, 2});
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
-}
-
-// Time-based loss detection tests.
-TEST_F(GeneralLossAlgorithmTest, NoLossFor500Nacks) {
- loss_algorithm_.SetLossDetectionType(kTime);
- const size_t kNumSentPackets = 5;
- // Transmit 5 packets.
- for (size_t i = 1; i <= kNumSentPackets; ++i) {
- SendDataPacket(i);
- }
- AckedPacketVector packets_acked;
- unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2));
- packets_acked.push_back(AckedPacket(
- QuicPacketNumber(2), kMaxOutgoingPacketSize, QuicTime::Zero()));
- for (size_t i = 1; i < 500; ++i) {
- VerifyLosses(2, packets_acked, std::vector<uint64_t>{});
- packets_acked.clear();
- }
- EXPECT_EQ(1.25 * rtt_stats_.smoothed_rtt(),
- loss_algorithm_.GetLossTimeout() - clock_.Now());
-}
-
-TEST_F(GeneralLossAlgorithmTest, NoLossUntilTimeout) {
- loss_algorithm_.SetLossDetectionType(kTime);
- const size_t kNumSentPackets = 10;
- // Transmit 10 packets at 1/10th an RTT interval.
- for (size_t i = 1; i <= kNumSentPackets; ++i) {
- SendDataPacket(i);
- clock_.AdvanceTime(0.1 * rtt_stats_.smoothed_rtt());
- }
- AckedPacketVector packets_acked;
- // Expect the timer to not be set.
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
- // The packet should not be lost until 1.25 RTTs pass.
- unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2));
- packets_acked.push_back(AckedPacket(
- QuicPacketNumber(2), kMaxOutgoingPacketSize, QuicTime::Zero()));
- VerifyLosses(2, packets_acked, std::vector<uint64_t>{});
- packets_acked.clear();
- // Expect the timer to be set to 0.25 RTT's in the future.
- EXPECT_EQ(0.25 * rtt_stats_.smoothed_rtt(),
- loss_algorithm_.GetLossTimeout() - clock_.Now());
- VerifyLosses(2, packets_acked, std::vector<uint64_t>{});
- clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt());
- VerifyLosses(2, packets_acked, {1});
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
-}
-
-TEST_F(GeneralLossAlgorithmTest, NoLossWithoutNack) {
- loss_algorithm_.SetLossDetectionType(kTime);
- const size_t kNumSentPackets = 10;
- // Transmit 10 packets at 1/10th an RTT interval.
- for (size_t i = 1; i <= kNumSentPackets; ++i) {
- SendDataPacket(i);
- clock_.AdvanceTime(0.1 * rtt_stats_.smoothed_rtt());
- }
- AckedPacketVector packets_acked;
- // Expect the timer to not be set.
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
- // The packet should not be lost without a nack.
- unacked_packets_.RemoveFromInFlight(QuicPacketNumber(1));
- packets_acked.push_back(AckedPacket(
- QuicPacketNumber(1), kMaxOutgoingPacketSize, QuicTime::Zero()));
- VerifyLosses(1, packets_acked, std::vector<uint64_t>{});
- packets_acked.clear();
- // The timer should still not be set.
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
- clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt());
- VerifyLosses(1, packets_acked, std::vector<uint64_t>{});
- clock_.AdvanceTime(rtt_stats_.smoothed_rtt());
- VerifyLosses(1, packets_acked, std::vector<uint64_t>{});
-
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
-}
-
-TEST_F(GeneralLossAlgorithmTest, MultipleLossesAtOnce) {
- loss_algorithm_.SetLossDetectionType(kTime);
- const size_t kNumSentPackets = 10;
- // Transmit 10 packets at once and then go forward an RTT.
- for (size_t i = 1; i <= kNumSentPackets; ++i) {
- SendDataPacket(i);
- }
- AckedPacketVector packets_acked;
- clock_.AdvanceTime(rtt_stats_.smoothed_rtt());
- // Expect the timer to not be set.
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
- // The packet should not be lost until 1.25 RTTs pass.
- unacked_packets_.RemoveFromInFlight(QuicPacketNumber(10));
- packets_acked.push_back(AckedPacket(
- QuicPacketNumber(10), kMaxOutgoingPacketSize, QuicTime::Zero()));
- VerifyLosses(10, packets_acked, std::vector<uint64_t>{});
- packets_acked.clear();
- // Expect the timer to be set to 0.25 RTT's in the future.
- EXPECT_EQ(0.25 * rtt_stats_.smoothed_rtt(),
- loss_algorithm_.GetLossTimeout() - clock_.Now());
- clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt());
- VerifyLosses(10, packets_acked, {1, 2, 3, 4, 5, 6, 7, 8, 9});
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
-}
-
-TEST_F(GeneralLossAlgorithmTest, NoSpuriousLossesFromLargeReordering) {
- loss_algorithm_.SetLossDetectionType(kTime);
- const size_t kNumSentPackets = 10;
- // Transmit 10 packets at once and then go forward an RTT.
- for (size_t i = 1; i <= kNumSentPackets; ++i) {
- SendDataPacket(i);
- }
- AckedPacketVector packets_acked;
- clock_.AdvanceTime(rtt_stats_.smoothed_rtt());
- // Expect the timer to not be set.
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
- // The packet should not be lost until 1.25 RTTs pass.
-
- unacked_packets_.RemoveFromInFlight(QuicPacketNumber(10));
- packets_acked.push_back(AckedPacket(
- QuicPacketNumber(10), kMaxOutgoingPacketSize, QuicTime::Zero()));
- VerifyLosses(10, packets_acked, std::vector<uint64_t>{});
- packets_acked.clear();
- // Expect the timer to be set to 0.25 RTT's in the future.
- EXPECT_EQ(0.25 * rtt_stats_.smoothed_rtt(),
- loss_algorithm_.GetLossTimeout() - clock_.Now());
- clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt());
- // Now ack packets 1 to 9 and ensure the timer is no longer set and no packets
- // are lost.
- for (uint64_t i = 1; i <= 9; ++i) {
- unacked_packets_.RemoveFromInFlight(QuicPacketNumber(i));
- packets_acked.push_back(AckedPacket(
- QuicPacketNumber(i), kMaxOutgoingPacketSize, QuicTime::Zero()));
- VerifyLosses(i, packets_acked, std::vector<uint64_t>{});
- packets_acked.clear();
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
- }
-}
-
-TEST_F(GeneralLossAlgorithmTest, IncreaseThresholdUponSpuriousLoss) {
- loss_algorithm_.SetLossDetectionType(kAdaptiveTime);
- EXPECT_EQ(4, loss_algorithm_.reordering_shift());
- const size_t kNumSentPackets = 10;
- // Transmit 2 packets at 1/10th an RTT interval.
- for (size_t i = 1; i <= kNumSentPackets; ++i) {
- SendDataPacket(i);
- clock_.AdvanceTime(0.1 * rtt_stats_.smoothed_rtt());
- }
- EXPECT_EQ(QuicTime::Zero() + rtt_stats_.smoothed_rtt(), clock_.Now());
- AckedPacketVector packets_acked;
- // Expect the timer to not be set.
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
- // Packet 1 should not be lost until 1/16 RTTs pass.
- unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2));
- packets_acked.push_back(AckedPacket(
- QuicPacketNumber(2), kMaxOutgoingPacketSize, QuicTime::Zero()));
- VerifyLosses(2, packets_acked, std::vector<uint64_t>{});
- packets_acked.clear();
- // Expect the timer to be set to 1/16 RTT's in the future.
- EXPECT_EQ(rtt_stats_.smoothed_rtt() * (1.0f / 16),
- loss_algorithm_.GetLossTimeout() - clock_.Now());
- VerifyLosses(2, packets_acked, std::vector<uint64_t>{});
- clock_.AdvanceTime(rtt_stats_.smoothed_rtt() * (1.0f / 16));
- VerifyLosses(2, packets_acked, {1});
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
- // Retransmit packet 1 as 11 and 2 as 12.
- SendDataPacket(11);
- SendDataPacket(12);
-
- // Advance the time 1/4 RTT and indicate the loss was spurious.
- // The new threshold should be 1/2 RTT.
- clock_.AdvanceTime(rtt_stats_.smoothed_rtt() * (1.0f / 4));
- loss_algorithm_.SpuriousLossDetected(unacked_packets_, rtt_stats_,
- clock_.Now(), QuicPacketNumber(1),
- QuicPacketNumber(2));
- EXPECT_EQ(1, loss_algorithm_.reordering_shift());
-}
-
TEST_F(GeneralLossAlgorithmTest, IncreaseTimeThresholdUponSpuriousLoss) {
- loss_algorithm_.SetLossDetectionType(kIetfLossDetection);
loss_algorithm_.enable_adaptive_time_threshold();
loss_algorithm_.set_reordering_shift(kDefaultLossDelayShift);
EXPECT_EQ(kDefaultLossDelayShift, loss_algorithm_.reordering_shift());
@@ -563,7 +310,7 @@ TEST_F(GeneralLossAlgorithmTest, IncreaseTimeThresholdUponSpuriousLoss) {
}
TEST_F(GeneralLossAlgorithmTest, IncreaseReorderingThresholdUponSpuriousLoss) {
- loss_algorithm_.enable_adaptive_reordering_threshold();
+ loss_algorithm_.set_use_adaptive_reordering_threshold(true);
for (size_t i = 1; i <= 4; ++i) {
SendDataPacket(i);
}
@@ -626,7 +373,7 @@ TEST_F(GeneralLossAlgorithmTest, IncreaseReorderingThresholdUponSpuriousLoss) {
}
TEST_F(GeneralLossAlgorithmTest, DefaultIetfLossDetection) {
- loss_algorithm_.SetLossDetectionType(kIetfLossDetection);
+ loss_algorithm_.set_reordering_shift(kDefaultIetfLossDelayShift);
for (size_t i = 1; i <= 6; ++i) {
SendDataPacket(i);
}
@@ -670,7 +417,6 @@ TEST_F(GeneralLossAlgorithmTest, DefaultIetfLossDetection) {
}
TEST_F(GeneralLossAlgorithmTest, IetfLossDetectionWithOneFourthRttDelay) {
- loss_algorithm_.SetLossDetectionType(kIetfLossDetection);
loss_algorithm_.set_reordering_shift(2);
SendDataPacket(1);
SendDataPacket(2);
@@ -690,6 +436,30 @@ TEST_F(GeneralLossAlgorithmTest, IetfLossDetectionWithOneFourthRttDelay) {
EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
}
+TEST_F(GeneralLossAlgorithmTest, NoPacketThresholdForRuntPackets) {
+ loss_algorithm_.disable_packet_threshold_for_runt_packets();
+ for (size_t i = 1; i <= 6; ++i) {
+ SendDataPacket(i);
+ }
+ // Send a small packet.
+ SendDataPacket(7, /*encrypted_length=*/kDefaultLength / 2);
+ // No packet threshold for runt packet.
+ AckedPacketVector packets_acked;
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(7));
+ packets_acked.push_back(AckedPacket(
+ QuicPacketNumber(7), kMaxOutgoingPacketSize, QuicTime::Zero()));
+ // Verify no packet is detected lost because packet 7 is a runt.
+ VerifyLosses(7, packets_acked, std::vector<uint64_t>{});
+ EXPECT_EQ(clock_.Now() + rtt_stats_.smoothed_rtt() +
+ (rtt_stats_.smoothed_rtt() >> 2),
+ loss_algorithm_.GetLossTimeout());
+ clock_.AdvanceTime(rtt_stats_.smoothed_rtt() +
+ (rtt_stats_.smoothed_rtt() >> 2));
+ // Verify packets are declared lost because time threshold has passed.
+ VerifyLosses(7, packets_acked, {1, 2, 3, 4, 5, 6});
+ EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/loss_detection_interface.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/loss_detection_interface.h
index af9c1962656..729cbad62ad 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/loss_detection_interface.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/loss_detection_interface.h
@@ -20,9 +20,6 @@ class RttStats;
class QUIC_EXPORT_PRIVATE LossDetectionInterface {
public:
virtual ~LossDetectionInterface() {}
-
- virtual LossDetectionType GetLossDetectionType() const = 0;
-
// Called when a new ack arrives or the loss alarm fires.
virtual void DetectLosses(const QuicUnackedPacketMap& unacked_packets,
QuicTime time,
@@ -42,6 +39,12 @@ class QUIC_EXPORT_PRIVATE LossDetectionInterface {
QuicTime ack_receive_time,
QuicPacketNumber packet_number,
QuicPacketNumber previous_largest_acked) = 0;
+
+ virtual void OnConfigNegotiated() = 0;
+
+ virtual void OnMinRttAvailable() = 0;
+
+ virtual void OnConnectionClosed() = 0;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender.cc
index dbdc924af97..2ba07ab67d1 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender.cc
@@ -25,7 +25,7 @@ PacingSender::PacingSender()
ideal_next_packet_send_time_(QuicTime::Zero()),
initial_burst_size_(kInitialUnpacedBurst),
lumpy_tokens_(0),
- alarm_granularity_(QuicTime::Delta::FromMilliseconds(1)),
+ alarm_granularity_(kAlarmGranularity),
pacing_limited_(false) {
if (GetQuicReloadableFlag(quic_donot_reset_ideal_next_packet_send_time)) {
QUIC_RELOADABLE_FLAG_COUNT(quic_donot_reset_ideal_next_packet_send_time);
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.cc
index f4cbf381cf3..d3853d70f4e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.cc
@@ -27,6 +27,7 @@ RttStats::RttStats()
smoothed_rtt_(QuicTime::Delta::Zero()),
previous_srtt_(QuicTime::Delta::Zero()),
mean_deviation_(QuicTime::Delta::Zero()),
+ calculate_standard_deviation_(false),
initial_rtt_(QuicTime::Delta::FromMilliseconds(kInitialRttMs)),
max_ack_delay_(QuicTime::Delta::Zero()),
last_update_time_(QuicTime::Zero()),
@@ -77,6 +78,9 @@ void RttStats::UpdateRtt(QuicTime::Delta send_delta,
}
}
latest_rtt_ = rtt_sample;
+ if (calculate_standard_deviation_) {
+ standard_deviation_calculator_.OnNewRttSample(rtt_sample, smoothed_rtt_);
+ }
// First time call.
if (smoothed_rtt_.IsZero()) {
smoothed_rtt_ = rtt_sample;
@@ -101,4 +105,30 @@ void RttStats::OnConnectionMigration() {
max_ack_delay_ = QuicTime::Delta::Zero();
}
+QuicTime::Delta RttStats::GetStandardOrMeanDeviation() const {
+ DCHECK(calculate_standard_deviation_);
+ if (!standard_deviation_calculator_.has_valid_standard_deviation) {
+ return mean_deviation_;
+ }
+ return standard_deviation_calculator_.CalculateStandardDeviation();
+}
+
+void RttStats::StandardDeviationCaculator::OnNewRttSample(
+ QuicTime::Delta rtt_sample,
+ QuicTime::Delta smoothed_rtt) {
+ double new_value = rtt_sample.ToMicroseconds();
+ if (smoothed_rtt.IsZero()) {
+ return;
+ }
+ has_valid_standard_deviation = true;
+ const double delta = new_value - smoothed_rtt.ToMicroseconds();
+ m2 = kOneMinusBeta * m2 + kBeta * pow(delta, 2);
+}
+
+QuicTime::Delta
+RttStats::StandardDeviationCaculator::CalculateStandardDeviation() const {
+ DCHECK(has_valid_standard_deviation);
+ return QuicTime::Delta::FromMicroseconds(sqrt(m2));
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h
index 1c0466a424f..9062c7a339c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h
@@ -23,6 +23,24 @@ class RttStatsPeer;
class QUIC_EXPORT_PRIVATE RttStats {
public:
+ // Calculates running standard-deviation using Welford's algorithm:
+ // https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#
+ // Welford's_Online_algorithm.
+ struct QUIC_EXPORT_PRIVATE StandardDeviationCaculator {
+ StandardDeviationCaculator() {}
+
+ // Called when a new RTT sample is available.
+ void OnNewRttSample(QuicTime::Delta rtt_sample,
+ QuicTime::Delta smoothed_rtt);
+ // Calculates the standard deviation.
+ QuicTime::Delta CalculateStandardDeviation() const;
+
+ bool has_valid_standard_deviation = false;
+
+ private:
+ double m2 = 0;
+ };
+
RttStats();
RttStats(const RttStats&) = delete;
RttStats& operator=(const RttStats&) = delete;
@@ -73,6 +91,10 @@ class QUIC_EXPORT_PRIVATE RttStats {
QuicTime::Delta mean_deviation() const { return mean_deviation_; }
+ // Returns standard deviation if there is a valid one. Otherwise, returns
+ // mean_deviation_.
+ QuicTime::Delta GetStandardOrMeanDeviation() const;
+
QuicTime last_update_time() const { return last_update_time_; }
bool ignore_max_ack_delay() const { return ignore_max_ack_delay_; }
@@ -85,6 +107,10 @@ class QUIC_EXPORT_PRIVATE RttStats {
max_ack_delay_ = std::max(max_ack_delay_, initial_max_ack_delay);
}
+ void EnableStandardDeviationCalculation() {
+ calculate_standard_deviation_ = true;
+ }
+
private:
friend class test::RttStatsPeer;
@@ -96,6 +122,10 @@ class QUIC_EXPORT_PRIVATE RttStats {
// Approximation of standard deviation, the error is roughly 1.25 times
// larger than the standard deviation, for a normally distributed signal.
QuicTime::Delta mean_deviation_;
+ // Standard deviation calculator. Only used calculate_standard_deviation_ is
+ // true.
+ StandardDeviationCaculator standard_deviation_calculator_;
+ bool calculate_standard_deviation_;
QuicTime::Delta initial_rtt_;
// The maximum ack delay observed over the connection after excluding ack
// delays that were too large to be included in an RTT measurement.
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats_test.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats_test.cc
index be5f4d679f0..1b0e545af2c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats_test.cc
@@ -9,6 +9,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_mock_log.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/rtt_stats_peer.h"
using testing::_;
@@ -216,5 +217,54 @@ TEST_F(RttStatsTest, ResetAfterConnectionMigrations) {
EXPECT_EQ(QuicTime::Delta::Zero(), rtt_stats_.min_rtt());
}
+TEST_F(RttStatsTest, StandardDeviationCaculatorTest1) {
+ // All samples are the same.
+ rtt_stats_.EnableStandardDeviationCalculation();
+ rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(10),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ EXPECT_EQ(rtt_stats_.mean_deviation(),
+ rtt_stats_.GetStandardOrMeanDeviation());
+
+ rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(10),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(10),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ EXPECT_EQ(QuicTime::Delta::Zero(), rtt_stats_.GetStandardOrMeanDeviation());
+}
+
+TEST_F(RttStatsTest, StandardDeviationCaculatorTest2) {
+ // Small variance.
+ rtt_stats_.EnableStandardDeviationCalculation();
+ rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(10),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(10),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(10),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(9),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(11),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ EXPECT_LT(QuicTime::Delta::FromMicroseconds(500),
+ rtt_stats_.GetStandardOrMeanDeviation());
+ EXPECT_GT(QuicTime::Delta::FromMilliseconds(1),
+ rtt_stats_.GetStandardOrMeanDeviation());
+}
+
+TEST_F(RttStatsTest, StandardDeviationCaculatorTest3) {
+ // Some variance.
+ rtt_stats_.EnableStandardDeviationCalculation();
+ rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(50),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(50),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ EXPECT_APPROX_EQ(rtt_stats_.mean_deviation(),
+ rtt_stats_.GetStandardOrMeanDeviation(), 0.25f);
+}
+
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.cc
index 83529c6e76c..d7b2eca3c74 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.cc
@@ -4,10 +4,10 @@
#include "net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h"
+#include "net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.h"
#include "net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.h"
#include "net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_bbr2_sender.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_fallthrough.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
@@ -26,7 +26,8 @@ SendAlgorithmInterface* SendAlgorithmInterface::Create(
CongestionControlType congestion_control_type,
QuicRandom* random,
QuicConnectionStats* stats,
- QuicPacketCount initial_congestion_window) {
+ QuicPacketCount initial_congestion_window,
+ SendAlgorithmInterface* old_send_algorithm) {
QuicPacketCount max_congestion_window =
GetQuicFlag(FLAGS_quic_max_congestion_window);
switch (congestion_control_type) {
@@ -36,9 +37,13 @@ SendAlgorithmInterface* SendAlgorithmInterface::Create(
initial_congestion_window, max_congestion_window,
random, stats);
case kBBRv2:
- return new QuicBbr2Sender(clock->ApproximateNow(), rtt_stats,
- unacked_packets, initial_congestion_window,
- max_congestion_window, random, stats);
+ return new Bbr2Sender(
+ clock->ApproximateNow(), rtt_stats, unacked_packets,
+ initial_congestion_window, max_congestion_window, random, stats,
+ old_send_algorithm &&
+ old_send_algorithm->GetCongestionControlType() == kBBR
+ ? static_cast<BbrSender*>(old_send_algorithm)
+ : nullptr);
case kPCC:
if (GetQuicReloadableFlag(quic_enable_pcc3)) {
return CreatePccSender(clock, rtt_stats, unacked_packets, random, stats,
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h
index 628e0d62e0c..2bfc2dfbcf3 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h
@@ -13,13 +13,13 @@
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
#include "net/third_party/quiche/src/quic/core/quic_bandwidth.h"
+#include "net/third_party/quiche/src/quic/core/quic_clock.h"
#include "net/third_party/quiche/src/quic/core/quic_config.h"
#include "net/third_party/quiche/src/quic/core/quic_connection_stats.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_unacked_packet_map.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
namespace quic {
@@ -45,24 +45,30 @@ class QUIC_EXPORT_PRIVATE SendAlgorithmInterface {
quic_fix_bbr_cwnd_in_bandwidth_resumption(
GetQuicReloadableFlag(quic_fix_bbr_cwnd_in_bandwidth_resumption)),
quic_bbr_fix_pacing_rate(
- GetQuicReloadableFlag(quic_bbr_fix_pacing_rate)) {}
+ GetQuicReloadableFlag(quic_bbr_fix_pacing_rate)),
+ quic_bbr_donot_inject_bandwidth(
+ GetQuicReloadableFlag(quic_bbr_donot_inject_bandwidth)) {}
bool operator==(const NetworkParams& other) const {
return bandwidth == other.bandwidth && rtt == other.rtt &&
allow_cwnd_to_decrease == other.allow_cwnd_to_decrease &&
quic_fix_bbr_cwnd_in_bandwidth_resumption ==
other.quic_fix_bbr_cwnd_in_bandwidth_resumption &&
- quic_bbr_fix_pacing_rate == other.quic_bbr_fix_pacing_rate;
+ quic_bbr_fix_pacing_rate == other.quic_bbr_fix_pacing_rate &&
+ quic_bbr_donot_inject_bandwidth ==
+ other.quic_bbr_donot_inject_bandwidth;
}
QuicBandwidth bandwidth;
QuicTime::Delta rtt;
bool allow_cwnd_to_decrease;
// Code changes that are controlled by flags.
- // TODO(b/131899599): Remove when impact of fix is measured.
+ // TODO(b/131899599): Remove after impact of fix is measured.
bool quic_fix_bbr_cwnd_in_bandwidth_resumption;
- // TODO(b/143540157): Remove when impact of fix is measured.
+ // TODO(b/143540157): Remove after impact of fix is measured.
bool quic_bbr_fix_pacing_rate;
+ // TODO(b/72089315, b/143891040): Remove after impact of fix is measured.
+ bool quic_bbr_donot_inject_bandwidth;
};
static SendAlgorithmInterface* Create(
@@ -72,7 +78,8 @@ class QUIC_EXPORT_PRIVATE SendAlgorithmInterface {
CongestionControlType type,
QuicRandom* random,
QuicConnectionStats* stats,
- QuicPacketCount initial_congestion_window);
+ QuicPacketCount initial_congestion_window,
+ SendAlgorithmInterface* old_send_algorithm);
virtual ~SendAlgorithmInterface() {}
@@ -104,6 +111,9 @@ class QUIC_EXPORT_PRIVATE SendAlgorithmInterface {
QuicByteCount bytes,
HasRetransmittableData is_retransmittable) = 0;
+ // Inform that |packet_number| has been neutered.
+ virtual void OnPacketNeutered(QuicPacketNumber packet_number) = 0;
+
// Called when the retransmission timeout fires. Neither OnPacketAbandoned
// nor OnPacketLost will be called for these packets.
virtual void OnRetransmissionTimeout(bool packets_retransmitted) = 0;
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_test.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_test.cc
index b3638132adf..9937cf89a37 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_test.cc
@@ -13,7 +13,6 @@
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
@@ -23,6 +22,7 @@
#include "net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/switch.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
namespace quic {
namespace test {
@@ -134,7 +134,7 @@ struct TestParams {
std::string TestParamToString(
const testing::TestParamInfo<TestParams>& params) {
- return QuicStrCat(
+ return quiche::QuicheStrCat(
CongestionControlTypeToString(params.param.congestion_control_type), "_");
}
@@ -171,7 +171,7 @@ class SendAlgorithmTest : public QuicTestWithParam<TestParams> {
QuicConnectionPeer::GetSentPacketManager(
quic_sender_.connection())),
GetParam().congestion_control_type, &random_, &stats_,
- kInitialCongestionWindowPackets);
+ kInitialCongestionWindowPackets, nullptr);
quic_sender_.RecordTrace();
QuicConnectionPeer::SetSendAlgorithm(quic_sender_.connection(), sender_);
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.cc
index cf400e5a1cc..bd2e24ec202 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.cc
@@ -136,7 +136,7 @@ void TcpCubicSenderBytes::OnCongestionEvent(
OnPacketLost(lost_packet.packet_number, lost_packet.bytes_lost,
prior_in_flight);
}
- for (const AckedPacket acked_packet : acked_packets) {
+ for (const AckedPacket& acked_packet : acked_packets) {
OnPacketAcked(acked_packet.packet_number, acked_packet.bytes_acked,
prior_in_flight, event_time);
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.h
index 9144b8a5913..7a36f761c1a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.h
@@ -61,6 +61,7 @@ class QUIC_EXPORT_PRIVATE TcpCubicSenderBytes : public SendAlgorithmInterface {
QuicPacketNumber packet_number,
QuicByteCount bytes,
HasRetransmittableData is_retransmittable) override;
+ void OnPacketNeutered(QuicPacketNumber /*packet_number*/) override {}
void OnRetransmissionTimeout(bool packets_retransmitted) override;
bool CanSend(QuicByteCount bytes_in_flight) override;
QuicBandwidth PacingRate(QuicByteCount bytes_in_flight) const override;
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc
index 04c0e8a41ec..13a253b97d0 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc
@@ -786,7 +786,7 @@ TEST_F(TcpCubicSenderBytesTest, DefaultMaxCwnd) {
QuicConnectionStats stats;
std::unique_ptr<SendAlgorithmInterface> sender(SendAlgorithmInterface::Create(
&clock_, &rtt_stats, /*unacked_packets=*/nullptr, kCubicBytes,
- QuicRandom::GetInstance(), &stats, kInitialCongestionWindow));
+ QuicRandom::GetInstance(), &stats, kInitialCongestionWindow, nullptr));
AckedPacketVector acked_packets;
LostPacketVector missing_packets;
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.cc
index 4e7f07b3b10..73b26f5cda7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.cc
@@ -6,30 +6,17 @@
#include <algorithm>
-namespace quic {
+#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
-UberLossAlgorithm::UberLossAlgorithm() : UberLossAlgorithm(kNack) {}
+namespace quic {
-UberLossAlgorithm::UberLossAlgorithm(LossDetectionType loss_type)
- : loss_type_(loss_type) {
- SetLossDetectionType(loss_type);
+UberLossAlgorithm::UberLossAlgorithm() {
for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
general_loss_algorithms_[i].SetPacketNumberSpace(
static_cast<PacketNumberSpace>(i));
}
}
-LossDetectionType UberLossAlgorithm::GetLossDetectionType() const {
- return loss_type_;
-}
-
-void UberLossAlgorithm::SetLossDetectionType(LossDetectionType loss_type) {
- loss_type_ = loss_type;
- for (auto& loss_algorithm : general_loss_algorithms_) {
- loss_algorithm.SetLossDetectionType(loss_type);
- }
-}
-
void UberLossAlgorithm::DetectLosses(
const QuicUnackedPacketMap& unacked_packets,
QuicTime time,
@@ -81,15 +68,57 @@ void UberLossAlgorithm::SpuriousLossDetected(
packet_number, previous_largest_acked);
}
+void UberLossAlgorithm::SetLossDetectionTuner(
+ std::unique_ptr<LossDetectionTunerInterface> tuner) {
+ if (tuner_ != nullptr) {
+ QUIC_BUG << "LossDetectionTuner can only be set once when session begins.";
+ return;
+ }
+ tuner_ = std::move(tuner);
+}
+
+void UberLossAlgorithm::MaybeStartTuning() {
+ if (tuner_ == nullptr || tuner_started_) {
+ return;
+ }
+
+ tuner_started_ = tuner_->Start(&tuned_parameters_);
+}
+
+void UberLossAlgorithm::OnConfigNegotiated() {}
+
+void UberLossAlgorithm::OnMinRttAvailable() {
+ MaybeStartTuning();
+}
+
+void UberLossAlgorithm::OnConnectionClosed() {
+ if (tuner_ != nullptr && tuner_started_) {
+ tuner_->Finish(tuned_parameters_);
+ }
+}
+
void UberLossAlgorithm::SetReorderingShift(int reordering_shift) {
for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
general_loss_algorithms_[i].set_reordering_shift(reordering_shift);
}
}
+void UberLossAlgorithm::SetReorderingThreshold(
+ QuicPacketCount reordering_threshold) {
+ for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
+ general_loss_algorithms_[i].set_reordering_threshold(reordering_threshold);
+ }
+}
+
void UberLossAlgorithm::EnableAdaptiveReorderingThreshold() {
for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
- general_loss_algorithms_[i].enable_adaptive_reordering_threshold();
+ general_loss_algorithms_[i].set_use_adaptive_reordering_threshold(true);
+ }
+}
+
+void UberLossAlgorithm::DisableAdaptiveReorderingThreshold() {
+ for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
+ general_loss_algorithms_[i].set_use_adaptive_reordering_threshold(false);
}
}
@@ -99,4 +128,18 @@ void UberLossAlgorithm::EnableAdaptiveTimeThreshold() {
}
}
+void UberLossAlgorithm::DisablePacketThresholdForRuntPackets() {
+ for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
+ general_loss_algorithms_[i].disable_packet_threshold_for_runt_packets();
+ }
+}
+
+void UberLossAlgorithm::ResetLossDetection(PacketNumberSpace space) {
+ if (space >= NUM_PACKET_NUMBER_SPACES) {
+ QUIC_BUG << "Invalid packet number space: " << space;
+ return;
+ }
+ general_loss_algorithms_[space].Reset();
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.h
index f922bba1abf..ff1ac817b3c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.h
@@ -6,6 +6,7 @@
#define QUICHE_QUIC_CORE_CONGESTION_CONTROL_UBER_LOSS_ALGORITHM_H_
#include "net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_optional.h"
namespace quic {
@@ -15,21 +16,36 @@ class QuicSentPacketManagerPeer;
} // namespace test
+struct QUIC_EXPORT_PRIVATE LossDetectionParameters {
+ // See GeneralLossAlgorithm for the meaning of reordering_(shift|threshold).
+ quiche::QuicheOptional<int> reordering_shift;
+ quiche::QuicheOptional<QuicPacketCount> reordering_threshold;
+};
+
+class QUIC_EXPORT_PRIVATE LossDetectionTunerInterface {
+ public:
+ virtual ~LossDetectionTunerInterface() {}
+
+ // Start the tuning by choosing parameters and saving them into |*params|.
+ // Called near the start of a QUIC session, see the .cc file for exactly
+ // where.
+ virtual bool Start(LossDetectionParameters* params) = 0;
+
+ // Finish tuning. The tuner is expected to use the actual loss detection
+ // performance(for its definition of performance) to improve the parameter
+ // selection for future QUIC sessions.
+ // Called when a QUIC session closes.
+ virtual void Finish(const LossDetectionParameters& params) = 0;
+};
+
// This class comprises multiple loss algorithms, each per packet number space.
class QUIC_EXPORT_PRIVATE UberLossAlgorithm : public LossDetectionInterface {
public:
UberLossAlgorithm();
- explicit UberLossAlgorithm(LossDetectionType loss_type);
UberLossAlgorithm(const UberLossAlgorithm&) = delete;
UberLossAlgorithm& operator=(const UberLossAlgorithm&) = delete;
~UberLossAlgorithm() override {}
- LossDetectionType GetLossDetectionType() const override;
-
- // Switches the loss detection type to |loss_type| and resets loss algorithm
- // for all packet number spaces.
- void SetLossDetectionType(LossDetectionType loss_type);
-
// Detects lost packets.
void DetectLosses(const QuicUnackedPacketMap& unacked_packets,
QuicTime time,
@@ -48,21 +64,45 @@ class QUIC_EXPORT_PRIVATE UberLossAlgorithm : public LossDetectionInterface {
QuicPacketNumber packet_number,
QuicPacketNumber previous_largest_acked) override;
+ void SetLossDetectionTuner(
+ std::unique_ptr<LossDetectionTunerInterface> tuner);
+ void OnConfigNegotiated() override;
+ void OnMinRttAvailable() override;
+ void OnConnectionClosed() override;
+
// Sets reordering_shift for all packet number spaces.
void SetReorderingShift(int reordering_shift);
+ // Sets reordering_threshold for all packet number spaces.
+ void SetReorderingThreshold(QuicPacketCount reordering_threshold);
+
// Enable adaptive reordering threshold of all packet number spaces.
void EnableAdaptiveReorderingThreshold();
+ // Disable adaptive reordering threshold of all packet number spaces.
+ void DisableAdaptiveReorderingThreshold();
+
// Enable adaptive time threshold of all packet number spaces.
void EnableAdaptiveTimeThreshold();
+ // Disable packet threshold loss detection for *runt* packets.
+ void DisablePacketThresholdForRuntPackets();
+
+ // Called to reset loss detection of |space|.
+ void ResetLossDetection(PacketNumberSpace space);
+
private:
friend class test::QuicSentPacketManagerPeer;
- LossDetectionType loss_type_;
+ void MaybeStartTuning();
+
// One loss algorithm per packet number space.
GeneralLossAlgorithm general_loss_algorithms_[NUM_PACKET_NUMBER_SPACES];
+
+ // Used to tune reordering_shift and reordering_threshold.
+ std::unique_ptr<LossDetectionTunerInterface> tuner_;
+ LossDetectionParameters tuned_parameters_;
+ bool tuner_started_ = false;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm_test.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm_test.cc
index 79d0ff76867..a3daf095d56 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm_test.cc
@@ -115,7 +115,8 @@ TEST_F(UberLossAlgorithmTest, ScenarioB) {
APPLICATION_DATA, QuicPacketNumber(4));
// No packet loss by acking 4.
VerifyLosses(4, packets_acked_, std::vector<uint64_t>{});
- EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
+ EXPECT_EQ(clock_.Now() + 1.25 * rtt_stats_.smoothed_rtt(),
+ loss_algorithm_.GetLossTimeout());
// Acking 6 causes 3 to be detected loss.
AckPackets({6});
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/windowed_filter_test.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/windowed_filter_test.cc
index 30387e062db..d91e80e4b82 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/windowed_filter_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/windowed_filter_test.cc
@@ -7,6 +7,7 @@
#include "net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h"
#include "net/third_party/quiche/src/quic/core/quic_bandwidth.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_decrypter.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_decrypter.cc
index ab441b79466..f3be16e1d18 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_decrypter.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_decrypter.cc
@@ -11,9 +11,10 @@
#include "third_party/boringssl/src/include/openssl/err.h"
#include "third_party/boringssl/src/include/openssl/evp.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -33,7 +34,7 @@ void DLogOpenSslErrors() {
#else
while (uint32_t error = ERR_get_error()) {
char buf[120];
- ERR_error_string_n(error, buf, QUIC_ARRAYSIZE(buf));
+ ERR_error_string_n(error, buf, QUICHE_ARRAYSIZE(buf));
QUIC_DLOG(ERROR) << "OpenSSL error: " << buf;
}
#endif
@@ -68,7 +69,7 @@ AeadBaseDecrypter::AeadBaseDecrypter(const EVP_AEAD* (*aead_getter)(),
AeadBaseDecrypter::~AeadBaseDecrypter() {}
-bool AeadBaseDecrypter::SetKey(QuicStringPiece key) {
+bool AeadBaseDecrypter::SetKey(quiche::QuicheStringPiece key) {
DCHECK_EQ(key.size(), key_size_);
if (key.size() != key_size_) {
return false;
@@ -85,7 +86,7 @@ bool AeadBaseDecrypter::SetKey(QuicStringPiece key) {
return true;
}
-bool AeadBaseDecrypter::SetNoncePrefix(QuicStringPiece nonce_prefix) {
+bool AeadBaseDecrypter::SetNoncePrefix(quiche::QuicheStringPiece nonce_prefix) {
if (use_ietf_nonce_construction_) {
QUIC_BUG << "Attempted to set nonce prefix on IETF QUIC crypter";
return false;
@@ -98,7 +99,7 @@ bool AeadBaseDecrypter::SetNoncePrefix(QuicStringPiece nonce_prefix) {
return true;
}
-bool AeadBaseDecrypter::SetIV(QuicStringPiece iv) {
+bool AeadBaseDecrypter::SetIV(quiche::QuicheStringPiece iv) {
if (!use_ietf_nonce_construction_) {
QUIC_BUG << "Attempted to set IV on Google QUIC crypter";
return false;
@@ -111,7 +112,7 @@ bool AeadBaseDecrypter::SetIV(QuicStringPiece iv) {
return true;
}
-bool AeadBaseDecrypter::SetPreliminaryKey(QuicStringPiece key) {
+bool AeadBaseDecrypter::SetPreliminaryKey(quiche::QuicheStringPiece key) {
DCHECK(!have_preliminary_key_);
SetKey(key);
have_preliminary_key_ = true;
@@ -131,9 +132,10 @@ bool AeadBaseDecrypter::SetDiversificationNonce(
prefix_size -= sizeof(QuicPacketNumber);
}
DiversifyPreliminaryKey(
- QuicStringPiece(reinterpret_cast<const char*>(key_), key_size_),
- QuicStringPiece(reinterpret_cast<const char*>(iv_), prefix_size), nonce,
- key_size_, prefix_size, &key, &nonce_prefix);
+ quiche::QuicheStringPiece(reinterpret_cast<const char*>(key_), key_size_),
+ quiche::QuicheStringPiece(reinterpret_cast<const char*>(iv_),
+ prefix_size),
+ nonce, key_size_, prefix_size, &key, &nonce_prefix);
if (!SetKey(key) ||
(!use_ietf_nonce_construction_ && !SetNoncePrefix(nonce_prefix)) ||
@@ -147,8 +149,8 @@ bool AeadBaseDecrypter::SetDiversificationNonce(
}
bool AeadBaseDecrypter::DecryptPacket(uint64_t packet_number,
- QuicStringPiece associated_data,
- QuicStringPiece ciphertext,
+ quiche::QuicheStringPiece associated_data,
+ quiche::QuicheStringPiece ciphertext,
char* output,
size_t* output_length,
size_t max_output_length) {
@@ -199,13 +201,14 @@ size_t AeadBaseDecrypter::GetIVSize() const {
return nonce_size_;
}
-QuicStringPiece AeadBaseDecrypter::GetKey() const {
- return QuicStringPiece(reinterpret_cast<const char*>(key_), key_size_);
+quiche::QuicheStringPiece AeadBaseDecrypter::GetKey() const {
+ return quiche::QuicheStringPiece(reinterpret_cast<const char*>(key_),
+ key_size_);
}
-QuicStringPiece AeadBaseDecrypter::GetNoncePrefix() const {
- return QuicStringPiece(reinterpret_cast<const char*>(iv_),
- nonce_size_ - sizeof(QuicPacketNumber));
+quiche::QuicheStringPiece AeadBaseDecrypter::GetNoncePrefix() const {
+ return quiche::QuicheStringPiece(reinterpret_cast<const char*>(iv_),
+ nonce_size_ - sizeof(QuicPacketNumber));
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_decrypter.h b/chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_decrypter.h
index f0c5b01002d..e69b0edddc8 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_decrypter.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_decrypter.h
@@ -10,7 +10,7 @@
#include "third_party/boringssl/src/include/openssl/aead.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -29,22 +29,22 @@ class QUIC_EXPORT_PRIVATE AeadBaseDecrypter : public QuicDecrypter {
~AeadBaseDecrypter() override;
// QuicDecrypter implementation
- bool SetKey(QuicStringPiece key) override;
- bool SetNoncePrefix(QuicStringPiece nonce_prefix) override;
- bool SetIV(QuicStringPiece iv) override;
- bool SetPreliminaryKey(QuicStringPiece key) override;
+ bool SetKey(quiche::QuicheStringPiece key) override;
+ bool SetNoncePrefix(quiche::QuicheStringPiece nonce_prefix) override;
+ bool SetIV(quiche::QuicheStringPiece iv) override;
+ bool SetPreliminaryKey(quiche::QuicheStringPiece key) override;
bool SetDiversificationNonce(const DiversificationNonce& nonce) override;
bool DecryptPacket(uint64_t packet_number,
- QuicStringPiece associated_data,
- QuicStringPiece ciphertext,
+ quiche::QuicheStringPiece associated_data,
+ quiche::QuicheStringPiece ciphertext,
char* output,
size_t* output_length,
size_t max_output_length) override;
size_t GetKeySize() const override;
size_t GetNoncePrefixSize() const override;
size_t GetIVSize() const override;
- QuicStringPiece GetKey() const override;
- QuicStringPiece GetNoncePrefix() const override;
+ quiche::QuicheStringPiece GetKey() const override;
+ quiche::QuicheStringPiece GetNoncePrefix() const override;
protected:
// Make these constants available to the subclasses so that the subclasses
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_encrypter.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_encrypter.cc
index a3173f54456..14aca267927 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_encrypter.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_encrypter.cc
@@ -9,9 +9,10 @@
#include "third_party/boringssl/src/include/openssl/evp.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_aligned.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -26,7 +27,7 @@ void DLogOpenSslErrors() {
#else
while (unsigned long error = ERR_get_error()) {
char buf[120];
- ERR_error_string_n(error, buf, QUIC_ARRAYSIZE(buf));
+ ERR_error_string_n(error, buf, QUICHE_ARRAYSIZE(buf));
QUIC_DLOG(ERROR) << "OpenSSL error: " << buf;
}
#endif
@@ -58,7 +59,7 @@ AeadBaseEncrypter::AeadBaseEncrypter(const EVP_AEAD* (*aead_getter)(),
AeadBaseEncrypter::~AeadBaseEncrypter() {}
-bool AeadBaseEncrypter::SetKey(QuicStringPiece key) {
+bool AeadBaseEncrypter::SetKey(quiche::QuicheStringPiece key) {
DCHECK_EQ(key.size(), key_size_);
if (key.size() != key_size_) {
return false;
@@ -76,7 +77,7 @@ bool AeadBaseEncrypter::SetKey(QuicStringPiece key) {
return true;
}
-bool AeadBaseEncrypter::SetNoncePrefix(QuicStringPiece nonce_prefix) {
+bool AeadBaseEncrypter::SetNoncePrefix(quiche::QuicheStringPiece nonce_prefix) {
if (use_ietf_nonce_construction_) {
QUIC_BUG << "Attempted to set nonce prefix on IETF QUIC crypter";
return false;
@@ -89,7 +90,7 @@ bool AeadBaseEncrypter::SetNoncePrefix(QuicStringPiece nonce_prefix) {
return true;
}
-bool AeadBaseEncrypter::SetIV(QuicStringPiece iv) {
+bool AeadBaseEncrypter::SetIV(quiche::QuicheStringPiece iv) {
if (!use_ietf_nonce_construction_) {
QUIC_BUG << "Attempted to set IV on Google QUIC crypter";
return false;
@@ -102,9 +103,9 @@ bool AeadBaseEncrypter::SetIV(QuicStringPiece iv) {
return true;
}
-bool AeadBaseEncrypter::Encrypt(QuicStringPiece nonce,
- QuicStringPiece associated_data,
- QuicStringPiece plaintext,
+bool AeadBaseEncrypter::Encrypt(quiche::QuicheStringPiece nonce,
+ quiche::QuicheStringPiece associated_data,
+ quiche::QuicheStringPiece plaintext,
unsigned char* output) {
DCHECK_EQ(nonce.size(), nonce_size_);
@@ -124,8 +125,8 @@ bool AeadBaseEncrypter::Encrypt(QuicStringPiece nonce,
}
bool AeadBaseEncrypter::EncryptPacket(uint64_t packet_number,
- QuicStringPiece associated_data,
- QuicStringPiece plaintext,
+ quiche::QuicheStringPiece associated_data,
+ quiche::QuicheStringPiece plaintext,
char* output,
size_t* output_length,
size_t max_output_length) {
@@ -147,8 +148,9 @@ bool AeadBaseEncrypter::EncryptPacket(uint64_t packet_number,
memcpy(nonce_buffer + prefix_len, &packet_number, sizeof(packet_number));
}
- if (!Encrypt(QuicStringPiece(nonce_buffer, nonce_size_), associated_data,
- plaintext, reinterpret_cast<unsigned char*>(output))) {
+ if (!Encrypt(quiche::QuicheStringPiece(nonce_buffer, nonce_size_),
+ associated_data, plaintext,
+ reinterpret_cast<unsigned char*>(output))) {
return false;
}
*output_length = ciphertext_size;
@@ -175,13 +177,14 @@ size_t AeadBaseEncrypter::GetCiphertextSize(size_t plaintext_size) const {
return plaintext_size + auth_tag_size_;
}
-QuicStringPiece AeadBaseEncrypter::GetKey() const {
- return QuicStringPiece(reinterpret_cast<const char*>(key_), key_size_);
+quiche::QuicheStringPiece AeadBaseEncrypter::GetKey() const {
+ return quiche::QuicheStringPiece(reinterpret_cast<const char*>(key_),
+ key_size_);
}
-QuicStringPiece AeadBaseEncrypter::GetNoncePrefix() const {
- return QuicStringPiece(reinterpret_cast<const char*>(iv_),
- GetNoncePrefixSize());
+quiche::QuicheStringPiece AeadBaseEncrypter::GetNoncePrefix() const {
+ return quiche::QuicheStringPiece(reinterpret_cast<const char*>(iv_),
+ GetNoncePrefixSize());
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_encrypter.h b/chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_encrypter.h
index 51ac8e34690..5209a023caa 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_encrypter.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_encrypter.h
@@ -10,7 +10,7 @@
#include "third_party/boringssl/src/include/openssl/aead.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -29,12 +29,12 @@ class QUIC_EXPORT_PRIVATE AeadBaseEncrypter : public QuicEncrypter {
~AeadBaseEncrypter() override;
// QuicEncrypter implementation
- bool SetKey(QuicStringPiece key) override;
- bool SetNoncePrefix(QuicStringPiece nonce_prefix) override;
- bool SetIV(QuicStringPiece iv) override;
+ bool SetKey(quiche::QuicheStringPiece key) override;
+ bool SetNoncePrefix(quiche::QuicheStringPiece nonce_prefix) override;
+ bool SetIV(quiche::QuicheStringPiece iv) override;
bool EncryptPacket(uint64_t packet_number,
- QuicStringPiece associated_data,
- QuicStringPiece plaintext,
+ quiche::QuicheStringPiece associated_data,
+ quiche::QuicheStringPiece plaintext,
char* output,
size_t* output_length,
size_t max_output_length) override;
@@ -43,14 +43,14 @@ class QUIC_EXPORT_PRIVATE AeadBaseEncrypter : public QuicEncrypter {
size_t GetIVSize() const override;
size_t GetMaxPlaintextSize(size_t ciphertext_size) const override;
size_t GetCiphertextSize(size_t plaintext_size) const override;
- QuicStringPiece GetKey() const override;
- QuicStringPiece GetNoncePrefix() const override;
+ quiche::QuicheStringPiece GetKey() const override;
+ quiche::QuicheStringPiece GetNoncePrefix() const override;
// Necessary so unit tests can explicitly specify a nonce, instead of an IV
// (or nonce prefix) and packet number.
- bool Encrypt(QuicStringPiece nonce,
- QuicStringPiece associated_data,
- QuicStringPiece plaintext,
+ bool Encrypt(quiche::QuicheStringPiece nonce,
+ quiche::QuicheStringPiece associated_data,
+ quiche::QuicheStringPiece plaintext,
unsigned char* output);
protected:
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc
index 9ce4bda19ba..0319d4280f0 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc
@@ -8,10 +8,12 @@
#include <string>
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
+#include "net/third_party/quiche/src/common/test_tools/quiche_test_utils.h"
namespace {
@@ -200,12 +202,12 @@ namespace test {
// DecryptWithNonce wraps the |Decrypt| method of |decrypter| to allow passing
// in an nonce and also to allocate the buffer needed for the plaintext.
QuicData* DecryptWithNonce(Aes128Gcm12Decrypter* decrypter,
- QuicStringPiece nonce,
- QuicStringPiece associated_data,
- QuicStringPiece ciphertext) {
+ quiche::QuicheStringPiece nonce,
+ quiche::QuicheStringPiece associated_data,
+ quiche::QuicheStringPiece ciphertext) {
uint64_t packet_number;
- QuicStringPiece nonce_prefix(nonce.data(),
- nonce.size() - sizeof(packet_number));
+ quiche::QuicheStringPiece nonce_prefix(nonce.data(),
+ nonce.size() - sizeof(packet_number));
decrypter->SetNoncePrefix(nonce_prefix);
memcpy(&packet_number, nonce.data() + nonce_prefix.size(),
sizeof(packet_number));
@@ -223,7 +225,7 @@ QuicData* DecryptWithNonce(Aes128Gcm12Decrypter* decrypter,
class Aes128Gcm12DecrypterTest : public QuicTest {};
TEST_F(Aes128Gcm12DecrypterTest, Decrypt) {
- for (size_t i = 0; i < QUIC_ARRAYSIZE(test_group_array); i++) {
+ for (size_t i = 0; i < QUICHE_ARRAYSIZE(test_group_array); i++) {
SCOPED_TRACE(i);
const TestVector* test_vectors = test_group_array[i];
const TestGroupInfo& test_info = test_group_info[i];
@@ -232,14 +234,14 @@ TEST_F(Aes128Gcm12DecrypterTest, Decrypt) {
bool has_pt = test_vectors[j].pt;
// Decode the test vector.
- std::string key = QuicTextUtils::HexDecode(test_vectors[j].key);
- std::string iv = QuicTextUtils::HexDecode(test_vectors[j].iv);
- std::string ct = QuicTextUtils::HexDecode(test_vectors[j].ct);
- std::string aad = QuicTextUtils::HexDecode(test_vectors[j].aad);
- std::string tag = QuicTextUtils::HexDecode(test_vectors[j].tag);
+ std::string key = quiche::QuicheTextUtils::HexDecode(test_vectors[j].key);
+ std::string iv = quiche::QuicheTextUtils::HexDecode(test_vectors[j].iv);
+ std::string ct = quiche::QuicheTextUtils::HexDecode(test_vectors[j].ct);
+ std::string aad = quiche::QuicheTextUtils::HexDecode(test_vectors[j].aad);
+ std::string tag = quiche::QuicheTextUtils::HexDecode(test_vectors[j].tag);
std::string pt;
if (has_pt) {
- pt = QuicTextUtils::HexDecode(test_vectors[j].pt);
+ pt = quiche::QuicheTextUtils::HexDecode(test_vectors[j].pt);
}
// The test vector's lengths should look sane. Note that the lengths
@@ -263,12 +265,12 @@ TEST_F(Aes128Gcm12DecrypterTest, Decrypt) {
Aes128Gcm12Decrypter decrypter;
ASSERT_TRUE(decrypter.SetKey(key));
- std::unique_ptr<QuicData> decrypted(
- DecryptWithNonce(&decrypter, iv,
- // This deliberately tests that the decrypter can
- // handle an AAD that is set to nullptr, as opposed
- // to a zero-length, non-nullptr pointer.
- aad.length() ? aad : QuicStringPiece(), ciphertext));
+ std::unique_ptr<QuicData> decrypted(DecryptWithNonce(
+ &decrypter, iv,
+ // This deliberately tests that the decrypter can
+ // handle an AAD that is set to nullptr, as opposed
+ // to a zero-length, non-nullptr pointer.
+ aad.length() ? aad : quiche::QuicheStringPiece(), ciphertext));
if (!decrypted) {
EXPECT_FALSE(has_pt);
continue;
@@ -276,8 +278,8 @@ TEST_F(Aes128Gcm12DecrypterTest, Decrypt) {
EXPECT_TRUE(has_pt);
ASSERT_EQ(pt.length(), decrypted->length());
- test::CompareCharArraysWithHexError("plaintext", decrypted->data(),
- pt.length(), pt.data(), pt.length());
+ quiche::test::CompareCharArraysWithHexError(
+ "plaintext", decrypted->data(), pt.length(), pt.data(), pt.length());
}
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_encrypter_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_encrypter_test.cc
index d529d5d60d4..bc3f6112867 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_encrypter_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_encrypter_test.cc
@@ -8,10 +8,12 @@
#include <string>
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
+#include "net/third_party/quiche/src/common/test_tools/quiche_test_utils.h"
namespace {
@@ -158,9 +160,9 @@ namespace test {
// EncryptWithNonce wraps the |Encrypt| method of |encrypter| to allow passing
// in an nonce and also to allocate the buffer needed for the ciphertext.
QuicData* EncryptWithNonce(Aes128Gcm12Encrypter* encrypter,
- QuicStringPiece nonce,
- QuicStringPiece associated_data,
- QuicStringPiece plaintext) {
+ quiche::QuicheStringPiece nonce,
+ quiche::QuicheStringPiece associated_data,
+ quiche::QuicheStringPiece plaintext) {
size_t ciphertext_size = encrypter->GetCiphertextSize(plaintext.length());
std::unique_ptr<char[]> ciphertext(new char[ciphertext_size]);
@@ -175,18 +177,18 @@ QuicData* EncryptWithNonce(Aes128Gcm12Encrypter* encrypter,
class Aes128Gcm12EncrypterTest : public QuicTest {};
TEST_F(Aes128Gcm12EncrypterTest, Encrypt) {
- for (size_t i = 0; i < QUIC_ARRAYSIZE(test_group_array); i++) {
+ for (size_t i = 0; i < QUICHE_ARRAYSIZE(test_group_array); i++) {
SCOPED_TRACE(i);
const TestVector* test_vectors = test_group_array[i];
const TestGroupInfo& test_info = test_group_info[i];
for (size_t j = 0; test_vectors[j].key != nullptr; j++) {
// Decode the test vector.
- std::string key = QuicTextUtils::HexDecode(test_vectors[j].key);
- std::string iv = QuicTextUtils::HexDecode(test_vectors[j].iv);
- std::string pt = QuicTextUtils::HexDecode(test_vectors[j].pt);
- std::string aad = QuicTextUtils::HexDecode(test_vectors[j].aad);
- std::string ct = QuicTextUtils::HexDecode(test_vectors[j].ct);
- std::string tag = QuicTextUtils::HexDecode(test_vectors[j].tag);
+ std::string key = quiche::QuicheTextUtils::HexDecode(test_vectors[j].key);
+ std::string iv = quiche::QuicheTextUtils::HexDecode(test_vectors[j].iv);
+ std::string pt = quiche::QuicheTextUtils::HexDecode(test_vectors[j].pt);
+ std::string aad = quiche::QuicheTextUtils::HexDecode(test_vectors[j].aad);
+ std::string ct = quiche::QuicheTextUtils::HexDecode(test_vectors[j].ct);
+ std::string tag = quiche::QuicheTextUtils::HexDecode(test_vectors[j].tag);
// The test vector's lengths should look sane. Note that the lengths
// in |test_info| are in bits.
@@ -199,12 +201,12 @@ TEST_F(Aes128Gcm12EncrypterTest, Encrypt) {
Aes128Gcm12Encrypter encrypter;
ASSERT_TRUE(encrypter.SetKey(key));
- std::unique_ptr<QuicData> encrypted(
- EncryptWithNonce(&encrypter, iv,
- // This deliberately tests that the encrypter can
- // handle an AAD that is set to nullptr, as opposed
- // to a zero-length, non-nullptr pointer.
- aad.length() ? aad : QuicStringPiece(), pt));
+ std::unique_ptr<QuicData> encrypted(EncryptWithNonce(
+ &encrypter, iv,
+ // This deliberately tests that the encrypter can
+ // handle an AAD that is set to nullptr, as opposed
+ // to a zero-length, non-nullptr pointer.
+ aad.length() ? aad : quiche::QuicheStringPiece(), pt));
ASSERT_TRUE(encrypted.get());
// The test vectors have 16 byte authenticators but this code only uses
@@ -214,9 +216,9 @@ TEST_F(Aes128Gcm12EncrypterTest, Encrypt) {
tag.resize(Aes128Gcm12Encrypter::kAuthTagSize);
ASSERT_EQ(ct.length() + tag.length(), encrypted->length());
- test::CompareCharArraysWithHexError("ciphertext", encrypted->data(),
- ct.length(), ct.data(), ct.length());
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
+ "ciphertext", encrypted->data(), ct.length(), ct.data(), ct.length());
+ quiche::test::CompareCharArraysWithHexError(
"authentication tag", encrypted->data() + ct.length(), tag.length(),
tag.data(), tag.length());
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_decrypter_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_decrypter_test.cc
index 579f76d498d..a444284618f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_decrypter_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_decrypter_test.cc
@@ -8,10 +8,11 @@
#include <string>
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
+#include "net/third_party/quiche/src/common/test_tools/quiche_test_utils.h"
namespace {
@@ -200,9 +201,9 @@ namespace test {
// DecryptWithNonce wraps the |Decrypt| method of |decrypter| to allow passing
// in an nonce and also to allocate the buffer needed for the plaintext.
QuicData* DecryptWithNonce(Aes128GcmDecrypter* decrypter,
- QuicStringPiece nonce,
- QuicStringPiece associated_data,
- QuicStringPiece ciphertext) {
+ quiche::QuicheStringPiece nonce,
+ quiche::QuicheStringPiece associated_data,
+ quiche::QuicheStringPiece ciphertext) {
decrypter->SetIV(nonce);
std::unique_ptr<char[]> output(new char[ciphertext.length()]);
size_t output_length = 0;
@@ -218,7 +219,7 @@ QuicData* DecryptWithNonce(Aes128GcmDecrypter* decrypter,
class Aes128GcmDecrypterTest : public QuicTest {};
TEST_F(Aes128GcmDecrypterTest, Decrypt) {
- for (size_t i = 0; i < QUIC_ARRAYSIZE(test_group_array); i++) {
+ for (size_t i = 0; i < QUICHE_ARRAYSIZE(test_group_array); i++) {
SCOPED_TRACE(i);
const TestVector* test_vectors = test_group_array[i];
const TestGroupInfo& test_info = test_group_info[i];
@@ -227,14 +228,14 @@ TEST_F(Aes128GcmDecrypterTest, Decrypt) {
bool has_pt = test_vectors[j].pt;
// Decode the test vector.
- std::string key = QuicTextUtils::HexDecode(test_vectors[j].key);
- std::string iv = QuicTextUtils::HexDecode(test_vectors[j].iv);
- std::string ct = QuicTextUtils::HexDecode(test_vectors[j].ct);
- std::string aad = QuicTextUtils::HexDecode(test_vectors[j].aad);
- std::string tag = QuicTextUtils::HexDecode(test_vectors[j].tag);
+ std::string key = quiche::QuicheTextUtils::HexDecode(test_vectors[j].key);
+ std::string iv = quiche::QuicheTextUtils::HexDecode(test_vectors[j].iv);
+ std::string ct = quiche::QuicheTextUtils::HexDecode(test_vectors[j].ct);
+ std::string aad = quiche::QuicheTextUtils::HexDecode(test_vectors[j].aad);
+ std::string tag = quiche::QuicheTextUtils::HexDecode(test_vectors[j].tag);
std::string pt;
if (has_pt) {
- pt = QuicTextUtils::HexDecode(test_vectors[j].pt);
+ pt = quiche::QuicheTextUtils::HexDecode(test_vectors[j].pt);
}
// The test vector's lengths should look sane. Note that the lengths
@@ -252,12 +253,12 @@ TEST_F(Aes128GcmDecrypterTest, Decrypt) {
Aes128GcmDecrypter decrypter;
ASSERT_TRUE(decrypter.SetKey(key));
- std::unique_ptr<QuicData> decrypted(
- DecryptWithNonce(&decrypter, iv,
- // This deliberately tests that the decrypter can
- // handle an AAD that is set to nullptr, as opposed
- // to a zero-length, non-nullptr pointer.
- aad.length() ? aad : QuicStringPiece(), ciphertext));
+ std::unique_ptr<QuicData> decrypted(DecryptWithNonce(
+ &decrypter, iv,
+ // This deliberately tests that the decrypter can
+ // handle an AAD that is set to nullptr, as opposed
+ // to a zero-length, non-nullptr pointer.
+ aad.length() ? aad : quiche::QuicheStringPiece(), ciphertext));
if (!decrypted) {
EXPECT_FALSE(has_pt);
continue;
@@ -265,8 +266,8 @@ TEST_F(Aes128GcmDecrypterTest, Decrypt) {
EXPECT_TRUE(has_pt);
ASSERT_EQ(pt.length(), decrypted->length());
- test::CompareCharArraysWithHexError("plaintext", decrypted->data(),
- pt.length(), pt.data(), pt.length());
+ quiche::test::CompareCharArraysWithHexError(
+ "plaintext", decrypted->data(), pt.length(), pt.data(), pt.length());
}
}
}
@@ -274,17 +275,17 @@ TEST_F(Aes128GcmDecrypterTest, Decrypt) {
TEST_F(Aes128GcmDecrypterTest, GenerateHeaderProtectionMask) {
Aes128GcmDecrypter decrypter;
std::string key =
- QuicTextUtils::HexDecode("d9132370cb18476ab833649cf080d970");
+ quiche::QuicheTextUtils::HexDecode("d9132370cb18476ab833649cf080d970");
std::string sample =
- QuicTextUtils::HexDecode("d1d7998068517adb769b48b924a32c47");
+ quiche::QuicheTextUtils::HexDecode("d1d7998068517adb769b48b924a32c47");
QuicDataReader sample_reader(sample.data(), sample.size());
ASSERT_TRUE(decrypter.SetHeaderProtectionKey(key));
std::string mask = decrypter.GenerateHeaderProtectionMask(&sample_reader);
std::string expected_mask =
- QuicTextUtils::HexDecode("b132c37d6164da4ea4dc9b763aceec27");
- test::CompareCharArraysWithHexError("header protection mask", mask.data(),
- mask.size(), expected_mask.data(),
- expected_mask.size());
+ quiche::QuicheTextUtils::HexDecode("b132c37d6164da4ea4dc9b763aceec27");
+ quiche::test::CompareCharArraysWithHexError(
+ "header protection mask", mask.data(), mask.size(), expected_mask.data(),
+ expected_mask.size());
}
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_encrypter_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_encrypter_test.cc
index c557e118170..69f8c4d0f3e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_encrypter_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_encrypter_test.cc
@@ -8,10 +8,11 @@
#include <string>
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
+#include "net/third_party/quiche/src/common/test_tools/quiche_test_utils.h"
namespace {
@@ -158,9 +159,9 @@ namespace test {
// EncryptWithNonce wraps the |Encrypt| method of |encrypter| to allow passing
// in an nonce and also to allocate the buffer needed for the ciphertext.
QuicData* EncryptWithNonce(Aes128GcmEncrypter* encrypter,
- QuicStringPiece nonce,
- QuicStringPiece associated_data,
- QuicStringPiece plaintext) {
+ quiche::QuicheStringPiece nonce,
+ quiche::QuicheStringPiece associated_data,
+ quiche::QuicheStringPiece plaintext) {
size_t ciphertext_size = encrypter->GetCiphertextSize(plaintext.length());
std::unique_ptr<char[]> ciphertext(new char[ciphertext_size]);
@@ -175,18 +176,18 @@ QuicData* EncryptWithNonce(Aes128GcmEncrypter* encrypter,
class Aes128GcmEncrypterTest : public QuicTest {};
TEST_F(Aes128GcmEncrypterTest, Encrypt) {
- for (size_t i = 0; i < QUIC_ARRAYSIZE(test_group_array); i++) {
+ for (size_t i = 0; i < QUICHE_ARRAYSIZE(test_group_array); i++) {
SCOPED_TRACE(i);
const TestVector* test_vectors = test_group_array[i];
const TestGroupInfo& test_info = test_group_info[i];
for (size_t j = 0; test_vectors[j].key != nullptr; j++) {
// Decode the test vector.
- std::string key = QuicTextUtils::HexDecode(test_vectors[j].key);
- std::string iv = QuicTextUtils::HexDecode(test_vectors[j].iv);
- std::string pt = QuicTextUtils::HexDecode(test_vectors[j].pt);
- std::string aad = QuicTextUtils::HexDecode(test_vectors[j].aad);
- std::string ct = QuicTextUtils::HexDecode(test_vectors[j].ct);
- std::string tag = QuicTextUtils::HexDecode(test_vectors[j].tag);
+ std::string key = quiche::QuicheTextUtils::HexDecode(test_vectors[j].key);
+ std::string iv = quiche::QuicheTextUtils::HexDecode(test_vectors[j].iv);
+ std::string pt = quiche::QuicheTextUtils::HexDecode(test_vectors[j].pt);
+ std::string aad = quiche::QuicheTextUtils::HexDecode(test_vectors[j].aad);
+ std::string ct = quiche::QuicheTextUtils::HexDecode(test_vectors[j].ct);
+ std::string tag = quiche::QuicheTextUtils::HexDecode(test_vectors[j].tag);
// The test vector's lengths should look sane. Note that the lengths
// in |test_info| are in bits.
@@ -199,18 +200,18 @@ TEST_F(Aes128GcmEncrypterTest, Encrypt) {
Aes128GcmEncrypter encrypter;
ASSERT_TRUE(encrypter.SetKey(key));
- std::unique_ptr<QuicData> encrypted(
- EncryptWithNonce(&encrypter, iv,
- // This deliberately tests that the encrypter can
- // handle an AAD that is set to nullptr, as opposed
- // to a zero-length, non-nullptr pointer.
- aad.length() ? aad : QuicStringPiece(), pt));
+ std::unique_ptr<QuicData> encrypted(EncryptWithNonce(
+ &encrypter, iv,
+ // This deliberately tests that the encrypter can
+ // handle an AAD that is set to nullptr, as opposed
+ // to a zero-length, non-nullptr pointer.
+ aad.length() ? aad : quiche::QuicheStringPiece(), pt));
ASSERT_TRUE(encrypted.get());
ASSERT_EQ(ct.length() + tag.length(), encrypted->length());
- test::CompareCharArraysWithHexError("ciphertext", encrypted->data(),
- ct.length(), ct.data(), ct.length());
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
+ "ciphertext", encrypted->data(), ct.length(), ct.data(), ct.length());
+ quiche::test::CompareCharArraysWithHexError(
"authentication tag", encrypted->data() + ct.length(), tag.length(),
tag.data(), tag.length());
}
@@ -219,13 +220,15 @@ TEST_F(Aes128GcmEncrypterTest, Encrypt) {
TEST_F(Aes128GcmEncrypterTest, EncryptPacket) {
std::string key =
- QuicTextUtils::HexDecode("d95a145250826c25a77b6a84fd4d34fc");
- std::string iv = QuicTextUtils::HexDecode("50c4431ebb18283448e276e2");
+ quiche::QuicheTextUtils::HexDecode("d95a145250826c25a77b6a84fd4d34fc");
+ std::string iv =
+ quiche::QuicheTextUtils::HexDecode("50c4431ebb18283448e276e2");
uint64_t packet_num = 0x13278f44;
std::string aad =
- QuicTextUtils::HexDecode("875d49f64a70c9cbe713278f44ff000005");
- std::string pt = QuicTextUtils::HexDecode("aa0003a250bd000000000001");
- std::string ct = QuicTextUtils::HexDecode(
+ quiche::QuicheTextUtils::HexDecode("875d49f64a70c9cbe713278f44ff000005");
+ std::string pt =
+ quiche::QuicheTextUtils::HexDecode("aa0003a250bd000000000001");
+ std::string ct = quiche::QuicheTextUtils::HexDecode(
"7dd4708b989ee7d38a013e3656e9b37beefd05808fe1ab41e3b4f2c0");
std::vector<char> out(ct.size());
@@ -237,8 +240,8 @@ TEST_F(Aes128GcmEncrypterTest, EncryptPacket) {
ASSERT_TRUE(encrypter.EncryptPacket(packet_num, aad, pt, out.data(),
&out_size, out.size()));
EXPECT_EQ(out_size, out.size());
- test::CompareCharArraysWithHexError("ciphertext", out.data(), out.size(),
- ct.data(), ct.size());
+ quiche::test::CompareCharArraysWithHexError("ciphertext", out.data(),
+ out.size(), ct.data(), ct.size());
}
TEST_F(Aes128GcmEncrypterTest, GetMaxPlaintextSize) {
@@ -258,16 +261,16 @@ TEST_F(Aes128GcmEncrypterTest, GetCiphertextSize) {
TEST_F(Aes128GcmEncrypterTest, GenerateHeaderProtectionMask) {
Aes128GcmEncrypter encrypter;
std::string key =
- QuicTextUtils::HexDecode("d9132370cb18476ab833649cf080d970");
+ quiche::QuicheTextUtils::HexDecode("d9132370cb18476ab833649cf080d970");
std::string sample =
- QuicTextUtils::HexDecode("d1d7998068517adb769b48b924a32c47");
+ quiche::QuicheTextUtils::HexDecode("d1d7998068517adb769b48b924a32c47");
ASSERT_TRUE(encrypter.SetHeaderProtectionKey(key));
std::string mask = encrypter.GenerateHeaderProtectionMask(sample);
std::string expected_mask =
- QuicTextUtils::HexDecode("b132c37d6164da4ea4dc9b763aceec27");
- test::CompareCharArraysWithHexError("header protection mask", mask.data(),
- mask.size(), expected_mask.data(),
- expected_mask.size());
+ quiche::QuicheTextUtils::HexDecode("b132c37d6164da4ea4dc9b763aceec27");
+ quiche::test::CompareCharArraysWithHexError(
+ "header protection mask", mask.data(), mask.size(), expected_mask.data(),
+ expected_mask.size());
}
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_256_gcm_decrypter_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_256_gcm_decrypter_test.cc
index b3d61c7798f..7c6972489e4 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_256_gcm_decrypter_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_256_gcm_decrypter_test.cc
@@ -8,10 +8,12 @@
#include <string>
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
+#include "net/third_party/quiche/src/common/test_tools/quiche_test_utils.h"
namespace {
@@ -204,9 +206,9 @@ namespace test {
// DecryptWithNonce wraps the |Decrypt| method of |decrypter| to allow passing
// in an nonce and also to allocate the buffer needed for the plaintext.
QuicData* DecryptWithNonce(Aes256GcmDecrypter* decrypter,
- QuicStringPiece nonce,
- QuicStringPiece associated_data,
- QuicStringPiece ciphertext) {
+ quiche::QuicheStringPiece nonce,
+ quiche::QuicheStringPiece associated_data,
+ quiche::QuicheStringPiece ciphertext) {
decrypter->SetIV(nonce);
std::unique_ptr<char[]> output(new char[ciphertext.length()]);
size_t output_length = 0;
@@ -222,7 +224,7 @@ QuicData* DecryptWithNonce(Aes256GcmDecrypter* decrypter,
class Aes256GcmDecrypterTest : public QuicTest {};
TEST_F(Aes256GcmDecrypterTest, Decrypt) {
- for (size_t i = 0; i < QUIC_ARRAYSIZE(test_group_array); i++) {
+ for (size_t i = 0; i < QUICHE_ARRAYSIZE(test_group_array); i++) {
SCOPED_TRACE(i);
const TestVector* test_vectors = test_group_array[i];
const TestGroupInfo& test_info = test_group_info[i];
@@ -231,14 +233,14 @@ TEST_F(Aes256GcmDecrypterTest, Decrypt) {
bool has_pt = test_vectors[j].pt;
// Decode the test vector.
- std::string key = QuicTextUtils::HexDecode(test_vectors[j].key);
- std::string iv = QuicTextUtils::HexDecode(test_vectors[j].iv);
- std::string ct = QuicTextUtils::HexDecode(test_vectors[j].ct);
- std::string aad = QuicTextUtils::HexDecode(test_vectors[j].aad);
- std::string tag = QuicTextUtils::HexDecode(test_vectors[j].tag);
+ std::string key = quiche::QuicheTextUtils::HexDecode(test_vectors[j].key);
+ std::string iv = quiche::QuicheTextUtils::HexDecode(test_vectors[j].iv);
+ std::string ct = quiche::QuicheTextUtils::HexDecode(test_vectors[j].ct);
+ std::string aad = quiche::QuicheTextUtils::HexDecode(test_vectors[j].aad);
+ std::string tag = quiche::QuicheTextUtils::HexDecode(test_vectors[j].tag);
std::string pt;
if (has_pt) {
- pt = QuicTextUtils::HexDecode(test_vectors[j].pt);
+ pt = quiche::QuicheTextUtils::HexDecode(test_vectors[j].pt);
}
// The test vector's lengths should look sane. Note that the lengths
@@ -256,12 +258,12 @@ TEST_F(Aes256GcmDecrypterTest, Decrypt) {
Aes256GcmDecrypter decrypter;
ASSERT_TRUE(decrypter.SetKey(key));
- std::unique_ptr<QuicData> decrypted(
- DecryptWithNonce(&decrypter, iv,
- // This deliberately tests that the decrypter can
- // handle an AAD that is set to nullptr, as opposed
- // to a zero-length, non-nullptr pointer.
- aad.length() ? aad : QuicStringPiece(), ciphertext));
+ std::unique_ptr<QuicData> decrypted(DecryptWithNonce(
+ &decrypter, iv,
+ // This deliberately tests that the decrypter can
+ // handle an AAD that is set to nullptr, as opposed
+ // to a zero-length, non-nullptr pointer.
+ aad.length() ? aad : quiche::QuicheStringPiece(), ciphertext));
if (!decrypted) {
EXPECT_FALSE(has_pt);
continue;
@@ -269,26 +271,26 @@ TEST_F(Aes256GcmDecrypterTest, Decrypt) {
EXPECT_TRUE(has_pt);
ASSERT_EQ(pt.length(), decrypted->length());
- test::CompareCharArraysWithHexError("plaintext", decrypted->data(),
- pt.length(), pt.data(), pt.length());
+ quiche::test::CompareCharArraysWithHexError(
+ "plaintext", decrypted->data(), pt.length(), pt.data(), pt.length());
}
}
}
TEST_F(Aes256GcmDecrypterTest, GenerateHeaderProtectionMask) {
Aes256GcmDecrypter decrypter;
- std::string key = QuicTextUtils::HexDecode(
+ std::string key = quiche::QuicheTextUtils::HexDecode(
"ed23ecbf54d426def5c52c3dcfc84434e62e57781d3125bb21ed91b7d3e07788");
std::string sample =
- QuicTextUtils::HexDecode("4d190c474be2b8babafb49ec4e38e810");
+ quiche::QuicheTextUtils::HexDecode("4d190c474be2b8babafb49ec4e38e810");
QuicDataReader sample_reader(sample.data(), sample.size());
ASSERT_TRUE(decrypter.SetHeaderProtectionKey(key));
std::string mask = decrypter.GenerateHeaderProtectionMask(&sample_reader);
std::string expected_mask =
- QuicTextUtils::HexDecode("db9ed4e6ccd033af2eae01407199c56e");
- test::CompareCharArraysWithHexError("header protection mask", mask.data(),
- mask.size(), expected_mask.data(),
- expected_mask.size());
+ quiche::QuicheTextUtils::HexDecode("db9ed4e6ccd033af2eae01407199c56e");
+ quiche::test::CompareCharArraysWithHexError(
+ "header protection mask", mask.data(), mask.size(), expected_mask.data(),
+ expected_mask.size());
}
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_256_gcm_encrypter_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_256_gcm_encrypter_test.cc
index 03f6b752399..089926261d8 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_256_gcm_encrypter_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_256_gcm_encrypter_test.cc
@@ -8,10 +8,12 @@
#include <string>
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
+#include "net/third_party/quiche/src/common/test_tools/quiche_test_utils.h"
namespace {
@@ -165,9 +167,9 @@ namespace test {
// EncryptWithNonce wraps the |Encrypt| method of |encrypter| to allow passing
// in an nonce and also to allocate the buffer needed for the ciphertext.
QuicData* EncryptWithNonce(Aes256GcmEncrypter* encrypter,
- QuicStringPiece nonce,
- QuicStringPiece associated_data,
- QuicStringPiece plaintext) {
+ quiche::QuicheStringPiece nonce,
+ quiche::QuicheStringPiece associated_data,
+ quiche::QuicheStringPiece plaintext) {
size_t ciphertext_size = encrypter->GetCiphertextSize(plaintext.length());
std::unique_ptr<char[]> ciphertext(new char[ciphertext_size]);
@@ -182,18 +184,18 @@ QuicData* EncryptWithNonce(Aes256GcmEncrypter* encrypter,
class Aes256GcmEncrypterTest : public QuicTest {};
TEST_F(Aes256GcmEncrypterTest, Encrypt) {
- for (size_t i = 0; i < QUIC_ARRAYSIZE(test_group_array); i++) {
+ for (size_t i = 0; i < QUICHE_ARRAYSIZE(test_group_array); i++) {
SCOPED_TRACE(i);
const TestVector* test_vectors = test_group_array[i];
const TestGroupInfo& test_info = test_group_info[i];
for (size_t j = 0; test_vectors[j].key != nullptr; j++) {
// Decode the test vector.
- std::string key = QuicTextUtils::HexDecode(test_vectors[j].key);
- std::string iv = QuicTextUtils::HexDecode(test_vectors[j].iv);
- std::string pt = QuicTextUtils::HexDecode(test_vectors[j].pt);
- std::string aad = QuicTextUtils::HexDecode(test_vectors[j].aad);
- std::string ct = QuicTextUtils::HexDecode(test_vectors[j].ct);
- std::string tag = QuicTextUtils::HexDecode(test_vectors[j].tag);
+ std::string key = quiche::QuicheTextUtils::HexDecode(test_vectors[j].key);
+ std::string iv = quiche::QuicheTextUtils::HexDecode(test_vectors[j].iv);
+ std::string pt = quiche::QuicheTextUtils::HexDecode(test_vectors[j].pt);
+ std::string aad = quiche::QuicheTextUtils::HexDecode(test_vectors[j].aad);
+ std::string ct = quiche::QuicheTextUtils::HexDecode(test_vectors[j].ct);
+ std::string tag = quiche::QuicheTextUtils::HexDecode(test_vectors[j].tag);
// The test vector's lengths should look sane. Note that the lengths
// in |test_info| are in bits.
@@ -206,18 +208,18 @@ TEST_F(Aes256GcmEncrypterTest, Encrypt) {
Aes256GcmEncrypter encrypter;
ASSERT_TRUE(encrypter.SetKey(key));
- std::unique_ptr<QuicData> encrypted(
- EncryptWithNonce(&encrypter, iv,
- // This deliberately tests that the encrypter can
- // handle an AAD that is set to nullptr, as opposed
- // to a zero-length, non-nullptr pointer.
- aad.length() ? aad : QuicStringPiece(), pt));
+ std::unique_ptr<QuicData> encrypted(EncryptWithNonce(
+ &encrypter, iv,
+ // This deliberately tests that the encrypter can
+ // handle an AAD that is set to nullptr, as opposed
+ // to a zero-length, non-nullptr pointer.
+ aad.length() ? aad : quiche::QuicheStringPiece(), pt));
ASSERT_TRUE(encrypted.get());
ASSERT_EQ(ct.length() + tag.length(), encrypted->length());
- test::CompareCharArraysWithHexError("ciphertext", encrypted->data(),
- ct.length(), ct.data(), ct.length());
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
+ "ciphertext", encrypted->data(), ct.length(), ct.data(), ct.length());
+ quiche::test::CompareCharArraysWithHexError(
"authentication tag", encrypted->data() + ct.length(), tag.length(),
tag.data(), tag.length());
}
@@ -240,17 +242,17 @@ TEST_F(Aes256GcmEncrypterTest, GetCiphertextSize) {
TEST_F(Aes256GcmEncrypterTest, GenerateHeaderProtectionMask) {
Aes256GcmEncrypter encrypter;
- std::string key = QuicTextUtils::HexDecode(
+ std::string key = quiche::QuicheTextUtils::HexDecode(
"ed23ecbf54d426def5c52c3dcfc84434e62e57781d3125bb21ed91b7d3e07788");
std::string sample =
- QuicTextUtils::HexDecode("4d190c474be2b8babafb49ec4e38e810");
+ quiche::QuicheTextUtils::HexDecode("4d190c474be2b8babafb49ec4e38e810");
ASSERT_TRUE(encrypter.SetHeaderProtectionKey(key));
std::string mask = encrypter.GenerateHeaderProtectionMask(sample);
std::string expected_mask =
- QuicTextUtils::HexDecode("db9ed4e6ccd033af2eae01407199c56e");
- test::CompareCharArraysWithHexError("header protection mask", mask.data(),
- mask.size(), expected_mask.data(),
- expected_mask.size());
+ quiche::QuicheTextUtils::HexDecode("db9ed4e6ccd033af2eae01407199c56e");
+ quiche::test::CompareCharArraysWithHexError(
+ "header protection mask", mask.data(), mask.size(), expected_mask.data(),
+ expected_mask.size());
}
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_decrypter.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_decrypter.cc
index 6888ab22f6c..f8c83f3118a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_decrypter.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_decrypter.cc
@@ -6,10 +6,11 @@
#include "third_party/boringssl/src/include/openssl/aes.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
-bool AesBaseDecrypter::SetHeaderProtectionKey(QuicStringPiece key) {
+bool AesBaseDecrypter::SetHeaderProtectionKey(quiche::QuicheStringPiece key) {
if (key.size() != GetKeySize()) {
QUIC_BUG << "Invalid key size for header protection";
return false;
@@ -24,7 +25,7 @@ bool AesBaseDecrypter::SetHeaderProtectionKey(QuicStringPiece key) {
std::string AesBaseDecrypter::GenerateHeaderProtectionMask(
QuicDataReader* sample_reader) {
- QuicStringPiece sample;
+ quiche::QuicheStringPiece sample;
if (!sample_reader->ReadStringPiece(&sample, AES_BLOCK_SIZE)) {
return std::string();
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_decrypter.h b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_decrypter.h
index e8e1cc80aa8..2ff63a7ab2c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_decrypter.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_decrypter.h
@@ -10,7 +10,7 @@
#include "third_party/boringssl/src/include/openssl/aes.h"
#include "net/third_party/quiche/src/quic/core/crypto/aead_base_decrypter.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -18,7 +18,7 @@ class QUIC_EXPORT_PRIVATE AesBaseDecrypter : public AeadBaseDecrypter {
public:
using AeadBaseDecrypter::AeadBaseDecrypter;
- bool SetHeaderProtectionKey(QuicStringPiece key) override;
+ bool SetHeaderProtectionKey(quiche::QuicheStringPiece key) override;
std::string GenerateHeaderProtectionMask(
QuicDataReader* sample_reader) override;
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_encrypter.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_encrypter.cc
index cdb21b85a43..c620329e226 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_encrypter.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_encrypter.cc
@@ -6,10 +6,11 @@
#include "third_party/boringssl/src/include/openssl/aes.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
-bool AesBaseEncrypter::SetHeaderProtectionKey(QuicStringPiece key) {
+bool AesBaseEncrypter::SetHeaderProtectionKey(quiche::QuicheStringPiece key) {
if (key.size() != GetKeySize()) {
QUIC_BUG << "Invalid key size for header protection: " << key.size();
return false;
@@ -23,7 +24,7 @@ bool AesBaseEncrypter::SetHeaderProtectionKey(QuicStringPiece key) {
}
std::string AesBaseEncrypter::GenerateHeaderProtectionMask(
- QuicStringPiece sample) {
+ quiche::QuicheStringPiece sample) {
if (sample.size() != AES_BLOCK_SIZE) {
return std::string();
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_encrypter.h b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_encrypter.h
index e115ebac820..ba518fe5593 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_encrypter.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_encrypter.h
@@ -10,7 +10,7 @@
#include "third_party/boringssl/src/include/openssl/aes.h"
#include "net/third_party/quiche/src/quic/core/crypto/aead_base_encrypter.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -18,8 +18,9 @@ class QUIC_EXPORT_PRIVATE AesBaseEncrypter : public AeadBaseEncrypter {
public:
using AeadBaseEncrypter::AeadBaseEncrypter;
- bool SetHeaderProtectionKey(QuicStringPiece key) override;
- std::string GenerateHeaderProtectionMask(QuicStringPiece sample) override;
+ bool SetHeaderProtectionKey(quiche::QuicheStringPiece key) override;
+ std::string GenerateHeaderProtectionMask(
+ quiche::QuicheStringPiece sample) override;
private:
// The key used for packet number encryption.
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/boring_utils.h b/chromium/net/third_party/quiche/src/quic/core/crypto/boring_utils.h
new file mode 100644
index 00000000000..5af87ae2c5c
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/boring_utils.h
@@ -0,0 +1,29 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_CORE_CRYPTO_BORING_UTILS_H_
+#define QUICHE_QUIC_CORE_CRYPTO_BORING_UTILS_H_
+
+#include "third_party/boringssl/src/include/openssl/bytestring.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+
+namespace quic {
+
+inline QUIC_EXPORT_PRIVATE quiche::QuicheStringPiece CbsToStringPiece(CBS cbs) {
+ return quiche::QuicheStringPiece(
+ reinterpret_cast<const char*>(CBS_data(&cbs)), CBS_len(&cbs));
+}
+
+inline QUIC_EXPORT_PRIVATE CBS
+StringPieceToCbs(quiche::QuicheStringPiece piece) {
+ CBS result;
+ CBS_init(&result, reinterpret_cast<const uint8_t*>(piece.data()),
+ piece.size());
+ return result;
+}
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_CRYPTO_BORING_UTILS_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/cert_compressor.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/cert_compressor.cc
index 45d842dcc3e..a1ba748730e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/cert_compressor.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/cert_compressor.cc
@@ -10,6 +10,7 @@
#include <utility>
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "third_party/zlib/zlib.h"
namespace quic {
@@ -174,10 +175,11 @@ struct CertEntry {
// efficiently represent |certs| to a peer who has the common sets identified
// by |client_common_set_hashes| and who has cached the certificates with the
// 64-bit, FNV-1a hashes in |client_cached_cert_hashes|.
-std::vector<CertEntry> MatchCerts(const std::vector<std::string>& certs,
- QuicStringPiece client_common_set_hashes,
- QuicStringPiece client_cached_cert_hashes,
- const CommonCertSets* common_sets) {
+std::vector<CertEntry> MatchCerts(
+ const std::vector<std::string>& certs,
+ quiche::QuicheStringPiece client_common_set_hashes,
+ quiche::QuicheStringPiece client_cached_cert_hashes,
+ const CommonCertSets* common_sets) {
std::vector<CertEntry> entries;
entries.reserve(certs.size());
@@ -328,12 +330,12 @@ std::vector<uint64_t> HashCerts(const std::vector<std::string>& certs) {
// |in_out| and writes them to |out_entries|. CACHED and COMMON entries are
// resolved using |cached_certs| and |common_sets| and written to |out_certs|.
// |in_out| is updated to contain the trailing data.
-bool ParseEntries(QuicStringPiece* in_out,
+bool ParseEntries(quiche::QuicheStringPiece* in_out,
const std::vector<std::string>& cached_certs,
const CommonCertSets* common_sets,
std::vector<CertEntry>* out_entries,
std::vector<std::string>* out_certs) {
- QuicStringPiece in = *in_out;
+ quiche::QuicheStringPiece in = *in_out;
std::vector<uint64_t> cached_hashes;
out_entries->clear();
@@ -392,7 +394,7 @@ bool ParseEntries(QuicStringPiece* in_out,
memcpy(&entry.index, in.data(), sizeof(uint32_t));
in.remove_prefix(sizeof(uint32_t));
- QuicStringPiece cert =
+ quiche::QuicheStringPiece cert =
common_sets->GetCert(entry.set_hash, entry.index);
if (cert.empty()) {
return false;
@@ -450,8 +452,8 @@ class ScopedZLib {
// static
std::string CertCompressor::CompressChain(
const std::vector<std::string>& certs,
- QuicStringPiece client_common_set_hashes,
- QuicStringPiece client_cached_cert_hashes,
+ quiche::QuicheStringPiece client_common_set_hashes,
+ quiche::QuicheStringPiece client_cached_cert_hashes,
const CommonCertSets* common_sets) {
const std::vector<CertEntry> entries = MatchCerts(
certs, client_common_set_hashes, client_cached_cert_hashes, common_sets);
@@ -551,7 +553,7 @@ std::string CertCompressor::CompressChain(
// static
bool CertCompressor::DecompressChain(
- QuicStringPiece in,
+ quiche::QuicheStringPiece in,
const std::vector<std::string>& cached_certs,
const CommonCertSets* common_sets,
std::vector<std::string>* out_certs) {
@@ -562,7 +564,7 @@ bool CertCompressor::DecompressChain(
DCHECK_EQ(entries.size(), out_certs->size());
std::unique_ptr<uint8_t[]> uncompressed_data;
- QuicStringPiece uncompressed;
+ quiche::QuicheStringPiece uncompressed;
if (!in.empty()) {
if (in.size() < sizeof(uint32_t)) {
@@ -607,7 +609,7 @@ bool CertCompressor::DecompressChain(
return false;
}
- uncompressed = QuicStringPiece(
+ uncompressed = quiche::QuicheStringPiece(
reinterpret_cast<char*>(uncompressed_data.get()), uncompressed_size);
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/cert_compressor.h b/chromium/net/third_party/quiche/src/quic/core/crypto/cert_compressor.h
index ca696bdf79c..dfb4d21c916 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/cert_compressor.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/cert_compressor.h
@@ -11,7 +11,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/common_cert_set.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -36,16 +36,17 @@ class QUIC_EXPORT_PRIVATE CertCompressor {
// sets known locally and |client_common_set_hashes| contains the hashes of
// the common sets known to the peer. |client_cached_cert_hashes| contains
// 64-bit, FNV-1a hashes of certificates that the peer already possesses.
- static std::string CompressChain(const std::vector<std::string>& certs,
- QuicStringPiece client_common_set_hashes,
- QuicStringPiece client_cached_cert_hashes,
- const CommonCertSets* common_sets);
+ static std::string CompressChain(
+ const std::vector<std::string>& certs,
+ quiche::QuicheStringPiece client_common_set_hashes,
+ quiche::QuicheStringPiece client_cached_cert_hashes,
+ const CommonCertSets* common_sets);
// DecompressChain decompresses the result of |CompressChain|, given in |in|,
// into a series of certificates that are written to |out_certs|.
// |cached_certs| contains certificates that the peer may have omitted and
// |common_sets| contains the common certificate sets known locally.
- static bool DecompressChain(QuicStringPiece in,
+ static bool DecompressChain(quiche::QuicheStringPiece in,
const std::vector<std::string>& cached_certs,
const CommonCertSets* common_sets,
std::vector<std::string>* out_certs);
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/cert_compressor_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/cert_compressor_test.cc
index 1341f790d56..a7517f4c180 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/cert_compressor_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/cert_compressor_test.cc
@@ -9,8 +9,9 @@
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
namespace test {
@@ -20,8 +21,8 @@ class CertCompressorTest : public QuicTest {};
TEST_F(CertCompressorTest, EmptyChain) {
std::vector<std::string> chain;
const std::string compressed = CertCompressor::CompressChain(
- chain, QuicStringPiece(), QuicStringPiece(), nullptr);
- EXPECT_EQ("00", QuicTextUtils::HexEncode(compressed));
+ chain, quiche::QuicheStringPiece(), quiche::QuicheStringPiece(), nullptr);
+ EXPECT_EQ("00", quiche::QuicheTextUtils::HexEncode(compressed));
std::vector<std::string> chain2, cached_certs;
ASSERT_TRUE(CertCompressor::DecompressChain(compressed, cached_certs, nullptr,
@@ -33,9 +34,10 @@ TEST_F(CertCompressorTest, Compressed) {
std::vector<std::string> chain;
chain.push_back("testcert");
const std::string compressed = CertCompressor::CompressChain(
- chain, QuicStringPiece(), QuicStringPiece(), nullptr);
+ chain, quiche::QuicheStringPiece(), quiche::QuicheStringPiece(), nullptr);
ASSERT_GE(compressed.size(), 2u);
- EXPECT_EQ("0100", QuicTextUtils::HexEncode(compressed.substr(0, 2)));
+ EXPECT_EQ("0100",
+ quiche::QuicheTextUtils::HexEncode(compressed.substr(0, 2)));
std::vector<std::string> chain2, cached_certs;
ASSERT_TRUE(CertCompressor::DecompressChain(compressed, cached_certs, nullptr,
@@ -52,15 +54,15 @@ TEST_F(CertCompressorTest, Common) {
crypto_test_utils::MockCommonCertSets(chain[0], set_hash, 1));
const std::string compressed = CertCompressor::CompressChain(
chain,
- QuicStringPiece(reinterpret_cast<const char*>(&set_hash),
- sizeof(set_hash)),
- QuicStringPiece(), common_sets.get());
+ quiche::QuicheStringPiece(reinterpret_cast<const char*>(&set_hash),
+ sizeof(set_hash)),
+ quiche::QuicheStringPiece(), common_sets.get());
EXPECT_EQ(
"03" /* common */
"2a00000000000000" /* set hash 42 */
"01000000" /* index 1 */
"00" /* end of list */,
- QuicTextUtils::HexEncode(compressed));
+ quiche::QuicheTextUtils::HexEncode(compressed));
std::vector<std::string> chain2, cached_certs;
ASSERT_TRUE(CertCompressor::DecompressChain(compressed, cached_certs,
@@ -73,13 +75,14 @@ TEST_F(CertCompressorTest, Cached) {
std::vector<std::string> chain;
chain.push_back("testcert");
uint64_t hash = QuicUtils::FNV1a_64_Hash(chain[0]);
- QuicStringPiece hash_bytes(reinterpret_cast<char*>(&hash), sizeof(hash));
+ quiche::QuicheStringPiece hash_bytes(reinterpret_cast<char*>(&hash),
+ sizeof(hash));
const std::string compressed = CertCompressor::CompressChain(
- chain, QuicStringPiece(), hash_bytes, nullptr);
+ chain, quiche::QuicheStringPiece(), hash_bytes, nullptr);
- EXPECT_EQ("02" /* cached */ + QuicTextUtils::HexEncode(hash_bytes) +
+ EXPECT_EQ("02" /* cached */ + quiche::QuicheTextUtils::HexEncode(hash_bytes) +
"00" /* end of list */,
- QuicTextUtils::HexEncode(compressed));
+ quiche::QuicheTextUtils::HexEncode(compressed));
std::vector<std::string> cached_certs, chain2;
cached_certs.push_back(chain[0]);
@@ -93,26 +96,26 @@ TEST_F(CertCompressorTest, BadInputs) {
std::vector<std::string> cached_certs, chain;
EXPECT_FALSE(CertCompressor::DecompressChain(
- QuicTextUtils::HexEncode("04") /* bad entry type */, cached_certs,
- nullptr, &chain));
+ quiche::QuicheTextUtils::HexEncode("04") /* bad entry type */,
+ cached_certs, nullptr, &chain));
EXPECT_FALSE(CertCompressor::DecompressChain(
- QuicTextUtils::HexEncode("01") /* no terminator */, cached_certs, nullptr,
- &chain));
+ quiche::QuicheTextUtils::HexEncode("01") /* no terminator */,
+ cached_certs, nullptr, &chain));
EXPECT_FALSE(CertCompressor::DecompressChain(
- QuicTextUtils::HexEncode("0200") /* hash truncated */, cached_certs,
- nullptr, &chain));
+ quiche::QuicheTextUtils::HexEncode("0200") /* hash truncated */,
+ cached_certs, nullptr, &chain));
EXPECT_FALSE(CertCompressor::DecompressChain(
- QuicTextUtils::HexEncode("0300") /* hash and index truncated */,
+ quiche::QuicheTextUtils::HexEncode("0300") /* hash and index truncated */,
cached_certs, nullptr, &chain));
/* without a CommonCertSets */
EXPECT_FALSE(CertCompressor::DecompressChain(
- QuicTextUtils::HexEncode("03"
- "0000000000000000"
- "00000000"),
+ quiche::QuicheTextUtils::HexEncode("03"
+ "0000000000000000"
+ "00000000"),
cached_certs, nullptr, &chain));
std::unique_ptr<CommonCertSets> common_sets(
@@ -120,9 +123,9 @@ TEST_F(CertCompressorTest, BadInputs) {
/* incorrect hash and index */
EXPECT_FALSE(CertCompressor::DecompressChain(
- QuicTextUtils::HexEncode("03"
- "a200000000000000"
- "00000000"),
+ quiche::QuicheTextUtils::HexEncode("03"
+ "a200000000000000"
+ "00000000"),
cached_certs, nullptr, &chain));
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_view.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_view.cc
new file mode 100644
index 00000000000..6400528c8fd
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_view.cc
@@ -0,0 +1,246 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/crypto/certificate_view.h"
+
+#include <cstdint>
+#include <memory>
+
+#include "third_party/boringssl/src/include/openssl/bytestring.h"
+#include "third_party/boringssl/src/include/openssl/ec.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
+#include "third_party/boringssl/src/include/openssl/nid.h"
+#include "net/third_party/quiche/src/quic/core/crypto/boring_utils.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_ip_address.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+
+// The literals below were encoded using `ascii2der | xxd -i`. The comments
+// above the literals are the contents in the der2ascii syntax.
+namespace {
+
+// X.509 version 3 (version numbering starts with zero).
+// INTEGER { 2 }
+constexpr uint8_t kX509Version[] = {0x02, 0x01, 0x02};
+
+// 2.5.29.17
+constexpr uint8_t kSubjectAltNameOid[] = {0x55, 0x1d, 0x11};
+
+} // namespace
+
+namespace quic {
+
+std::unique_ptr<CertificateView> CertificateView::ParseSingleCertificate(
+ quiche::QuicheStringPiece certificate) {
+ std::unique_ptr<CertificateView> result(new CertificateView());
+ CBS top = StringPieceToCbs(certificate);
+
+ CBS top_certificate, tbs_certificate, signature_algorithm, signature;
+ if (!CBS_get_asn1(&top, &top_certificate, CBS_ASN1_SEQUENCE) ||
+ CBS_len(&top) != 0) {
+ return nullptr;
+ }
+
+ // Certificate ::= SEQUENCE {
+ if (
+ // tbsCertificate TBSCertificate,
+ !CBS_get_asn1(&top_certificate, &tbs_certificate, CBS_ASN1_SEQUENCE) ||
+
+ // signatureAlgorithm AlgorithmIdentifier,
+ !CBS_get_asn1(&top_certificate, &signature_algorithm,
+ CBS_ASN1_SEQUENCE) ||
+
+ // signature BIT STRING }
+ !CBS_get_asn1(&top_certificate, &signature, CBS_ASN1_BITSTRING) ||
+ CBS_len(&top_certificate) != 0) {
+ return nullptr;
+ }
+
+ int has_version, has_extensions;
+ CBS version, serial, signature_algorithm_inner, issuer, validity, subject,
+ spki, issuer_id, subject_id, extensions_outer;
+ // TBSCertificate ::= SEQUENCE {
+ if (
+ // version [0] Version DEFAULT v1,
+ !CBS_get_optional_asn1(
+ &tbs_certificate, &version, &has_version,
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0) ||
+
+ // serialNumber CertificateSerialNumber,
+ !CBS_get_asn1(&tbs_certificate, &serial, CBS_ASN1_INTEGER) ||
+
+ // signature AlgorithmIdentifier,
+ !CBS_get_asn1(&tbs_certificate, &signature_algorithm_inner,
+ CBS_ASN1_SEQUENCE) ||
+
+ // issuer Name,
+ !CBS_get_asn1(&tbs_certificate, &issuer, CBS_ASN1_SEQUENCE) ||
+
+ // validity Validity,
+ !CBS_get_asn1(&tbs_certificate, &validity, CBS_ASN1_SEQUENCE) ||
+
+ // subject Name,
+ !CBS_get_asn1(&tbs_certificate, &subject, CBS_ASN1_SEQUENCE) ||
+
+ // subjectPublicKeyInfo SubjectPublicKeyInfo,
+ !CBS_get_asn1_element(&tbs_certificate, &spki, CBS_ASN1_SEQUENCE) ||
+
+ // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
+ // -- If present, version MUST be v2 or v3
+ !CBS_get_optional_asn1(&tbs_certificate, &issuer_id, nullptr,
+ CBS_ASN1_CONTEXT_SPECIFIC | 1) ||
+
+ // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
+ // -- If present, version MUST be v2 or v3
+ !CBS_get_optional_asn1(&tbs_certificate, &subject_id, nullptr,
+ CBS_ASN1_CONTEXT_SPECIFIC | 2) ||
+
+ // extensions [3] Extensions OPTIONAL
+ // -- If present, version MUST be v3 -- }
+ !CBS_get_optional_asn1(
+ &tbs_certificate, &extensions_outer, &has_extensions,
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 3) ||
+
+ CBS_len(&tbs_certificate) != 0) {
+ return nullptr;
+ }
+
+ result->public_key_.reset(EVP_parse_public_key(&spki));
+ if (result->public_key_ == nullptr) {
+ QUIC_DLOG(WARNING) << "Failed to parse the public key";
+ return nullptr;
+ }
+ if (!result->ValidatePublicKeyParameters()) {
+ QUIC_DLOG(WARNING) << "Public key has invalid parameters";
+ return nullptr;
+ }
+
+ // Only support X.509v3.
+ if (!has_version ||
+ !CBS_mem_equal(&version, kX509Version, sizeof(kX509Version))) {
+ QUIC_DLOG(WARNING) << "Bad X.509 version";
+ return nullptr;
+ }
+
+ if (!has_extensions) {
+ return nullptr;
+ }
+
+ CBS extensions;
+ if (!CBS_get_asn1(&extensions_outer, &extensions, CBS_ASN1_SEQUENCE) ||
+ CBS_len(&extensions_outer) != 0) {
+ QUIC_DLOG(WARNING) << "Failed to extract the extension sequence";
+ return nullptr;
+ }
+ if (!result->ParseExtensions(extensions)) {
+ QUIC_DLOG(WARNING) << "Failed to parse extensions";
+ return nullptr;
+ }
+
+ return result;
+}
+
+bool CertificateView::ParseExtensions(CBS extensions) {
+ while (CBS_len(&extensions) != 0) {
+ CBS extension, oid, critical, payload;
+ if (
+ // Extension ::= SEQUENCE {
+ !CBS_get_asn1(&extensions, &extension, CBS_ASN1_SEQUENCE) ||
+ // extnID OBJECT IDENTIFIER,
+ !CBS_get_asn1(&extension, &oid, CBS_ASN1_OBJECT) ||
+ // critical BOOLEAN DEFAULT FALSE,
+ !CBS_get_optional_asn1(&extension, &critical, nullptr,
+ CBS_ASN1_BOOLEAN) ||
+ // extnValue OCTET STRING
+ // -- contains the DER encoding of an ASN.1 value
+ // -- corresponding to the extension type identified
+ // -- by extnID
+ !CBS_get_asn1(&extension, &payload, CBS_ASN1_OCTETSTRING) ||
+ CBS_len(&extension) != 0) {
+ QUIC_DLOG(WARNING) << "Bad extension entry";
+ return false;
+ }
+
+ if (CBS_mem_equal(&oid, kSubjectAltNameOid, sizeof(kSubjectAltNameOid))) {
+ CBS alt_names;
+ if (!CBS_get_asn1(&payload, &alt_names, CBS_ASN1_SEQUENCE) ||
+ CBS_len(&payload) != 0) {
+ QUIC_DLOG(WARNING) << "Failed to parse subjectAltName";
+ return false;
+ }
+ while (CBS_len(&alt_names) != 0) {
+ CBS alt_name_cbs;
+ unsigned int alt_name_tag;
+ if (!CBS_get_any_asn1(&alt_names, &alt_name_cbs, &alt_name_tag)) {
+ QUIC_DLOG(WARNING) << "Failed to parse subjectAltName";
+ return false;
+ }
+
+ quiche::QuicheStringPiece alt_name = CbsToStringPiece(alt_name_cbs);
+ QuicIpAddress ip_address;
+ // GeneralName ::= CHOICE {
+ switch (alt_name_tag) {
+ // dNSName [2] IA5String,
+ case CBS_ASN1_CONTEXT_SPECIFIC | 2:
+ subject_alt_name_domains_.push_back(alt_name);
+ break;
+
+ // iPAddress [7] OCTET STRING,
+ case CBS_ASN1_CONTEXT_SPECIFIC | 7:
+ if (!ip_address.FromPackedString(alt_name.data(),
+ alt_name.size())) {
+ QUIC_DLOG(WARNING) << "Failed to parse subjectAltName IP address";
+ return false;
+ }
+ subject_alt_name_ips_.push_back(ip_address);
+ break;
+
+ default:
+ QUIC_DLOG(WARNING) << "Invalid subjectAltName tag";
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+bool CertificateView::ValidatePublicKeyParameters() {
+ // The profile here affects what certificates can be used:
+ // (1) when QUIC is used as a server library without any custom certificate
+ // provider logic,
+ // (2) when QuicTransport is handling self-signed certificates.
+ // The goal is to allow at minimum any certificate that would be allowed on a
+ // regular Web session over TLS 1.3 while ensuring we do not expose any
+ // algorithms we don't want to support long-term.
+ switch (EVP_PKEY_id(public_key_.get())) {
+ case EVP_PKEY_RSA:
+ return EVP_PKEY_bits(public_key_.get()) >= 2048;
+ case EVP_PKEY_EC: {
+ const EC_KEY* key = EVP_PKEY_get0_EC_KEY(public_key_.get());
+ if (key == nullptr) {
+ return false;
+ }
+ const EC_GROUP* group = EC_KEY_get0_group(key);
+ if (group == nullptr) {
+ return false;
+ }
+ const int curve_nid = EC_GROUP_get_curve_name(group);
+ switch (curve_nid) {
+ case NID_X9_62_prime256v1:
+ case NID_secp384r1:
+ return true;
+ default:
+ return false;
+ }
+ }
+ case EVP_PKEY_ED25519:
+ return true;
+ default:
+ return false;
+ }
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_view.h b/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_view.h
new file mode 100644
index 00000000000..3569f4e0d87
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_view.h
@@ -0,0 +1,57 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_CORE_CRYPTO_CERTIFICATE_VIEW_H_
+#define QUICHE_QUIC_CORE_CRYPTO_CERTIFICATE_VIEW_H_
+
+#include <memory>
+
+#include "third_party/boringssl/src/include/openssl/bytestring.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
+#include "net/third_party/quiche/src/quic/core/crypto/boring_utils.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_ip_address.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+
+namespace quic {
+
+// CertificateView represents a parsed version of a single X.509 certificate. As
+// the word "view" implies, it does not take ownership of the underlying strings
+// and consists primarily of pointers into the certificate that is passed into
+// the parser.
+class QUIC_EXPORT_PRIVATE CertificateView {
+ public:
+ // Parses a single DER-encoded X.509 certificate. Returns nullptr on parse
+ // error.
+ static std::unique_ptr<CertificateView> ParseSingleCertificate(
+ quiche::QuicheStringPiece certificate);
+
+ EVP_PKEY* public_key() { return public_key_.get(); }
+
+ const std::vector<quiche::QuicheStringPiece>& subject_alt_name_domains()
+ const {
+ return subject_alt_name_domains_;
+ }
+ const std::vector<QuicIpAddress>& subject_alt_name_ips() const {
+ return subject_alt_name_ips_;
+ }
+
+ private:
+ CertificateView() = default;
+
+ // Public key parsed from SPKI.
+ bssl::UniquePtr<EVP_PKEY> public_key_;
+
+ // SubjectAltName, https://tools.ietf.org/html/rfc5280#section-4.2.1.6
+ std::vector<quiche::QuicheStringPiece> subject_alt_name_domains_;
+ std::vector<QuicIpAddress> subject_alt_name_ips_;
+
+ // Called from ParseSingleCertificate().
+ bool ParseExtensions(CBS extensions);
+ bool ValidatePublicKeyParameters();
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_CRYPTO_CERTIFICATE_VIEW_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_view_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_view_test.cc
new file mode 100644
index 00000000000..6be0e4ae7a6
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/certificate_view_test.cc
@@ -0,0 +1,144 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/crypto/certificate_view.h"
+
+#include "third_party/boringssl/src/include/openssl/base.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_ip_address.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+
+namespace quic {
+namespace {
+
+using testing::ElementsAre;
+
+// A test certificate generated by //net/tools/quic/certs/generate-certs.sh.
+constexpr char kTestCertificate[] = {
+ '\x30', '\x82', '\x03', '\xb4', '\x30', '\x82', '\x02', '\x9c', '\xa0',
+ '\x03', '\x02', '\x01', '\x02', '\x02', '\x01', '\x01', '\x30', '\x0d',
+ '\x06', '\x09', '\x2a', '\x86', '\x48', '\x86', '\xf7', '\x0d', '\x01',
+ '\x01', '\x0b', '\x05', '\x00', '\x30', '\x1e', '\x31', '\x1c', '\x30',
+ '\x1a', '\x06', '\x03', '\x55', '\x04', '\x03', '\x0c', '\x13', '\x51',
+ '\x55', '\x49', '\x43', '\x20', '\x53', '\x65', '\x72', '\x76', '\x65',
+ '\x72', '\x20', '\x52', '\x6f', '\x6f', '\x74', '\x20', '\x43', '\x41',
+ '\x30', '\x1e', '\x17', '\x0d', '\x32', '\x30', '\x30', '\x31', '\x33',
+ '\x30', '\x31', '\x38', '\x31', '\x33', '\x35', '\x39', '\x5a', '\x17',
+ '\x0d', '\x32', '\x30', '\x30', '\x32', '\x30', '\x32', '\x31', '\x38',
+ '\x31', '\x33', '\x35', '\x39', '\x5a', '\x30', '\x64', '\x31', '\x0b',
+ '\x30', '\x09', '\x06', '\x03', '\x55', '\x04', '\x06', '\x13', '\x02',
+ '\x55', '\x53', '\x31', '\x13', '\x30', '\x11', '\x06', '\x03', '\x55',
+ '\x04', '\x08', '\x0c', '\x0a', '\x43', '\x61', '\x6c', '\x69', '\x66',
+ '\x6f', '\x72', '\x6e', '\x69', '\x61', '\x31', '\x16', '\x30', '\x14',
+ '\x06', '\x03', '\x55', '\x04', '\x07', '\x0c', '\x0d', '\x4d', '\x6f',
+ '\x75', '\x6e', '\x74', '\x61', '\x69', '\x6e', '\x20', '\x56', '\x69',
+ '\x65', '\x77', '\x31', '\x14', '\x30', '\x12', '\x06', '\x03', '\x55',
+ '\x04', '\x0a', '\x0c', '\x0b', '\x51', '\x55', '\x49', '\x43', '\x20',
+ '\x53', '\x65', '\x72', '\x76', '\x65', '\x72', '\x31', '\x12', '\x30',
+ '\x10', '\x06', '\x03', '\x55', '\x04', '\x03', '\x0c', '\x09', '\x31',
+ '\x32', '\x37', '\x2e', '\x30', '\x2e', '\x30', '\x2e', '\x31', '\x30',
+ '\x82', '\x01', '\x22', '\x30', '\x0d', '\x06', '\x09', '\x2a', '\x86',
+ '\x48', '\x86', '\xf7', '\x0d', '\x01', '\x01', '\x01', '\x05', '\x00',
+ '\x03', '\x82', '\x01', '\x0f', '\x00', '\x30', '\x82', '\x01', '\x0a',
+ '\x02', '\x82', '\x01', '\x01', '\x00', '\xc5', '\xe2', '\x51', '\x6d',
+ '\x3f', '\xd6', '\x28', '\xf2', '\xad', '\x34', '\x73', '\x87', '\x64',
+ '\xca', '\x33', '\x19', '\x33', '\xb7', '\x75', '\x91', '\xab', '\x31',
+ '\x19', '\x2b', '\xe3', '\xa4', '\x26', '\x09', '\x29', '\x8b', '\x2d',
+ '\xf7', '\x52', '\x75', '\xa7', '\x55', '\x15', '\xf0', '\x11', '\xc7',
+ '\xc2', '\xc4', '\xed', '\x18', '\x1b', '\x33', '\x0b', '\x71', '\x32',
+ '\xe6', '\x35', '\x89', '\xcd', '\x2d', '\x5a', '\x05', '\x57', '\x4e',
+ '\xc2', '\x78', '\x75', '\x65', '\x72', '\x2d', '\x8a', '\x17', '\x83',
+ '\xd6', '\x32', '\x90', '\x85', '\xf8', '\x22', '\xe2', '\x65', '\xa9',
+ '\xe0', '\xa0', '\xfe', '\x19', '\xb2', '\x39', '\x2d', '\x14', '\x03',
+ '\x10', '\x2f', '\xcc', '\x8b', '\x5e', '\xaa', '\x25', '\x27', '\x0d',
+ '\xa3', '\x37', '\x10', '\x0c', '\x17', '\xec', '\xf0', '\x8b', '\xc5',
+ '\x6b', '\xed', '\x6b', '\x5e', '\xb2', '\xe2', '\x35', '\x3e', '\x46',
+ '\x3b', '\xf7', '\xf6', '\x59', '\xb1', '\xe0', '\x16', '\xa6', '\xfb',
+ '\x03', '\xbf', '\x84', '\x4f', '\xce', '\x64', '\x15', '\x0d', '\x59',
+ '\x99', '\xa6', '\xf0', '\x7f', '\x8a', '\x33', '\x4b', '\xbb', '\x0b',
+ '\xb8', '\xf2', '\xd1', '\x27', '\x90', '\x8f', '\x38', '\xf8', '\x5a',
+ '\x41', '\x82', '\x07', '\x9b', '\x0d', '\xd9', '\x52', '\xe0', '\x70',
+ '\xff', '\xde', '\xda', '\xd8', '\x25', '\x4e', '\x2f', '\x2d', '\x9f',
+ '\xaf', '\x92', '\x63', '\xc7', '\x42', '\xb4', '\xdc', '\x16', '\x95',
+ '\x23', '\x05', '\x02', '\x6b', '\xb0', '\xe8', '\xc5', '\xfe', '\x15',
+ '\x9a', '\xe8', '\x7d', '\x2f', '\xdc', '\x43', '\xf4', '\x70', '\x91',
+ '\x1a', '\x93', '\xbe', '\x71', '\xaf', '\x85', '\x84', '\xdb', '\xcf',
+ '\x6b', '\x5c', '\x80', '\xb2', '\xd3', '\xf3', '\x42', '\x6e', '\x24',
+ '\xec', '\x2a', '\x62', '\x99', '\xc6', '\x3c', '\xe5', '\x32', '\xe5',
+ '\x72', '\x37', '\x30', '\x9b', '\x0b', '\xe4', '\x06', '\xb4', '\x64',
+ '\x26', '\x95', '\x59', '\xba', '\xf1', '\x53', '\x83', '\x3d', '\x99',
+ '\x6d', '\xf0', '\x80', '\xe2', '\xdb', '\x6b', '\x34', '\x52', '\x06',
+ '\x77', '\x3c', '\x73', '\xbe', '\xc6', '\xe3', '\xce', '\xb2', '\x11',
+ '\x02', '\x03', '\x01', '\x00', '\x01', '\xa3', '\x81', '\xb6', '\x30',
+ '\x81', '\xb3', '\x30', '\x0c', '\x06', '\x03', '\x55', '\x1d', '\x13',
+ '\x01', '\x01', '\xff', '\x04', '\x02', '\x30', '\x00', '\x30', '\x1d',
+ '\x06', '\x03', '\x55', '\x1d', '\x0e', '\x04', '\x16', '\x04', '\x14',
+ '\xc8', '\x54', '\x28', '\xf6', '\xd2', '\xd5', '\x12', '\x35', '\x89',
+ '\x15', '\x75', '\xb8', '\xbf', '\xdd', '\xfb', '\x4a', '\xfc', '\x6c',
+ '\x89', '\xde', '\x30', '\x1f', '\x06', '\x03', '\x55', '\x1d', '\x23',
+ '\x04', '\x18', '\x30', '\x16', '\x80', '\x14', '\x50', '\xe4', '\x1d',
+ '\xc3', '\x1a', '\xfb', '\xfd', '\x38', '\xdd', '\xa2', '\x05', '\xfd',
+ '\xc8', '\xfa', '\x57', '\x0a', '\xc1', '\x06', '\x0f', '\xae', '\x30',
+ '\x1d', '\x06', '\x03', '\x55', '\x1d', '\x25', '\x04', '\x16', '\x30',
+ '\x14', '\x06', '\x08', '\x2b', '\x06', '\x01', '\x05', '\x05', '\x07',
+ '\x03', '\x01', '\x06', '\x08', '\x2b', '\x06', '\x01', '\x05', '\x05',
+ '\x07', '\x03', '\x02', '\x30', '\x44', '\x06', '\x03', '\x55', '\x1d',
+ '\x11', '\x04', '\x3d', '\x30', '\x3b', '\x82', '\x0f', '\x77', '\x77',
+ '\x77', '\x2e', '\x65', '\x78', '\x61', '\x6d', '\x70', '\x6c', '\x65',
+ '\x2e', '\x6f', '\x72', '\x67', '\x82', '\x10', '\x6d', '\x61', '\x69',
+ '\x6c', '\x2e', '\x65', '\x78', '\x61', '\x6d', '\x70', '\x6c', '\x65',
+ '\x2e', '\x6f', '\x72', '\x67', '\x82', '\x10', '\x6d', '\x61', '\x69',
+ '\x6c', '\x2e', '\x65', '\x78', '\x61', '\x6d', '\x70', '\x6c', '\x65',
+ '\x2e', '\x63', '\x6f', '\x6d', '\x87', '\x04', '\x7f', '\x00', '\x00',
+ '\x01', '\x30', '\x0d', '\x06', '\x09', '\x2a', '\x86', '\x48', '\x86',
+ '\xf7', '\x0d', '\x01', '\x01', '\x0b', '\x05', '\x00', '\x03', '\x82',
+ '\x01', '\x01', '\x00', '\x45', '\x41', '\x7a', '\x68', '\xe0', '\xa7',
+ '\x59', '\xa1', '\x62', '\x54', '\x73', '\x74', '\x14', '\x4f', '\xde',
+ '\x9c', '\x51', '\xac', '\x25', '\x97', '\x70', '\xf7', '\x09', '\x51',
+ '\x39', '\x72', '\x39', '\x3c', '\xd0', '\x31', '\xe1', '\xc3', '\x02',
+ '\x91', '\x14', '\x4d', '\x8f', '\x1d', '\x31', '\xab', '\x98', '\x7e',
+ '\xe6', '\xbb', '\xab', '\x6a', '\xd9', '\xc5', '\x86', '\xaa', '\x4e',
+ '\x6a', '\x48', '\xe9', '\xf8', '\xd7', '\xb3', '\x1d', '\xa0', '\xc5',
+ '\xe6', '\xbf', '\x4c', '\x5a', '\x9b', '\xb5', '\x78', '\x01', '\xa3',
+ '\x39', '\x7b', '\x5f', '\xbc', '\xb8', '\xa7', '\xc2', '\x71', '\xb0',
+ '\x7b', '\xdd', '\xa1', '\x87', '\xa6', '\x54', '\x9c', '\xf6', '\x59',
+ '\x81', '\xb1', '\x2c', '\xde', '\xc5', '\x8a', '\xa2', '\x06', '\x89',
+ '\xb5', '\xc1', '\x7a', '\xbe', '\x0c', '\x9f', '\x3d', '\xde', '\x81',
+ '\x48', '\x53', '\x71', '\x7b', '\x8d', '\xc7', '\xea', '\x87', '\xd7',
+ '\xd1', '\xda', '\x94', '\xb4', '\xc5', '\xac', '\x1e', '\x83', '\xa3',
+ '\x42', '\x7d', '\xe6', '\xab', '\x3f', '\xd6', '\x1c', '\xd6', '\x65',
+ '\xc3', '\x60', '\xe9', '\x76', '\x54', '\x79', '\x3f', '\xeb', '\x65',
+ '\x85', '\x4f', '\x60', '\x7d', '\xbb', '\x96', '\x03', '\x54', '\x2e',
+ '\xd0', '\x1b', '\xe2', '\x6c', '\x2d', '\x91', '\xae', '\x33', '\x9c',
+ '\x04', '\xc4', '\x44', '\x0a', '\x7d', '\x5f', '\xbb', '\x80', '\xa2',
+ '\x01', '\xbc', '\x90', '\x81', '\xa5', '\xdc', '\x4a', '\xc8', '\x77',
+ '\xc9', '\x8d', '\x34', '\x17', '\xe6', '\x2a', '\x7d', '\x02', '\x1e',
+ '\x32', '\x3f', '\x7d', '\xd7', '\x0c', '\x80', '\x5b', '\xc6', '\x94',
+ '\x6a', '\x42', '\x36', '\x05', '\x9f', '\x9e', '\xc5', '\x85', '\x9f',
+ '\x60', '\xe3', '\x72', '\x73', '\x34', '\x39', '\x44', '\x75', '\x55',
+ '\x60', '\x24', '\x7a', '\x8b', '\x09', '\x74', '\x84', '\x72', '\xfd',
+ '\x91', '\x68', '\x93', '\x57', '\x9e', '\x70', '\x46', '\x4d', '\xe4',
+ '\x30', '\x84', '\x5f', '\x20', '\x07', '\xad', '\xfd', '\x86', '\x32',
+ '\xd3', '\xfb', '\xba', '\xaf', '\xd9', '\x61', '\x14', '\x3c', '\xe0',
+ '\xa1', '\xa9', '\x51', '\x51', '\x0f', '\xad', '\x60'};
+
+TEST(CertificateViewTest, Parse) {
+ quiche::QuicheStringPiece certificate(kTestCertificate,
+ sizeof(kTestCertificate));
+ std::unique_ptr<CertificateView> view =
+ CertificateView::ParseSingleCertificate(certificate);
+ ASSERT_TRUE(view != nullptr);
+
+ EXPECT_THAT(view->subject_alt_name_domains(),
+ ElementsAre(quiche::QuicheStringPiece("www.example.org"),
+ quiche::QuicheStringPiece("mail.example.org"),
+ quiche::QuicheStringPiece("mail.example.com")));
+ EXPECT_THAT(view->subject_alt_name_ips(),
+ ElementsAre(QuicIpAddress::Loopback4()));
+ EXPECT_EQ(EVP_PKEY_id(view->public_key()), EVP_PKEY_RSA);
+}
+
+} // namespace
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_decrypter_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_decrypter_test.cc
index 930af24a3b3..83e52b10e2c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_decrypter_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_decrypter_test.cc
@@ -9,8 +9,10 @@
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
+#include "net/third_party/quiche/src/common/test_tools/quiche_test_utils.h"
namespace {
@@ -113,12 +115,12 @@ namespace test {
// DecryptWithNonce wraps the |Decrypt| method of |decrypter| to allow passing
// in an nonce and also to allocate the buffer needed for the plaintext.
QuicData* DecryptWithNonce(ChaCha20Poly1305Decrypter* decrypter,
- QuicStringPiece nonce,
- QuicStringPiece associated_data,
- QuicStringPiece ciphertext) {
+ quiche::QuicheStringPiece nonce,
+ quiche::QuicheStringPiece associated_data,
+ quiche::QuicheStringPiece ciphertext) {
uint64_t packet_number;
- QuicStringPiece nonce_prefix(nonce.data(),
- nonce.size() - sizeof(packet_number));
+ quiche::QuicheStringPiece nonce_prefix(nonce.data(),
+ nonce.size() - sizeof(packet_number));
decrypter->SetNoncePrefix(nonce_prefix);
memcpy(&packet_number, nonce.data() + nonce_prefix.size(),
sizeof(packet_number));
@@ -141,14 +143,15 @@ TEST_F(ChaCha20Poly1305DecrypterTest, Decrypt) {
bool has_pt = test_vectors[i].pt;
// Decode the test vector.
- std::string key = QuicTextUtils::HexDecode(test_vectors[i].key);
- std::string iv = QuicTextUtils::HexDecode(test_vectors[i].iv);
- std::string fixed = QuicTextUtils::HexDecode(test_vectors[i].fixed);
- std::string aad = QuicTextUtils::HexDecode(test_vectors[i].aad);
- std::string ct = QuicTextUtils::HexDecode(test_vectors[i].ct);
+ std::string key = quiche::QuicheTextUtils::HexDecode(test_vectors[i].key);
+ std::string iv = quiche::QuicheTextUtils::HexDecode(test_vectors[i].iv);
+ std::string fixed =
+ quiche::QuicheTextUtils::HexDecode(test_vectors[i].fixed);
+ std::string aad = quiche::QuicheTextUtils::HexDecode(test_vectors[i].aad);
+ std::string ct = quiche::QuicheTextUtils::HexDecode(test_vectors[i].ct);
std::string pt;
if (has_pt) {
- pt = QuicTextUtils::HexDecode(test_vectors[i].pt);
+ pt = quiche::QuicheTextUtils::HexDecode(test_vectors[i].pt);
}
ChaCha20Poly1305Decrypter decrypter;
@@ -157,7 +160,8 @@ TEST_F(ChaCha20Poly1305DecrypterTest, Decrypt) {
&decrypter, fixed + iv,
// This deliberately tests that the decrypter can handle an AAD that
// is set to nullptr, as opposed to a zero-length, non-nullptr pointer.
- QuicStringPiece(aad.length() ? aad.data() : nullptr, aad.length()),
+ quiche::QuicheStringPiece(aad.length() ? aad.data() : nullptr,
+ aad.length()),
ct));
if (!decrypted) {
EXPECT_FALSE(has_pt);
@@ -167,8 +171,8 @@ TEST_F(ChaCha20Poly1305DecrypterTest, Decrypt) {
EXPECT_EQ(12u, ct.size() - decrypted->length());
ASSERT_EQ(pt.length(), decrypted->length());
- test::CompareCharArraysWithHexError("plaintext", decrypted->data(),
- pt.length(), pt.data(), pt.length());
+ quiche::test::CompareCharArraysWithHexError(
+ "plaintext", decrypted->data(), pt.length(), pt.data(), pt.length());
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_encrypter_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_encrypter_test.cc
index 4584d9673b2..47ee3d03a06 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_encrypter_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_encrypter_test.cc
@@ -9,10 +9,12 @@
#include "net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_decrypter.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
+#include "net/third_party/quiche/src/common/test_tools/quiche_test_utils.h"
namespace {
@@ -70,9 +72,9 @@ namespace test {
// EncryptWithNonce wraps the |Encrypt| method of |encrypter| to allow passing
// in an nonce and also to allocate the buffer needed for the ciphertext.
QuicData* EncryptWithNonce(ChaCha20Poly1305Encrypter* encrypter,
- QuicStringPiece nonce,
- QuicStringPiece associated_data,
- QuicStringPiece plaintext) {
+ quiche::QuicheStringPiece nonce,
+ quiche::QuicheStringPiece associated_data,
+ quiche::QuicheStringPiece plaintext) {
size_t ciphertext_size = encrypter->GetCiphertextSize(plaintext.length());
std::unique_ptr<char[]> ciphertext(new char[ciphertext_size]);
@@ -90,7 +92,7 @@ TEST_F(ChaCha20Poly1305EncrypterTest, EncryptThenDecrypt) {
ChaCha20Poly1305Encrypter encrypter;
ChaCha20Poly1305Decrypter decrypter;
- std::string key = QuicTextUtils::HexDecode(test_vectors[0].key);
+ std::string key = quiche::QuicheTextUtils::HexDecode(test_vectors[0].key);
ASSERT_TRUE(encrypter.SetKey(key));
ASSERT_TRUE(decrypter.SetKey(key));
ASSERT_TRUE(encrypter.SetNoncePrefix("abcd"));
@@ -103,23 +105,24 @@ TEST_F(ChaCha20Poly1305EncrypterTest, EncryptThenDecrypt) {
size_t len;
ASSERT_TRUE(encrypter.EncryptPacket(packet_number, associated_data, plaintext,
encrypted, &len,
- QUIC_ARRAYSIZE(encrypted)));
- QuicStringPiece ciphertext(encrypted, len);
+ QUICHE_ARRAYSIZE(encrypted)));
+ quiche::QuicheStringPiece ciphertext(encrypted, len);
char decrypted[1024];
ASSERT_TRUE(decrypter.DecryptPacket(packet_number, associated_data,
ciphertext, decrypted, &len,
- QUIC_ARRAYSIZE(decrypted)));
+ QUICHE_ARRAYSIZE(decrypted)));
}
TEST_F(ChaCha20Poly1305EncrypterTest, Encrypt) {
for (size_t i = 0; test_vectors[i].key != nullptr; i++) {
// Decode the test vector.
- std::string key = QuicTextUtils::HexDecode(test_vectors[i].key);
- std::string pt = QuicTextUtils::HexDecode(test_vectors[i].pt);
- std::string iv = QuicTextUtils::HexDecode(test_vectors[i].iv);
- std::string fixed = QuicTextUtils::HexDecode(test_vectors[i].fixed);
- std::string aad = QuicTextUtils::HexDecode(test_vectors[i].aad);
- std::string ct = QuicTextUtils::HexDecode(test_vectors[i].ct);
+ std::string key = quiche::QuicheTextUtils::HexDecode(test_vectors[i].key);
+ std::string pt = quiche::QuicheTextUtils::HexDecode(test_vectors[i].pt);
+ std::string iv = quiche::QuicheTextUtils::HexDecode(test_vectors[i].iv);
+ std::string fixed =
+ quiche::QuicheTextUtils::HexDecode(test_vectors[i].fixed);
+ std::string aad = quiche::QuicheTextUtils::HexDecode(test_vectors[i].aad);
+ std::string ct = quiche::QuicheTextUtils::HexDecode(test_vectors[i].ct);
ChaCha20Poly1305Encrypter encrypter;
ASSERT_TRUE(encrypter.SetKey(key));
@@ -127,15 +130,16 @@ TEST_F(ChaCha20Poly1305EncrypterTest, Encrypt) {
&encrypter, fixed + iv,
// This deliberately tests that the encrypter can handle an AAD that
// is set to nullptr, as opposed to a zero-length, non-nullptr pointer.
- QuicStringPiece(aad.length() ? aad.data() : nullptr, aad.length()),
+ quiche::QuicheStringPiece(aad.length() ? aad.data() : nullptr,
+ aad.length()),
pt));
ASSERT_TRUE(encrypted.get());
EXPECT_EQ(12u, ct.size() - pt.size());
EXPECT_EQ(12u, encrypted->length() - pt.size());
- test::CompareCharArraysWithHexError("ciphertext", encrypted->data(),
- encrypted->length(), ct.data(),
- ct.length());
+ quiche::test::CompareCharArraysWithHexError("ciphertext", encrypted->data(),
+ encrypted->length(), ct.data(),
+ ct.length());
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_tls_decrypter_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_tls_decrypter_test.cc
index 90052d60520..9127cd4634a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_tls_decrypter_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_tls_decrypter_test.cc
@@ -9,8 +9,10 @@
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
+#include "net/third_party/quiche/src/common/test_tools/quiche_test_utils.h"
namespace {
@@ -113,9 +115,9 @@ namespace test {
// DecryptWithNonce wraps the |Decrypt| method of |decrypter| to allow passing
// in an nonce and also to allocate the buffer needed for the plaintext.
QuicData* DecryptWithNonce(ChaCha20Poly1305TlsDecrypter* decrypter,
- QuicStringPiece nonce,
- QuicStringPiece associated_data,
- QuicStringPiece ciphertext) {
+ quiche::QuicheStringPiece nonce,
+ quiche::QuicheStringPiece associated_data,
+ quiche::QuicheStringPiece ciphertext) {
decrypter->SetIV(nonce);
std::unique_ptr<char[]> output(new char[ciphertext.length()]);
size_t output_length = 0;
@@ -136,14 +138,15 @@ TEST_F(ChaCha20Poly1305TlsDecrypterTest, Decrypt) {
bool has_pt = test_vectors[i].pt;
// Decode the test vector.
- std::string key = QuicTextUtils::HexDecode(test_vectors[i].key);
- std::string iv = QuicTextUtils::HexDecode(test_vectors[i].iv);
- std::string fixed = QuicTextUtils::HexDecode(test_vectors[i].fixed);
- std::string aad = QuicTextUtils::HexDecode(test_vectors[i].aad);
- std::string ct = QuicTextUtils::HexDecode(test_vectors[i].ct);
+ std::string key = quiche::QuicheTextUtils::HexDecode(test_vectors[i].key);
+ std::string iv = quiche::QuicheTextUtils::HexDecode(test_vectors[i].iv);
+ std::string fixed =
+ quiche::QuicheTextUtils::HexDecode(test_vectors[i].fixed);
+ std::string aad = quiche::QuicheTextUtils::HexDecode(test_vectors[i].aad);
+ std::string ct = quiche::QuicheTextUtils::HexDecode(test_vectors[i].ct);
std::string pt;
if (has_pt) {
- pt = QuicTextUtils::HexDecode(test_vectors[i].pt);
+ pt = quiche::QuicheTextUtils::HexDecode(test_vectors[i].pt);
}
ChaCha20Poly1305TlsDecrypter decrypter;
@@ -152,7 +155,8 @@ TEST_F(ChaCha20Poly1305TlsDecrypterTest, Decrypt) {
&decrypter, fixed + iv,
// This deliberately tests that the decrypter can handle an AAD that
// is set to nullptr, as opposed to a zero-length, non-nullptr pointer.
- QuicStringPiece(aad.length() ? aad.data() : nullptr, aad.length()),
+ quiche::QuicheStringPiece(aad.length() ? aad.data() : nullptr,
+ aad.length()),
ct));
if (!decrypted) {
EXPECT_FALSE(has_pt);
@@ -162,24 +166,24 @@ TEST_F(ChaCha20Poly1305TlsDecrypterTest, Decrypt) {
EXPECT_EQ(16u, ct.size() - decrypted->length());
ASSERT_EQ(pt.length(), decrypted->length());
- test::CompareCharArraysWithHexError("plaintext", decrypted->data(),
- pt.length(), pt.data(), pt.length());
+ quiche::test::CompareCharArraysWithHexError(
+ "plaintext", decrypted->data(), pt.length(), pt.data(), pt.length());
}
}
TEST_F(ChaCha20Poly1305TlsDecrypterTest, GenerateHeaderProtectionMask) {
ChaCha20Poly1305TlsDecrypter decrypter;
- std::string key = QuicTextUtils::HexDecode(
+ std::string key = quiche::QuicheTextUtils::HexDecode(
"6a067f432787bd6034dd3f08f07fc9703a27e58c70e2d88d948b7f6489923cc7");
std::string sample =
- QuicTextUtils::HexDecode("1210d91cceb45c716b023f492c29e612");
+ quiche::QuicheTextUtils::HexDecode("1210d91cceb45c716b023f492c29e612");
QuicDataReader sample_reader(sample.data(), sample.size());
ASSERT_TRUE(decrypter.SetHeaderProtectionKey(key));
std::string mask = decrypter.GenerateHeaderProtectionMask(&sample_reader);
- std::string expected_mask = QuicTextUtils::HexDecode("1cc2cd98dc");
- test::CompareCharArraysWithHexError("header protection mask", mask.data(),
- mask.size(), expected_mask.data(),
- expected_mask.size());
+ std::string expected_mask = quiche::QuicheTextUtils::HexDecode("1cc2cd98dc");
+ quiche::test::CompareCharArraysWithHexError(
+ "header protection mask", mask.data(), mask.size(), expected_mask.data(),
+ expected_mask.size());
}
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_tls_encrypter_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_tls_encrypter_test.cc
index ef4a8e869fe..dd642a323a8 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_tls_encrypter_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_tls_encrypter_test.cc
@@ -9,10 +9,12 @@
#include "net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_tls_decrypter.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
+#include "net/third_party/quiche/src/common/test_tools/quiche_test_utils.h"
namespace {
@@ -70,9 +72,9 @@ namespace test {
// EncryptWithNonce wraps the |Encrypt| method of |encrypter| to allow passing
// in an nonce and also to allocate the buffer needed for the ciphertext.
QuicData* EncryptWithNonce(ChaCha20Poly1305TlsEncrypter* encrypter,
- QuicStringPiece nonce,
- QuicStringPiece associated_data,
- QuicStringPiece plaintext) {
+ quiche::QuicheStringPiece nonce,
+ quiche::QuicheStringPiece associated_data,
+ quiche::QuicheStringPiece plaintext) {
size_t ciphertext_size = encrypter->GetCiphertextSize(plaintext.length());
std::unique_ptr<char[]> ciphertext(new char[ciphertext_size]);
@@ -90,7 +92,7 @@ TEST_F(ChaCha20Poly1305TlsEncrypterTest, EncryptThenDecrypt) {
ChaCha20Poly1305TlsEncrypter encrypter;
ChaCha20Poly1305TlsDecrypter decrypter;
- std::string key = QuicTextUtils::HexDecode(test_vectors[0].key);
+ std::string key = quiche::QuicheTextUtils::HexDecode(test_vectors[0].key);
ASSERT_TRUE(encrypter.SetKey(key));
ASSERT_TRUE(decrypter.SetKey(key));
ASSERT_TRUE(encrypter.SetIV("abcdefghijkl"));
@@ -103,23 +105,24 @@ TEST_F(ChaCha20Poly1305TlsEncrypterTest, EncryptThenDecrypt) {
size_t len;
ASSERT_TRUE(encrypter.EncryptPacket(packet_number, associated_data, plaintext,
encrypted, &len,
- QUIC_ARRAYSIZE(encrypted)));
- QuicStringPiece ciphertext(encrypted, len);
+ QUICHE_ARRAYSIZE(encrypted)));
+ quiche::QuicheStringPiece ciphertext(encrypted, len);
char decrypted[1024];
ASSERT_TRUE(decrypter.DecryptPacket(packet_number, associated_data,
ciphertext, decrypted, &len,
- QUIC_ARRAYSIZE(decrypted)));
+ QUICHE_ARRAYSIZE(decrypted)));
}
TEST_F(ChaCha20Poly1305TlsEncrypterTest, Encrypt) {
for (size_t i = 0; test_vectors[i].key != nullptr; i++) {
// Decode the test vector.
- std::string key = QuicTextUtils::HexDecode(test_vectors[i].key);
- std::string pt = QuicTextUtils::HexDecode(test_vectors[i].pt);
- std::string iv = QuicTextUtils::HexDecode(test_vectors[i].iv);
- std::string fixed = QuicTextUtils::HexDecode(test_vectors[i].fixed);
- std::string aad = QuicTextUtils::HexDecode(test_vectors[i].aad);
- std::string ct = QuicTextUtils::HexDecode(test_vectors[i].ct);
+ std::string key = quiche::QuicheTextUtils::HexDecode(test_vectors[i].key);
+ std::string pt = quiche::QuicheTextUtils::HexDecode(test_vectors[i].pt);
+ std::string iv = quiche::QuicheTextUtils::HexDecode(test_vectors[i].iv);
+ std::string fixed =
+ quiche::QuicheTextUtils::HexDecode(test_vectors[i].fixed);
+ std::string aad = quiche::QuicheTextUtils::HexDecode(test_vectors[i].aad);
+ std::string ct = quiche::QuicheTextUtils::HexDecode(test_vectors[i].ct);
ChaCha20Poly1305TlsEncrypter encrypter;
ASSERT_TRUE(encrypter.SetKey(key));
@@ -127,15 +130,16 @@ TEST_F(ChaCha20Poly1305TlsEncrypterTest, Encrypt) {
&encrypter, fixed + iv,
// This deliberately tests that the encrypter can handle an AAD that
// is set to nullptr, as opposed to a zero-length, non-nullptr pointer.
- QuicStringPiece(aad.length() ? aad.data() : nullptr, aad.length()),
+ quiche::QuicheStringPiece(aad.length() ? aad.data() : nullptr,
+ aad.length()),
pt));
ASSERT_TRUE(encrypted.get());
EXPECT_EQ(16u, ct.size() - pt.size());
EXPECT_EQ(16u, encrypted->length() - pt.size());
- test::CompareCharArraysWithHexError("ciphertext", encrypted->data(),
- encrypted->length(), ct.data(),
- ct.length());
+ quiche::test::CompareCharArraysWithHexError("ciphertext", encrypted->data(),
+ encrypted->length(), ct.data(),
+ ct.length());
}
}
@@ -155,16 +159,16 @@ TEST_F(ChaCha20Poly1305TlsEncrypterTest, GetCiphertextSize) {
TEST_F(ChaCha20Poly1305TlsEncrypterTest, GenerateHeaderProtectionMask) {
ChaCha20Poly1305TlsEncrypter encrypter;
- std::string key = QuicTextUtils::HexDecode(
+ std::string key = quiche::QuicheTextUtils::HexDecode(
"6a067f432787bd6034dd3f08f07fc9703a27e58c70e2d88d948b7f6489923cc7");
std::string sample =
- QuicTextUtils::HexDecode("1210d91cceb45c716b023f492c29e612");
+ quiche::QuicheTextUtils::HexDecode("1210d91cceb45c716b023f492c29e612");
ASSERT_TRUE(encrypter.SetHeaderProtectionKey(key));
std::string mask = encrypter.GenerateHeaderProtectionMask(sample);
- std::string expected_mask = QuicTextUtils::HexDecode("1cc2cd98dc");
- test::CompareCharArraysWithHexError("header protection mask", mask.data(),
- mask.size(), expected_mask.data(),
- expected_mask.size());
+ std::string expected_mask = quiche::QuicheTextUtils::HexDecode("1cc2cd98dc");
+ quiche::test::CompareCharArraysWithHexError(
+ "header protection mask", mask.data(), mask.size(), expected_mask.data(),
+ expected_mask.size());
}
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_decrypter.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_decrypter.cc
index c67fd89d4ef..bc09b667d5e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_decrypter.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_decrypter.cc
@@ -8,13 +8,15 @@
#include "third_party/boringssl/src/include/openssl/chacha.h"
#include "net/third_party/quiche/src/quic/core/quic_data_reader.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
-bool ChaChaBaseDecrypter::SetHeaderProtectionKey(QuicStringPiece key) {
+bool ChaChaBaseDecrypter::SetHeaderProtectionKey(
+ quiche::QuicheStringPiece key) {
if (key.size() != GetKeySize()) {
QUIC_BUG << "Invalid key size for header protection";
return false;
@@ -25,7 +27,7 @@ bool ChaChaBaseDecrypter::SetHeaderProtectionKey(QuicStringPiece key) {
std::string ChaChaBaseDecrypter::GenerateHeaderProtectionMask(
QuicDataReader* sample_reader) {
- QuicStringPiece sample;
+ quiche::QuicheStringPiece sample;
if (!sample_reader->ReadStringPiece(&sample, 16)) {
return std::string();
}
@@ -34,9 +36,9 @@ std::string ChaChaBaseDecrypter::GenerateHeaderProtectionMask(
QuicDataReader(sample.data(), 4, quiche::HOST_BYTE_ORDER)
.ReadUInt32(&counter);
const uint8_t zeroes[] = {0, 0, 0, 0, 0};
- std::string out(QUIC_ARRAYSIZE(zeroes), 0);
+ std::string out(QUICHE_ARRAYSIZE(zeroes), 0);
CRYPTO_chacha_20(reinterpret_cast<uint8_t*>(const_cast<char*>(out.data())),
- zeroes, QUIC_ARRAYSIZE(zeroes), pne_key_, nonce, counter);
+ zeroes, QUICHE_ARRAYSIZE(zeroes), pne_key_, nonce, counter);
return out;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_decrypter.h b/chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_decrypter.h
index d7ad7419526..24ca820a9ec 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_decrypter.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_decrypter.h
@@ -9,7 +9,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/aead_base_decrypter.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -17,7 +17,7 @@ class QUIC_EXPORT_PRIVATE ChaChaBaseDecrypter : public AeadBaseDecrypter {
public:
using AeadBaseDecrypter::AeadBaseDecrypter;
- bool SetHeaderProtectionKey(QuicStringPiece key) override;
+ bool SetHeaderProtectionKey(quiche::QuicheStringPiece key) override;
std::string GenerateHeaderProtectionMask(
QuicDataReader* sample_reader) override;
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_encrypter.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_encrypter.cc
index 9c465a944c9..7fdc019e70c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_encrypter.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_encrypter.cc
@@ -6,13 +6,15 @@
#include "third_party/boringssl/src/include/openssl/chacha.h"
#include "net/third_party/quiche/src/quic/core/quic_data_reader.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
-bool ChaChaBaseEncrypter::SetHeaderProtectionKey(QuicStringPiece key) {
+bool ChaChaBaseEncrypter::SetHeaderProtectionKey(
+ quiche::QuicheStringPiece key) {
if (key.size() != GetKeySize()) {
QUIC_BUG << "Invalid key size for header protection";
return false;
@@ -22,7 +24,7 @@ bool ChaChaBaseEncrypter::SetHeaderProtectionKey(QuicStringPiece key) {
}
std::string ChaChaBaseEncrypter::GenerateHeaderProtectionMask(
- QuicStringPiece sample) {
+ quiche::QuicheStringPiece sample) {
if (sample.size() != 16) {
return std::string();
}
@@ -31,9 +33,9 @@ std::string ChaChaBaseEncrypter::GenerateHeaderProtectionMask(
QuicDataReader(sample.data(), 4, quiche::HOST_BYTE_ORDER)
.ReadUInt32(&counter);
const uint8_t zeroes[] = {0, 0, 0, 0, 0};
- std::string out(QUIC_ARRAYSIZE(zeroes), 0);
+ std::string out(QUICHE_ARRAYSIZE(zeroes), 0);
CRYPTO_chacha_20(reinterpret_cast<uint8_t*>(const_cast<char*>(out.data())),
- zeroes, QUIC_ARRAYSIZE(zeroes), pne_key_, nonce, counter);
+ zeroes, QUICHE_ARRAYSIZE(zeroes), pne_key_, nonce, counter);
return out;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_encrypter.h b/chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_encrypter.h
index 7c086acf81f..16d1df1020b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_encrypter.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_encrypter.h
@@ -9,7 +9,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/aead_base_encrypter.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -17,8 +17,9 @@ class QUIC_EXPORT_PRIVATE ChaChaBaseEncrypter : public AeadBaseEncrypter {
public:
using AeadBaseEncrypter::AeadBaseEncrypter;
- bool SetHeaderProtectionKey(QuicStringPiece key) override;
- std::string GenerateHeaderProtectionMask(QuicStringPiece sample) override;
+ bool SetHeaderProtectionKey(quiche::QuicheStringPiece key) override;
+ std::string GenerateHeaderProtectionMask(
+ quiche::QuicheStringPiece sample) override;
private:
// The key used for packet number encryption.
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/channel_id.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/channel_id.cc
index 0c4a3e94e8d..facd552772b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/channel_id.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/channel_id.cc
@@ -11,6 +11,7 @@
#include "third_party/boringssl/src/include/openssl/ecdsa.h"
#include "third_party/boringssl/src/include/openssl/nid.h"
#include "third_party/boringssl/src/include/openssl/sha.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -20,16 +21,16 @@ const char ChannelIDVerifier::kContextStr[] = "QUIC ChannelID";
const char ChannelIDVerifier::kClientToServerStr[] = "client -> server";
// static
-bool ChannelIDVerifier::Verify(QuicStringPiece key,
- QuicStringPiece signed_data,
- QuicStringPiece signature) {
+bool ChannelIDVerifier::Verify(quiche::QuicheStringPiece key,
+ quiche::QuicheStringPiece signed_data,
+ quiche::QuicheStringPiece signature) {
return VerifyRaw(key, signed_data, signature, true);
}
// static
-bool ChannelIDVerifier::VerifyRaw(QuicStringPiece key,
- QuicStringPiece signed_data,
- QuicStringPiece signature,
+bool ChannelIDVerifier::VerifyRaw(quiche::QuicheStringPiece key,
+ quiche::QuicheStringPiece signed_data,
+ quiche::QuicheStringPiece signature,
bool is_channel_id_signature) {
if (key.size() != 32 * 2 || signature.size() != 32 * 2) {
return false;
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/channel_id.h b/chromium/net/third_party/quiche/src/quic/core/crypto/channel_id.h
index 8719394ce47..c04aac33c06 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/channel_id.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/channel_id.h
@@ -10,7 +10,7 @@
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -30,17 +30,17 @@ class QUIC_EXPORT_PRIVATE ChannelIDVerifier {
// Verify returns true iff |signature| is a valid signature of |signed_data|
// by |key|.
- static bool Verify(QuicStringPiece key,
- QuicStringPiece signed_data,
- QuicStringPiece signature);
+ static bool Verify(quiche::QuicheStringPiece key,
+ quiche::QuicheStringPiece signed_data,
+ quiche::QuicheStringPiece signature);
// FOR TESTING ONLY: VerifyRaw returns true iff |signature| is a valid
// signature of |signed_data| by |key|. |is_channel_id_signature| indicates
// whether |signature| is a ChannelID signature (with kContextStr prepended
// to the data to be signed).
- static bool VerifyRaw(QuicStringPiece key,
- QuicStringPiece signed_data,
- QuicStringPiece signature,
+ static bool VerifyRaw(quiche::QuicheStringPiece key,
+ quiche::QuicheStringPiece signed_data,
+ quiche::QuicheStringPiece signature,
bool is_channel_id_signature);
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/channel_id_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/channel_id_test.cc
index c69e3289be4..d4a14cd88a4 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/channel_id_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/channel_id_test.cc
@@ -9,6 +9,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
@@ -277,8 +278,9 @@ TEST_F(ChannelIDTest, VerifyKnownAnswerTest) {
EXPECT_EQ(
test_vector[i].result,
ChannelIDVerifier::VerifyRaw(
- QuicStringPiece(key, sizeof(key)), QuicStringPiece(msg, msg_len),
- QuicStringPiece(signature, sizeof(signature)), false));
+ quiche::QuicheStringPiece(key, sizeof(key)),
+ quiche::QuicheStringPiece(msg, msg_len),
+ quiche::QuicheStringPiece(signature, sizeof(signature)), false));
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/common_cert_set.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/common_cert_set.cc
index 2f337f4bf95..0ccbf2d3d0c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/common_cert_set.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/common_cert_set.cc
@@ -7,7 +7,8 @@
#include <cstddef>
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -55,7 +56,7 @@ const uint64_t kSetHashes[] = {
// Compare returns a value less than, equal to or greater than zero if |a| is
// lexicographically less than, equal to or greater than |b|, respectively.
-int Compare(QuicStringPiece a, const unsigned char* b, size_t b_len) {
+int Compare(quiche::QuicheStringPiece a, const unsigned char* b, size_t b_len) {
size_t len = a.size();
if (len > b_len) {
len = b_len;
@@ -78,16 +79,18 @@ int Compare(QuicStringPiece a, const unsigned char* b, size_t b_len) {
class CommonCertSetsQUIC : public CommonCertSets {
public:
// CommonCertSets interface.
- QuicStringPiece GetCommonHashes() const override {
- return QuicStringPiece(reinterpret_cast<const char*>(kSetHashes),
- sizeof(uint64_t) * QUIC_ARRAYSIZE(kSetHashes));
+ quiche::QuicheStringPiece GetCommonHashes() const override {
+ return quiche::QuicheStringPiece(
+ reinterpret_cast<const char*>(kSetHashes),
+ sizeof(uint64_t) * QUICHE_ARRAYSIZE(kSetHashes));
}
- QuicStringPiece GetCert(uint64_t hash, uint32_t index) const override {
- for (size_t i = 0; i < QUIC_ARRAYSIZE(kSets); i++) {
+ quiche::QuicheStringPiece GetCert(uint64_t hash,
+ uint32_t index) const override {
+ for (size_t i = 0; i < QUICHE_ARRAYSIZE(kSets); i++) {
if (kSets[i].hash == hash) {
if (index < kSets[i].num_certs) {
- return QuicStringPiece(
+ return quiche::QuicheStringPiece(
reinterpret_cast<const char*>(kSets[i].certs[index]),
kSets[i].lens[index]);
}
@@ -95,11 +98,11 @@ class CommonCertSetsQUIC : public CommonCertSets {
}
}
- return QuicStringPiece();
+ return quiche::QuicheStringPiece();
}
- bool MatchCert(QuicStringPiece cert,
- QuicStringPiece common_set_hashes,
+ bool MatchCert(quiche::QuicheStringPiece cert,
+ quiche::QuicheStringPiece common_set_hashes,
uint64_t* out_hash,
uint32_t* out_index) const override {
if (common_set_hashes.size() % sizeof(uint64_t) != 0) {
@@ -111,7 +114,7 @@ class CommonCertSetsQUIC : public CommonCertSets {
memcpy(&hash, common_set_hashes.data() + i * sizeof(uint64_t),
sizeof(uint64_t));
- for (size_t j = 0; j < QUIC_ARRAYSIZE(kSets); j++) {
+ for (size_t j = 0; j < QUICHE_ARRAYSIZE(kSets); j++) {
if (kSets[j].hash != hash) {
continue;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/common_cert_set.h b/chromium/net/third_party/quiche/src/quic/core/crypto/common_cert_set.h
index 57c0feafc9a..af211ad79ff 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/common_cert_set.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/common_cert_set.h
@@ -9,7 +9,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -22,22 +22,23 @@ class QUIC_EXPORT_PRIVATE CommonCertSets {
// GetInstanceQUIC returns the standard QUIC common certificate sets.
static const CommonCertSets* GetInstanceQUIC();
- // GetCommonHashes returns a QuicStringPiece containing the hashes of common
- // sets supported by this object. The 64-bit hashes are concatenated in the
- // QuicStringPiece.
- virtual QuicStringPiece GetCommonHashes() const = 0;
+ // GetCommonHashes returns a quiche::QuicheStringPiece containing the hashes
+ // of common sets supported by this object. The 64-bit hashes are concatenated
+ // in the quiche::QuicheStringPiece.
+ virtual quiche::QuicheStringPiece GetCommonHashes() const = 0;
// GetCert returns a specific certificate (at index |index|) in the common
// set identified by |hash|. If no such certificate is known, an empty
- // QuicStringPiece is returned.
- virtual QuicStringPiece GetCert(uint64_t hash, uint32_t index) const = 0;
+ // quiche::QuicheStringPiece is returned.
+ virtual quiche::QuicheStringPiece GetCert(uint64_t hash,
+ uint32_t index) const = 0;
// MatchCert tries to find |cert| in one of the common certificate sets
// identified by |common_set_hashes|. On success it puts the hash of the
// set in |out_hash|, the index of |cert| in the set in |out_index| and
// returns true. Otherwise it returns false.
- virtual bool MatchCert(QuicStringPiece cert,
- QuicStringPiece common_set_hashes,
+ virtual bool MatchCert(quiche::QuicheStringPiece cert,
+ quiche::QuicheStringPiece common_set_hashes,
uint64_t* out_hash,
uint32_t* out_index) const = 0;
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/common_cert_set_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/common_cert_set_test.cc
index 04720e1fd62..148914d02e0 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/common_cert_set_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/common_cert_set_test.cc
@@ -7,6 +7,7 @@
#include <cstdint>
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
@@ -192,8 +193,8 @@ static const unsigned char kGIACertificate3[] = {
class CommonCertSetsTest : public QuicTest {};
TEST_F(CommonCertSetsTest, FindGIA_2) {
- QuicStringPiece gia(reinterpret_cast<const char*>(kGIACertificate2),
- sizeof(kGIACertificate2));
+ quiche::QuicheStringPiece gia(reinterpret_cast<const char*>(kGIACertificate2),
+ sizeof(kGIACertificate2));
const CommonCertSets* sets(CommonCertSets::GetInstanceQUIC());
// Common Cert Set 2's hash.
@@ -202,19 +203,20 @@ TEST_F(CommonCertSetsTest, FindGIA_2) {
uint32_t index;
ASSERT_TRUE(sets->MatchCert(
gia,
- QuicStringPiece(reinterpret_cast<const char*>(&in_hash), sizeof(in_hash)),
+ quiche::QuicheStringPiece(reinterpret_cast<const char*>(&in_hash),
+ sizeof(in_hash)),
&hash, &index));
EXPECT_EQ(in_hash, hash);
- QuicStringPiece gia_copy = sets->GetCert(hash, index);
+ quiche::QuicheStringPiece gia_copy = sets->GetCert(hash, index);
EXPECT_FALSE(gia_copy.empty());
ASSERT_EQ(gia.size(), gia_copy.size());
EXPECT_EQ(0, memcmp(gia.data(), gia_copy.data(), gia.size()));
}
TEST_F(CommonCertSetsTest, FindGIA_3) {
- QuicStringPiece gia(reinterpret_cast<const char*>(kGIACertificate3),
- sizeof(kGIACertificate3));
+ quiche::QuicheStringPiece gia(reinterpret_cast<const char*>(kGIACertificate3),
+ sizeof(kGIACertificate3));
const CommonCertSets* sets(CommonCertSets::GetInstanceQUIC());
// Common Cert Set 3's hash.
@@ -223,11 +225,12 @@ TEST_F(CommonCertSetsTest, FindGIA_3) {
uint32_t index;
ASSERT_TRUE(sets->MatchCert(
gia,
- QuicStringPiece(reinterpret_cast<const char*>(&in_hash), sizeof(in_hash)),
+ quiche::QuicheStringPiece(reinterpret_cast<const char*>(&in_hash),
+ sizeof(in_hash)),
&hash, &index));
EXPECT_EQ(in_hash, hash);
- QuicStringPiece gia_copy = sets->GetCert(hash, index);
+ quiche::QuicheStringPiece gia_copy = sets->GetCert(hash, index);
EXPECT_FALSE(gia_copy.empty());
ASSERT_EQ(gia.size(), gia_copy.size());
EXPECT_EQ(0, memcmp(gia.data(), gia_copy.data(), gia.size()));
@@ -235,13 +238,14 @@ TEST_F(CommonCertSetsTest, FindGIA_3) {
TEST_F(CommonCertSetsTest, NonMatch) {
const CommonCertSets* sets(CommonCertSets::GetInstanceQUIC());
- QuicStringPiece not_a_cert("hello");
+ quiche::QuicheStringPiece not_a_cert("hello");
const uint64_t in_hash = UINT64_C(0xc9fef74053f99f39);
uint64_t hash;
uint32_t index;
EXPECT_FALSE(sets->MatchCert(
not_a_cert,
- QuicStringPiece(reinterpret_cast<const char*>(&in_hash), sizeof(in_hash)),
+ quiche::QuicheStringPiece(reinterpret_cast<const char*>(&in_hash),
+ sizeof(in_hash)),
&hash, &index));
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_framer.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_framer.cc
index c3dd2aa142b..6a18884f6bd 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_framer.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_framer.cc
@@ -13,9 +13,9 @@
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_fallthrough.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -60,7 +60,7 @@ CryptoFramer::~CryptoFramer() {}
// static
std::unique_ptr<CryptoHandshakeMessage> CryptoFramer::ParseMessage(
- QuicStringPiece in) {
+ quiche::QuicheStringPiece in) {
OneShotVisitor visitor;
CryptoFramer framer;
@@ -81,12 +81,12 @@ const std::string& CryptoFramer::error_detail() const {
return error_detail_;
}
-bool CryptoFramer::ProcessInput(QuicStringPiece input,
+bool CryptoFramer::ProcessInput(quiche::QuicheStringPiece input,
EncryptionLevel /*level*/) {
return ProcessInput(input);
}
-bool CryptoFramer::ProcessInput(QuicStringPiece input) {
+bool CryptoFramer::ProcessInput(quiche::QuicheStringPiece input) {
DCHECK_EQ(QUIC_NO_ERROR, error_);
if (error_ != QUIC_NO_ERROR) {
return false;
@@ -121,7 +121,7 @@ void CryptoFramer::ForceHandshake() {
QuicDataReader reader(buffer_.data(), buffer_.length(),
quiche::HOST_BYTE_ORDER);
for (const std::pair<QuicTag, size_t>& item : tags_and_lengths_) {
- QuicStringPiece value;
+ quiche::QuicheStringPiece value;
if (reader.BytesRemaining() < item.second) {
break;
}
@@ -243,7 +243,7 @@ void CryptoFramer::Clear() {
state_ = STATE_READING_TAG;
}
-QuicErrorCode CryptoFramer::Process(QuicStringPiece input) {
+QuicErrorCode CryptoFramer::Process(quiche::QuicheStringPiece input) {
// Add this data to the buffer.
buffer_.append(input.data(), input.length());
QuicDataReader reader(buffer_.data(), buffer_.length(),
@@ -265,7 +265,7 @@ QuicErrorCode CryptoFramer::Process(QuicStringPiece input) {
}
reader.ReadUInt16(&num_entries_);
if (num_entries_ > kMaxEntries) {
- error_detail_ = QuicStrCat(num_entries_, " entries");
+ error_detail_ = quiche::QuicheStrCat(num_entries_, " entries");
return QUIC_CRYPTO_TOO_MANY_ENTRIES;
}
uint16_t padding;
@@ -287,10 +287,10 @@ QuicErrorCode CryptoFramer::Process(QuicStringPiece input) {
reader.ReadTag(&tag);
if (i > 0 && tag <= tags_and_lengths_[i - 1].first) {
if (tag == tags_and_lengths_[i - 1].first) {
- error_detail_ = QuicStrCat("Duplicate tag:", tag);
+ error_detail_ = quiche::QuicheStrCat("Duplicate tag:", tag);
return QUIC_CRYPTO_DUPLICATE_TAG;
}
- error_detail_ = QuicStrCat("Tag ", tag, " out of order");
+ error_detail_ = quiche::QuicheStrCat("Tag ", tag, " out of order");
return QUIC_CRYPTO_TAGS_OUT_OF_ORDER;
}
@@ -298,8 +298,8 @@ QuicErrorCode CryptoFramer::Process(QuicStringPiece input) {
reader.ReadUInt32(&end_offset);
if (end_offset < last_end_offset) {
- error_detail_ =
- QuicStrCat("End offset: ", end_offset, " vs ", last_end_offset);
+ error_detail_ = quiche::QuicheStrCat("End offset: ", end_offset,
+ " vs ", last_end_offset);
return QUIC_CRYPTO_TAGS_OUT_OF_ORDER;
}
tags_and_lengths_.push_back(std::make_pair(
@@ -319,7 +319,7 @@ QuicErrorCode CryptoFramer::Process(QuicStringPiece input) {
<< values_len_ - reader.BytesRemaining() << " bytes.";
}
for (const std::pair<QuicTag, size_t>& item : tags_and_lengths_) {
- QuicStringPiece value;
+ quiche::QuicheStringPiece value;
if (!reader.ReadStringPiece(&value, item.second)) {
DCHECK(process_truncated_messages_);
// Store an empty value.
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_framer.h b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_framer.h
index 5dcc81a87fe..8dc0d96eba1 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_framer.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_framer.h
@@ -15,7 +15,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_message_parser.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -42,11 +42,11 @@ class QUIC_EXPORT_PRIVATE CryptoFramer : public CryptoMessageParser {
~CryptoFramer() override;
- // ParseMessage parses exactly one message from the given QuicStringPiece. If
- // there is an error, the message is truncated, or the message has trailing
- // garbage then nullptr will be returned.
+ // ParseMessage parses exactly one message from the given
+ // quiche::QuicheStringPiece. If there is an error, the message is truncated,
+ // or the message has trailing garbage then nullptr will be returned.
static std::unique_ptr<CryptoHandshakeMessage> ParseMessage(
- QuicStringPiece in);
+ quiche::QuicheStringPiece in);
// Set callbacks to be called from the framer. A visitor must be set, or
// else the framer will crash. It is acceptable for the visitor to do
@@ -63,8 +63,9 @@ class QUIC_EXPORT_PRIVATE CryptoFramer : public CryptoMessageParser {
// false if there was an error, and true otherwise. ProcessInput optionally
// takes an EncryptionLevel, but it is ignored. The variant with the
// EncryptionLevel is provided to match the CryptoMessageParser interface.
- bool ProcessInput(QuicStringPiece input, EncryptionLevel level) override;
- bool ProcessInput(QuicStringPiece input);
+ bool ProcessInput(quiche::QuicheStringPiece input,
+ EncryptionLevel level) override;
+ bool ProcessInput(quiche::QuicheStringPiece input);
// Returns the number of bytes of buffered input data remaining to be
// parsed.
@@ -95,7 +96,7 @@ class QUIC_EXPORT_PRIVATE CryptoFramer : public CryptoMessageParser {
// Process does does the work of |ProcessInput|, but returns an error code,
// doesn't set error_ and doesn't call |visitor_->OnError()|.
- QuicErrorCode Process(QuicStringPiece input);
+ QuicErrorCode Process(quiche::QuicheStringPiece input);
static bool WritePadTag(QuicDataWriter* writer,
size_t pad_length,
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_framer_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_framer_test.cc
index 4ca98a55b3f..d598c4956d1 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_framer_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_framer_test.cc
@@ -11,11 +11,13 @@
#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/test_tools/quiche_test_utils.h"
namespace quic {
namespace test {
@@ -81,9 +83,9 @@ TEST(CryptoFramerTest, ConstructHandshakeMessage) {
CryptoFramer framer;
std::unique_ptr<QuicData> data = framer.ConstructHandshakeMessage(message);
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet),
- QUIC_ARRAYSIZE(packet));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(packet),
+ QUICHE_ARRAYSIZE(packet));
}
TEST(CryptoFramerTest, ConstructHandshakeMessageWithTwoKeys) {
@@ -117,9 +119,9 @@ TEST(CryptoFramerTest, ConstructHandshakeMessageWithTwoKeys) {
std::unique_ptr<QuicData> data = framer.ConstructHandshakeMessage(message);
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet),
- QUIC_ARRAYSIZE(packet));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(packet),
+ QUICHE_ARRAYSIZE(packet));
}
TEST(CryptoFramerTest, ConstructHandshakeMessageZeroLength) {
@@ -144,9 +146,9 @@ TEST(CryptoFramerTest, ConstructHandshakeMessageZeroLength) {
std::unique_ptr<QuicData> data = framer.ConstructHandshakeMessage(message);
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet),
- QUIC_ARRAYSIZE(packet));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(packet),
+ QUICHE_ARRAYSIZE(packet));
}
TEST(CryptoFramerTest, ConstructHandshakeMessageTooManyEntries) {
@@ -194,9 +196,9 @@ TEST(CryptoFramerTest, ConstructHandshakeMessageMinimumSize) {
std::unique_ptr<QuicData> data = framer.ConstructHandshakeMessage(message);
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet),
- QUIC_ARRAYSIZE(packet));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(packet),
+ QUICHE_ARRAYSIZE(packet));
}
TEST(CryptoFramerTest, ConstructHandshakeMessageMinimumSizePadLast) {
@@ -230,9 +232,9 @@ TEST(CryptoFramerTest, ConstructHandshakeMessageMinimumSizePadLast) {
std::unique_ptr<QuicData> data = framer.ConstructHandshakeMessage(message);
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet),
- QUIC_ARRAYSIZE(packet));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(packet),
+ QUICHE_ARRAYSIZE(packet));
}
TEST(CryptoFramerTest, ProcessInput) {
@@ -262,7 +264,7 @@ TEST(CryptoFramerTest, ProcessInput) {
};
EXPECT_TRUE(framer.ProcessInput(
- QuicStringPiece(AsChars(input), QUIC_ARRAYSIZE(input))));
+ quiche::QuicheStringPiece(AsChars(input), QUICHE_ARRAYSIZE(input))));
EXPECT_EQ(0u, framer.InputBytesRemaining());
EXPECT_EQ(0, visitor.error_count_);
ASSERT_EQ(1u, visitor.messages_.size());
@@ -306,7 +308,7 @@ TEST(CryptoFramerTest, ProcessInputWithThreeKeys) {
};
EXPECT_TRUE(framer.ProcessInput(
- QuicStringPiece(AsChars(input), QUIC_ARRAYSIZE(input))));
+ quiche::QuicheStringPiece(AsChars(input), QUICHE_ARRAYSIZE(input))));
EXPECT_EQ(0u, framer.InputBytesRemaining());
EXPECT_EQ(0, visitor.error_count_);
ASSERT_EQ(1u, visitor.messages_.size());
@@ -344,8 +346,9 @@ TEST(CryptoFramerTest, ProcessInputIncrementally) {
'g', 'h', 'i', 'j', 'k',
};
- for (size_t i = 0; i < QUIC_ARRAYSIZE(input); i++) {
- EXPECT_TRUE(framer.ProcessInput(QuicStringPiece(AsChars(input) + i, 1)));
+ for (size_t i = 0; i < QUICHE_ARRAYSIZE(input); i++) {
+ EXPECT_TRUE(
+ framer.ProcessInput(quiche::QuicheStringPiece(AsChars(input) + i, 1)));
}
EXPECT_EQ(0u, framer.InputBytesRemaining());
ASSERT_EQ(1u, visitor.messages_.size());
@@ -379,8 +382,8 @@ TEST(CryptoFramerTest, ProcessInputTagsOutOfOrder) {
};
EXPECT_FALSE(framer.ProcessInput(
- QuicStringPiece(AsChars(input), QUIC_ARRAYSIZE(input))));
- EXPECT_EQ(QUIC_CRYPTO_TAGS_OUT_OF_ORDER, framer.error());
+ quiche::QuicheStringPiece(AsChars(input), QUICHE_ARRAYSIZE(input))));
+ EXPECT_THAT(framer.error(), IsError(QUIC_CRYPTO_TAGS_OUT_OF_ORDER));
EXPECT_EQ(1, visitor.error_count_);
}
@@ -407,8 +410,8 @@ TEST(CryptoFramerTest, ProcessEndOffsetsOutOfOrder) {
};
EXPECT_FALSE(framer.ProcessInput(
- QuicStringPiece(AsChars(input), QUIC_ARRAYSIZE(input))));
- EXPECT_EQ(QUIC_CRYPTO_TAGS_OUT_OF_ORDER, framer.error());
+ quiche::QuicheStringPiece(AsChars(input), QUICHE_ARRAYSIZE(input))));
+ EXPECT_THAT(framer.error(), IsError(QUIC_CRYPTO_TAGS_OUT_OF_ORDER));
EXPECT_EQ(1, visitor.error_count_);
}
@@ -427,8 +430,8 @@ TEST(CryptoFramerTest, ProcessInputTooManyEntries) {
};
EXPECT_FALSE(framer.ProcessInput(
- QuicStringPiece(AsChars(input), QUIC_ARRAYSIZE(input))));
- EXPECT_EQ(QUIC_CRYPTO_TOO_MANY_ENTRIES, framer.error());
+ quiche::QuicheStringPiece(AsChars(input), QUICHE_ARRAYSIZE(input))));
+ EXPECT_THAT(framer.error(), IsError(QUIC_CRYPTO_TOO_MANY_ENTRIES));
EXPECT_EQ(1, visitor.error_count_);
}
@@ -455,7 +458,7 @@ TEST(CryptoFramerTest, ProcessInputZeroLength) {
};
EXPECT_TRUE(framer.ProcessInput(
- QuicStringPiece(AsChars(input), QUIC_ARRAYSIZE(input))));
+ quiche::QuicheStringPiece(AsChars(input), QUICHE_ARRAYSIZE(input))));
EXPECT_EQ(0, visitor.error_count_);
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.cc
index 56f0bd62a1f..d5b4635d1d4 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.cc
@@ -13,9 +13,10 @@
#include "net/third_party/quiche/src/quic/core/quic_socket_address_coder.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
@@ -85,7 +86,7 @@ void CryptoHandshakeMessage::SetVersion(QuicTag tag,
}
void CryptoHandshakeMessage::SetStringPiece(QuicTag tag,
- QuicStringPiece value) {
+ quiche::QuicheStringPiece value) {
tag_value_map_[tag] = std::string(value);
}
@@ -147,8 +148,9 @@ QuicErrorCode CryptoHandshakeMessage::GetVersionLabel(
return QUIC_NO_ERROR;
}
-bool CryptoHandshakeMessage::GetStringPiece(QuicTag tag,
- QuicStringPiece* out) const {
+bool CryptoHandshakeMessage::GetStringPiece(
+ QuicTag tag,
+ quiche::QuicheStringPiece* out) const {
auto it = tag_value_map_.find(tag);
if (it == tag_value_map_.end()) {
return false;
@@ -164,8 +166,8 @@ bool CryptoHandshakeMessage::HasStringPiece(QuicTag tag) const {
QuicErrorCode CryptoHandshakeMessage::GetNthValue24(
QuicTag tag,
unsigned index,
- QuicStringPiece* out) const {
- QuicStringPiece value;
+ quiche::QuicheStringPiece* out) const {
+ quiche::QuicheStringPiece value;
if (!GetStringPiece(tag, &value)) {
return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
}
@@ -190,7 +192,7 @@ QuicErrorCode CryptoHandshakeMessage::GetNthValue24(
}
if (i == index) {
- *out = QuicStringPiece(value.data(), size);
+ *out = quiche::QuicheStringPiece(value.data(), size);
return QUIC_NO_ERROR;
}
@@ -284,7 +286,7 @@ std::string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const {
if (it->second.size() == 4) {
uint32_t value;
memcpy(&value, it->second.data(), sizeof(value));
- ret += QuicTextUtils::Uint64ToString(value);
+ ret += quiche::QuicheTextUtils::Uint64ToString(value);
done = true;
}
break;
@@ -345,8 +347,8 @@ std::string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const {
}
break;
case kPAD:
- ret += QuicStringPrintf("(%d bytes of padding)",
- static_cast<int>(it->second.size()));
+ ret += quiche::QuicheStringPrintf("(%d bytes of padding)",
+ static_cast<int>(it->second.size()));
done = true;
break;
case kSNI:
@@ -359,7 +361,7 @@ std::string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const {
if (!done) {
// If there's no specific format for this tag, or the value is invalid,
// then just use hex.
- ret += "0x" + QuicTextUtils::HexEncode(it->second);
+ ret += "0x" + quiche::QuicheTextUtils::HexEncode(it->second);
}
ret += "\n";
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h
index 6819e3655ce..409738a1f81 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h
@@ -13,8 +13,8 @@
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_uint128.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -75,7 +75,7 @@ class QUIC_EXPORT_PRIVATE CryptoHandshakeMessage {
const QuicTagValueMap& tag_value_map() const { return tag_value_map_; }
- void SetStringPiece(QuicTag tag, QuicStringPiece value);
+ void SetStringPiece(QuicTag tag, quiche::QuicheStringPiece value);
// Erase removes a tag/value, if present, from the message.
void Erase(QuicTag tag);
@@ -96,7 +96,7 @@ class QUIC_EXPORT_PRIVATE CryptoHandshakeMessage {
// Otherwise it populates |out| with the label and returns QUIC_NO_ERROR.
QuicErrorCode GetVersionLabel(QuicTag tag, QuicVersionLabel* out) const;
- bool GetStringPiece(QuicTag tag, QuicStringPiece* out) const;
+ bool GetStringPiece(QuicTag tag, quiche::QuicheStringPiece* out) const;
bool HasStringPiece(QuicTag tag) const;
// GetNthValue24 interprets the value with the given tag to be a series of
@@ -104,7 +104,7 @@ class QUIC_EXPORT_PRIVATE CryptoHandshakeMessage {
// index.
QuicErrorCode GetNthValue24(QuicTag tag,
unsigned index,
- QuicStringPiece* out) const;
+ quiche::QuicheStringPiece* out) const;
QuicErrorCode GetUint32(QuicTag tag, uint32_t* out) const;
QuicErrorCode GetUint64(QuicTag tag, uint64_t* out) const;
QuicErrorCode GetUint128(QuicTag tag, QuicUint128* out) const;
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_message_parser.h b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_message_parser.h
index 2638a196d37..80386646368 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_message_parser.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_message_parser.h
@@ -9,7 +9,7 @@
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -23,7 +23,8 @@ class QUIC_EXPORT_PRIVATE CryptoMessageParser {
// Processes input data, which must be delivered in order. The input data
// being processed was received at encryption level |level|. Returns
// false if there was an error, and true otherwise.
- virtual bool ProcessInput(QuicStringPiece input, EncryptionLevel level) = 0;
+ virtual bool ProcessInput(quiche::QuicheStringPiece input,
+ EncryptionLevel level) = 0;
// Returns the number of bytes of buffered input data remaining to be
// parsed.
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_message_printer_bin.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_message_printer_bin.cc
index 67cd531dd72..f5584adad55 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_message_printer_bin.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_message_printer_bin.cc
@@ -12,7 +12,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/crypto_framer.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
using std::cerr;
using std::cout;
@@ -47,7 +47,7 @@ int main(int argc, char* argv[]) {
quic::CryptoFramer framer;
framer.set_visitor(&printer);
framer.set_process_truncated_messages(true);
- std::string input = quic::QuicTextUtils::HexDecode(messages[0]);
+ std::string input = quiche::QuicheTextUtils::HexDecode(messages[0]);
if (!framer.ProcessInput(input)) {
return 1;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h
index 9707fb5b0ca..8af8a0429d1 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h
@@ -82,16 +82,13 @@ const QuicTag kTBBR = TAG('T', 'B', 'B', 'R'); // Reduced Buffer Bloat TCP
const QuicTag k1RTT = TAG('1', 'R', 'T', 'T'); // STARTUP in BBR for 1 RTT
const QuicTag k2RTT = TAG('2', 'R', 'T', 'T'); // STARTUP in BBR for 2 RTTs
const QuicTag kLRTT = TAG('L', 'R', 'T', 'T'); // Exit STARTUP in BBR on loss
-const QuicTag kBBS1 = TAG('B', 'B', 'S', '1'); // Rate-based recovery in
- // BBR STARTUP
+const QuicTag kBBS1 = TAG('B', 'B', 'S', '1'); // DEPRECATED
const QuicTag kBBS2 = TAG('B', 'B', 'S', '2'); // More aggressive packet
// conservation in BBR STARTUP
const QuicTag kBBS3 = TAG('B', 'B', 'S', '3'); // Slowstart packet
// conservation in BBR STARTUP
-const QuicTag kBBS4 = TAG('B', 'B', 'S', '4'); // Reduce rate in STARTUP by
- // bytes_lost / CWND.
-const QuicTag kBBS5 = TAG('B', 'B', 'S', '5'); // Reduce rate in STARTUP by
- // 2 * bytes_lost / CWND.
+const QuicTag kBBS4 = TAG('B', 'B', 'S', '4'); // DEPRECATED
+const QuicTag kBBS5 = TAG('B', 'B', 'S', '5'); // DEPRECATED
const QuicTag kBBRR = TAG('B', 'B', 'R', 'R'); // Rate-based recovery in BBR
const QuicTag kBBR1 = TAG('B', 'B', 'R', '1'); // DEPRECATED
const QuicTag kBBR2 = TAG('B', 'B', 'R', '2'); // DEPRECATED
@@ -99,15 +96,9 @@ const QuicTag kBBR3 = TAG('B', 'B', 'R', '3'); // Fully drain the queue once
// per cycle
const QuicTag kBBR4 = TAG('B', 'B', 'R', '4'); // 20 RTT ack aggregation
const QuicTag kBBR5 = TAG('B', 'B', 'R', '5'); // 40 RTT ack aggregation
-const QuicTag kBBR6 = TAG('B', 'B', 'R', '6'); // PROBE_RTT with 0.75 * BDP
-const QuicTag kBBR7 = TAG('B', 'B', 'R', '7'); // Skip PROBE_RTT if rtt has
- // not changed 12.5%
-const QuicTag kBBR8 = TAG('B', 'B', 'R', '8'); // Disable PROBE_RTT when
- // recently app-limited
const QuicTag kBBR9 = TAG('B', 'B', 'R', '9'); // Ignore app-limited calls in
// BBR if enough inflight.
-const QuicTag kBBRS = TAG('B', 'B', 'R', 'S'); // Use 1.5x pacing in startup
- // after a loss has occurred.
+const QuicTag kBBRS = TAG('B', 'B', 'R', 'S'); // DEPRECATED
const QuicTag kBBQ1 = TAG('B', 'B', 'Q', '1'); // BBR with lower 2.77 STARTUP
// pacing and CWND gain.
const QuicTag kBBQ2 = TAG('B', 'B', 'Q', '2'); // BBR with lower 2.0 STARTUP
@@ -126,6 +117,13 @@ const QuicTag kIW10 = TAG('I', 'W', '1', '0'); // Force ICWND to 10
const QuicTag kIW20 = TAG('I', 'W', '2', '0'); // Force ICWND to 20
const QuicTag kIW50 = TAG('I', 'W', '5', '0'); // Force ICWND to 50
const QuicTag kB2ON = TAG('B', '2', 'O', 'N'); // Enable BBRv2
+const QuicTag kB2NA = TAG('B', '2', 'N', 'A'); // For BBRv2, do not add ack
+ // height to queueing threshold
+const QuicTag kB2RP = TAG('B', '2', 'R', 'P'); // For BBRv2, run PROBE_RTT on
+ // the regular schedule
+const QuicTag kBSAO = TAG('B', 'S', 'A', 'O'); // Avoid Overestimation in
+ // Bandwidth Sampler with ack
+ // aggregation
const QuicTag kNTLP = TAG('N', 'T', 'L', 'P'); // No tail loss probe
const QuicTag k1TLP = TAG('1', 'T', 'L', 'P'); // 1 tail loss probe
const QuicTag k1RTO = TAG('1', 'R', 'T', 'O'); // Send 1 packet upon RTO
@@ -143,6 +141,7 @@ const QuicTag kMAD2 = TAG('M', 'A', 'D', '2'); // No min TLP
const QuicTag kMAD3 = TAG('M', 'A', 'D', '3'); // No min RTO
const QuicTag kMAD4 = TAG('M', 'A', 'D', '4'); // IETF style TLP
const QuicTag kMAD5 = TAG('M', 'A', 'D', '5'); // IETF style TLP with 2x mult
+const QuicTag k1ACK = TAG('1', 'A', 'C', 'K'); // 1 fast ack for reordering
const QuicTag kACD0 = TAG('A', 'D', 'D', '0'); // Disable ack decimation
const QuicTag kACKD = TAG('A', 'C', 'K', 'D'); // Ack decimation style acking.
const QuicTag kAKD2 = TAG('A', 'K', 'D', '2'); // Ack decimation tolerating
@@ -163,6 +162,8 @@ const QuicTag kCONH = TAG('C', 'O', 'N', 'H'); // Conservative Handshake
const QuicTag kLFAK = TAG('L', 'F', 'A', 'K'); // Don't invoke FACK on the
// first ack.
const QuicTag kSTMP = TAG('S', 'T', 'M', 'P'); // Send and process timestamps
+const QuicTag kEACK = TAG('E', 'A', 'C', 'K'); // Bundle ack-eliciting frame
+ // with an ACK after PTO/RTO
const QuicTag kILD0 = TAG('I', 'L', 'D', '0'); // IETF style loss detection
// (default with 1/8 RTT time
@@ -181,6 +182,8 @@ const QuicTag kILD4 = TAG('I', 'L', 'D', '4'); // IETF style loss detection
// threshold (default 1/4 RTT)
// and adaptive packet
// threshold
+const QuicTag kRUNT = TAG('R', 'U', 'N', 'T'); // No packet threshold loss
+ // detection for "runt" packet.
// TODO(fayang): Remove this connection option when QUIC_VERSION_35, is removed
// Since MAX_HEADER_LIST_SIZE settings frame is supported instead.
const QuicTag kSMHL = TAG('S', 'M', 'H', 'L'); // Support MAX_HEADER_LIST_SIZE
@@ -209,6 +212,19 @@ const QuicTag kPEB2 = TAG('P', 'E', 'B', '2'); // Start exponential backoff
// since 2nd PTO.
const QuicTag kPVS1 = TAG('P', 'V', 'S', '1'); // Use 2 * rttvar when
// calculating PTO timeout.
+const QuicTag kPAG1 = TAG('P', 'A', 'G', '1'); // Make 1st PTO more aggressive
+const QuicTag kPAG2 = TAG('P', 'A', 'G', '2'); // Make first 2 PTOs more
+ // aggressive
+const QuicTag kPSDA = TAG('P', 'S', 'D', 'A'); // Use standard deviation when
+ // calculating PTO timeout.
+const QuicTag kPLE1 = TAG('P', 'L', 'E', '1'); // Arm the 1st PTO with
+ // earliest in flight sent time
+ // and at least 0.5*srtt from
+ // last sent packet.
+const QuicTag kPLE2 = TAG('P', 'L', 'E', '2'); // Arm the 1st PTO with
+ // earliest in flight sent time
+ // and at least 1.5*srtt from
+ // last sent packet.
// Optional support of truncated Connection IDs. If sent by a peer, the value
// is the minimum number of bytes allowed for the connection ID sent to the
@@ -238,6 +254,14 @@ const QuicTag kBWS6 = TAG('B', 'W', 'S', '6'); // QUIC Initial CWND - Enabled
const QuicTag kBWS7 = TAG('B', 'W', 'S', '7'); // QUIC Initial CWND - Enabled
// with 0.75 * default
// multiplier.
+const QuicTag kBWM3 = TAG('B', 'W', 'M', '3'); // Consider overshooting if
+ // bytes lost after bandwidth
+ // resumption * 3 > IW.
+const QuicTag kBWM4 = TAG('B', 'W', 'M', '4'); // Consider overshooting if
+ // bytes lost after bandwidth
+ // resumption * 4 > IW.
+const QuicTag kICW1 = TAG('I', 'C', 'W', '1'); // Max initial congestion window
+ // 100.
// Enable path MTU discovery experiment.
const QuicTag kMTUH = TAG('M', 'T', 'U', 'H'); // High-target MTU discovery.
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer.cc
index c44cbb9d7ed..78cf768dcc6 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer.cc
@@ -11,6 +11,7 @@
#include "third_party/boringssl/src/include/openssl/err.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -67,7 +68,7 @@ void CryptoSecretBoxer::SetKeys(const std::vector<std::string>& keys) {
}
std::string CryptoSecretBoxer::Box(QuicRandom* rand,
- QuicStringPiece plaintext) const {
+ quiche::QuicheStringPiece plaintext) const {
// The box is formatted as:
// 12 bytes of random nonce
// n bytes of ciphertext
@@ -103,9 +104,9 @@ std::string CryptoSecretBoxer::Box(QuicRandom* rand,
return ret;
}
-bool CryptoSecretBoxer::Unbox(QuicStringPiece in_ciphertext,
+bool CryptoSecretBoxer::Unbox(quiche::QuicheStringPiece in_ciphertext,
std::string* out_storage,
- QuicStringPiece* out) const {
+ quiche::QuicheStringPiece* out) const {
if (in_ciphertext.size() < kSIVNonceSize) {
return false;
}
@@ -129,7 +130,7 @@ bool CryptoSecretBoxer::Unbox(QuicStringPiece in_ciphertext,
kSIVNonceSize, ciphertext, ciphertext_len, nullptr,
0)) {
ok = true;
- *out = QuicStringPiece(out_storage->data(), bytes_written);
+ *out = quiche::QuicheStringPiece(out_storage->data(), bytes_written);
break;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer.h b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer.h
index eba7a57baea..dc4e0b14cb8 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer.h
@@ -12,7 +12,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_mutex.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -41,16 +41,16 @@ class QUIC_EXPORT_PRIVATE CryptoSecretBoxer {
// returns the resulting ciphertext. Since an authenticator and nonce are
// included, the result will be slightly larger than |plaintext|. The first
// key in the vector supplied to |SetKeys| will be used.
- std::string Box(QuicRandom* rand, QuicStringPiece plaintext) const;
+ std::string Box(QuicRandom* rand, quiche::QuicheStringPiece plaintext) const;
// Unbox takes the result of a previous call to |Box| in |ciphertext| and
// authenticates+decrypts it. If |ciphertext| cannot be decrypted with any of
// the supplied keys, the function returns false. Otherwise, |out_storage| is
// used to store the result and |out| is set to point into |out_storage| and
// contains the original plaintext.
- bool Unbox(QuicStringPiece ciphertext,
+ bool Unbox(quiche::QuicheStringPiece ciphertext,
std::string* out_storage,
- QuicStringPiece* out) const;
+ quiche::QuicheStringPiece* out) const;
private:
struct State;
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer_test.cc
index 06505d91308..57a5712f07b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer_test.cc
@@ -8,6 +8,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
@@ -15,7 +16,7 @@ namespace test {
class CryptoSecretBoxerTest : public QuicTest {};
TEST_F(CryptoSecretBoxerTest, BoxAndUnbox) {
- QuicStringPiece message("hello world");
+ quiche::QuicheStringPiece message("hello world");
CryptoSecretBoxer boxer;
boxer.SetKeys({std::string(CryptoSecretBoxer::GetKeySize(), 0x11)});
@@ -23,7 +24,7 @@ TEST_F(CryptoSecretBoxerTest, BoxAndUnbox) {
const std::string box = boxer.Box(QuicRandom::GetInstance(), message);
std::string storage;
- QuicStringPiece result;
+ quiche::QuicheStringPiece result;
EXPECT_TRUE(boxer.Unbox(box, &storage, &result));
EXPECT_EQ(result, message);
@@ -39,10 +40,10 @@ TEST_F(CryptoSecretBoxerTest, BoxAndUnbox) {
// Helper function to test whether one boxer can decode the output of another.
static bool CanDecode(const CryptoSecretBoxer& decoder,
const CryptoSecretBoxer& encoder) {
- QuicStringPiece message("hello world");
+ quiche::QuicheStringPiece message("hello world");
const std::string boxed = encoder.Box(QuicRandom::GetInstance(), message);
std::string storage;
- QuicStringPiece result;
+ quiche::QuicheStringPiece result;
bool ok = decoder.Unbox(boxed, &storage, &result);
if (ok) {
EXPECT_EQ(result, message);
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_server_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_server_test.cc
index 2db49d22a42..4cf618b8a6a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_server_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_server_test.cc
@@ -21,18 +21,18 @@
#include "net/third_party/quiche/src/quic/core/proto/crypto_server_config_proto.h"
#include "net/third_party/quiche/src/quic/core/quic_socket_address_coder.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/failing_proof_source.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_random.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_crypto_server_config_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
namespace test {
@@ -127,7 +127,7 @@ class CryptoServerTest : public QuicTestWithParam<TestParams> {
std::unique_ptr<CryptoHandshakeMessage> msg(
config_.AddConfig(primary_config, clock_.WallNow()));
- QuicStringPiece orbit;
+ quiche::QuicheStringPiece orbit;
CHECK(msg->GetStringPiece(kORBT, &orbit));
CHECK_EQ(sizeof(orbit_), orbit.size());
memcpy(orbit_, orbit.data(), orbit.size());
@@ -135,9 +135,9 @@ class CryptoServerTest : public QuicTestWithParam<TestParams> {
char public_value[32];
memset(public_value, 42, sizeof(public_value));
- nonce_hex_ = "#" + QuicTextUtils::HexEncode(GenerateNonce());
- pub_hex_ =
- "#" + QuicTextUtils::HexEncode(public_value, sizeof(public_value));
+ nonce_hex_ = "#" + quiche::QuicheTextUtils::HexEncode(GenerateNonce());
+ pub_hex_ = "#" + quiche::QuicheTextUtils::HexEncode(public_value,
+ sizeof(public_value));
CryptoHandshakeMessage client_hello =
crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
@@ -154,19 +154,19 @@ class CryptoServerTest : public QuicTestWithParam<TestParams> {
CheckRejectTag();
const HandshakeFailureReason kRejectReasons[] = {
SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
- CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
+ CheckRejectReasons(kRejectReasons, QUICHE_ARRAYSIZE(kRejectReasons));
- QuicStringPiece srct;
+ quiche::QuicheStringPiece srct;
ASSERT_TRUE(out_.GetStringPiece(kSourceAddressTokenTag, &srct));
- srct_hex_ = "#" + QuicTextUtils::HexEncode(srct);
+ srct_hex_ = "#" + quiche::QuicheTextUtils::HexEncode(srct);
- QuicStringPiece scfg;
+ quiche::QuicheStringPiece scfg;
ASSERT_TRUE(out_.GetStringPiece(kSCFG, &scfg));
server_config_ = CryptoFramer::ParseMessage(scfg);
- QuicStringPiece scid;
+ quiche::QuicheStringPiece scid;
ASSERT_TRUE(server_config_->GetStringPiece(kSCID, &scid));
- scid_hex_ = "#" + QuicTextUtils::HexEncode(scid);
+ scid_hex_ = "#" + quiche::QuicheTextUtils::HexEncode(scid);
signed_config_ = QuicReferenceCountedPointer<QuicSignedServerConfig>(
new QuicSignedServerConfig());
@@ -211,7 +211,7 @@ class CryptoServerTest : public QuicTestWithParam<TestParams> {
EXPECT_EQ(CreateQuicVersionLabel(supported_versions_[i]), versions[i]);
}
- QuicStringPiece address;
+ quiche::QuicheStringPiece address;
ASSERT_TRUE(server_hello.GetStringPiece(kCADR, &address));
QuicSocketAddressCoder decoder;
ASSERT_TRUE(decoder.Decode(address.data(), address.size()));
@@ -313,7 +313,8 @@ class CryptoServerTest : public QuicTestWithParam<TestParams> {
std::string nonce;
CryptoUtils::GenerateNonce(
clock_.WallNow(), rand_,
- QuicStringPiece(reinterpret_cast<const char*>(orbit_), sizeof(orbit_)),
+ quiche::QuicheStringPiece(reinterpret_cast<const char*>(orbit_),
+ sizeof(orbit_)),
&nonce);
return nonce;
}
@@ -324,7 +325,7 @@ class CryptoServerTest : public QuicTestWithParam<TestParams> {
QuicTagVector reject_reasons;
static_assert(sizeof(QuicTag) == sizeof(uint32_t), "header out of sync");
QuicErrorCode error_code = out_.GetTaglist(kRREJ, &reject_reasons);
- ASSERT_EQ(QUIC_NO_ERROR, error_code);
+ ASSERT_THAT(error_code, IsQuicNoError());
EXPECT_EQ(expected_count, reject_reasons.size());
for (size_t i = 0; i < reject_reasons.size(); ++i) {
@@ -339,8 +340,8 @@ class CryptoServerTest : public QuicTestWithParam<TestParams> {
std::string XlctHexString() {
uint64_t xlct = crypto_test_utils::LeafCertHashForTesting();
- return "#" + QuicTextUtils::HexEncode(reinterpret_cast<char*>(&xlct),
- sizeof(xlct));
+ return "#" + quiche::QuicheTextUtils::HexEncode(
+ reinterpret_cast<char*>(&xlct), sizeof(xlct));
}
protected:
@@ -385,7 +386,7 @@ TEST_P(CryptoServerTest, BadSNI) {
};
// clang-format on
- for (size_t i = 0; i < QUIC_ARRAYSIZE(kBadSNIs); i++) {
+ for (size_t i = 0; i < QUICHE_ARRAYSIZE(kBadSNIs); i++) {
CryptoHandshakeMessage msg =
crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
{"SNI", kBadSNIs[i]},
@@ -394,7 +395,7 @@ TEST_P(CryptoServerTest, BadSNI) {
ShouldFailMentioning("SNI", msg);
const HandshakeFailureReason kRejectReasons[] = {
SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
- CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
+ CheckRejectReasons(kRejectReasons, QUICHE_ARRAYSIZE(kRejectReasons));
}
}
@@ -412,7 +413,7 @@ TEST_P(CryptoServerTest, DefaultCert) {
kClientHelloMinimumSize);
ShouldSucceed(msg);
- QuicStringPiece cert, proof, cert_sct;
+ quiche::QuicheStringPiece cert, proof, cert_sct;
EXPECT_TRUE(out_.GetStringPiece(kCertificateTag, &cert));
EXPECT_TRUE(out_.GetStringPiece(kPROF, &proof));
EXPECT_TRUE(out_.GetStringPiece(kCertificateSCTTag, &cert_sct));
@@ -420,7 +421,7 @@ TEST_P(CryptoServerTest, DefaultCert) {
EXPECT_NE(0u, proof.size());
const HandshakeFailureReason kRejectReasons[] = {
SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
- CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
+ CheckRejectReasons(kRejectReasons, QUICHE_ARRAYSIZE(kRejectReasons));
EXPECT_LT(0u, cert_sct.size());
}
@@ -441,13 +442,13 @@ TEST_P(CryptoServerTest, RejectTooLarge) {
config_.set_chlo_multiplier(1);
ShouldSucceed(msg);
- QuicStringPiece cert, proof, cert_sct;
+ quiche::QuicheStringPiece cert, proof, cert_sct;
EXPECT_FALSE(out_.GetStringPiece(kCertificateTag, &cert));
EXPECT_FALSE(out_.GetStringPiece(kPROF, &proof));
EXPECT_FALSE(out_.GetStringPiece(kCertificateSCTTag, &cert_sct));
const HandshakeFailureReason kRejectReasons[] = {
SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
- CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
+ CheckRejectReasons(kRejectReasons, QUICHE_ARRAYSIZE(kRejectReasons));
}
TEST_P(CryptoServerTest, RejectNotTooLarge) {
@@ -468,13 +469,13 @@ TEST_P(CryptoServerTest, RejectNotTooLarge) {
config_.set_chlo_multiplier(1);
ShouldSucceed(msg);
- QuicStringPiece cert, proof, cert_sct;
+ quiche::QuicheStringPiece cert, proof, cert_sct;
EXPECT_TRUE(out_.GetStringPiece(kCertificateTag, &cert));
EXPECT_TRUE(out_.GetStringPiece(kPROF, &proof));
EXPECT_TRUE(out_.GetStringPiece(kCertificateSCTTag, &cert_sct));
const HandshakeFailureReason kRejectReasons[] = {
SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
- CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
+ CheckRejectReasons(kRejectReasons, QUICHE_ARRAYSIZE(kRejectReasons));
}
TEST_P(CryptoServerTest, RejectTooLargeButValidSTK) {
@@ -495,7 +496,7 @@ TEST_P(CryptoServerTest, RejectTooLargeButValidSTK) {
config_.set_chlo_multiplier(1);
ShouldSucceed(msg);
- QuicStringPiece cert, proof, cert_sct;
+ quiche::QuicheStringPiece cert, proof, cert_sct;
EXPECT_TRUE(out_.GetStringPiece(kCertificateTag, &cert));
EXPECT_TRUE(out_.GetStringPiece(kPROF, &proof));
EXPECT_TRUE(out_.GetStringPiece(kCertificateSCTTag, &cert_sct));
@@ -503,7 +504,7 @@ TEST_P(CryptoServerTest, RejectTooLargeButValidSTK) {
EXPECT_NE(0u, proof.size());
const HandshakeFailureReason kRejectReasons[] = {
SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
- CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
+ CheckRejectReasons(kRejectReasons, QUICHE_ARRAYSIZE(kRejectReasons));
}
TEST_P(CryptoServerTest, TooSmall) {
@@ -513,7 +514,7 @@ TEST_P(CryptoServerTest, TooSmall) {
const HandshakeFailureReason kRejectReasons[] = {
SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
- CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
+ CheckRejectReasons(kRejectReasons, QUICHE_ARRAYSIZE(kRejectReasons));
}
TEST_P(CryptoServerTest, BadSourceAddressToken) {
@@ -527,7 +528,7 @@ TEST_P(CryptoServerTest, BadSourceAddressToken) {
};
// clang-format on
- for (size_t i = 0; i < QUIC_ARRAYSIZE(kBadSourceAddressTokens); i++) {
+ for (size_t i = 0; i < QUICHE_ARRAYSIZE(kBadSourceAddressTokens); i++) {
CryptoHandshakeMessage msg =
crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
{"STK", kBadSourceAddressTokens[i]},
@@ -536,7 +537,7 @@ TEST_P(CryptoServerTest, BadSourceAddressToken) {
ShouldSucceed(msg);
const HandshakeFailureReason kRejectReasons[] = {
SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
- CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
+ CheckRejectReasons(kRejectReasons, QUICHE_ARRAYSIZE(kRejectReasons));
}
}
@@ -549,7 +550,7 @@ TEST_P(CryptoServerTest, BadClientNonce) {
};
// clang-format on
- for (size_t i = 0; i < QUIC_ARRAYSIZE(kBadNonces); i++) {
+ for (size_t i = 0; i < QUICHE_ARRAYSIZE(kBadNonces); i++) {
// Invalid nonces should be ignored, in an inchoate CHLO.
CryptoHandshakeMessage msg =
@@ -561,7 +562,7 @@ TEST_P(CryptoServerTest, BadClientNonce) {
ShouldSucceed(msg);
const HandshakeFailureReason kRejectReasons[] = {
SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
- CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
+ CheckRejectReasons(kRejectReasons, QUICHE_ARRAYSIZE(kRejectReasons));
// Invalid nonces should result in CLIENT_NONCE_INVALID_FAILURE.
CryptoHandshakeMessage msg1 =
@@ -582,7 +583,7 @@ TEST_P(CryptoServerTest, BadClientNonce) {
CheckRejectTag();
const HandshakeFailureReason kRejectReasons1[] = {
CLIENT_NONCE_INVALID_FAILURE};
- CheckRejectReasons(kRejectReasons1, QUIC_ARRAYSIZE(kRejectReasons1));
+ CheckRejectReasons(kRejectReasons1, QUICHE_ARRAYSIZE(kRejectReasons1));
}
}
@@ -596,7 +597,7 @@ TEST_P(CryptoServerTest, NoClientNonce) {
ShouldSucceed(msg);
const HandshakeFailureReason kRejectReasons[] = {
SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
- CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
+ CheckRejectReasons(kRejectReasons, QUICHE_ARRAYSIZE(kRejectReasons));
CryptoHandshakeMessage msg1 =
crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
@@ -613,7 +614,7 @@ TEST_P(CryptoServerTest, NoClientNonce) {
CheckRejectTag();
const HandshakeFailureReason kRejectReasons1[] = {
SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
- CheckRejectReasons(kRejectReasons1, QUIC_ARRAYSIZE(kRejectReasons1));
+ CheckRejectReasons(kRejectReasons1, QUICHE_ARRAYSIZE(kRejectReasons1));
}
TEST_P(CryptoServerTest, DowngradeAttack) {
@@ -632,7 +633,7 @@ TEST_P(CryptoServerTest, DowngradeAttack) {
ShouldFailMentioning("Downgrade", msg);
const HandshakeFailureReason kRejectReasons[] = {
SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
- CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
+ CheckRejectReasons(kRejectReasons, QUICHE_ARRAYSIZE(kRejectReasons));
}
TEST_P(CryptoServerTest, CorruptServerConfig) {
@@ -652,7 +653,7 @@ TEST_P(CryptoServerTest, CorruptServerConfig) {
CheckRejectTag();
const HandshakeFailureReason kRejectReasons[] = {
SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE};
- CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
+ CheckRejectReasons(kRejectReasons, QUICHE_ARRAYSIZE(kRejectReasons));
}
TEST_P(CryptoServerTest, CorruptSourceAddressToken) {
@@ -673,7 +674,7 @@ TEST_P(CryptoServerTest, CorruptSourceAddressToken) {
CheckRejectTag();
const HandshakeFailureReason kRejectReasons[] = {
SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE};
- CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
+ CheckRejectReasons(kRejectReasons, QUICHE_ARRAYSIZE(kRejectReasons));
}
TEST_P(CryptoServerTest, CorruptSourceAddressTokenIsStillAccepted) {
@@ -714,7 +715,7 @@ TEST_P(CryptoServerTest, CorruptClientNonceAndSourceAddressToken) {
CheckRejectTag();
const HandshakeFailureReason kRejectReasons[] = {
SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, CLIENT_NONCE_INVALID_FAILURE};
- CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
+ CheckRejectReasons(kRejectReasons, QUICHE_ARRAYSIZE(kRejectReasons));
}
TEST_P(CryptoServerTest, CorruptMultipleTags) {
@@ -738,7 +739,7 @@ TEST_P(CryptoServerTest, CorruptMultipleTags) {
const HandshakeFailureReason kRejectReasons[] = {
SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, CLIENT_NONCE_INVALID_FAILURE};
- CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
+ CheckRejectReasons(kRejectReasons, QUICHE_ARRAYSIZE(kRejectReasons));
}
TEST_P(CryptoServerTest, NoServerNonce) {
@@ -787,15 +788,15 @@ TEST_P(CryptoServerTest, ProofForSuppliedServerConfig) {
CheckRejectTag();
const HandshakeFailureReason kRejectReasons[] = {
SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE};
- CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
+ CheckRejectReasons(kRejectReasons, QUICHE_ARRAYSIZE(kRejectReasons));
- QuicStringPiece cert, proof, scfg_str;
+ quiche::QuicheStringPiece cert, proof, scfg_str;
EXPECT_TRUE(out_.GetStringPiece(kCertificateTag, &cert));
EXPECT_TRUE(out_.GetStringPiece(kPROF, &proof));
EXPECT_TRUE(out_.GetStringPiece(kSCFG, &scfg_str));
std::unique_ptr<CryptoHandshakeMessage> scfg(
CryptoFramer::ParseMessage(scfg_str));
- QuicStringPiece scid;
+ quiche::QuicheStringPiece scid;
EXPECT_TRUE(scfg->GetStringPiece(kSCID, &scid));
EXPECT_NE(scid, kOldConfigId);
@@ -849,7 +850,7 @@ TEST_P(CryptoServerTest, RejectInvalidXlct) {
const HandshakeFailureReason kRejectReasons[] = {
INVALID_EXPECTED_LEAF_CERTIFICATE};
- CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
+ CheckRejectReasons(kRejectReasons, QUICHE_ARRAYSIZE(kRejectReasons));
}
TEST_P(CryptoServerTest, ValidXlct) {
@@ -895,7 +896,7 @@ TEST_P(CryptoServerTest, NonceInSHLO) {
ShouldSucceed(msg);
EXPECT_EQ(kSHLO, out_.tag());
- QuicStringPiece nonce;
+ quiche::QuicheStringPiece nonce;
EXPECT_TRUE(out_.GetStringPiece(kServerNonceTag, &nonce));
}
@@ -931,7 +932,7 @@ TEST_P(CryptoServerTest, TwoRttServerDropCachedCerts) {
ShouldSucceed(msg);
// Decompress cert chain from server to individual certs.
- QuicStringPiece certs_compressed;
+ quiche::QuicheStringPiece certs_compressed;
ASSERT_TRUE(out_.GetStringPiece(kCertificateTag, &certs_compressed));
ASSERT_NE(0u, certs_compressed.size());
std::vector<std::string> certs;
@@ -951,7 +952,7 @@ TEST_P(CryptoServerTest, TwoRttServerDropCachedCerts) {
ShouldSucceed(msg);
// Server responds with inchoate REJ containing valid source-address token.
- QuicStringPiece srct;
+ quiche::QuicheStringPiece srct;
ASSERT_TRUE(out_.GetStringPiece(kSourceAddressTokenTag, &srct));
// Client now drops cached certs; sends CHLO with updated source-address
@@ -1012,7 +1013,7 @@ TEST_F(CryptoServerConfigGenerationTest, SCIDVaries) {
std::unique_ptr<CryptoHandshakeMessage> scfg_b(
b.AddDefaultConfig(&rand_b, &clock, options));
- QuicStringPiece scid_a, scid_b;
+ quiche::QuicheStringPiece scid_a, scid_b;
EXPECT_TRUE(scfg_a->GetStringPiece(kSCID, &scid_a));
EXPECT_TRUE(scfg_b->GetStringPiece(kSCID, &scid_b));
@@ -1030,7 +1031,7 @@ TEST_F(CryptoServerConfigGenerationTest, SCIDIsHashOfServerConfig) {
std::unique_ptr<CryptoHandshakeMessage> scfg(
a.AddDefaultConfig(&rand_a, &clock, options));
- QuicStringPiece scid;
+ quiche::QuicheStringPiece scid;
EXPECT_TRUE(scfg->GetStringPiece(kSCID, &scid));
// Need to take a copy of |scid| has we're about to call |Erase|.
const std::string scid_str(scid);
@@ -1048,6 +1049,10 @@ TEST_F(CryptoServerConfigGenerationTest, SCIDIsHashOfServerConfig) {
EXPECT_EQ(0, memcmp(digest, scid_str.c_str(), scid.size()));
}
+// Those tests were declared incorrectly and thus never ran in first place.
+// TODO(b/147891553): figure out if we should fix or delete those.
+#if 0
+
class CryptoServerTestNoConfig : public CryptoServerTest {
public:
void SetUp() override {
@@ -1055,6 +1060,11 @@ class CryptoServerTestNoConfig : public CryptoServerTest {
}
};
+INSTANTIATE_TEST_SUITE_P(CryptoServerTestsNoConfig,
+ CryptoServerTestNoConfig,
+ ::testing::ValuesIn(GetTestParams()),
+ ::testing::PrintToStringParamName());
+
TEST_P(CryptoServerTestNoConfig, DontCrash) {
CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO(
{{"PDMD", "X509"}, {"VER\0", client_version_string_}},
@@ -1064,7 +1074,7 @@ TEST_P(CryptoServerTestNoConfig, DontCrash) {
const HandshakeFailureReason kRejectReasons[] = {
SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
- CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
+ CheckRejectReasons(kRejectReasons, QUICHE_ARRAYSIZE(kRejectReasons));
}
class CryptoServerTestOldVersion : public CryptoServerTest {
@@ -1076,6 +1086,11 @@ class CryptoServerTestOldVersion : public CryptoServerTest {
}
};
+INSTANTIATE_TEST_SUITE_P(CryptoServerTestsOldVersion,
+ CryptoServerTestOldVersion,
+ ::testing::ValuesIn(GetTestParams()),
+ ::testing::PrintToStringParamName());
+
TEST_P(CryptoServerTestOldVersion, ServerIgnoresXlct) {
CryptoHandshakeMessage msg =
crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
@@ -1119,5 +1134,7 @@ TEST_P(CryptoServerTestOldVersion, XlctNotRequired) {
EXPECT_EQ(kSHLO, out_.tag());
}
+#endif // 0
+
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.cc
index 037990ae797..b6c6b7ae434 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.cc
@@ -10,6 +10,7 @@
#include "third_party/boringssl/src/include/openssl/bytestring.h"
#include "third_party/boringssl/src/include/openssl/hkdf.h"
+#include "third_party/boringssl/src/include/openssl/mem.h"
#include "third_party/boringssl/src/include/openssl/sha.h"
#include "net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_decrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_encrypter.h"
@@ -23,14 +24,18 @@
#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_hkdf.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
+#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -69,7 +74,7 @@ std::vector<uint8_t> HkdfExpandLabel(const EVP_MD* prf,
!CBB_add_u8_length_prefixed(quic_hkdf_label.get(), &inner_label) ||
!CBB_add_bytes(&inner_label,
reinterpret_cast<const uint8_t*>(label_prefix),
- QUIC_ARRAYSIZE(label_prefix) - 1) ||
+ QUICHE_ARRAYSIZE(label_prefix) - 1) ||
!CBB_add_bytes(&inner_label,
reinterpret_cast<const uint8_t*>(label.data()),
label.size()) ||
@@ -100,33 +105,25 @@ void CryptoUtils::SetKeyAndIV(const EVP_MD* prf,
HkdfExpandLabel(prf, pp_secret, "quic iv", crypter->GetIVSize());
std::vector<uint8_t> pn =
HkdfExpandLabel(prf, pp_secret, "quic hp", crypter->GetKeySize());
- crypter->SetKey(
- QuicStringPiece(reinterpret_cast<char*>(key.data()), key.size()));
+ crypter->SetKey(quiche::QuicheStringPiece(reinterpret_cast<char*>(key.data()),
+ key.size()));
crypter->SetIV(
- QuicStringPiece(reinterpret_cast<char*>(iv.data()), iv.size()));
+ quiche::QuicheStringPiece(reinterpret_cast<char*>(iv.data()), iv.size()));
crypter->SetHeaderProtectionKey(
- QuicStringPiece(reinterpret_cast<char*>(pn.data()), pn.size()));
+ quiche::QuicheStringPiece(reinterpret_cast<char*>(pn.data()), pn.size()));
}
namespace {
-static_assert(kQuicIetfDraftVersion == 24, "Salts do not match draft version");
-// Salt from https://tools.ietf.org/html/draft-ietf-quic-tls-24#section-5.2
-const uint8_t kDraft23InitialSalt[] = {0xc3, 0xee, 0xf7, 0x12, 0xc7, 0x2e, 0xbb,
+// Salt from https://tools.ietf.org/html/draft-ietf-quic-tls-25#section-5.2
+// and https://tools.ietf.org/html/draft-ietf-quic-tls-27#section-5.2
+const uint8_t kDraft25InitialSalt[] = {0xc3, 0xee, 0xf7, 0x12, 0xc7, 0x2e, 0xbb,
0x5a, 0x11, 0xa7, 0xd2, 0x43, 0x2b, 0xb4,
0x63, 0x65, 0xbe, 0xf9, 0xf5, 0x02};
// Salts used by deployed versions of QUIC. When introducing a new version,
// generate a new salt by running `openssl rand -hex 20`.
-// Salt to use for initial obfuscators in version T048.
-const uint8_t kT048Salt[] = {0x1f, 0x89, 0xf6, 0xe7, 0xc2, 0x18, 0xf4,
- 0x2e, 0x6c, 0xe1, 0x9e, 0x91, 0xb2, 0x23,
- 0xbb, 0x4c, 0x47, 0xc9, 0x12, 0xff};
-// Salt to use for initial obfuscators in version T049.
-const uint8_t kT049Salt[] = {0x69, 0xe5, 0x79, 0x2a, 0x41, 0xd0, 0xa2,
- 0x9c, 0xf9, 0xbc, 0x5c, 0x04, 0x5a, 0xeb,
- 0xcf, 0xeb, 0x51, 0xf6, 0x9f, 0x22};
// Salt to use for initial obfuscators in version Q050.
const uint8_t kQ050Salt[] = {0x50, 0x45, 0x74, 0xef, 0xd0, 0x66, 0xfe,
0x2f, 0x9d, 0x94, 0x5c, 0xfc, 0xdb, 0xd3,
@@ -135,51 +132,40 @@ const uint8_t kQ050Salt[] = {0x50, 0x45, 0x74, 0xef, 0xd0, 0x66, 0xfe,
const uint8_t kT050Salt[] = {0x7f, 0xf5, 0x79, 0xe5, 0xac, 0xd0, 0x72,
0x91, 0x55, 0x80, 0x30, 0x4c, 0x43, 0xa2,
0x36, 0x7c, 0x60, 0x48, 0x83, 0x10};
-// Salt to use for initial obfuscators in version Q099.
-const uint8_t kQ099Salt[] = {0xc0, 0xa2, 0xee, 0x20, 0xc7, 0xe1, 0x83,
- 0x74, 0xc8, 0xa1, 0xa0, 0xc8, 0xa5, 0x21,
- 0xb5, 0x31, 0xee, 0x04, 0x7e, 0xc8};
const uint8_t* InitialSaltForVersion(const ParsedQuicVersion& version,
size_t* out_len) {
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
+ static_assert(SupportedVersions().size() == 8u,
"Supported versions out of sync with initial encryption salts");
switch (version.handshake_protocol) {
case PROTOCOL_QUIC_CRYPTO:
switch (version.transport_version) {
case QUIC_VERSION_50:
- *out_len = QUIC_ARRAYSIZE(kQ050Salt);
+ *out_len = QUICHE_ARRAYSIZE(kQ050Salt);
return kQ050Salt;
- case QUIC_VERSION_99:
- *out_len = QUIC_ARRAYSIZE(kQ099Salt);
- return kQ099Salt;
case QUIC_VERSION_RESERVED_FOR_NEGOTIATION:
// It doesn't matter what salt we use for
// QUIC_VERSION_RESERVED_FOR_NEGOTIATION, but some tests try to use a
// QuicFramer with QUIC_VERSION_RESERVED_FOR_NEGOTIATION and will hit
// the following QUIC_BUG if there isn't a case for it. ):
- *out_len = QUIC_ARRAYSIZE(kDraft23InitialSalt);
- return kDraft23InitialSalt;
+ *out_len = QUICHE_ARRAYSIZE(kDraft25InitialSalt);
+ return kDraft25InitialSalt;
default:
QUIC_BUG << "No initial obfuscation salt for version " << version;
}
break;
case PROTOCOL_TLS1_3:
switch (version.transport_version) {
- case QUIC_VERSION_48:
- *out_len = QUIC_ARRAYSIZE(kT048Salt);
- return kT048Salt;
- case QUIC_VERSION_49:
- *out_len = QUIC_ARRAYSIZE(kT049Salt);
- return kT049Salt;
case QUIC_VERSION_50:
- *out_len = QUIC_ARRAYSIZE(kT050Salt);
+ *out_len = QUICHE_ARRAYSIZE(kT050Salt);
return kT050Salt;
- case QUIC_VERSION_99:
- // ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99) uses the IETF
- // salt.
- *out_len = QUIC_ARRAYSIZE(kDraft23InitialSalt);
- return kDraft23InitialSalt;
+ case QUIC_VERSION_IETF_DRAFT_25:
+ *out_len = QUICHE_ARRAYSIZE(kDraft25InitialSalt);
+ return kDraft25InitialSalt;
+ case QUIC_VERSION_IETF_DRAFT_27:
+ // draft-27 uses the same salt as draft-25.
+ *out_len = QUICHE_ARRAYSIZE(kDraft25InitialSalt);
+ return kDraft25InitialSalt;
default:
QUIC_BUG << "No initial obfuscation salt for version " << version;
}
@@ -188,12 +174,63 @@ const uint8_t* InitialSaltForVersion(const ParsedQuicVersion& version,
default:
QUIC_BUG << "No initial obfuscation salt for version " << version;
}
- *out_len = QUIC_ARRAYSIZE(kDraft23InitialSalt);
- return kDraft23InitialSalt;
+ *out_len = QUICHE_ARRAYSIZE(kDraft25InitialSalt);
+ return kDraft25InitialSalt;
}
const char kPreSharedKeyLabel[] = "QUIC PSK";
+// Retry Integrity Protection Keys and Nonces.
+// https://tools.ietf.org/html/draft-ietf-quic-tls-25#section-5.8
+// https://tools.ietf.org/html/draft-ietf-quic-tls-27#section-5.8
+const uint8_t kDraft25RetryIntegrityKey[] = {0x4d, 0x32, 0xec, 0xdb, 0x2a, 0x21,
+ 0x33, 0xc8, 0x41, 0xe4, 0x04, 0x3d,
+ 0xf2, 0x7d, 0x44, 0x30};
+const uint8_t kDraft25RetryIntegrityNonce[] = {
+ 0x4d, 0x16, 0x11, 0xd0, 0x55, 0x13, 0xa5, 0x52, 0xc5, 0x87, 0xd5, 0x75};
+// Keys used by Google versions of QUIC. When introducing a new version,
+// generate a new key by running `openssl rand -hex 16`.
+const uint8_t kT050RetryIntegrityKey[] = {0xc9, 0x2d, 0x32, 0x3d, 0x9c, 0xe3,
+ 0x0d, 0xa0, 0x88, 0xb9, 0xb7, 0xbb,
+ 0xdc, 0xcd, 0x50, 0xc8};
+// Nonces used by Google versions of QUIC. When introducing a new version,
+// generate a new nonce by running `openssl rand -hex 12`.
+const uint8_t kT050RetryIntegrityNonce[] = {0x26, 0xe4, 0xd6, 0x23, 0x83, 0xd5,
+ 0xc7, 0x60, 0xea, 0x02, 0xb4, 0x1f};
+
+bool RetryIntegrityKeysForVersion(const ParsedQuicVersion& version,
+ quiche::QuicheStringPiece* key,
+ quiche::QuicheStringPiece* nonce) {
+ if (!version.HasRetryIntegrityTag()) {
+ QUIC_BUG << "Attempted to get retry integrity keys for invalid version "
+ << version;
+ return false;
+ }
+ if (version == ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_50)) {
+ *key = quiche::QuicheStringPiece(
+ reinterpret_cast<const char*>(kT050RetryIntegrityKey),
+ QUICHE_ARRAYSIZE(kT050RetryIntegrityKey));
+ *nonce = quiche::QuicheStringPiece(
+ reinterpret_cast<const char*>(kT050RetryIntegrityNonce),
+ QUICHE_ARRAYSIZE(kT050RetryIntegrityNonce));
+ return true;
+ }
+ if (version ==
+ ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_DRAFT_25) ||
+ version ==
+ ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_DRAFT_27)) {
+ *key = quiche::QuicheStringPiece(
+ reinterpret_cast<const char*>(kDraft25RetryIntegrityKey),
+ QUICHE_ARRAYSIZE(kDraft25RetryIntegrityKey));
+ *nonce = quiche::QuicheStringPiece(
+ reinterpret_cast<const char*>(kDraft25RetryIntegrityNonce),
+ QUICHE_ARRAYSIZE(kDraft25RetryIntegrityNonce));
+ return true;
+ }
+ QUIC_BUG << "Attempted to get retry integrity keys for version " << version;
+ return false;
+}
+
} // namespace
// static
@@ -252,9 +289,54 @@ void CryptoUtils::CreateInitialObfuscators(Perspective perspective,
}
// static
+bool CryptoUtils::ValidateRetryIntegrityTag(
+ ParsedQuicVersion version,
+ QuicConnectionId original_connection_id,
+ quiche::QuicheStringPiece retry_without_tag,
+ quiche::QuicheStringPiece integrity_tag) {
+ unsigned char computed_integrity_tag[kRetryIntegrityTagLength];
+ if (integrity_tag.length() != QUICHE_ARRAYSIZE(computed_integrity_tag)) {
+ QUIC_BUG << "Invalid retry integrity tag length " << integrity_tag.length();
+ return false;
+ }
+ char retry_pseudo_packet[kMaxIncomingPacketSize + 256];
+ QuicDataWriter writer(QUICHE_ARRAYSIZE(retry_pseudo_packet),
+ retry_pseudo_packet);
+ if (!writer.WriteLengthPrefixedConnectionId(original_connection_id)) {
+ QUIC_BUG << "Failed to write original connection ID in retry pseudo packet";
+ return false;
+ }
+ if (!writer.WriteStringPiece(retry_without_tag)) {
+ QUIC_BUG << "Failed to write retry without tag in retry pseudo packet";
+ return false;
+ }
+ quiche::QuicheStringPiece key;
+ quiche::QuicheStringPiece nonce;
+ if (!RetryIntegrityKeysForVersion(version, &key, &nonce)) {
+ // RetryIntegrityKeysForVersion already logs failures.
+ return false;
+ }
+ Aes128GcmEncrypter crypter;
+ crypter.SetKey(key);
+ quiche::QuicheStringPiece associated_data(writer.data(), writer.length());
+ quiche::QuicheStringPiece plaintext; // Plaintext is empty.
+ if (!crypter.Encrypt(nonce, associated_data, plaintext,
+ computed_integrity_tag)) {
+ QUIC_BUG << "Failed to compute retry integrity tag";
+ return false;
+ }
+ if (CRYPTO_memcmp(computed_integrity_tag, integrity_tag.data(),
+ QUICHE_ARRAYSIZE(computed_integrity_tag)) != 0) {
+ QUIC_DLOG(ERROR) << "Failed to validate retry integrity tag";
+ return false;
+ }
+ return true;
+}
+
+// static
void CryptoUtils::GenerateNonce(QuicWallTime now,
QuicRandom* random_generator,
- QuicStringPiece orbit,
+ quiche::QuicheStringPiece orbit,
std::string* nonce) {
// a 4-byte timestamp + 28 random bytes.
nonce->reserve(kNonceSize);
@@ -280,11 +362,11 @@ void CryptoUtils::GenerateNonce(QuicWallTime now,
// static
bool CryptoUtils::DeriveKeys(const ParsedQuicVersion& version,
- QuicStringPiece premaster_secret,
+ quiche::QuicheStringPiece premaster_secret,
QuicTag aead,
- QuicStringPiece client_nonce,
- QuicStringPiece server_nonce,
- QuicStringPiece pre_shared_key,
+ quiche::QuicheStringPiece client_nonce,
+ quiche::QuicheStringPiece server_nonce,
+ quiche::QuicheStringPiece pre_shared_key,
const std::string& hkdf_input,
Perspective perspective,
Diversification diversification,
@@ -293,7 +375,7 @@ bool CryptoUtils::DeriveKeys(const ParsedQuicVersion& version,
// If the connection is using PSK, concatenate it with the pre-master secret.
std::unique_ptr<char[]> psk_premaster_secret;
if (!pre_shared_key.empty()) {
- const QuicStringPiece label(kPreSharedKeyLabel);
+ const quiche::QuicheStringPiece label(kPreSharedKeyLabel);
const size_t psk_premaster_secret_size = label.size() + 1 +
pre_shared_key.size() + 8 +
premaster_secret.size() + 8;
@@ -311,8 +393,8 @@ bool CryptoUtils::DeriveKeys(const ParsedQuicVersion& version,
return false;
}
- premaster_secret =
- QuicStringPiece(psk_premaster_secret.get(), psk_premaster_secret_size);
+ premaster_secret = quiche::QuicheStringPiece(psk_premaster_secret.get(),
+ psk_premaster_secret_size);
}
crypters->encrypter = QuicEncrypter::Create(version, aead);
@@ -326,7 +408,7 @@ bool CryptoUtils::DeriveKeys(const ParsedQuicVersion& version,
size_t subkey_secret_bytes =
subkey_secret == nullptr ? 0 : premaster_secret.length();
- QuicStringPiece nonce = client_nonce;
+ quiche::QuicheStringPiece nonce = client_nonce;
std::string nonce_storage;
if (!server_nonce.empty()) {
nonce_storage = std::string(client_nonce) + std::string(server_nonce);
@@ -423,9 +505,9 @@ bool CryptoUtils::DeriveKeys(const ParsedQuicVersion& version,
}
// static
-bool CryptoUtils::ExportKeyingMaterial(QuicStringPiece subkey_secret,
- QuicStringPiece label,
- QuicStringPiece context,
+bool CryptoUtils::ExportKeyingMaterial(quiche::QuicheStringPiece subkey_secret,
+ quiche::QuicheStringPiece label,
+ quiche::QuicheStringPiece context,
size_t result_len,
std::string* result) {
for (size_t i = 0; i < label.length(); i++) {
@@ -445,14 +527,14 @@ bool CryptoUtils::ExportKeyingMaterial(QuicStringPiece subkey_secret,
info.append(reinterpret_cast<char*>(&context_length), sizeof(context_length));
info.append(context.data(), context.length());
- QuicHKDF hkdf(subkey_secret, QuicStringPiece() /* no salt */, info,
+ QuicHKDF hkdf(subkey_secret, quiche::QuicheStringPiece() /* no salt */, info,
result_len, 0 /* no fixed IV */, 0 /* no subkey secret */);
*result = std::string(hkdf.client_write_key());
return true;
}
// static
-uint64_t CryptoUtils::ComputeLeafCertHash(QuicStringPiece cert) {
+uint64_t CryptoUtils::ComputeLeafCertHash(quiche::QuicheStringPiece cert) {
return QuicUtils::FNV1a_64_Hash(cert);
}
@@ -492,7 +574,7 @@ QuicErrorCode CryptoUtils::ValidateServerHelloVersions(
// reports that there was a version negotiation during the handshake.
// Ensure that these two lists are identical.
if (mismatch) {
- *error_details = QuicStrCat(
+ *error_details = quiche::QuicheStrCat(
"Downgrade attack detected: ServerVersions(", server_versions.size(),
")[", QuicVersionLabelVectorToString(server_versions, ",", 30),
"] NegotiatedVersions(", negotiated_versions.size(), ")[",
@@ -538,10 +620,11 @@ QuicErrorCode CryptoUtils::ValidateClientHelloVersion(
// downgrade attack.
for (size_t i = 0; i < supported_versions.size(); ++i) {
if (client_version == CreateQuicVersionLabel(supported_versions[i])) {
- *error_details = QuicStrCat(
+ *error_details = quiche::QuicheStrCat(
"Downgrade attack detected: ClientVersion[",
- QuicVersionLabelToString(client_version), "] SupportedVersions(",
- supported_versions.size(), ")[",
+ QuicVersionLabelToString(client_version), "] ConnectionVersion[",
+ ParsedQuicVersionToString(connection_version),
+ "] SupportedVersions(", supported_versions.size(), ")[",
ParsedQuicVersionVectorToString(supported_versions, ",", 30), "]");
return QUIC_VERSION_NEGOTIATION_MISMATCH;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.h b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.h
index da746e3d63c..6c167f8f694 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.h
@@ -16,10 +16,12 @@
#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_crypter.h"
+#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -95,13 +97,22 @@ class QUIC_EXPORT_PRIVATE CryptoUtils {
QuicConnectionId connection_id,
CrypterPair* crypters);
+ // IETF QUIC Retry packets carry a retry integrity tag to detect packet
+ // corruption and make it harder for an attacker to spoof. This function
+ // checks whether a given retry packet is valid.
+ static bool ValidateRetryIntegrityTag(
+ ParsedQuicVersion version,
+ QuicConnectionId original_connection_id,
+ quiche::QuicheStringPiece retry_without_tag,
+ quiche::QuicheStringPiece integrity_tag);
+
// Generates the connection nonce. The nonce is formed as:
// <4 bytes> current time
// <8 bytes> |orbit| (or random if |orbit| is empty)
// <20 bytes> random
static void GenerateNonce(QuicWallTime now,
QuicRandom* random_generator,
- QuicStringPiece orbit,
+ quiche::QuicheStringPiece orbit,
std::string* nonce);
// DeriveKeys populates |crypters->encrypter|, |crypters->decrypter|, and
@@ -124,11 +135,11 @@ class QUIC_EXPORT_PRIVATE CryptoUtils {
// |SetDiversificationNonce| with a diversification nonce will be needed to
// complete keying.
static bool DeriveKeys(const ParsedQuicVersion& version,
- QuicStringPiece premaster_secret,
+ quiche::QuicheStringPiece premaster_secret,
QuicTag aead,
- QuicStringPiece client_nonce,
- QuicStringPiece server_nonce,
- QuicStringPiece pre_shared_key,
+ quiche::QuicheStringPiece client_nonce,
+ quiche::QuicheStringPiece server_nonce,
+ quiche::QuicheStringPiece pre_shared_key,
const std::string& hkdf_input,
Perspective perspective,
Diversification diversification,
@@ -139,15 +150,15 @@ class QUIC_EXPORT_PRIVATE CryptoUtils {
// dependent on |subkey_secret|, |label|, and |context|. Returns false if the
// parameters are invalid (e.g. |label| contains null bytes); returns true on
// success.
- static bool ExportKeyingMaterial(QuicStringPiece subkey_secret,
- QuicStringPiece label,
- QuicStringPiece context,
+ static bool ExportKeyingMaterial(quiche::QuicheStringPiece subkey_secret,
+ quiche::QuicheStringPiece label,
+ quiche::QuicheStringPiece context,
size_t result_len,
std::string* result);
// Computes the FNV-1a hash of the provided DER-encoded cert for use in the
// XLCT tag.
- static uint64_t ComputeLeafCertHash(QuicStringPiece cert);
+ static uint64_t ComputeLeafCertHash(quiche::QuicheStringPiece cert);
// Validates that |server_hello| is actually an SHLO message and that it is
// not part of a downgrade attack.
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils_test.cc
index 25adff22a69..edf80515a75 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils_test.cc
@@ -7,10 +7,11 @@
#include <string>
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
+#include "net/third_party/quiche/src/common/test_tools/quiche_test_utils.h"
namespace quic {
namespace test {
@@ -49,17 +50,19 @@ TEST_F(CryptoUtilsTest, TestExportKeyingMaterial) {
"c9a46ed0757bd1812f1f21b4d41e62125fec8364a21db7"},
};
- for (size_t i = 0; i < QUIC_ARRAYSIZE(test_vector); i++) {
+ for (size_t i = 0; i < QUICHE_ARRAYSIZE(test_vector); i++) {
// Decode the test vector.
std::string subkey_secret =
- QuicTextUtils::HexDecode(test_vector[i].subkey_secret);
- std::string label = QuicTextUtils::HexDecode(test_vector[i].label);
- std::string context = QuicTextUtils::HexDecode(test_vector[i].context);
+ quiche::QuicheTextUtils::HexDecode(test_vector[i].subkey_secret);
+ std::string label =
+ quiche::QuicheTextUtils::HexDecode(test_vector[i].label);
+ std::string context =
+ quiche::QuicheTextUtils::HexDecode(test_vector[i].context);
size_t result_len = test_vector[i].result_len;
bool expect_ok = test_vector[i].expected != nullptr;
std::string expected;
if (expect_ok) {
- expected = QuicTextUtils::HexDecode(test_vector[i].expected);
+ expected = quiche::QuicheTextUtils::HexDecode(test_vector[i].expected);
}
std::string result;
@@ -68,9 +71,9 @@ TEST_F(CryptoUtilsTest, TestExportKeyingMaterial) {
EXPECT_EQ(expect_ok, ok);
if (expect_ok) {
EXPECT_EQ(result_len, result.length());
- test::CompareCharArraysWithHexError("HKDF output", result.data(),
- result.length(), expected.data(),
- expected.length());
+ quiche::test::CompareCharArraysWithHexError(
+ "HKDF output", result.data(), result.length(), expected.data(),
+ expected.length());
}
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange.cc
index 044693df724..f4cc7937d7b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange.cc
@@ -11,6 +11,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -29,7 +30,7 @@ std::unique_ptr<Curve25519KeyExchange> Curve25519KeyExchange::New(
// static
std::unique_ptr<Curve25519KeyExchange> Curve25519KeyExchange::New(
- QuicStringPiece private_key) {
+ quiche::QuicheStringPiece private_key) {
// We don't want to #include the BoringSSL headers in the public header file,
// so we use literals for the sizes of private_key_ and public_key_. Here we
// assert that those values are equal to the values from the BoringSSL
@@ -59,7 +60,7 @@ std::string Curve25519KeyExchange::NewPrivateKey(QuicRandom* rand) {
}
bool Curve25519KeyExchange::CalculateSharedKeySync(
- QuicStringPiece peer_public_value,
+ quiche::QuicheStringPiece peer_public_value,
std::string* shared_key) const {
if (peer_public_value.size() != X25519_PUBLIC_VALUE_LEN) {
return false;
@@ -75,9 +76,9 @@ bool Curve25519KeyExchange::CalculateSharedKeySync(
return true;
}
-QuicStringPiece Curve25519KeyExchange::public_value() const {
- return QuicStringPiece(reinterpret_cast<const char*>(public_key_),
- sizeof(public_key_));
+quiche::QuicheStringPiece Curve25519KeyExchange::public_value() const {
+ return quiche::QuicheStringPiece(reinterpret_cast<const char*>(public_key_),
+ sizeof(public_key_));
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange.h b/chromium/net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange.h
index 31c6c0e8349..76fd23ff242 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange.h
@@ -10,7 +10,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/key_exchange.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -29,16 +29,16 @@ class QUIC_EXPORT_PRIVATE Curve25519KeyExchange
// New creates a new key-exchange object from a private key. If |private_key|
// is invalid, nullptr is returned.
static std::unique_ptr<Curve25519KeyExchange> New(
- QuicStringPiece private_key);
+ quiche::QuicheStringPiece private_key);
// NewPrivateKey returns a private key, generated from |rand|, suitable for
// passing to |New|.
static std::string NewPrivateKey(QuicRandom* rand);
// SynchronousKeyExchange interface.
- bool CalculateSharedKeySync(QuicStringPiece peer_public_value,
+ bool CalculateSharedKeySync(quiche::QuicheStringPiece peer_public_value,
std::string* shared_key) const override;
- QuicStringPiece public_value() const override;
+ quiche::QuicheStringPiece public_value() const override;
QuicTag type() const override { return kC255; }
private:
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange_test.cc
index 5003668efac..2e5dfb4edc1 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange_test.cc
@@ -10,6 +10,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
@@ -54,8 +55,8 @@ TEST_F(Curve25519KeyExchangeTest, SharedKey) {
std::unique_ptr<Curve25519KeyExchange> bob(
Curve25519KeyExchange::New(bob_key));
- const QuicStringPiece alice_public(alice->public_value());
- const QuicStringPiece bob_public(bob->public_value());
+ const quiche::QuicheStringPiece alice_public(alice->public_value());
+ const quiche::QuicheStringPiece bob_public(bob->public_value());
std::string alice_shared, bob_shared;
ASSERT_TRUE(alice->CalculateSharedKeySync(bob_public, &alice_shared));
@@ -78,8 +79,8 @@ TEST_F(Curve25519KeyExchangeTest, SharedKeyAsync) {
std::unique_ptr<Curve25519KeyExchange> bob(
Curve25519KeyExchange::New(bob_key));
- const QuicStringPiece alice_public(alice->public_value());
- const QuicStringPiece bob_public(bob->public_value());
+ const quiche::QuicheStringPiece alice_public(alice->public_value());
+ const quiche::QuicheStringPiece bob_public(bob->public_value());
std::string alice_shared, bob_shared;
TestCallbackResult alice_result;
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/key_exchange.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/key_exchange.cc
index 1969e75a31f..84f9c86802c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/key_exchange.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/key_exchange.cc
@@ -6,12 +6,13 @@
#include "net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange.h"
#include "net/third_party/quiche/src/quic/core/crypto/p256_key_exchange.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
std::unique_ptr<SynchronousKeyExchange> CreateLocalSynchronousKeyExchange(
QuicTag type,
- QuicStringPiece private_key) {
+ quiche::QuicheStringPiece private_key) {
switch (type) {
case kC255:
return Curve25519KeyExchange::New(private_key);
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/key_exchange.h b/chromium/net/third_party/quiche/src/quic/core/crypto/key_exchange.h
index 127dc62ea14..cb6fdbc8705 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/key_exchange.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/key_exchange.h
@@ -10,7 +10,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -48,7 +48,7 @@ class QUIC_EXPORT_PRIVATE AsynchronousKeyExchange {
// that |callback| might be invoked synchronously. Results will be written
// into |*shared_key|.
virtual void CalculateSharedKeyAsync(
- QuicStringPiece peer_public_value,
+ quiche::QuicheStringPiece peer_public_value,
std::string* shared_key,
std::unique_ptr<Callback> callback) const = 0;
@@ -66,7 +66,7 @@ class QUIC_EXPORT_PRIVATE SynchronousKeyExchange
// AyncKeyExchange API. Note that this method is marked 'final.' Subclasses
// should implement CalculateSharedKeySync only.
- void CalculateSharedKeyAsync(QuicStringPiece peer_public_value,
+ void CalculateSharedKeyAsync(quiche::QuicheStringPiece peer_public_value,
std::string* shared_key,
std::unique_ptr<Callback> callback) const final {
const bool ok = CalculateSharedKeySync(peer_public_value, shared_key);
@@ -75,14 +75,15 @@ class QUIC_EXPORT_PRIVATE SynchronousKeyExchange
// CalculateSharedKey computes the shared key between a local private key and
// a public value from the peer. Results will be written into |*shared_key|.
- virtual bool CalculateSharedKeySync(QuicStringPiece peer_public_value,
- std::string* shared_key) const = 0;
+ virtual bool CalculateSharedKeySync(
+ quiche::QuicheStringPiece peer_public_value,
+ std::string* shared_key) const = 0;
// public_value returns the local public key which can be sent to a peer in
- // order to complete a key exchange. The returned QuicStringPiece is a
- // reference to a member of this object and is only valid for as long as it
+ // order to complete a key exchange. The returned quiche::QuicheStringPiece is
+ // a reference to a member of this object and is only valid for as long as it
// exists.
- virtual QuicStringPiece public_value() const = 0;
+ virtual quiche::QuicheStringPiece public_value() const = 0;
};
// Create a SynchronousKeyExchange object which will use a keypair generated
@@ -91,7 +92,7 @@ class QUIC_EXPORT_PRIVATE SynchronousKeyExchange
// invalid.
std::unique_ptr<SynchronousKeyExchange> CreateLocalSynchronousKeyExchange(
QuicTag type,
- QuicStringPiece private_key);
+ quiche::QuicheStringPiece private_key);
// Create a SynchronousKeyExchange object which will use a keypair generated
// from |rand|, and a key-exchange algorithm specified by |type|, which must be
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/null_decrypter.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/null_decrypter.cc
index 51d8b11695b..d453a359ea6 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/null_decrypter.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/null_decrypter.cc
@@ -11,29 +11,30 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_uint128.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
NullDecrypter::NullDecrypter(Perspective perspective)
: perspective_(perspective) {}
-bool NullDecrypter::SetKey(QuicStringPiece key) {
+bool NullDecrypter::SetKey(quiche::QuicheStringPiece key) {
return key.empty();
}
-bool NullDecrypter::SetNoncePrefix(QuicStringPiece nonce_prefix) {
+bool NullDecrypter::SetNoncePrefix(quiche::QuicheStringPiece nonce_prefix) {
return nonce_prefix.empty();
}
-bool NullDecrypter::SetIV(QuicStringPiece iv) {
+bool NullDecrypter::SetIV(quiche::QuicheStringPiece iv) {
return iv.empty();
}
-bool NullDecrypter::SetHeaderProtectionKey(QuicStringPiece key) {
+bool NullDecrypter::SetHeaderProtectionKey(quiche::QuicheStringPiece key) {
return key.empty();
}
-bool NullDecrypter::SetPreliminaryKey(QuicStringPiece /*key*/) {
+bool NullDecrypter::SetPreliminaryKey(quiche::QuicheStringPiece /*key*/) {
QUIC_BUG << "Should not be called";
return false;
}
@@ -45,8 +46,8 @@ bool NullDecrypter::SetDiversificationNonce(
}
bool NullDecrypter::DecryptPacket(uint64_t /*packet_number*/,
- QuicStringPiece associated_data,
- QuicStringPiece ciphertext,
+ quiche::QuicheStringPiece associated_data,
+ quiche::QuicheStringPiece ciphertext,
char* output,
size_t* output_length,
size_t max_output_length) {
@@ -58,7 +59,7 @@ bool NullDecrypter::DecryptPacket(uint64_t /*packet_number*/,
return false;
}
- QuicStringPiece plaintext = reader.ReadRemainingPayload();
+ quiche::QuicheStringPiece plaintext = reader.ReadRemainingPayload();
if (plaintext.length() > max_output_length) {
QUIC_BUG << "Output buffer must be larger than the plaintext.";
return false;
@@ -89,12 +90,12 @@ size_t NullDecrypter::GetIVSize() const {
return 0;
}
-QuicStringPiece NullDecrypter::GetKey() const {
- return QuicStringPiece();
+quiche::QuicheStringPiece NullDecrypter::GetKey() const {
+ return quiche::QuicheStringPiece();
}
-QuicStringPiece NullDecrypter::GetNoncePrefix() const {
- return QuicStringPiece();
+quiche::QuicheStringPiece NullDecrypter::GetNoncePrefix() const {
+ return quiche::QuicheStringPiece();
}
uint32_t NullDecrypter::cipher_id() const {
@@ -111,8 +112,9 @@ bool NullDecrypter::ReadHash(QuicDataReader* reader, QuicUint128* hash) {
return true;
}
-QuicUint128 NullDecrypter::ComputeHash(const QuicStringPiece data1,
- const QuicStringPiece data2) const {
+QuicUint128 NullDecrypter::ComputeHash(
+ const quiche::QuicheStringPiece data1,
+ const quiche::QuicheStringPiece data2) const {
QuicUint128 correct_hash;
if (perspective_ == Perspective::IS_CLIENT) {
// Peer is a server.
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/null_decrypter.h b/chromium/net/third_party/quiche/src/quic/core/crypto/null_decrypter.h
index aac25bbfbe4..c3bd203f5d5 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/null_decrypter.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/null_decrypter.h
@@ -11,8 +11,8 @@
#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_uint128.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -29,15 +29,15 @@ class QUIC_EXPORT_PRIVATE NullDecrypter : public QuicDecrypter {
~NullDecrypter() override {}
// QuicDecrypter implementation
- bool SetKey(QuicStringPiece key) override;
- bool SetNoncePrefix(QuicStringPiece nonce_prefix) override;
- bool SetIV(QuicStringPiece iv) override;
- bool SetHeaderProtectionKey(QuicStringPiece key) override;
- bool SetPreliminaryKey(QuicStringPiece key) override;
+ bool SetKey(quiche::QuicheStringPiece key) override;
+ bool SetNoncePrefix(quiche::QuicheStringPiece nonce_prefix) override;
+ bool SetIV(quiche::QuicheStringPiece iv) override;
+ bool SetHeaderProtectionKey(quiche::QuicheStringPiece key) override;
+ bool SetPreliminaryKey(quiche::QuicheStringPiece key) override;
bool SetDiversificationNonce(const DiversificationNonce& nonce) override;
bool DecryptPacket(uint64_t packet_number,
- QuicStringPiece associated_data,
- QuicStringPiece ciphertext,
+ quiche::QuicheStringPiece associated_data,
+ quiche::QuicheStringPiece ciphertext,
char* output,
size_t* output_length,
size_t max_output_length) override;
@@ -46,14 +46,15 @@ class QUIC_EXPORT_PRIVATE NullDecrypter : public QuicDecrypter {
size_t GetKeySize() const override;
size_t GetNoncePrefixSize() const override;
size_t GetIVSize() const override;
- QuicStringPiece GetKey() const override;
- QuicStringPiece GetNoncePrefix() const override;
+ quiche::QuicheStringPiece GetKey() const override;
+ quiche::QuicheStringPiece GetNoncePrefix() const override;
uint32_t cipher_id() const override;
private:
bool ReadHash(QuicDataReader* reader, QuicUint128* hash);
- QuicUint128 ComputeHash(QuicStringPiece data1, QuicStringPiece data2) const;
+ QuicUint128 ComputeHash(quiche::QuicheStringPiece data1,
+ quiche::QuicheStringPiece data2) const;
Perspective perspective_;
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/null_decrypter_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/null_decrypter_test.cc
index 09b1aafdcfe..1baecad227e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/null_decrypter_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/null_decrypter_test.cc
@@ -3,9 +3,9 @@
// found in the LICENSE file.
#include "net/third_party/quiche/src/quic/core/crypto/null_decrypter.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
namespace quic {
namespace test {
@@ -38,14 +38,15 @@ TEST_F(NullDecrypterTest, DecryptClient) {
'!',
};
const char* data = reinterpret_cast<const char*>(expected);
- size_t len = QUIC_ARRAYSIZE(expected);
+ size_t len = QUICHE_ARRAYSIZE(expected);
NullDecrypter decrypter(Perspective::IS_SERVER);
char buffer[256];
size_t length = 0;
- ASSERT_TRUE(decrypter.DecryptPacket(
- 0, "hello world!", QuicStringPiece(data, len), buffer, &length, 256));
+ ASSERT_TRUE(decrypter.DecryptPacket(0, "hello world!",
+ quiche::QuicheStringPiece(data, len),
+ buffer, &length, 256));
EXPECT_LT(0u, length);
- EXPECT_EQ("goodbye!", QuicStringPiece(buffer, length));
+ EXPECT_EQ("goodbye!", quiche::QuicheStringPiece(buffer, length));
}
TEST_F(NullDecrypterTest, DecryptServer) {
@@ -74,14 +75,15 @@ TEST_F(NullDecrypterTest, DecryptServer) {
'!',
};
const char* data = reinterpret_cast<const char*>(expected);
- size_t len = QUIC_ARRAYSIZE(expected);
+ size_t len = QUICHE_ARRAYSIZE(expected);
NullDecrypter decrypter(Perspective::IS_CLIENT);
char buffer[256];
size_t length = 0;
- ASSERT_TRUE(decrypter.DecryptPacket(
- 0, "hello world!", QuicStringPiece(data, len), buffer, &length, 256));
+ ASSERT_TRUE(decrypter.DecryptPacket(0, "hello world!",
+ quiche::QuicheStringPiece(data, len),
+ buffer, &length, 256));
EXPECT_LT(0u, length);
- EXPECT_EQ("goodbye!", QuicStringPiece(buffer, length));
+ EXPECT_EQ("goodbye!", quiche::QuicheStringPiece(buffer, length));
}
TEST_F(NullDecrypterTest, BadHash) {
@@ -110,12 +112,13 @@ TEST_F(NullDecrypterTest, BadHash) {
'!',
};
const char* data = reinterpret_cast<const char*>(expected);
- size_t len = QUIC_ARRAYSIZE(expected);
+ size_t len = QUICHE_ARRAYSIZE(expected);
NullDecrypter decrypter(Perspective::IS_CLIENT);
char buffer[256];
size_t length = 0;
- ASSERT_FALSE(decrypter.DecryptPacket(
- 0, "hello world!", QuicStringPiece(data, len), buffer, &length, 256));
+ ASSERT_FALSE(decrypter.DecryptPacket(0, "hello world!",
+ quiche::QuicheStringPiece(data, len),
+ buffer, &length, 256));
}
TEST_F(NullDecrypterTest, ShortInput) {
@@ -124,12 +127,13 @@ TEST_F(NullDecrypterTest, ShortInput) {
0x46, 0x11, 0xea, 0x5f, 0xcf, 0x1d, 0x66, 0x5b, 0xba, 0xf0, 0xbc,
};
const char* data = reinterpret_cast<const char*>(expected);
- size_t len = QUIC_ARRAYSIZE(expected);
+ size_t len = QUICHE_ARRAYSIZE(expected);
NullDecrypter decrypter(Perspective::IS_CLIENT);
char buffer[256];
size_t length = 0;
- ASSERT_FALSE(decrypter.DecryptPacket(
- 0, "hello world!", QuicStringPiece(data, len), buffer, &length, 256));
+ ASSERT_FALSE(decrypter.DecryptPacket(0, "hello world!",
+ quiche::QuicheStringPiece(data, len),
+ buffer, &length, 256));
}
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/null_encrypter.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/null_encrypter.cc
index 1fe0fdfc8bf..4de151023af 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/null_encrypter.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/null_encrypter.cc
@@ -6,6 +6,7 @@
#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -14,25 +15,25 @@ const size_t kHashSizeShort = 12; // size of uint128 serialized short
NullEncrypter::NullEncrypter(Perspective perspective)
: perspective_(perspective) {}
-bool NullEncrypter::SetKey(QuicStringPiece key) {
+bool NullEncrypter::SetKey(quiche::QuicheStringPiece key) {
return key.empty();
}
-bool NullEncrypter::SetNoncePrefix(QuicStringPiece nonce_prefix) {
+bool NullEncrypter::SetNoncePrefix(quiche::QuicheStringPiece nonce_prefix) {
return nonce_prefix.empty();
}
-bool NullEncrypter::SetIV(QuicStringPiece iv) {
+bool NullEncrypter::SetIV(quiche::QuicheStringPiece iv) {
return iv.empty();
}
-bool NullEncrypter::SetHeaderProtectionKey(QuicStringPiece key) {
+bool NullEncrypter::SetHeaderProtectionKey(quiche::QuicheStringPiece key) {
return key.empty();
}
bool NullEncrypter::EncryptPacket(uint64_t /*packet_number*/,
- QuicStringPiece associated_data,
- QuicStringPiece plaintext,
+ quiche::QuicheStringPiece associated_data,
+ quiche::QuicheStringPiece plaintext,
char* output,
size_t* output_length,
size_t max_output_length) {
@@ -58,7 +59,7 @@ bool NullEncrypter::EncryptPacket(uint64_t /*packet_number*/,
}
std::string NullEncrypter::GenerateHeaderProtectionMask(
- QuicStringPiece /*sample*/) {
+ quiche::QuicheStringPiece /*sample*/) {
return std::string(5, 0);
}
@@ -82,12 +83,12 @@ size_t NullEncrypter::GetCiphertextSize(size_t plaintext_size) const {
return plaintext_size + GetHashLength();
}
-QuicStringPiece NullEncrypter::GetKey() const {
- return QuicStringPiece();
+quiche::QuicheStringPiece NullEncrypter::GetKey() const {
+ return quiche::QuicheStringPiece();
}
-QuicStringPiece NullEncrypter::GetNoncePrefix() const {
- return QuicStringPiece();
+quiche::QuicheStringPiece NullEncrypter::GetNoncePrefix() const {
+ return quiche::QuicheStringPiece();
}
size_t NullEncrypter::GetHashLength() const {
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/null_encrypter.h b/chromium/net/third_party/quiche/src/quic/core/crypto/null_encrypter.h
index efd6e239e04..bda73dc0ad8 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/null_encrypter.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/null_encrypter.h
@@ -10,7 +10,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -25,24 +25,25 @@ class QUIC_EXPORT_PRIVATE NullEncrypter : public QuicEncrypter {
~NullEncrypter() override {}
// QuicEncrypter implementation
- bool SetKey(QuicStringPiece key) override;
- bool SetNoncePrefix(QuicStringPiece nonce_prefix) override;
- bool SetIV(QuicStringPiece iv) override;
- bool SetHeaderProtectionKey(QuicStringPiece key) override;
+ bool SetKey(quiche::QuicheStringPiece key) override;
+ bool SetNoncePrefix(quiche::QuicheStringPiece nonce_prefix) override;
+ bool SetIV(quiche::QuicheStringPiece iv) override;
+ bool SetHeaderProtectionKey(quiche::QuicheStringPiece key) override;
bool EncryptPacket(uint64_t packet_number,
- QuicStringPiece associated_data,
- QuicStringPiece plaintext,
+ quiche::QuicheStringPiece associated_data,
+ quiche::QuicheStringPiece plaintext,
char* output,
size_t* output_length,
size_t max_output_length) override;
- std::string GenerateHeaderProtectionMask(QuicStringPiece sample) override;
+ std::string GenerateHeaderProtectionMask(
+ quiche::QuicheStringPiece sample) override;
size_t GetKeySize() const override;
size_t GetNoncePrefixSize() const override;
size_t GetIVSize() const override;
size_t GetMaxPlaintextSize(size_t ciphertext_size) const override;
size_t GetCiphertextSize(size_t plaintext_size) const override;
- QuicStringPiece GetKey() const override;
- QuicStringPiece GetNoncePrefix() const override;
+ quiche::QuicheStringPiece GetKey() const override;
+ quiche::QuicheStringPiece GetNoncePrefix() const override;
private:
size_t GetHashLength() const;
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/null_encrypter_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/null_encrypter_test.cc
index c6a89efbf29..c9b00d4c171 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/null_encrypter_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/null_encrypter_test.cc
@@ -3,9 +3,10 @@
// found in the LICENSE file.
#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/test_tools/quiche_test_utils.h"
namespace quic {
namespace test {
@@ -42,9 +43,9 @@ TEST_F(NullEncrypterTest, EncryptClient) {
NullEncrypter encrypter(Perspective::IS_CLIENT);
ASSERT_TRUE(encrypter.EncryptPacket(0, "hello world!", "goodbye!", encrypted,
&encrypted_len, 256));
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"encrypted data", encrypted, encrypted_len,
- reinterpret_cast<const char*>(expected), QUIC_ARRAYSIZE(expected));
+ reinterpret_cast<const char*>(expected), QUICHE_ARRAYSIZE(expected));
}
TEST_F(NullEncrypterTest, EncryptServer) {
@@ -77,9 +78,9 @@ TEST_F(NullEncrypterTest, EncryptServer) {
NullEncrypter encrypter(Perspective::IS_SERVER);
ASSERT_TRUE(encrypter.EncryptPacket(0, "hello world!", "goodbye!", encrypted,
&encrypted_len, 256));
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"encrypted data", encrypted, encrypted_len,
- reinterpret_cast<const char*>(expected), QUIC_ARRAYSIZE(expected));
+ reinterpret_cast<const char*>(expected), QUICHE_ARRAYSIZE(expected));
}
TEST_F(NullEncrypterTest, GetMaxPlaintextSize) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/p256_key_exchange.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/p256_key_exchange.cc
index 1cabc6459ef..a1b45ba5f9c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/p256_key_exchange.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/p256_key_exchange.cc
@@ -15,6 +15,7 @@
#include "third_party/boringssl/src/include/openssl/evp.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -32,7 +33,8 @@ std::unique_ptr<P256KeyExchange> P256KeyExchange::New() {
}
// static
-std::unique_ptr<P256KeyExchange> P256KeyExchange::New(QuicStringPiece key) {
+std::unique_ptr<P256KeyExchange> P256KeyExchange::New(
+ quiche::QuicheStringPiece key) {
if (key.empty()) {
QUIC_DLOG(INFO) << "Private key is empty";
return nullptr;
@@ -81,8 +83,9 @@ std::string P256KeyExchange::NewPrivateKey() {
return std::string(reinterpret_cast<char*>(private_key.get()), key_len);
}
-bool P256KeyExchange::CalculateSharedKeySync(QuicStringPiece peer_public_value,
- std::string* shared_key) const {
+bool P256KeyExchange::CalculateSharedKeySync(
+ quiche::QuicheStringPiece peer_public_value,
+ std::string* shared_key) const {
if (peer_public_value.size() != kUncompressedP256PointBytes) {
QUIC_DLOG(INFO) << "Peer public value is invalid";
return false;
@@ -111,9 +114,9 @@ bool P256KeyExchange::CalculateSharedKeySync(QuicStringPiece peer_public_value,
return true;
}
-QuicStringPiece P256KeyExchange::public_value() const {
- return QuicStringPiece(reinterpret_cast<const char*>(public_key_),
- sizeof(public_key_));
+quiche::QuicheStringPiece P256KeyExchange::public_value() const {
+ return quiche::QuicheStringPiece(reinterpret_cast<const char*>(public_key_),
+ sizeof(public_key_));
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/p256_key_exchange.h b/chromium/net/third_party/quiche/src/quic/core/crypto/p256_key_exchange.h
index a4e5709871c..10cc542597e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/p256_key_exchange.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/p256_key_exchange.h
@@ -11,7 +11,7 @@
#include "third_party/boringssl/src/include/openssl/base.h"
#include "net/third_party/quiche/src/quic/core/crypto/key_exchange.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -26,7 +26,8 @@ class QUIC_EXPORT_PRIVATE P256KeyExchange : public SynchronousKeyExchange {
// New creates a new key-exchange object from a private key. If |private_key|
// is invalid, nullptr is returned.
- static std::unique_ptr<P256KeyExchange> New(QuicStringPiece private_key);
+ static std::unique_ptr<P256KeyExchange> New(
+ quiche::QuicheStringPiece private_key);
// NewPrivateKey returns a private key, suitable for passing to |New|.
// If |NewPrivateKey| can't generate a private key, it returns an empty
@@ -34,9 +35,9 @@ class QUIC_EXPORT_PRIVATE P256KeyExchange : public SynchronousKeyExchange {
static std::string NewPrivateKey();
// SynchronousKeyExchange interface.
- bool CalculateSharedKeySync(QuicStringPiece peer_public_value,
+ bool CalculateSharedKeySync(quiche::QuicheStringPiece peer_public_value,
std::string* shared_key) const override;
- QuicStringPiece public_value() const override;
+ quiche::QuicheStringPiece public_value() const override;
QuicTag type() const override { return kP256; }
private:
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/p256_key_exchange_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/p256_key_exchange_test.cc
index 5e81be417d3..7e7dcd77a60 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/p256_key_exchange_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/p256_key_exchange_test.cc
@@ -9,6 +9,7 @@
#include <utility>
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
@@ -56,8 +57,8 @@ TEST_F(P256KeyExchangeTest, SharedKey) {
ASSERT_TRUE(alice != nullptr);
ASSERT_TRUE(bob != nullptr);
- const QuicStringPiece alice_public(alice->public_value());
- const QuicStringPiece bob_public(bob->public_value());
+ const quiche::QuicheStringPiece alice_public(alice->public_value());
+ const quiche::QuicheStringPiece bob_public(bob->public_value());
std::string alice_shared, bob_shared;
ASSERT_TRUE(alice->CalculateSharedKeySync(bob_public, &alice_shared));
@@ -83,8 +84,8 @@ TEST_F(P256KeyExchangeTest, AsyncSharedKey) {
ASSERT_TRUE(alice != nullptr);
ASSERT_TRUE(bob != nullptr);
- const QuicStringPiece alice_public(alice->public_value());
- const QuicStringPiece bob_public(bob->public_value());
+ const quiche::QuicheStringPiece alice_public(alice->public_value());
+ const quiche::QuicheStringPiece bob_public(bob->public_value());
std::string alice_shared, bob_shared;
TestCallbackResult alice_result;
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/proof_source.h b/chromium/net/third_party/quiche/src/quic/core/crypto/proof_source.h
index f774efc3f22..e208b94c26c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/proof_source.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/proof_source.h
@@ -14,7 +14,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_reference_counted.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -85,7 +85,13 @@ class QUIC_EXPORT_PRIVATE ProofSource {
//
// |signature| contains the signature of the data provided to
// ComputeTlsSignature. Its value is undefined if |ok| is false.
- virtual void Run(bool ok, std::string signature) = 0;
+ //
+ // |details| holds a pointer to an object representing the statistics, if
+ // any, gathered during the operation of ComputeTlsSignature. If no stats
+ // are available, this will be nullptr.
+ virtual void Run(bool ok,
+ std::string signature,
+ std::unique_ptr<Details> details) = 0;
private:
SignatureCallback(const SignatureCallback&) = delete;
@@ -116,7 +122,7 @@ class QUIC_EXPORT_PRIVATE ProofSource {
const std::string& hostname,
const std::string& server_config,
QuicTransportVersion transport_version,
- QuicStringPiece chlo_hash,
+ quiche::QuicheStringPiece chlo_hash,
std::unique_ptr<Callback> callback) = 0;
// Returns the certificate chain for |hostname| in leaf-first order.
@@ -136,7 +142,7 @@ class QUIC_EXPORT_PRIVATE ProofSource {
const QuicSocketAddress& server_address,
const std::string& hostname,
uint16_t signature_algorithm,
- QuicStringPiece in,
+ quiche::QuicheStringPiece in,
std::unique_ptr<SignatureCallback> callback) = 0;
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/proof_verifier.h b/chromium/net/third_party/quiche/src/quic/core/crypto/proof_verifier.h
index 38e978a2d6f..12036d69887 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/proof_verifier.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/proof_verifier.h
@@ -12,7 +12,7 @@
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -79,7 +79,7 @@ class QUIC_EXPORT_PRIVATE ProofVerifier {
const uint16_t port,
const std::string& server_config,
QuicTransportVersion transport_version,
- QuicStringPiece chlo_hash,
+ quiche::QuicheStringPiece chlo_hash,
const std::vector<std::string>& certs,
const std::string& cert_sct,
const std::string& signature,
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_compressed_certs_cache_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_compressed_certs_cache_test.cc
index f27ed0d6dd4..e8f7309cb83 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_compressed_certs_cache_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_compressed_certs_cache_test.cc
@@ -8,8 +8,8 @@
#include "net/third_party/quiche/src/quic/core/crypto/cert_compressor.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
@@ -17,7 +17,7 @@ namespace test {
namespace {
-class QuicCompressedCertsCacheTest : public testing::Test {
+class QuicCompressedCertsCacheTest : public QuicTest {
public:
QuicCompressedCertsCacheTest()
: certs_cache_(QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) {}
@@ -85,8 +85,8 @@ TEST_F(QuicCompressedCertsCacheTest, CacheMissDueToEviction) {
for (unsigned int i = 0;
i < QuicCompressedCertsCache::kQuicCompressedCertsCacheSize; i++) {
EXPECT_EQ(certs_cache_.Size(), i + 1);
- certs_cache_.Insert(chain, QuicTextUtils::Uint64ToString(i), "",
- QuicTextUtils::Uint64ToString(i));
+ certs_cache_.Insert(chain, quiche::QuicheTextUtils::Uint64ToString(i), "",
+ quiche::QuicheTextUtils::Uint64ToString(i));
}
EXPECT_EQ(certs_cache_.MaxSize(), certs_cache_.Size());
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypter.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypter.cc
index dc5bfb3ad84..d8e7f2d1c92 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypter.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypter.cc
@@ -3,11 +3,13 @@
// found in the LICENSE file.
#include "net/third_party/quiche/src/quic/core/crypto/quic_crypter.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
-bool QuicCrypter::SetNoncePrefixOrIV(const ParsedQuicVersion& version,
- QuicStringPiece nonce_prefix_or_iv) {
+bool QuicCrypter::SetNoncePrefixOrIV(
+ const ParsedQuicVersion& version,
+ quiche::QuicheStringPiece nonce_prefix_or_iv) {
if (version.UsesInitialObfuscators()) {
return SetIV(nonce_prefix_or_iv);
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypter.h b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypter.h
index 25a91e4aab8..a12cd6f9eb2 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypter.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypter.h
@@ -7,7 +7,7 @@
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -24,7 +24,7 @@ class QUIC_EXPORT_PRIVATE QuicCrypter {
//
// NOTE: The key is the client_write_key or server_write_key derived from
// the master secret.
- virtual bool SetKey(QuicStringPiece key) = 0;
+ virtual bool SetKey(quiche::QuicheStringPiece key) = 0;
// Sets the fixed initial bytes of the nonce. Returns true on success,
// false on failure. This method must only be used with Google QUIC crypters.
@@ -41,7 +41,7 @@ class QUIC_EXPORT_PRIVATE QuicCrypter {
//
// The security of the nonce format requires that QUIC never reuse a
// packet number, even when retransmitting a lost packet.
- virtual bool SetNoncePrefix(QuicStringPiece nonce_prefix) = 0;
+ virtual bool SetNoncePrefix(quiche::QuicheStringPiece nonce_prefix) = 0;
// Sets |iv| as the initialization vector to use when constructing the nonce.
// Returns true on success, false on failure. This method must only be used
@@ -68,15 +68,15 @@ class QUIC_EXPORT_PRIVATE QuicCrypter {
//
// The security of the nonce format requires that QUIC never reuse a
// packet number, even when retransmitting a lost packet.
- virtual bool SetIV(QuicStringPiece iv) = 0;
+ virtual bool SetIV(quiche::QuicheStringPiece iv) = 0;
// Calls SetNoncePrefix or SetIV depending on whether |version| uses the
// Google QUIC crypto or IETF QUIC nonce construction.
virtual bool SetNoncePrefixOrIV(const ParsedQuicVersion& version,
- QuicStringPiece nonce_prefix_or_iv);
+ quiche::QuicheStringPiece nonce_prefix_or_iv);
// Sets the key to use for header protection.
- virtual bool SetHeaderProtectionKey(QuicStringPiece key) = 0;
+ virtual bool SetHeaderProtectionKey(quiche::QuicheStringPiece key) = 0;
// GetKeySize, GetIVSize, and GetNoncePrefixSize are used to know how many
// bytes of key material needs to be derived from the master secret.
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.cc
index d674126b6df..7f8edc22cfe 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.cc
@@ -25,15 +25,15 @@
#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_client_stats.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_hostname_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
@@ -153,7 +153,7 @@ bool QuicCryptoClientConfig::CachedState::has_server_nonce() const {
QuicCryptoClientConfig::CachedState::ServerConfigState
QuicCryptoClientConfig::CachedState::SetServerConfig(
- QuicStringPiece server_config,
+ quiche::QuicheStringPiece server_config,
QuicWallTime now,
QuicWallTime expiry_time,
std::string* error_details) {
@@ -211,9 +211,9 @@ void QuicCryptoClientConfig::CachedState::InvalidateServerConfig() {
void QuicCryptoClientConfig::CachedState::SetProof(
const std::vector<std::string>& certs,
- QuicStringPiece cert_sct,
- QuicStringPiece chlo_hash,
- QuicStringPiece signature) {
+ quiche::QuicheStringPiece cert_sct,
+ quiche::QuicheStringPiece chlo_hash,
+ quiche::QuicheStringPiece signature) {
bool has_changed = signature != server_config_sig_ ||
chlo_hash != chlo_hash_ || certs_.size() != certs.size();
@@ -272,12 +272,12 @@ void QuicCryptoClientConfig::CachedState::SetProofInvalid() {
}
bool QuicCryptoClientConfig::CachedState::Initialize(
- QuicStringPiece server_config,
- QuicStringPiece source_address_token,
+ quiche::QuicheStringPiece server_config,
+ quiche::QuicheStringPiece source_address_token,
const std::vector<std::string>& certs,
const std::string& cert_sct,
- QuicStringPiece chlo_hash,
- QuicStringPiece signature,
+ quiche::QuicheStringPiece chlo_hash,
+ quiche::QuicheStringPiece signature,
QuicWallTime now,
QuicWallTime expiration_time) {
DCHECK(server_config_.empty());
@@ -345,12 +345,12 @@ QuicCryptoClientConfig::CachedState::proof_verify_details() const {
}
void QuicCryptoClientConfig::CachedState::set_source_address_token(
- QuicStringPiece token) {
+ quiche::QuicheStringPiece token) {
source_address_token_ = std::string(token);
}
void QuicCryptoClientConfig::CachedState::set_cert_sct(
- QuicStringPiece cert_sct) {
+ quiche::QuicheStringPiece cert_sct) {
cert_sct_ = std::string(cert_sct);
}
@@ -472,7 +472,7 @@ void QuicCryptoClientConfig::FillInchoateClientHello(
// the STK can be validated by the server.
const CryptoHandshakeMessage* scfg = cached->GetServerConfig();
if (scfg != nullptr) {
- QuicStringPiece scid;
+ quiche::QuicheStringPiece scid;
if (scfg->GetStringPiece(kSCID, &scid)) {
out->SetStringPiece(kSCID, scid);
}
@@ -487,9 +487,9 @@ void QuicCryptoClientConfig::FillInchoateClientHello(
}
char proof_nonce[32];
- rand->RandBytes(proof_nonce, QUIC_ARRAYSIZE(proof_nonce));
- out->SetStringPiece(
- kNONP, QuicStringPiece(proof_nonce, QUIC_ARRAYSIZE(proof_nonce)));
+ rand->RandBytes(proof_nonce, QUICHE_ARRAYSIZE(proof_nonce));
+ out->SetStringPiece(kNONP, quiche::QuicheStringPiece(
+ proof_nonce, QUICHE_ARRAYSIZE(proof_nonce)));
out->SetVector(kPDMD, QuicTagVector{kX509});
@@ -550,7 +550,7 @@ QuicErrorCode QuicCryptoClientConfig::FillClientHello(
return QUIC_CRYPTO_INTERNAL_ERROR;
}
- QuicStringPiece scid;
+ quiche::QuicheStringPiece scid;
if (!scfg->GetStringPiece(kSCID, &scid)) {
*error_details = "SCFG missing SCID";
return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
@@ -582,14 +582,14 @@ QuicErrorCode QuicCryptoClientConfig::FillClientHello(
out->SetVector(kAEAD, QuicTagVector{out_params->aead});
out->SetVector(kKEXS, QuicTagVector{out_params->key_exchange});
- QuicStringPiece public_value;
+ quiche::QuicheStringPiece public_value;
if (scfg->GetNthValue24(kPUBS, key_exchange_index, &public_value) !=
QUIC_NO_ERROR) {
*error_details = "Missing public value";
return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
}
- QuicStringPiece orbit;
+ quiche::QuicheStringPiece orbit;
if (!scfg->GetStringPiece(kORBT, &orbit) || orbit.size() != kOrbitSize) {
*error_details = "SCFG missing OBIT";
return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
@@ -672,13 +672,13 @@ QuicErrorCode QuicCryptoClientConfig::CacheNewServerConfig(
const CryptoHandshakeMessage& message,
QuicWallTime now,
QuicTransportVersion /*version*/,
- QuicStringPiece chlo_hash,
+ quiche::QuicheStringPiece chlo_hash,
const std::vector<std::string>& cached_certs,
CachedState* cached,
std::string* error_details) {
DCHECK(error_details != nullptr);
- QuicStringPiece scfg;
+ quiche::QuicheStringPiece scfg;
if (!message.GetStringPiece(kSCFG, &scfg)) {
*error_details = "Missing SCFG";
return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
@@ -703,12 +703,12 @@ QuicErrorCode QuicCryptoClientConfig::CacheNewServerConfig(
return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
}
- QuicStringPiece token;
+ quiche::QuicheStringPiece token;
if (message.GetStringPiece(kSourceAddressTokenTag, &token)) {
cached->set_source_address_token(token);
}
- QuicStringPiece proof, cert_bytes, cert_sct;
+ quiche::QuicheStringPiece proof, cert_bytes, cert_sct;
bool has_proof = message.GetStringPiece(kPROF, &proof);
bool has_cert = message.GetStringPiece(kCertificateTag, &cert_bytes);
if (has_proof && has_cert) {
@@ -744,7 +744,7 @@ QuicErrorCode QuicCryptoClientConfig::ProcessRejection(
const CryptoHandshakeMessage& rej,
QuicWallTime now,
const QuicTransportVersion version,
- QuicStringPiece chlo_hash,
+ quiche::QuicheStringPiece chlo_hash,
CachedState* cached,
QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
std::string* error_details) {
@@ -762,7 +762,7 @@ QuicErrorCode QuicCryptoClientConfig::ProcessRejection(
return error;
}
- QuicStringPiece nonce;
+ quiche::QuicheStringPiece nonce;
if (rej.GetStringPiece(kServerNonceTag, &nonce)) {
out_params->server_nonce = std::string(nonce);
}
@@ -787,12 +787,12 @@ QuicErrorCode QuicCryptoClientConfig::ProcessServerHello(
}
// Learn about updated source address tokens.
- QuicStringPiece token;
+ quiche::QuicheStringPiece token;
if (server_hello.GetStringPiece(kSourceAddressTokenTag, &token)) {
cached->set_source_address_token(token);
}
- QuicStringPiece shlo_nonce;
+ quiche::QuicheStringPiece shlo_nonce;
if (!server_hello.GetStringPiece(kServerNonceTag, &shlo_nonce)) {
*error_details = "server hello missing server nonce";
return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
@@ -801,7 +801,7 @@ QuicErrorCode QuicCryptoClientConfig::ProcessServerHello(
// TODO(agl):
// learn about updated SCFGs.
- QuicStringPiece public_value;
+ quiche::QuicheStringPiece public_value;
if (!server_hello.GetStringPiece(kPUBS, &public_value)) {
*error_details = "server hello missing forward secure public value";
return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
@@ -837,7 +837,7 @@ QuicErrorCode QuicCryptoClientConfig::ProcessServerConfigUpdate(
const CryptoHandshakeMessage& server_config_update,
QuicWallTime now,
const QuicTransportVersion version,
- QuicStringPiece chlo_hash,
+ quiche::QuicheStringPiece chlo_hash,
CachedState* cached,
QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
std::string* error_details) {
@@ -859,6 +859,15 @@ SessionCache* QuicCryptoClientConfig::session_cache() const {
return session_cache_.get();
}
+ProofSource* QuicCryptoClientConfig::proof_source() const {
+ return proof_source_.get();
+}
+
+void QuicCryptoClientConfig::set_proof_source(
+ std::unique_ptr<ProofSource> proof_source) {
+ proof_source_ = std::move(proof_source);
+}
+
SSL_CTX* QuicCryptoClientConfig::ssl_ctx() const {
return ssl_ctx_.get();
}
@@ -886,8 +895,8 @@ bool QuicCryptoClientConfig::PopulateFromCanonicalConfig(
DCHECK(server_state->IsEmpty());
size_t i = 0;
for (; i < canonical_suffixes_.size(); ++i) {
- if (QuicTextUtils::EndsWithIgnoreCase(server_id.host(),
- canonical_suffixes_[i])) {
+ if (quiche::QuicheTextUtils::EndsWithIgnoreCase(server_id.host(),
+ canonical_suffixes_[i])) {
break;
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h
index a3e1bcd18b2..e4f7061a82c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h
@@ -15,12 +15,13 @@
#include "third_party/boringssl/src/include/openssl/ssl.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
+#include "net/third_party/quiche/src/quic/core/crypto/proof_source.h"
#include "net/third_party/quiche/src/quic/core/crypto/transport_parameters.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_server_id.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_reference_counted.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -125,7 +126,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
// SetServerConfig checks that |server_config| parses correctly and stores
// it in |server_config_|. |now| is used to judge whether |server_config|
// has expired.
- ServerConfigState SetServerConfig(QuicStringPiece server_config,
+ ServerConfigState SetServerConfig(quiche::QuicheStringPiece server_config,
QuicWallTime now,
QuicWallTime expiry_time,
std::string* error_details);
@@ -135,9 +136,9 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
// SetProof stores a cert chain, cert signed timestamp and signature.
void SetProof(const std::vector<std::string>& certs,
- QuicStringPiece cert_sct,
- QuicStringPiece chlo_hash,
- QuicStringPiece signature);
+ quiche::QuicheStringPiece cert_sct,
+ quiche::QuicheStringPiece chlo_hash,
+ quiche::QuicheStringPiece signature);
// Clears all the data.
void Clear();
@@ -165,9 +166,9 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
uint64_t generation_counter() const;
const ProofVerifyDetails* proof_verify_details() const;
- void set_source_address_token(QuicStringPiece token);
+ void set_source_address_token(quiche::QuicheStringPiece token);
- void set_cert_sct(QuicStringPiece cert_sct);
+ void set_cert_sct(quiche::QuicheStringPiece cert_sct);
// Adds the connection ID to the queue of server-designated connection-ids.
void add_server_designated_connection_id(QuicConnectionId connection_id);
@@ -206,12 +207,12 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
// Initializes this cached state based on the arguments provided.
// Returns false if there is a problem parsing the server config.
- bool Initialize(QuicStringPiece server_config,
- QuicStringPiece source_address_token,
+ bool Initialize(quiche::QuicheStringPiece server_config,
+ quiche::QuicheStringPiece source_address_token,
const std::vector<std::string>& certs,
const std::string& cert_sct,
- QuicStringPiece chlo_hash,
- QuicStringPiece signature,
+ quiche::QuicheStringPiece chlo_hash,
+ quiche::QuicheStringPiece signature,
QuicWallTime now,
QuicWallTime expiration_time);
@@ -323,7 +324,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
const CryptoHandshakeMessage& rej,
QuicWallTime now,
QuicTransportVersion version,
- QuicStringPiece chlo_hash,
+ quiche::QuicheStringPiece chlo_hash,
CachedState* cached,
QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
std::string* error_details);
@@ -355,13 +356,15 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
const CryptoHandshakeMessage& server_update,
QuicWallTime now,
const QuicTransportVersion version,
- QuicStringPiece chlo_hash,
+ quiche::QuicheStringPiece chlo_hash,
CachedState* cached,
QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
std::string* error_details);
ProofVerifier* proof_verifier() const;
SessionCache* session_cache() const;
+ ProofSource* proof_source() const;
+ void set_proof_source(std::unique_ptr<ProofSource> proof_source);
SSL_CTX* ssl_ctx() const;
// Initialize the CachedState from |canonical_crypto_config| for the
@@ -389,7 +392,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
// Saves the |alpn| that will be passed in QUIC's CHLO message.
void set_alpn(const std::string& alpn) { alpn_ = alpn; }
- void set_pre_shared_key(QuicStringPiece psk) {
+ void set_pre_shared_key(quiche::QuicheStringPiece psk) {
pre_shared_key_ = std::string(psk);
}
@@ -413,7 +416,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
const CryptoHandshakeMessage& message,
QuicWallTime now,
QuicTransportVersion version,
- QuicStringPiece chlo_hash,
+ quiche::QuicheStringPiece chlo_hash,
const std::vector<std::string>& cached_certs,
CachedState* cached,
std::string* error_details);
@@ -441,6 +444,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
std::unique_ptr<ProofVerifier> proof_verifier_;
std::unique_ptr<SessionCache> session_cache_;
+ std::unique_ptr<ProofSource> proof_source_;
bssl::UniquePtr<SSL_CTX> ssl_ctx_;
// The |user_agent_id_| passed in QUIC's CHLO message.
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config_test.cc
index 8b5f116d107..4b6dcd71bcb 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config_test.cc
@@ -10,10 +10,12 @@
#include "net/third_party/quiche/src/quic/core/quic_server_id.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_random.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
using testing::StartsWith;
@@ -114,9 +116,9 @@ TEST_F(QuicCryptoClientConfigTest, CachedState_ServerDesignatedConnectionId) {
TEST_F(QuicCryptoClientConfigTest, CachedState_ServerIdConsumedBeforeSet) {
QuicCryptoClientConfig::CachedState state;
EXPECT_FALSE(state.has_server_designated_connection_id());
- EXPECT_QUIC_DEBUG_DEATH(state.GetNextServerDesignatedConnectionId(),
- "Attempting to consume a connection id "
- "that was never designated.");
+ EXPECT_QUIC_BUG(state.GetNextServerDesignatedConnectionId(),
+ "Attempting to consume a connection id "
+ "that was never designated.");
}
TEST_F(QuicCryptoClientConfigTest, CachedState_ServerNonce) {
@@ -153,9 +155,9 @@ TEST_F(QuicCryptoClientConfigTest, CachedState_ServerNonce) {
TEST_F(QuicCryptoClientConfigTest, CachedState_ServerNonceConsumedBeforeSet) {
QuicCryptoClientConfig::CachedState state;
EXPECT_FALSE(state.has_server_nonce());
- EXPECT_QUIC_DEBUG_DEATH(state.GetNextServerNonce(),
- "Attempting to consume a server nonce "
- "that was never designated.");
+ EXPECT_QUIC_BUG(state.GetNextServerNonce(),
+ "Attempting to consume a server nonce "
+ "that was never designated.");
}
TEST_F(QuicCryptoClientConfigTest, CachedState_InitializeFrom) {
@@ -186,15 +188,15 @@ TEST_F(QuicCryptoClientConfigTest, InchoateChlo) {
/* demand_x509_proof= */ true, params, &msg);
QuicVersionLabel cver;
- EXPECT_EQ(QUIC_NO_ERROR, msg.GetVersionLabel(kVER, &cver));
+ EXPECT_THAT(msg.GetVersionLabel(kVER, &cver), IsQuicNoError());
EXPECT_EQ(CreateQuicVersionLabel(QuicVersionMax()), cver);
- QuicStringPiece proof_nonce;
+ quiche::QuicheStringPiece proof_nonce;
EXPECT_TRUE(msg.GetStringPiece(kNONP, &proof_nonce));
EXPECT_EQ(std::string(32, 'r'), proof_nonce);
- QuicStringPiece user_agent_id;
+ quiche::QuicheStringPiece user_agent_id;
EXPECT_TRUE(msg.GetStringPiece(kUAID, &user_agent_id));
EXPECT_EQ("quic-tester", user_agent_id);
- QuicStringPiece alpn;
+ quiche::QuicheStringPiece alpn;
EXPECT_TRUE(msg.GetStringPiece(kALPN, &alpn));
EXPECT_EQ("hq", alpn);
@@ -241,9 +243,9 @@ TEST_F(QuicCryptoClientConfigTest, InchoateChloSecure) {
/* demand_x509_proof= */ true, params, &msg);
QuicTag pdmd;
- EXPECT_EQ(QUIC_NO_ERROR, msg.GetUint32(kPDMD, &pdmd));
+ EXPECT_THAT(msg.GetUint32(kPDMD, &pdmd), IsQuicNoError());
EXPECT_EQ(kX509, pdmd);
- QuicStringPiece scid;
+ quiche::QuicheStringPiece scid;
EXPECT_FALSE(msg.GetStringPiece(kSCID, &scid));
}
@@ -269,7 +271,7 @@ TEST_F(QuicCryptoClientConfigTest, InchoateChloSecureWithSCIDNoEXPY) {
config.FillInchoateClientHello(server_id, QuicVersionMax(), &state, &rand,
/* demand_x509_proof= */ true, params, &msg);
- QuicStringPiece scid;
+ quiche::QuicheStringPiece scid;
EXPECT_TRUE(msg.GetStringPiece(kSCID, &scid));
EXPECT_EQ("12345678", scid);
}
@@ -295,7 +297,7 @@ TEST_F(QuicCryptoClientConfigTest, InchoateChloSecureWithSCID) {
config.FillInchoateClientHello(server_id, QuicVersionMax(), &state, &rand,
/* demand_x509_proof= */ true, params, &msg);
- QuicStringPiece scid;
+ quiche::QuicheStringPiece scid;
EXPECT_TRUE(msg.GetStringPiece(kSCID, &scid));
EXPECT_EQ("12345678", scid);
}
@@ -316,7 +318,7 @@ TEST_F(QuicCryptoClientConfigTest, FillClientHello) {
// Verify that the version label has been set correctly in the CHLO.
QuicVersionLabel cver;
- EXPECT_EQ(QUIC_NO_ERROR, chlo.GetVersionLabel(kVER, &cver));
+ EXPECT_THAT(chlo.GetVersionLabel(kVER, &cver), IsQuicNoError());
EXPECT_EQ(CreateQuicVersionLabel(QuicVersionMax()), cver);
}
@@ -337,7 +339,7 @@ TEST_F(QuicCryptoClientConfigTest, FillClientHelloNoPadding) {
// Verify that the version label has been set correctly in the CHLO.
QuicVersionLabel cver;
- EXPECT_EQ(QUIC_NO_ERROR, chlo.GetVersionLabel(kVER, &cver));
+ EXPECT_THAT(chlo.GetVersionLabel(kVER, &cver), IsQuicNoError());
EXPECT_EQ(CreateQuicVersionLabel(QuicVersionMax()), cver);
EXPECT_EQ(chlo.minimum_size(), 1u);
}
@@ -363,10 +365,10 @@ TEST_F(QuicCryptoClientConfigTest, ProcessServerDowngradeAttack) {
new QuicCryptoNegotiatedParameters);
std::string error;
QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
- EXPECT_EQ(QUIC_VERSION_NEGOTIATION_MISMATCH,
- config.ProcessServerHello(
- msg, EmptyQuicConnectionId(), supported_versions.front(),
- supported_versions, &cached, out_params, &error));
+ EXPECT_THAT(config.ProcessServerHello(
+ msg, EmptyQuicConnectionId(), supported_versions.front(),
+ supported_versions, &cached, out_params, &error),
+ IsError(QUIC_VERSION_NEGOTIATION_MISMATCH));
EXPECT_THAT(error, StartsWith("Downgrade attack detected: ServerVersions"));
}
@@ -526,10 +528,10 @@ TEST_F(QuicCryptoClientConfigTest, ProcessReject) {
new QuicCryptoNegotiatedParameters);
std::string error;
QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
- EXPECT_EQ(QUIC_NO_ERROR,
- config.ProcessRejection(rej, QuicWallTime::FromUNIXSeconds(0),
- AllSupportedTransportVersions().front(), "",
- &cached, out_params, &error));
+ EXPECT_THAT(config.ProcessRejection(rej, QuicWallTime::FromUNIXSeconds(0),
+ AllSupportedTransportVersions().front(),
+ "", &cached, out_params, &error),
+ IsQuicNoError());
EXPECT_FALSE(cached.has_server_designated_connection_id());
EXPECT_FALSE(cached.has_server_nonce());
}
@@ -547,10 +549,10 @@ TEST_F(QuicCryptoClientConfigTest, ProcessRejectWithLongTTL) {
new QuicCryptoNegotiatedParameters);
std::string error;
QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
- EXPECT_EQ(QUIC_NO_ERROR,
- config.ProcessRejection(rej, QuicWallTime::FromUNIXSeconds(0),
- AllSupportedTransportVersions().front(), "",
- &cached, out_params, &error));
+ EXPECT_THAT(config.ProcessRejection(rej, QuicWallTime::FromUNIXSeconds(0),
+ AllSupportedTransportVersions().front(),
+ "", &cached, out_params, &error),
+ IsQuicNoError());
cached.SetProofValid();
EXPECT_FALSE(cached.IsComplete(QuicWallTime::FromUNIXSeconds(long_ttl)));
EXPECT_FALSE(
@@ -574,10 +576,10 @@ TEST_F(QuicCryptoClientConfigTest, ServerNonceinSHLO) {
QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params(
new QuicCryptoNegotiatedParameters);
std::string error_details;
- EXPECT_EQ(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
- config.ProcessServerHello(msg, EmptyQuicConnectionId(), version,
- supported_versions, &cached, out_params,
- &error_details));
+ EXPECT_THAT(config.ProcessServerHello(msg, EmptyQuicConnectionId(), version,
+ supported_versions, &cached, out_params,
+ &error_details),
+ IsError(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER));
EXPECT_EQ("server hello missing server nonce", error_details);
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.cc
index d5689862fcf..4dc34ffd13f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.cc
@@ -24,28 +24,30 @@
#include "net/third_party/quiche/src/quic/core/crypto/key_exchange.h"
#include "net/third_party/quiche/src/quic/core/crypto/p256_key_exchange.h"
#include "net/third_party/quiche/src/quic/core/crypto/proof_source.h"
+#include "net/third_party/quiche/src/quic/core/crypto/proof_verifier.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_hkdf.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
+#include "net/third_party/quiche/src/quic/core/crypto/server_proof_verifier.h"
#include "net/third_party/quiche/src/quic/core/crypto/tls_server_connection.h"
#include "net/third_party/quiche/src/quic/core/proto/crypto_server_config_proto.h"
#include "net/third_party/quiche/src/quic/core/proto/source_address_token_proto.h"
+#include "net/third_party/quiche/src/quic/core/quic_clock.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_socket_address_coder.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_cert_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_fallthrough.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_hostname_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_reference_counted.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
@@ -60,11 +62,11 @@ const size_t kMultiplier = 3;
const int kMaxTokenAddresses = 4;
std::string DeriveSourceAddressTokenKey(
- QuicStringPiece source_address_token_secret) {
- QuicHKDF hkdf(source_address_token_secret, QuicStringPiece() /* no salt */,
- "QUIC source address token key",
- CryptoSecretBoxer::GetKeySize(), 0 /* no fixed IV needed */,
- 0 /* no subkey secret */);
+ quiche::QuicheStringPiece source_address_token_secret) {
+ QuicHKDF hkdf(
+ source_address_token_secret, quiche::QuicheStringPiece() /* no salt */,
+ "QUIC source address token key", CryptoSecretBoxer::GetKeySize(),
+ 0 /* no fixed IV needed */, 0 /* no subkey secret */);
return std::string(hkdf.server_write_key());
}
@@ -78,7 +80,7 @@ class DefaultKeyExchangeSource : public KeyExchangeSource {
std::string /*server_config_id*/,
bool /* is_fallback */,
QuicTag type,
- QuicStringPiece private_key) override {
+ quiche::QuicheStringPiece private_key) override {
if (private_key.empty()) {
QUIC_LOG(WARNING) << "Server config contains key exchange method without "
"corresponding private key of type "
@@ -228,7 +230,7 @@ void QuicCryptoServerConfig::ProcessClientHelloContext::Succeed(
}
QuicCryptoServerConfig::QuicCryptoServerConfig(
- QuicStringPiece source_address_token_secret,
+ quiche::QuicheStringPiece source_address_token_secret,
QuicRandom* server_nonce_entropy,
std::unique_ptr<ProofSource> proof_source,
std::unique_ptr<KeyExchangeSource> key_exchange_source)
@@ -238,6 +240,7 @@ QuicCryptoServerConfig::QuicCryptoServerConfig(
primary_config_(nullptr),
next_config_promotion_time_(QuicWallTime::Zero()),
proof_source_(std::move(proof_source)),
+ client_cert_mode_(ClientCertMode::kNone),
key_exchange_source_(std::move(key_exchange_source)),
ssl_ctx_(TlsServerConnection::CreateSslCtx()),
source_address_token_future_secs_(3600),
@@ -276,7 +279,8 @@ QuicServerConfigProtobuf QuicCryptoServerConfig::GenerateConfig(
Curve25519KeyExchange::NewPrivateKey(rand);
std::unique_ptr<Curve25519KeyExchange> curve25519 =
Curve25519KeyExchange::New(curve25519_private_key);
- QuicStringPiece curve25519_public_value = curve25519->public_value();
+ quiche::QuicheStringPiece curve25519_public_value =
+ curve25519->public_value();
std::string encoded_public_values;
// First three bytes encode the length of the public value.
@@ -295,7 +299,7 @@ QuicServerConfigProtobuf QuicCryptoServerConfig::GenerateConfig(
p256_private_key = P256KeyExchange::NewPrivateKey();
std::unique_ptr<P256KeyExchange> p256(
P256KeyExchange::New(p256_private_key));
- QuicStringPiece p256_public_value = p256->public_value();
+ quiche::QuicheStringPiece p256_public_value = p256->public_value();
DCHECK_LT(p256_public_value.size(), (1U << 24));
encoded_public_values.push_back(
@@ -334,7 +338,8 @@ QuicServerConfigProtobuf QuicCryptoServerConfig::GenerateConfig(
DCHECK(options.orbit.empty());
rand->RandBytes(orbit_bytes, sizeof(orbit_bytes));
}
- msg.SetStringPiece(kORBT, QuicStringPiece(orbit_bytes, sizeof(orbit_bytes)));
+ msg.SetStringPiece(
+ kORBT, quiche::QuicheStringPiece(orbit_bytes, sizeof(orbit_bytes)));
if (options.channel_id_enabled) {
msg.SetVector(kPDMD, QuicTagVector{kCHID});
@@ -351,8 +356,9 @@ QuicServerConfigProtobuf QuicCryptoServerConfig::GenerateConfig(
serialized->length(), scid_bytes);
// The SCID is a truncated SHA-256 digest.
static_assert(16 <= SHA256_DIGEST_LENGTH, "SCID length too high.");
- msg.SetStringPiece(
- kSCID, QuicStringPiece(reinterpret_cast<const char*>(scid_bytes), 16));
+ msg.SetStringPiece(kSCID,
+ quiche::QuicheStringPiece(
+ reinterpret_cast<const char*>(scid_bytes), 16));
} else {
msg.SetStringPiece(kSCID, options.id);
}
@@ -401,7 +407,7 @@ std::unique_ptr<CryptoHandshakeMessage> QuicCryptoServerConfig::AddConfig(
if (configs_.find(config->id) != configs_.end()) {
QUIC_LOG(WARNING) << "Failed to add config because another with the same "
"server config id already exists: "
- << QuicTextUtils::HexEncode(config->id);
+ << quiche::QuicheTextUtils::HexEncode(config->id);
return nullptr;
}
@@ -447,7 +453,7 @@ bool QuicCryptoServerConfig::SetConfigs(
return false;
}
QUIC_LOG(INFO) << "Fallback config has scid "
- << QuicTextUtils::HexEncode(fallback_config->id);
+ << quiche::QuicheTextUtils::HexEncode(fallback_config->id);
parsed_configs.push_back(fallback_config);
} else {
QUIC_LOG(INFO) << "No fallback config provided";
@@ -467,25 +473,24 @@ bool QuicCryptoServerConfig::SetConfigs(
for (const QuicReferenceCountedPointer<Config>& config : parsed_configs) {
auto it = configs_.find(config->id);
if (it != configs_.end()) {
- QUIC_LOG(INFO) << "Keeping scid: " << QuicTextUtils::HexEncode(config->id)
- << " orbit: "
- << QuicTextUtils::HexEncode(
- reinterpret_cast<const char*>(config->orbit),
- kOrbitSize)
- << " new primary_time "
- << config->primary_time.ToUNIXSeconds()
- << " old primary_time "
- << it->second->primary_time.ToUNIXSeconds()
- << " new priority " << config->priority << " old priority "
- << it->second->priority;
+ QUIC_LOG(INFO)
+ << "Keeping scid: " << quiche::QuicheTextUtils::HexEncode(config->id)
+ << " orbit: "
+ << quiche::QuicheTextUtils::HexEncode(
+ reinterpret_cast<const char*>(config->orbit), kOrbitSize)
+ << " new primary_time " << config->primary_time.ToUNIXSeconds()
+ << " old primary_time " << it->second->primary_time.ToUNIXSeconds()
+ << " new priority " << config->priority << " old priority "
+ << it->second->priority;
// Update primary_time and priority.
it->second->primary_time = config->primary_time;
it->second->priority = config->priority;
new_configs.insert(*it);
} else {
- QUIC_LOG(INFO) << "Adding scid: " << QuicTextUtils::HexEncode(config->id)
+ QUIC_LOG(INFO) << "Adding scid: "
+ << quiche::QuicheTextUtils::HexEncode(config->id)
<< " orbit: "
- << QuicTextUtils::HexEncode(
+ << quiche::QuicheTextUtils::HexEncode(
reinterpret_cast<const char*>(config->orbit),
kOrbitSize)
<< " primary_time " << config->primary_time.ToUNIXSeconds()
@@ -531,7 +536,7 @@ void QuicCryptoServerConfig::ValidateClientHello(
new ValidateClientHelloResultCallback::Result(client_hello, client_ip,
now));
- QuicStringPiece requested_scid;
+ quiche::QuicheStringPiece requested_scid;
client_hello.GetStringPiece(kSCID, &requested_scid);
Configs configs;
if (!GetCurrentConfigs(now, requested_scid,
@@ -587,7 +592,7 @@ class QuicCryptoServerConfig::ProcessClientHelloAfterGetProofCallback
std::unique_ptr<ProofSource::Details> proof_source_details,
QuicTag key_exchange_type,
std::unique_ptr<CryptoHandshakeMessage> out,
- QuicStringPiece public_value,
+ quiche::QuicheStringPiece public_value,
std::unique_ptr<ProcessClientHelloContext> context,
const Configs& configs)
: config_(config),
@@ -680,7 +685,7 @@ void QuicCryptoServerConfig::ProcessClientHello(
return;
}
- QuicStringPiece requested_scid;
+ quiche::QuicheStringPiece requested_scid;
context->client_hello().GetStringPiece(kSCID, &requested_scid);
Configs configs;
if (!GetCurrentConfigs(context->clock()->WallNow(), requested_scid,
@@ -740,7 +745,7 @@ void QuicCryptoServerConfig::ProcessClientHelloAfterGetProof(
auto out_diversification_nonce = std::make_unique<DiversificationNonce>();
- QuicStringPiece cert_sct;
+ quiche::QuicheStringPiece cert_sct;
if (context->client_hello().GetStringPiece(kCertificateSCTTag, &cert_sct) &&
cert_sct.empty()) {
context->params()->sct_supported_by_client = true;
@@ -783,7 +788,7 @@ void QuicCryptoServerConfig::ProcessClientHelloAfterGetProof(
return;
}
- QuicStringPiece public_value;
+ quiche::QuicheStringPiece public_value;
if (!context->client_hello().GetStringPiece(kPUBS, &public_value)) {
context->Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
"Missing public value");
@@ -806,7 +811,7 @@ void QuicCryptoServerConfig::ProcessClientHelloAfterCalculateSharedKeys(
std::unique_ptr<ProofSource::Details> proof_source_details,
QuicTag key_exchange_type,
std::unique_ptr<CryptoHandshakeMessage> out,
- QuicStringPiece public_value,
+ quiche::QuicheStringPiece public_value,
std::unique_ptr<ProcessClientHelloContext> context,
const Configs& configs) const {
QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(
@@ -853,7 +858,7 @@ void QuicCryptoServerConfig::ProcessClientHelloAfterCalculateSharedKeys(
}
hkdf_suffix.append(context->signed_config()->chain->certs.at(0));
- QuicStringPiece cetv_ciphertext;
+ quiche::QuicheStringPiece cetv_ciphertext;
if (configs.requested->channel_id_enabled &&
context->client_hello().GetStringPiece(kCETV, &cetv_ciphertext)) {
CryptoHandshakeMessage client_hello_copy(context->client_hello());
@@ -886,21 +891,22 @@ void QuicCryptoServerConfig::ProcessClientHelloAfterCalculateSharedKeys(
char plaintext[kMaxOutgoingPacketSize];
size_t plaintext_length = 0;
const bool success = crypters.decrypter->DecryptPacket(
- 0 /* packet number */, QuicStringPiece() /* associated data */,
- cetv_ciphertext, plaintext, &plaintext_length, kMaxOutgoingPacketSize);
+ 0 /* packet number */,
+ quiche::QuicheStringPiece() /* associated data */, cetv_ciphertext,
+ plaintext, &plaintext_length, kMaxOutgoingPacketSize);
if (!success) {
context->Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
"CETV decryption failure");
return;
}
std::unique_ptr<CryptoHandshakeMessage> cetv(CryptoFramer::ParseMessage(
- QuicStringPiece(plaintext, plaintext_length)));
+ quiche::QuicheStringPiece(plaintext, plaintext_length)));
if (!cetv) {
context->Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER, "CETV parse error");
return;
}
- QuicStringPiece key, signature;
+ quiche::QuicheStringPiece key, signature;
if (cetv->GetStringPiece(kCIDK, &key) &&
cetv->GetStringPiece(kCIDS, &signature)) {
if (!ChannelIDVerifier::Verify(key, hkdf_input, signature)) {
@@ -1037,7 +1043,7 @@ void QuicCryptoServerConfig::SendRejectWithFallbackConfigAfterGetProof(
QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
QuicCryptoServerConfig::GetConfigWithScid(
- QuicStringPiece requested_scid) const {
+ quiche::QuicheStringPiece requested_scid) const {
configs_lock_.AssertReaderHeld();
if (!requested_scid.empty()) {
@@ -1054,7 +1060,7 @@ QuicCryptoServerConfig::GetConfigWithScid(
bool QuicCryptoServerConfig::GetCurrentConfigs(
const QuicWallTime& now,
- QuicStringPiece requested_scid,
+ quiche::QuicheStringPiece requested_scid,
QuicReferenceCountedPointer<Config> old_primary_config,
Configs* configs) const {
QuicReaderMutexLock locked(&configs_lock_);
@@ -1157,9 +1163,10 @@ void QuicCryptoServerConfig::SelectNewPrimaryConfig(
primary_config_ = new_primary;
new_primary->is_primary = true;
QUIC_DLOG(INFO) << "New primary config. orbit: "
- << QuicTextUtils::HexEncode(reinterpret_cast<const char*>(
- primary_config_->orbit),
- kOrbitSize);
+ << quiche::QuicheTextUtils::HexEncode(
+ reinterpret_cast<const char*>(
+ primary_config_->orbit),
+ kOrbitSize);
if (primary_config_changed_cb_ != nullptr) {
primary_config_changed_cb_->Run(primary_config_->id);
}
@@ -1176,10 +1183,11 @@ void QuicCryptoServerConfig::SelectNewPrimaryConfig(
primary_config_ = new_primary;
new_primary->is_primary = true;
QUIC_DLOG(INFO) << "New primary config. orbit: "
- << QuicTextUtils::HexEncode(
+ << quiche::QuicheTextUtils::HexEncode(
reinterpret_cast<const char*>(primary_config_->orbit),
kOrbitSize)
- << " scid: " << QuicTextUtils::HexEncode(primary_config_->id);
+ << " scid: "
+ << quiche::QuicheTextUtils::HexEncode(primary_config_->id);
next_config_promotion_time_ = QuicWallTime::Zero();
if (primary_config_changed_cb_ != nullptr) {
primary_config_changed_cb_->Run(primary_config_->id);
@@ -1215,7 +1223,7 @@ void QuicCryptoServerConfig::EvaluateClientHello(
HandshakeFailureReason source_address_token_error = MAX_FAILURE_REASON;
if (validate_source_address_token_) {
- QuicStringPiece srct;
+ quiche::QuicheStringPiece srct;
if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct)) {
Config& config =
configs.requested != nullptr ? *configs.requested : *configs.primary;
@@ -1238,7 +1246,7 @@ void QuicCryptoServerConfig::EvaluateClientHello(
}
if (!configs.requested) {
- QuicStringPiece requested_scid;
+ quiche::QuicheStringPiece requested_scid;
if (client_hello.GetStringPiece(kSCID, &requested_scid)) {
info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
} else {
@@ -1292,7 +1300,7 @@ void QuicCryptoServerConfig::EvaluateClientHello(
void QuicCryptoServerConfig::BuildServerConfigUpdateMessage(
QuicTransportVersion version,
- QuicStringPiece chlo_hash,
+ quiche::QuicheStringPiece chlo_hash,
const SourceAddressTokens& previous_source_address_tokens,
const QuicSocketAddress& server_address,
const QuicIpAddress& client_ip,
@@ -1440,13 +1448,13 @@ void QuicCryptoServerConfig::BuildRejection(
return;
}
- QuicStringPiece client_common_set_hashes;
+ quiche::QuicheStringPiece client_common_set_hashes;
if (context.client_hello().GetStringPiece(kCCS, &client_common_set_hashes)) {
context.params()->client_common_set_hashes =
std::string(client_common_set_hashes);
}
- QuicStringPiece client_cached_cert_hashes;
+ quiche::QuicheStringPiece client_cached_cert_hashes;
if (context.client_hello().GetStringPiece(kCCRT,
&client_cached_cert_hashes)) {
context.params()->client_cached_cert_hashes =
@@ -1494,7 +1502,7 @@ void QuicCryptoServerConfig::BuildRejection(
// This is for debugging b/28342827.
const std::vector<std::string>& certs =
context.signed_config()->chain->certs;
- QuicStringPiece ca_subject;
+ quiche::QuicheStringPiece ca_subject;
if (!certs.empty()) {
QuicCertUtils::ExtractSubjectNameFromDERCert(certs[0], &ca_subject);
}
@@ -1561,7 +1569,7 @@ QuicCryptoServerConfig::ParseConfigProtobuf(
config->priority = protobuf.priority();
- QuicStringPiece scid;
+ quiche::QuicheStringPiece scid;
if (!msg->GetStringPiece(kSCID, &scid)) {
QUIC_LOG(WARNING) << "Server config message is missing SCID";
return nullptr;
@@ -1579,7 +1587,7 @@ QuicCryptoServerConfig::ParseConfigProtobuf(
return nullptr;
}
- QuicStringPiece orbit;
+ quiche::QuicheStringPiece orbit;
if (!msg->GetStringPiece(kORBT, &orbit)) {
QUIC_LOG(WARNING) << "Server config message is missing ORBT";
return nullptr;
@@ -1727,16 +1735,33 @@ ProofSource* QuicCryptoServerConfig::proof_source() const {
return proof_source_.get();
}
+ServerProofVerifier* QuicCryptoServerConfig::proof_verifier() const {
+ return proof_verifier_.get();
+}
+
+void QuicCryptoServerConfig::set_proof_verifier(
+ std::unique_ptr<ServerProofVerifier> proof_verifier) {
+ proof_verifier_ = std::move(proof_verifier);
+}
+
+ClientCertMode QuicCryptoServerConfig::client_cert_mode() const {
+ return client_cert_mode_;
+}
+
+void QuicCryptoServerConfig::set_client_cert_mode(ClientCertMode mode) {
+ client_cert_mode_ = mode;
+}
+
SSL_CTX* QuicCryptoServerConfig::ssl_ctx() const {
return ssl_ctx_.get();
}
HandshakeFailureReason QuicCryptoServerConfig::ParseSourceAddressToken(
const Config& config,
- QuicStringPiece token,
+ quiche::QuicheStringPiece token,
SourceAddressTokens* tokens) const {
std::string storage;
- QuicStringPiece plaintext;
+ quiche::QuicheStringPiece plaintext;
if (!config.source_address_token_boxer->Unbox(token, &storage, &plaintext)) {
return SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE;
}
@@ -1826,8 +1851,8 @@ std::string QuicCryptoServerConfig::NewServerNonce(QuicRandom* rand,
sizeof(server_nonce) - sizeof(timestamp));
return server_nonce_boxer_.Box(
- rand, QuicStringPiece(reinterpret_cast<char*>(server_nonce),
- sizeof(server_nonce)));
+ rand, quiche::QuicheStringPiece(reinterpret_cast<char*>(server_nonce),
+ sizeof(server_nonce)));
}
bool QuicCryptoServerConfig::ValidateExpectedLeafCertificate(
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h
index 809ebaec575..4a8cb737c98 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h
@@ -19,8 +19,10 @@
#include "net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer.h"
#include "net/third_party/quiche/src/quic/core/crypto/key_exchange.h"
#include "net/third_party/quiche/src/quic/core/crypto/proof_source.h"
+#include "net/third_party/quiche/src/quic/core/crypto/proof_verifier.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_compressed_certs_cache.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_proof.h"
+#include "net/third_party/quiche/src/quic/core/crypto/server_proof_verifier.h"
#include "net/third_party/quiche/src/quic/core/proto/cached_network_parameters_proto.h"
#include "net/third_party/quiche/src/quic/core/proto/source_address_token_proto.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
@@ -28,7 +30,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_mutex.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_reference_counted.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -52,10 +54,10 @@ struct QUIC_EXPORT_PRIVATE ClientHelloInfo {
// Outputs from EvaluateClientHello.
bool valid_source_address_token;
- QuicStringPiece sni;
- QuicStringPiece client_nonce;
- QuicStringPiece server_nonce;
- QuicStringPiece user_agent_id;
+ quiche::QuicheStringPiece sni;
+ quiche::QuicheStringPiece client_nonce;
+ quiche::QuicheStringPiece server_nonce;
+ quiche::QuicheStringPiece user_agent_id;
SourceAddressTokens source_address_tokens;
// Errors from EvaluateClientHello.
@@ -169,7 +171,7 @@ class QUIC_EXPORT_PRIVATE KeyExchangeSource {
std::string server_config_id,
bool is_fallback,
QuicTag type,
- QuicStringPiece private_key) = 0;
+ quiche::QuicheStringPiece private_key) = 0;
};
// QuicCryptoServerConfig contains the crypto configuration of a QUIC server.
@@ -213,7 +215,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig {
// |proof_source|: provides certificate chains and signatures.
// |key_exchange_source|: provides key-exchange functionality.
QuicCryptoServerConfig(
- QuicStringPiece source_address_token_secret,
+ quiche::QuicheStringPiece source_address_token_secret,
QuicRandom* server_nonce_entropy,
std::unique_ptr<ProofSource> proof_source,
std::unique_ptr<KeyExchangeSource> key_exchange_source);
@@ -355,7 +357,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig {
// |cached_network_params| is optional, and can be nullptr.
void BuildServerConfigUpdateMessage(
QuicTransportVersion version,
- QuicStringPiece chlo_hash,
+ quiche::QuicheStringPiece chlo_hash,
const SourceAddressTokens& previous_source_address_tokens,
const QuicSocketAddress& server_address,
const QuicIpAddress& client_ip,
@@ -422,10 +424,15 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig {
}
ProofSource* proof_source() const;
+ ServerProofVerifier* proof_verifier() const;
+ void set_proof_verifier(std::unique_ptr<ServerProofVerifier> proof_verifier);
+
+ ClientCertMode client_cert_mode() const;
+ void set_client_cert_mode(ClientCertMode client_cert_mode);
SSL_CTX* ssl_ctx() const;
- void set_pre_shared_key(QuicStringPiece psk) {
+ void set_pre_shared_key(quiche::QuicheStringPiece psk) {
pre_shared_key_ = std::string(psk);
}
@@ -507,7 +514,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig {
// Get a ref to the config with a given server config id.
QuicReferenceCountedPointer<Config> GetConfigWithScid(
- QuicStringPiece requested_scid) const
+ quiche::QuicheStringPiece requested_scid) const
QUIC_SHARED_LOCKS_REQUIRED(configs_lock_);
// A snapshot of the configs associated with an in-progress handshake.
@@ -524,7 +531,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig {
// Returns true if any configs are loaded. If false is returned, |configs| is
// not modified.
bool GetCurrentConfigs(const QuicWallTime& now,
- QuicStringPiece requested_scid,
+ quiche::QuicheStringPiece requested_scid,
QuicReferenceCountedPointer<Config> old_primary_config,
Configs* configs) const;
@@ -677,7 +684,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig {
std::unique_ptr<ProofSource::Details> proof_source_details,
QuicTag key_exchange_type,
std::unique_ptr<CryptoHandshakeMessage> out,
- QuicStringPiece public_value,
+ quiche::QuicheStringPiece public_value,
std::unique_ptr<ProcessClientHelloContext> context,
const Configs& configs) const;
@@ -751,7 +758,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig {
// failure.
HandshakeFailureReason ParseSourceAddressToken(
const Config& config,
- QuicStringPiece token,
+ quiche::QuicheStringPiece token,
SourceAddressTokens* tokens) const;
// ValidateSourceAddressTokens returns HANDSHAKE_OK if the source address
@@ -908,6 +915,8 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig {
// proof_source_ contains an object that can provide certificate chains and
// signatures.
std::unique_ptr<ProofSource> proof_source_;
+ std::unique_ptr<ServerProofVerifier> proof_verifier_;
+ ClientCertMode client_cert_mode_;
// key_exchange_source_ contains an object that can provide key exchange
// objects.
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config_test.cc
index 8f9e4ba776a..8dd1108b37f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config_test.cc
@@ -16,12 +16,15 @@
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
#include "net/third_party/quiche/src/quic/core/proto/crypto_server_config_proto.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_crypto_server_config_peer.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
namespace test {
@@ -52,7 +55,7 @@ TEST_F(QuicCryptoServerConfigTest, ServerConfig) {
// The default configuration should have AES-GCM and at least one ChaCha20
// cipher.
QuicTagVector aead;
- ASSERT_EQ(QUIC_NO_ERROR, message->GetTaglist(kAEAD, &aead));
+ ASSERT_THAT(message->GetTaglist(kAEAD, &aead), IsQuicNoError());
EXPECT_THAT(aead, ::testing::Contains(kAESG));
EXPECT_LE(1u, aead.size());
}
@@ -139,7 +142,7 @@ TEST_F(QuicCryptoServerConfigTest, CompressDifferentCerts) {
static const uint64_t set_hash = 42;
std::unique_ptr<CommonCertSets> common_sets(
crypto_test_utils::MockCommonCertSets(certs[0], set_hash, 1));
- QuicStringPiece different_common_certs(
+ quiche::QuicheStringPiece different_common_certs(
reinterpret_cast<const char*>(&set_hash), sizeof(set_hash));
std::string compressed3 = QuicCryptoServerConfigPeer::CompressChain(
&compressed_certs_cache, chain, std::string(different_common_certs),
@@ -190,15 +193,16 @@ class SourceAddressTokenTest : public QuicTest {
clock_.WallNow(), cached_network_params);
}
- HandshakeFailureReason ValidateSourceAddressTokens(std::string config_id,
- QuicStringPiece srct,
- const QuicIpAddress& ip) {
+ HandshakeFailureReason ValidateSourceAddressTokens(
+ std::string config_id,
+ quiche::QuicheStringPiece srct,
+ const QuicIpAddress& ip) {
return ValidateSourceAddressTokens(config_id, srct, ip, nullptr);
}
HandshakeFailureReason ValidateSourceAddressTokens(
std::string config_id,
- QuicStringPiece srct,
+ quiche::QuicheStringPiece srct,
const QuicIpAddress& ip,
CachedNetworkParameters* cached_network_params) {
return peer_.ValidateSourceAddressTokens(
@@ -352,7 +356,8 @@ class CryptoServerConfigsTest : public QuicTest {
QuicCryptoServerConfig::GenerateConfig(rand_, &clock_, options);
protobuf.set_primary_time(primary_time);
protobuf.set_priority(priority);
- if (QuicTextUtils::StartsWith(std::string(server_config_id), "INVALID")) {
+ if (quiche::QuicheTextUtils::StartsWith(std::string(server_config_id),
+ "INVALID")) {
protobuf.clear_key();
has_invalid = true;
}
@@ -478,15 +483,23 @@ TEST_F(CryptoServerConfigsTest, AdvancePrimaryViaValidate) {
CryptoHandshakeMessage client_hello;
QuicIpAddress client_ip;
QuicSocketAddress server_address;
- QuicTransportVersion version = QUIC_VERSION_99;
+ QuicTransportVersion transport_version = QUIC_VERSION_UNSUPPORTED;
+ for (const ParsedQuicVersion& version : AllSupportedVersions()) {
+ if (version.handshake_protocol == PROTOCOL_QUIC_CRYPTO) {
+ transport_version = version.transport_version;
+ break;
+ }
+ }
+ ASSERT_NE(transport_version, QUIC_VERSION_UNSUPPORTED);
MockClock clock;
QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config(
new QuicSignedServerConfig);
std::unique_ptr<ValidateClientHelloResultCallback> done_cb(
new ValidateCallback);
clock.AdvanceTime(QuicTime::Delta::FromSeconds(1100));
- config_.ValidateClientHello(client_hello, client_ip, server_address, version,
- &clock, signed_config, std::move(done_cb));
+ config_.ValidateClientHello(client_hello, client_ip, server_address,
+ transport_version, &clock, signed_config,
+ std::move(done_cb));
test_peer_.CheckConfigs({{"a", false}, {"b", true}});
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_decrypter.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_decrypter.cc
index 33c563f72ed..c4249017cae 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_decrypter.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_decrypter.cc
@@ -18,6 +18,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/quic_hkdf.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -61,15 +62,16 @@ std::unique_ptr<QuicDecrypter> QuicDecrypter::CreateFromCipherSuite(
}
// static
-void QuicDecrypter::DiversifyPreliminaryKey(QuicStringPiece preliminary_key,
- QuicStringPiece nonce_prefix,
- const DiversificationNonce& nonce,
- size_t key_size,
- size_t nonce_prefix_size,
- std::string* out_key,
- std::string* out_nonce_prefix) {
+void QuicDecrypter::DiversifyPreliminaryKey(
+ quiche::QuicheStringPiece preliminary_key,
+ quiche::QuicheStringPiece nonce_prefix,
+ const DiversificationNonce& nonce,
+ size_t key_size,
+ size_t nonce_prefix_size,
+ std::string* out_key,
+ std::string* out_nonce_prefix) {
QuicHKDF hkdf((std::string(preliminary_key)) + (std::string(nonce_prefix)),
- QuicStringPiece(nonce.data(), nonce.size()),
+ quiche::QuicheStringPiece(nonce.data(), nonce.size()),
"QUIC key diversification", 0, key_size, 0, nonce_prefix_size,
0);
*out_key = std::string(hkdf.server_write_key());
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h
index aed18e4a722..7f4d93d323a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h
@@ -14,7 +14,7 @@
#include "net/third_party/quiche/src/quic/core/quic_data_reader.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -38,7 +38,7 @@ class QUIC_EXPORT_PRIVATE QuicDecrypter : public QuicCrypter {
//
// If this function is called, neither |SetKey| nor |SetNoncePrefix| may be
// called.
- virtual bool SetPreliminaryKey(QuicStringPiece key) = 0;
+ virtual bool SetPreliminaryKey(quiche::QuicheStringPiece key) = 0;
// SetDiversificationNonce uses |nonce| to derive final keys based on the
// input keying material given by calling |SetPreliminaryKey|.
@@ -56,8 +56,8 @@ class QUIC_EXPORT_PRIVATE QuicDecrypter : public QuicCrypter {
// TODO(wtc): add a way for DecryptPacket to report decryption failure due
// to non-authentic inputs, as opposed to other reasons for failure.
virtual bool DecryptPacket(uint64_t packet_number,
- QuicStringPiece associated_data,
- QuicStringPiece ciphertext,
+ quiche::QuicheStringPiece associated_data,
+ quiche::QuicheStringPiece ciphertext,
char* output,
size_t* output_length,
size_t max_output_length) = 0;
@@ -74,11 +74,11 @@ class QUIC_EXPORT_PRIVATE QuicDecrypter : public QuicCrypter {
virtual uint32_t cipher_id() const = 0;
// For use by unit tests only.
- virtual QuicStringPiece GetKey() const = 0;
- virtual QuicStringPiece GetNoncePrefix() const = 0;
+ virtual quiche::QuicheStringPiece GetKey() const = 0;
+ virtual quiche::QuicheStringPiece GetNoncePrefix() const = 0;
- static void DiversifyPreliminaryKey(QuicStringPiece preliminary_key,
- QuicStringPiece nonce_prefix,
+ static void DiversifyPreliminaryKey(quiche::QuicheStringPiece preliminary_key,
+ quiche::QuicheStringPiece nonce_prefix,
const DiversificationNonce& nonce,
size_t key_size,
size_t nonce_prefix_size,
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h
index d318329c7e2..6fe552d1778 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h
@@ -11,7 +11,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/quic_crypter.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -36,8 +36,8 @@ class QUIC_EXPORT_PRIVATE QuicEncrypter : public QuicCrypter {
// |associated_data|. If |output| overlaps with |plaintext| then
// |plaintext| must be <= |output|.
virtual bool EncryptPacket(uint64_t packet_number,
- QuicStringPiece associated_data,
- QuicStringPiece plaintext,
+ quiche::QuicheStringPiece associated_data,
+ quiche::QuicheStringPiece plaintext,
char* output,
size_t* output_length,
size_t max_output_length) = 0;
@@ -46,7 +46,8 @@ class QUIC_EXPORT_PRIVATE QuicEncrypter : public QuicCrypter {
// generate a mask to use for header protection, and returns that mask. On
// success, the mask will be at least 5 bytes long; on failure the string will
// be empty.
- virtual std::string GenerateHeaderProtectionMask(QuicStringPiece sample) = 0;
+ virtual std::string GenerateHeaderProtectionMask(
+ quiche::QuicheStringPiece sample) = 0;
// Returns the maximum length of plaintext that can be encrypted
// to ciphertext no larger than |ciphertext_size|.
@@ -57,8 +58,8 @@ class QUIC_EXPORT_PRIVATE QuicEncrypter : public QuicCrypter {
virtual size_t GetCiphertextSize(size_t plaintext_size) const = 0;
// For use by unit tests only.
- virtual QuicStringPiece GetKey() const = 0;
- virtual QuicStringPiece GetNoncePrefix() const = 0;
+ virtual quiche::QuicheStringPiece GetKey() const = 0;
+ virtual quiche::QuicheStringPiece GetNoncePrefix() const = 0;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf.cc
index 1bd9ad54c2b..28cf4a93a18 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf.cc
@@ -9,15 +9,16 @@
#include "third_party/boringssl/src/include/openssl/digest.h"
#include "third_party/boringssl/src/include/openssl/hkdf.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
const size_t kSHA256HashLength = 32;
const size_t kMaxKeyMaterialSize = kSHA256HashLength * 256;
-QuicHKDF::QuicHKDF(QuicStringPiece secret,
- QuicStringPiece salt,
- QuicStringPiece info,
+QuicHKDF::QuicHKDF(quiche::QuicheStringPiece secret,
+ quiche::QuicheStringPiece salt,
+ quiche::QuicheStringPiece info,
size_t key_bytes_to_generate,
size_t iv_bytes_to_generate,
size_t subkey_secret_bytes_to_generate)
@@ -30,9 +31,9 @@ QuicHKDF::QuicHKDF(QuicStringPiece secret,
iv_bytes_to_generate,
subkey_secret_bytes_to_generate) {}
-QuicHKDF::QuicHKDF(QuicStringPiece secret,
- QuicStringPiece salt,
- QuicStringPiece info,
+QuicHKDF::QuicHKDF(quiche::QuicheStringPiece secret,
+ quiche::QuicheStringPiece salt,
+ quiche::QuicheStringPiece info,
size_t client_key_bytes_to_generate,
size_t server_key_bytes_to_generate,
size_t client_iv_bytes_to_generate,
@@ -59,44 +60,44 @@ QuicHKDF::QuicHKDF(QuicStringPiece secret,
size_t j = 0;
if (client_key_bytes_to_generate) {
- client_write_key_ = QuicStringPiece(reinterpret_cast<char*>(&output_[j]),
- client_key_bytes_to_generate);
+ client_write_key_ = quiche::QuicheStringPiece(
+ reinterpret_cast<char*>(&output_[j]), client_key_bytes_to_generate);
j += client_key_bytes_to_generate;
}
if (server_key_bytes_to_generate) {
- server_write_key_ = QuicStringPiece(reinterpret_cast<char*>(&output_[j]),
- server_key_bytes_to_generate);
+ server_write_key_ = quiche::QuicheStringPiece(
+ reinterpret_cast<char*>(&output_[j]), server_key_bytes_to_generate);
j += server_key_bytes_to_generate;
}
if (client_iv_bytes_to_generate) {
- client_write_iv_ = QuicStringPiece(reinterpret_cast<char*>(&output_[j]),
- client_iv_bytes_to_generate);
+ client_write_iv_ = quiche::QuicheStringPiece(
+ reinterpret_cast<char*>(&output_[j]), client_iv_bytes_to_generate);
j += client_iv_bytes_to_generate;
}
if (server_iv_bytes_to_generate) {
- server_write_iv_ = QuicStringPiece(reinterpret_cast<char*>(&output_[j]),
- server_iv_bytes_to_generate);
+ server_write_iv_ = quiche::QuicheStringPiece(
+ reinterpret_cast<char*>(&output_[j]), server_iv_bytes_to_generate);
j += server_iv_bytes_to_generate;
}
if (subkey_secret_bytes_to_generate) {
- subkey_secret_ = QuicStringPiece(reinterpret_cast<char*>(&output_[j]),
- subkey_secret_bytes_to_generate);
+ subkey_secret_ = quiche::QuicheStringPiece(
+ reinterpret_cast<char*>(&output_[j]), subkey_secret_bytes_to_generate);
j += subkey_secret_bytes_to_generate;
}
// Repeat client and server key bytes for header protection keys.
if (client_key_bytes_to_generate) {
- client_hp_key_ = QuicStringPiece(reinterpret_cast<char*>(&output_[j]),
- client_key_bytes_to_generate);
+ client_hp_key_ = quiche::QuicheStringPiece(
+ reinterpret_cast<char*>(&output_[j]), client_key_bytes_to_generate);
j += client_key_bytes_to_generate;
}
if (server_key_bytes_to_generate) {
- server_hp_key_ = QuicStringPiece(reinterpret_cast<char*>(&output_[j]),
- server_key_bytes_to_generate);
+ server_hp_key_ = quiche::QuicheStringPiece(
+ reinterpret_cast<char*>(&output_[j]), server_key_bytes_to_generate);
j += server_key_bytes_to_generate;
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf.h b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf.h
index 94d45bc91a6..2945173f421 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf.h
@@ -8,7 +8,7 @@
#include <vector>
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -31,18 +31,18 @@ class QUIC_EXPORT_PRIVATE QuicHKDF {
// client and server.
// |subkey_secret_bytes_to_generate|: the number of bytes of subkey secret to
// generate, shared between client and server.
- QuicHKDF(QuicStringPiece secret,
- QuicStringPiece salt,
- QuicStringPiece info,
+ QuicHKDF(quiche::QuicheStringPiece secret,
+ quiche::QuicheStringPiece salt,
+ quiche::QuicheStringPiece info,
size_t key_bytes_to_generate,
size_t iv_bytes_to_generate,
size_t subkey_secret_bytes_to_generate);
// An alternative constructor that allows the client and server key/IV
// lengths to be different.
- QuicHKDF(QuicStringPiece secret,
- QuicStringPiece salt,
- QuicStringPiece info,
+ QuicHKDF(quiche::QuicheStringPiece secret,
+ quiche::QuicheStringPiece salt,
+ quiche::QuicheStringPiece info,
size_t client_key_bytes_to_generate,
size_t server_key_bytes_to_generate,
size_t client_iv_bytes_to_generate,
@@ -51,24 +51,28 @@ class QUIC_EXPORT_PRIVATE QuicHKDF {
~QuicHKDF();
- QuicStringPiece client_write_key() const { return client_write_key_; }
- QuicStringPiece client_write_iv() const { return client_write_iv_; }
- QuicStringPiece server_write_key() const { return server_write_key_; }
- QuicStringPiece server_write_iv() const { return server_write_iv_; }
- QuicStringPiece subkey_secret() const { return subkey_secret_; }
- QuicStringPiece client_hp_key() const { return client_hp_key_; }
- QuicStringPiece server_hp_key() const { return server_hp_key_; }
+ quiche::QuicheStringPiece client_write_key() const {
+ return client_write_key_;
+ }
+ quiche::QuicheStringPiece client_write_iv() const { return client_write_iv_; }
+ quiche::QuicheStringPiece server_write_key() const {
+ return server_write_key_;
+ }
+ quiche::QuicheStringPiece server_write_iv() const { return server_write_iv_; }
+ quiche::QuicheStringPiece subkey_secret() const { return subkey_secret_; }
+ quiche::QuicheStringPiece client_hp_key() const { return client_hp_key_; }
+ quiche::QuicheStringPiece server_hp_key() const { return server_hp_key_; }
private:
std::vector<uint8_t> output_;
- QuicStringPiece client_write_key_;
- QuicStringPiece server_write_key_;
- QuicStringPiece client_write_iv_;
- QuicStringPiece server_write_iv_;
- QuicStringPiece subkey_secret_;
- QuicStringPiece client_hp_key_;
- QuicStringPiece server_hp_key_;
+ quiche::QuicheStringPiece client_write_key_;
+ quiche::QuicheStringPiece server_write_key_;
+ quiche::QuicheStringPiece client_write_iv_;
+ quiche::QuicheStringPiece server_write_iv_;
+ quiche::QuicheStringPiece subkey_secret_;
+ quiche::QuicheStringPiece client_hp_key_;
+ quiche::QuicheStringPiece server_hp_key_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf_test.cc
index e40bebf62e6..8b74f633d02 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf_test.cc
@@ -6,9 +6,9 @@
#include <string>
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
namespace test {
@@ -67,14 +67,15 @@ static const HKDFInput kHKDFInputs[] = {
class QuicHKDFTest : public QuicTest {};
TEST_F(QuicHKDFTest, HKDF) {
- for (size_t i = 0; i < QUIC_ARRAYSIZE(kHKDFInputs); i++) {
+ for (size_t i = 0; i < QUICHE_ARRAYSIZE(kHKDFInputs); i++) {
const HKDFInput& test(kHKDFInputs[i]);
SCOPED_TRACE(i);
- const std::string key = QuicTextUtils::HexDecode(test.key_hex);
- const std::string salt = QuicTextUtils::HexDecode(test.salt_hex);
- const std::string info = QuicTextUtils::HexDecode(test.info_hex);
- const std::string expected = QuicTextUtils::HexDecode(test.output_hex);
+ const std::string key = quiche::QuicheTextUtils::HexDecode(test.key_hex);
+ const std::string salt = quiche::QuicheTextUtils::HexDecode(test.salt_hex);
+ const std::string info = quiche::QuicheTextUtils::HexDecode(test.info_hex);
+ const std::string expected =
+ quiche::QuicheTextUtils::HexDecode(test.output_hex);
// We set the key_length to the length of the expected output and then take
// the result from the first key, which is the client write key.
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/server_proof_verifier.h b/chromium/net/third_party/quiche/src/quic/core/crypto/server_proof_verifier.h
new file mode 100644
index 00000000000..94fe131bd07
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/server_proof_verifier.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_CORE_CRYPTO_SERVER_PROOF_VERIFIER_H_
+#define QUICHE_QUIC_CORE_CRYPTO_SERVER_PROOF_VERIFIER_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "net/third_party/quiche/src/quic/core/crypto/proof_verifier.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+
+namespace quic {
+
+// A ServerProofVerifier checks the certificate chain presented by a client.
+class QUIC_EXPORT_PRIVATE ServerProofVerifier {
+ public:
+ virtual ~ServerProofVerifier() {}
+
+ // VerifyCertChain checks that |certs| is a valid chain. On success, it
+ // returns QUIC_SUCCESS. On failure, it returns QUIC_FAILURE and sets
+ // |*error_details| to a description of the problem. In either case it may set
+ // |*details|, which the caller takes ownership of.
+ //
+ // |context| specifies an implementation specific struct (which may be nullptr
+ // for some implementations) that provides useful information for the
+ // verifier, e.g. logging handles.
+ //
+ // This function may also return QUIC_PENDING, in which case the
+ // ServerProofVerifier will call back, on the original thread, via |callback|
+ // when complete. In this case, the ServerProofVerifier will take ownership of
+ // |callback|.
+ virtual QuicAsyncStatus VerifyCertChain(
+ const std::vector<std::string>& certs,
+ std::string* error_details,
+ std::unique_ptr<ProofVerifierCallback> callback) = 0;
+};
+
+} // namespace quic
+#endif // QUICHE_QUIC_CORE_CRYPTO_SERVER_PROOF_VERIFIER_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.cc
index d28db2292e4..b0d2147c286 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.cc
@@ -5,6 +5,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/tls_connection.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -107,10 +108,18 @@ TlsConnection* TlsConnection::ConnectionFromSsl(const SSL* ssl) {
ssl, SslIndexSingleton::GetInstance()->ssl_ex_data_index_connection()));
}
+// TODO(nharper): Once
+// https://boringssl-review.googlesource.com/c/boringssl/+/40127 lands and is
+// rolled into google3, remove the BORINGSSL_API_VERSION check.
const SSL_QUIC_METHOD TlsConnection::kSslQuicMethod{
- TlsConnection::SetEncryptionSecretCallback,
- TlsConnection::WriteMessageCallback, TlsConnection::FlushFlightCallback,
- TlsConnection::SendAlertCallback};
+#if BORINGSSL_API_VERSION < 10
+ TlsConnection::SetEncryptionSecretCallback,
+#else
+ TlsConnection::SetReadSecretCallback, TlsConnection::SetWriteSecretCallback,
+#endif
+ TlsConnection::WriteMessageCallback, TlsConnection::FlushFlightCallback,
+ TlsConnection::SendAlertCallback
+};
// static
int TlsConnection::SetEncryptionSecretCallback(
@@ -124,8 +133,44 @@ int TlsConnection::SetEncryptionSecretCallback(
std::vector<uint8_t> read_secret(key_length), write_secret(key_length);
memcpy(read_secret.data(), read_key, key_length);
memcpy(write_secret.data(), write_key, key_length);
- ConnectionFromSsl(ssl)->delegate_->SetEncryptionSecret(
- QuicEncryptionLevel(level), read_secret, write_secret);
+ TlsConnection::Delegate* delegate = ConnectionFromSsl(ssl)->delegate_;
+ const SSL_CIPHER* cipher = SSL_get_pending_cipher(ssl);
+ delegate->SetWriteSecret(QuicEncryptionLevel(level), cipher, write_secret);
+ if (!delegate->SetReadSecret(QuicEncryptionLevel(level), cipher,
+ read_secret)) {
+ return 0;
+ }
+ return 1;
+}
+
+// static
+int TlsConnection::SetReadSecretCallback(SSL* ssl,
+ enum ssl_encryption_level_t level,
+ const SSL_CIPHER* cipher,
+ const uint8_t* secret,
+ size_t secret_length) {
+ // TODO(nharper): replace this vector with a span (which unfortunately doesn't
+ // yet exist in quic/platform/api).
+ std::vector<uint8_t> secret_vec(secret, secret + secret_length);
+ TlsConnection::Delegate* delegate = ConnectionFromSsl(ssl)->delegate_;
+ if (!delegate->SetReadSecret(QuicEncryptionLevel(level), cipher,
+ secret_vec)) {
+ return 0;
+ }
+ return 1;
+}
+
+// static
+int TlsConnection::SetWriteSecretCallback(SSL* ssl,
+ enum ssl_encryption_level_t level,
+ const SSL_CIPHER* cipher,
+ const uint8_t* secret,
+ size_t secret_length) {
+ // TODO(nharper): replace this vector with a span (which unfortunately doesn't
+ // yet exist in quic/platform/api).
+ std::vector<uint8_t> secret_vec(secret, secret + secret_length);
+ TlsConnection::Delegate* delegate = ConnectionFromSsl(ssl)->delegate_;
+ delegate->SetWriteSecret(QuicEncryptionLevel(level), cipher, secret_vec);
return 1;
}
@@ -136,7 +181,7 @@ int TlsConnection::WriteMessageCallback(SSL* ssl,
size_t len) {
ConnectionFromSsl(ssl)->delegate_->WriteMessage(
QuicEncryptionLevel(level),
- QuicStringPiece(reinterpret_cast<const char*>(data), len));
+ quiche::QuicheStringPiece(reinterpret_cast<const char*>(data), len));
return 1;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.h b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.h
index fd4f64b1978..d65f63c68e5 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.h
@@ -9,7 +9,7 @@
#include "third_party/boringssl/src/include/openssl/ssl.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -31,21 +31,29 @@ class QUIC_EXPORT_PRIVATE TlsConnection {
virtual ~Delegate() {}
protected:
- // SetEncryptionSecret provides the encryption secrets to use at a
- // particular encryption level |level|. The secrets provided here are the
- // ones from the TLS 1.3 key schedule (RFC 8446 section 7.1), in particular
- // the handshake traffic secrets and application traffic secrets. For a
- // given level |level|, |read_secret| is the secret used for reading data,
- // and |write_secret| is the secret used for writing data.
- virtual void SetEncryptionSecret(
- EncryptionLevel level,
- const std::vector<uint8_t>& read_secret,
- const std::vector<uint8_t>& write_secret) = 0;
+ // SetWriteSecret provides the encryption secret used to encrypt messages at
+ // encryption level |level|. The secret provided here is the one from the
+ // TLS 1.3 key schedule (RFC 8446 section 7.1), in particular the handshake
+ // traffic secrets and application traffic secrets. The provided write
+ // secret must be used with the provided cipher suite |cipher|.
+ virtual void SetWriteSecret(EncryptionLevel level,
+ const SSL_CIPHER* cipher,
+ const std::vector<uint8_t>& write_secret) = 0;
+
+ // SetReadSecret is similar to SetWriteSecret, except that it is used for
+ // decrypting messages. SetReadSecret at a particular level is always called
+ // after SetWriteSecret for that level, except for ENCRYPTION_ZERO_RTT,
+ // where the EncryptionLevel for SetWriteSecret is
+ // ENCRYPTION_FORWARD_SECURE.
+ virtual bool SetReadSecret(EncryptionLevel level,
+ const SSL_CIPHER* cipher,
+ const std::vector<uint8_t>& read_secret) = 0;
// WriteMessage is called when there is |data| from the TLS stack ready for
// the QUIC stack to write in a crypto frame. The data must be transmitted
// at encryption level |level|.
- virtual void WriteMessage(EncryptionLevel level, QuicStringPiece data) = 0;
+ virtual void WriteMessage(EncryptionLevel level,
+ quiche::QuicheStringPiece data) = 0;
// FlushFlight is called to signal that the current flight of messages have
// all been written (via calls to WriteMessage) and can be flushed to the
@@ -98,6 +106,16 @@ class QUIC_EXPORT_PRIVATE TlsConnection {
const uint8_t* read_key,
const uint8_t* write_key,
size_t key_length);
+ static int SetReadSecretCallback(SSL* ssl,
+ enum ssl_encryption_level_t level,
+ const SSL_CIPHER* cipher,
+ const uint8_t* secret,
+ size_t secret_len);
+ static int SetWriteSecretCallback(SSL* ssl,
+ enum ssl_encryption_level_t level,
+ const SSL_CIPHER* cipher,
+ const uint8_t* secret,
+ size_t secret_len);
static int WriteMessageCallback(SSL* ssl,
enum ssl_encryption_level_t level,
const uint8_t* data,
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.cc
index f539a089d2c..bdc941ade7c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.cc
@@ -4,6 +4,8 @@
#include "net/third_party/quiche/src/quic/core/crypto/tls_server_connection.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+
namespace quic {
TlsServerConnection::TlsServerConnection(SSL_CTX* ssl_ctx, Delegate* delegate)
@@ -66,7 +68,7 @@ ssl_private_key_result_t TlsServerConnection::PrivateKeySign(SSL* ssl,
size_t in_len) {
return ConnectionFromSsl(ssl)->delegate_->PrivateKeySign(
out, out_len, max_out, sig_alg,
- QuicStringPiece(reinterpret_cast<const char*>(in), in_len));
+ quiche::QuicheStringPiece(reinterpret_cast<const char*>(in), in_len));
}
// static
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.h b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.h
index 96d71e2bef1..85ce7e79a81 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.h
@@ -6,6 +6,7 @@
#define QUICHE_QUIC_CORE_CRYPTO_TLS_SERVER_CONNECTION_H_
#include "net/third_party/quiche/src/quic/core/crypto/tls_connection.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -41,11 +42,12 @@ class QUIC_EXPORT_PRIVATE TlsServerConnection : public TlsConnection {
// ssl_private_key_failure is returned. Otherwise, ssl_private_key_success
// is returned with the signature put in |*out| and the length in
// |*out_len|.
- virtual ssl_private_key_result_t PrivateKeySign(uint8_t* out,
- size_t* out_len,
- size_t max_out,
- uint16_t sig_alg,
- QuicStringPiece in) = 0;
+ virtual ssl_private_key_result_t PrivateKeySign(
+ uint8_t* out,
+ size_t* out_len,
+ size_t max_out,
+ uint16_t sig_alg,
+ quiche::QuicheStringPiece in) = 0;
// When PrivateKeySign returns ssl_private_key_retry, PrivateKeyComplete
// will be called after the async sign operation has completed.
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.cc
index a870017b0b3..4cefcddad22 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.cc
@@ -9,7 +9,6 @@
#include <forward_list>
#include <utility>
-#include "third_party/boringssl/src/include/openssl/bytestring.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_framer.h"
#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
#include "net/third_party/quiche/src/quic/core/quic_data_reader.h"
@@ -18,7 +17,9 @@
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
@@ -27,7 +28,7 @@ namespace quic {
// When parameters are encoded, one of these enum values is used to indicate
// which parameter is encoded. The supported draft version is noted in
// transport_parameters.h.
-enum TransportParameters::TransportParameterId : uint16_t {
+enum TransportParameters::TransportParameterId : uint64_t {
kOriginalConnectionId = 0,
kIdleTimeout = 1,
kStatelessResetToken = 2,
@@ -57,7 +58,6 @@ namespace {
// the parameters. These come from the "Transport Parameter Definitions"
// section of draft-ietf-quic-transport.
const uint64_t kMinMaxPacketSizeTransportParam = 1200;
-const uint64_t kDefaultMaxPacketSizeTransportParam = 65527;
const uint64_t kMaxAckDelayExponentTransportParam = 20;
const uint64_t kDefaultAckDelayExponentTransportParam = 3;
const uint64_t kMaxMaxAckDelayTransportParam = 16383;
@@ -104,7 +104,89 @@ std::string TransportParameterIdToString(
case TransportParameters::kGoogleQuicVersion:
return "google-version";
}
- return "Unknown(" + QuicTextUtils::Uint64ToString(param_id) + ")";
+ return "Unknown(" + quiche::QuicheTextUtils::Uint64ToString(param_id) + ")";
+}
+
+bool WriteTransportParameterId(
+ QuicDataWriter* writer,
+ TransportParameters::TransportParameterId param_id,
+ ParsedQuicVersion version) {
+ if (version.HasVarIntTransportParams()) {
+ if (!writer->WriteVarInt62(param_id)) {
+ QUIC_BUG << "Failed to write param_id for "
+ << TransportParameterIdToString(param_id);
+ return false;
+ }
+ } else {
+ if (static_cast<uint64_t>(param_id) >
+ std::numeric_limits<uint16_t>::max()) {
+ QUIC_BUG << "Cannot serialize transport parameter "
+ << TransportParameterIdToString(param_id) << " with version "
+ << version;
+ return false;
+ }
+ if (!writer->WriteUInt16(param_id)) {
+ QUIC_BUG << "Failed to write param_id16 for "
+ << TransportParameterIdToString(param_id);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool WriteTransportParameterLength(QuicDataWriter* writer,
+ uint64_t length,
+ ParsedQuicVersion version) {
+ if (version.HasVarIntTransportParams()) {
+ return writer->WriteVarInt62(length);
+ }
+ if (length > std::numeric_limits<uint16_t>::max()) {
+ QUIC_BUG << "Cannot serialize transport parameter length " << length
+ << " with version " << version;
+ return false;
+ }
+ return writer->WriteUInt16(length);
+}
+
+bool WriteTransportParameterStringPiece(QuicDataWriter* writer,
+ quiche::QuicheStringPiece value,
+ ParsedQuicVersion version) {
+ if (version.HasVarIntTransportParams()) {
+ return writer->WriteStringPieceVarInt62(value);
+ }
+ return writer->WriteStringPiece16(value);
+}
+
+bool ReadTransportParameterId(
+ QuicDataReader* reader,
+ ParsedQuicVersion version,
+ TransportParameters::TransportParameterId* out_param_id) {
+ if (version.HasVarIntTransportParams()) {
+ uint64_t param_id64;
+ if (!reader->ReadVarInt62(&param_id64)) {
+ return false;
+ }
+ *out_param_id =
+ static_cast<TransportParameters::TransportParameterId>(param_id64);
+ } else {
+ uint16_t param_id16;
+ if (!reader->ReadUInt16(&param_id16)) {
+ return false;
+ }
+ *out_param_id =
+ static_cast<TransportParameters::TransportParameterId>(param_id16);
+ }
+ return true;
+}
+
+bool ReadTransportParameterLengthAndValue(
+ QuicDataReader* reader,
+ ParsedQuicVersion version,
+ quiche::QuicheStringPiece* out_value) {
+ if (version.HasVarIntTransportParams()) {
+ return reader->ReadStringPieceVarInt62(out_value);
+ }
+ return reader->ReadStringPiece16(out_value);
}
} // namespace
@@ -119,7 +201,7 @@ TransportParameters::IntegerParameter::IntegerParameter(
default_value_(default_value),
min_value_(min_value),
max_value_(max_value),
- has_been_read_from_cbs_(false) {
+ has_been_read_(false) {
DCHECK_LE(min_value, default_value);
DCHECK_LE(default_value, max_value);
DCHECK_LE(max_value, kVarInt62MaxValue);
@@ -145,47 +227,56 @@ bool TransportParameters::IntegerParameter::IsValid() const {
return min_value_ <= value_ && value_ <= max_value_;
}
-bool TransportParameters::IntegerParameter::WriteToCbb(CBB* parent_cbb) const {
+bool TransportParameters::IntegerParameter::Write(
+ QuicDataWriter* writer,
+ ParsedQuicVersion version) const {
DCHECK(IsValid());
if (value_ == default_value_) {
// Do not write if the value is default.
return true;
}
- uint8_t encoded_data[sizeof(uint64_t)] = {};
- QuicDataWriter writer(sizeof(encoded_data),
- reinterpret_cast<char*>(encoded_data));
- writer.WriteVarInt62(value_);
- const uint16_t value_length = writer.length();
- DCHECK_LE(value_length, sizeof(encoded_data));
- const bool ok = CBB_add_u16(parent_cbb, param_id_) &&
- CBB_add_u16(parent_cbb, value_length) &&
- CBB_add_bytes(parent_cbb, encoded_data, value_length);
- QUIC_BUG_IF(!ok) << "Failed to write " << this;
- return ok;
-}
-
-bool TransportParameters::IntegerParameter::ReadFromCbs(CBS* const value_cbs) {
- if (has_been_read_from_cbs_) {
- QUIC_DLOG(ERROR) << "Received a second "
- << TransportParameterIdToString(param_id_);
+ if (!WriteTransportParameterId(writer, param_id_, version)) {
+ QUIC_BUG << "Failed to write param_id for " << *this;
return false;
}
- has_been_read_from_cbs_ = true;
- QuicDataReader reader(reinterpret_cast<const char*>(CBS_data(value_cbs)),
- CBS_len(value_cbs));
- QuicVariableLengthIntegerLength value_length = reader.PeekVarInt62Length();
- if (value_length == 0 || !reader.ReadVarInt62(&value_)) {
- QUIC_DLOG(ERROR) << "Failed to parse value for "
- << TransportParameterIdToString(param_id_);
+ const QuicVariableLengthIntegerLength value_length =
+ QuicDataWriter::GetVarInt62Len(value_);
+ if (version.HasVarIntTransportParams()) {
+ if (!writer->WriteVarInt62(value_length)) {
+ QUIC_BUG << "Failed to write value_length for " << *this;
+ return false;
+ }
+ } else {
+ if (!writer->WriteUInt16(value_length)) {
+ QUIC_BUG << "Failed to write value_length16 for " << *this;
+ return false;
+ }
+ }
+ if (!writer->WriteVarInt62(value_, value_length)) {
+ QUIC_BUG << "Failed to write value for " << *this;
+ return false;
+ }
+ return true;
+}
+
+bool TransportParameters::IntegerParameter::Read(QuicDataReader* reader,
+ std::string* error_details) {
+ if (has_been_read_) {
+ *error_details =
+ "Received a second " + TransportParameterIdToString(param_id_);
return false;
}
- if (!reader.IsDoneReading()) {
- QUIC_DLOG(ERROR) << "Received unexpected " << reader.BytesRemaining()
- << " bytes after parsing " << this;
+ has_been_read_ = true;
+
+ if (!reader->ReadVarInt62(&value_)) {
+ *error_details =
+ "Failed to parse value for " + TransportParameterIdToString(param_id_);
return false;
}
- if (!CBS_skip(value_cbs, value_length)) {
- QUIC_BUG << "Failed to advance CBS past value for " << this;
+ if (!reader->IsDoneReading()) {
+ *error_details =
+ quiche::QuicheStrCat("Received unexpected ", reader->BytesRemaining(),
+ " bytes after parsing ", this->ToString(false));
return false;
}
return true;
@@ -198,7 +289,7 @@ std::string TransportParameters::IntegerParameter::ToString(
}
std::string rv = for_use_in_list ? " " : "";
rv += TransportParameterIdToString(param_id_) + " ";
- rv += QuicTextUtils::Uint64ToString(value_);
+ rv += quiche::QuicheTextUtils::Uint64ToString(value_);
if (!IsValid()) {
rv += " (Invalid)";
}
@@ -230,7 +321,7 @@ std::string TransportParameters::PreferredAddress::ToString() const {
return "[" + ipv4_socket_address.ToString() + " " +
ipv6_socket_address.ToString() + " connection_id " +
connection_id.ToString() + " stateless_reset_token " +
- QuicTextUtils::HexEncode(
+ quiche::QuicheTextUtils::HexEncode(
reinterpret_cast<const char*>(stateless_reset_token.data()),
stateless_reset_token.size()) +
"]";
@@ -262,7 +353,7 @@ std::string TransportParameters::ToString() const {
rv += idle_timeout_milliseconds.ToString(/*for_use_in_list=*/true);
if (!stateless_reset_token.empty()) {
rv += " " + TransportParameterIdToString(kStatelessResetToken) + " " +
- QuicTextUtils::HexEncode(
+ quiche::QuicheTextUtils::HexEncode(
reinterpret_cast<const char*>(stateless_reset_token.data()),
stateless_reset_token.size());
}
@@ -289,8 +380,8 @@ std::string TransportParameters::ToString() const {
}
rv += "]";
for (const auto& kv : custom_parameters) {
- rv += " 0x" + QuicTextUtils::Hex(static_cast<uint32_t>(kv.first));
- rv += "=" + QuicTextUtils::HexEncode(kv.second);
+ rv += " 0x" + quiche::QuicheTextUtils::Hex(static_cast<uint32_t>(kv.first));
+ rv += "=" + quiche::QuicheTextUtils::HexEncode(kv.second);
}
return rv;
}
@@ -325,39 +416,40 @@ TransportParameters::TransportParameters()
// ParseTransportParameters.
{}
-bool TransportParameters::AreValid() const {
+bool TransportParameters::AreValid(std::string* error_details) const {
DCHECK(perspective == Perspective::IS_CLIENT ||
perspective == Perspective::IS_SERVER);
if (perspective == Perspective::IS_CLIENT && !stateless_reset_token.empty()) {
- QUIC_DLOG(ERROR) << "Client cannot send stateless reset token";
+ *error_details = "Client cannot send stateless reset token";
return false;
}
if (perspective == Perspective::IS_CLIENT &&
!original_connection_id.IsEmpty()) {
- QUIC_DLOG(ERROR) << "Client cannot send original connection ID";
+ *error_details = "Client cannot send original connection ID";
return false;
}
if (!stateless_reset_token.empty() &&
stateless_reset_token.size() != kStatelessResetTokenLength) {
- QUIC_DLOG(ERROR) << "Stateless reset token has bad length "
- << stateless_reset_token.size();
+ *error_details = quiche::QuicheStrCat(
+ "Stateless reset token has bad length ", stateless_reset_token.size());
return false;
}
if (perspective == Perspective::IS_CLIENT && preferred_address) {
- QUIC_DLOG(ERROR) << "Client cannot send preferred address";
+ *error_details = "Client cannot send preferred address";
return false;
}
if (preferred_address && preferred_address->stateless_reset_token.size() !=
kStatelessResetTokenLength) {
- QUIC_DLOG(ERROR)
- << "Preferred address stateless reset token has bad length "
- << preferred_address->stateless_reset_token.size();
+ *error_details = quiche::QuicheStrCat(
+ "Preferred address stateless reset token has bad length ",
+ preferred_address->stateless_reset_token.size());
return false;
}
if (preferred_address &&
(!preferred_address->ipv4_socket_address.host().IsIPv4() ||
!preferred_address->ipv6_socket_address.host().IsIPv6())) {
QUIC_BUG << "Preferred address family failure";
+ *error_details = "Internal preferred address family failure";
return false;
}
const bool ok =
@@ -370,104 +462,112 @@ bool TransportParameters::AreValid() const {
ack_delay_exponent.IsValid() && max_ack_delay.IsValid() &&
active_connection_id_limit.IsValid() && max_datagram_frame_size.IsValid();
if (!ok) {
- QUIC_DLOG(ERROR) << "Invalid transport parameters " << *this;
+ *error_details = "Invalid transport parameters " + this->ToString();
}
return ok;
}
TransportParameters::~TransportParameters() = default;
-bool SerializeTransportParameters(ParsedQuicVersion /*version*/,
+bool SerializeTransportParameters(ParsedQuicVersion version,
const TransportParameters& in,
std::vector<uint8_t>* out) {
- if (!in.AreValid()) {
- QUIC_DLOG(ERROR) << "Not serializing invalid transport parameters " << in;
+ std::string error_details;
+ if (!in.AreValid(&error_details)) {
+ QUIC_BUG << "Not serializing invalid transport parameters: "
+ << error_details;
return false;
}
if (in.version == 0 || (in.perspective == Perspective::IS_SERVER &&
in.supported_versions.empty())) {
- QUIC_DLOG(ERROR) << "Refusing to serialize without versions";
+ QUIC_BUG << "Refusing to serialize without versions";
return false;
}
- bssl::ScopedCBB cbb;
// Empirically transport parameters generally fit within 128 bytes.
- // The CBB will grow to fit larger serializations if required.
- if (!CBB_init(cbb.get(), 128)) {
- QUIC_BUG << "Failed to initialize CBB for " << in;
- return false;
- }
-
- CBB params;
- // Add length of the transport parameters list.
- if (!CBB_add_u16_length_prefixed(cbb.get(), &params)) {
- QUIC_BUG << "Failed to write parameter length for " << in;
- return false;
+ // For now we hope this will be enough.
+ // TODO(dschinazi) make this grow if needed.
+ static const size_t kMaxTransportParametersLength = 4096;
+ out->resize(kMaxTransportParametersLength);
+ QuicDataWriter writer(out->size(), reinterpret_cast<char*>(out->data()));
+
+ if (!version.HasVarIntTransportParams()) {
+ // Versions that do not use variable integer transport parameters carry
+ // a 16-bit length of the remaining transport parameters. We write 0 here
+ // to reserve 16 bits, and we fill it in at the end of this function.
+ // TODO(b/150465921) add support for doing this in QuicDataWriter.
+ if (!writer.WriteUInt16(0)) {
+ QUIC_BUG << "Failed to write transport parameter fake length prefix for "
+ << in;
+ return false;
+ }
}
// original_connection_id
- CBB original_connection_id_param;
if (!in.original_connection_id.IsEmpty()) {
DCHECK_EQ(Perspective::IS_SERVER, in.perspective);
- if (!CBB_add_u16(&params, TransportParameters::kOriginalConnectionId) ||
- !CBB_add_u16_length_prefixed(&params, &original_connection_id_param) ||
- !CBB_add_bytes(
- &original_connection_id_param,
- reinterpret_cast<const uint8_t*>(in.original_connection_id.data()),
- in.original_connection_id.length())) {
+ if (!WriteTransportParameterId(
+ &writer, TransportParameters::kOriginalConnectionId, version) ||
+ !WriteTransportParameterStringPiece(
+ &writer,
+ quiche::QuicheStringPiece(in.original_connection_id.data(),
+ in.original_connection_id.length()),
+ version)) {
QUIC_BUG << "Failed to write original_connection_id "
<< in.original_connection_id << " for " << in;
return false;
}
}
- if (!in.idle_timeout_milliseconds.WriteToCbb(&params)) {
+ if (!in.idle_timeout_milliseconds.Write(&writer, version)) {
QUIC_BUG << "Failed to write idle_timeout for " << in;
return false;
}
// stateless_reset_token
- CBB stateless_reset_token_param;
if (!in.stateless_reset_token.empty()) {
DCHECK_EQ(kStatelessResetTokenLength, in.stateless_reset_token.size());
DCHECK_EQ(Perspective::IS_SERVER, in.perspective);
- if (!CBB_add_u16(&params, TransportParameters::kStatelessResetToken) ||
- !CBB_add_u16_length_prefixed(&params, &stateless_reset_token_param) ||
- !CBB_add_bytes(&stateless_reset_token_param,
- in.stateless_reset_token.data(),
- in.stateless_reset_token.size())) {
+ if (!WriteTransportParameterId(
+ &writer, TransportParameters::kStatelessResetToken, version) ||
+ !WriteTransportParameterStringPiece(
+ &writer,
+ quiche::QuicheStringPiece(
+ reinterpret_cast<const char*>(in.stateless_reset_token.data()),
+ in.stateless_reset_token.size()),
+ version)) {
QUIC_BUG << "Failed to write stateless_reset_token of length "
<< in.stateless_reset_token.size() << " for " << in;
return false;
}
}
- if (!in.max_packet_size.WriteToCbb(&params) ||
- !in.initial_max_data.WriteToCbb(&params) ||
- !in.initial_max_stream_data_bidi_local.WriteToCbb(&params) ||
- !in.initial_max_stream_data_bidi_remote.WriteToCbb(&params) ||
- !in.initial_max_stream_data_uni.WriteToCbb(&params) ||
- !in.initial_max_streams_bidi.WriteToCbb(&params) ||
- !in.initial_max_streams_uni.WriteToCbb(&params) ||
- !in.ack_delay_exponent.WriteToCbb(&params) ||
- !in.max_ack_delay.WriteToCbb(&params) ||
- !in.active_connection_id_limit.WriteToCbb(&params) ||
- !in.max_datagram_frame_size.WriteToCbb(&params)) {
+ if (!in.max_packet_size.Write(&writer, version) ||
+ !in.initial_max_data.Write(&writer, version) ||
+ !in.initial_max_stream_data_bidi_local.Write(&writer, version) ||
+ !in.initial_max_stream_data_bidi_remote.Write(&writer, version) ||
+ !in.initial_max_stream_data_uni.Write(&writer, version) ||
+ !in.initial_max_streams_bidi.Write(&writer, version) ||
+ !in.initial_max_streams_uni.Write(&writer, version) ||
+ !in.ack_delay_exponent.Write(&writer, version) ||
+ !in.max_ack_delay.Write(&writer, version) ||
+ !in.active_connection_id_limit.Write(&writer, version) ||
+ !in.max_datagram_frame_size.Write(&writer, version)) {
QUIC_BUG << "Failed to write integers for " << in;
return false;
}
// disable_migration
if (in.disable_migration) {
- if (!CBB_add_u16(&params, TransportParameters::kDisableMigration) ||
- !CBB_add_u16(&params, 0u)) { // 0 is the length of this parameter.
+ if (!WriteTransportParameterId(
+ &writer, TransportParameters::kDisableMigration, version) ||
+ !WriteTransportParameterLength(&writer, /*length=*/0, version)) {
QUIC_BUG << "Failed to write disable_migration for " << in;
return false;
}
}
// preferred_address
- CBB preferred_address_params, preferred_address_connection_id_param;
if (in.preferred_address) {
std::string v4_address_bytes =
in.preferred_address->ipv4_socket_address.host().ToPackedString();
@@ -479,45 +579,39 @@ bool SerializeTransportParameters(ParsedQuicVersion /*version*/,
QUIC_BUG << "Bad lengths " << *in.preferred_address;
return false;
}
- if (!CBB_add_u16(&params, TransportParameters::kPreferredAddress) ||
- !CBB_add_u16_length_prefixed(&params, &preferred_address_params) ||
- !CBB_add_bytes(
- &preferred_address_params,
- reinterpret_cast<const uint8_t*>(v4_address_bytes.data()),
- v4_address_bytes.length()) ||
- !CBB_add_u16(&preferred_address_params,
- in.preferred_address->ipv4_socket_address.port()) ||
- !CBB_add_bytes(
- &preferred_address_params,
- reinterpret_cast<const uint8_t*>(v6_address_bytes.data()),
- v6_address_bytes.length()) ||
- !CBB_add_u16(&preferred_address_params,
- in.preferred_address->ipv6_socket_address.port()) ||
- !CBB_add_u8_length_prefixed(&preferred_address_params,
- &preferred_address_connection_id_param) ||
- !CBB_add_bytes(&preferred_address_connection_id_param,
- reinterpret_cast<const uint8_t*>(
- in.preferred_address->connection_id.data()),
- in.preferred_address->connection_id.length()) ||
- !CBB_add_bytes(&preferred_address_params,
- in.preferred_address->stateless_reset_token.data(),
- in.preferred_address->stateless_reset_token.size())) {
+ const uint64_t preferred_address_length =
+ v4_address_bytes.length() + /* IPv4 port */ sizeof(uint16_t) +
+ v6_address_bytes.length() + /* IPv6 port */ sizeof(uint16_t) +
+ /* connection ID length byte */ sizeof(uint8_t) +
+ in.preferred_address->connection_id.length() +
+ in.preferred_address->stateless_reset_token.size();
+ if (!WriteTransportParameterId(
+ &writer, TransportParameters::kPreferredAddress, version) ||
+ !WriteTransportParameterLength(&writer, preferred_address_length,
+ version) ||
+ !writer.WriteStringPiece(v4_address_bytes) ||
+ !writer.WriteUInt16(in.preferred_address->ipv4_socket_address.port()) ||
+ !writer.WriteStringPiece(v6_address_bytes) ||
+ !writer.WriteUInt16(in.preferred_address->ipv6_socket_address.port()) ||
+ !writer.WriteUInt8(in.preferred_address->connection_id.length()) ||
+ !writer.WriteBytes(in.preferred_address->connection_id.data(),
+ in.preferred_address->connection_id.length()) ||
+ !writer.WriteBytes(
+ in.preferred_address->stateless_reset_token.data(),
+ in.preferred_address->stateless_reset_token.size())) {
QUIC_BUG << "Failed to write preferred_address for " << in;
return false;
}
}
// Google-specific non-standard parameter.
- CBB google_quic_params;
if (in.google_quic_params) {
const QuicData& serialized_google_quic_params =
in.google_quic_params->GetSerialized();
- if (!CBB_add_u16(&params, TransportParameters::kGoogleQuicParam) ||
- !CBB_add_u16_length_prefixed(&params, &google_quic_params) ||
- !CBB_add_bytes(&google_quic_params,
- reinterpret_cast<const uint8_t*>(
- serialized_google_quic_params.data()),
- serialized_google_quic_params.length())) {
+ if (!WriteTransportParameterId(
+ &writer, TransportParameters::kGoogleQuicParam, version) ||
+ !WriteTransportParameterStringPiece(
+ &writer, serialized_google_quic_params.AsStringPiece(), version)) {
QUIC_BUG << "Failed to write Google params of length "
<< serialized_google_quic_params.length() << " for " << in;
return false;
@@ -525,51 +619,65 @@ bool SerializeTransportParameters(ParsedQuicVersion /*version*/,
}
// Google-specific version extension.
- CBB google_version_params;
- if (!CBB_add_u16(&params, TransportParameters::kGoogleQuicVersion) ||
- !CBB_add_u16_length_prefixed(&params, &google_version_params) ||
- !CBB_add_u32(&google_version_params, in.version)) {
+ static_assert(sizeof(QuicVersionLabel) == sizeof(uint32_t), "bad length");
+ uint64_t google_version_length = sizeof(in.version);
+ if (in.perspective == Perspective::IS_SERVER) {
+ google_version_length +=
+ /* versions length */ sizeof(uint8_t) +
+ sizeof(QuicVersionLabel) * in.supported_versions.size();
+ }
+ if (!WriteTransportParameterId(
+ &writer, TransportParameters::kGoogleQuicVersion, version) ||
+ !WriteTransportParameterLength(&writer, google_version_length, version) ||
+ !writer.WriteUInt32(in.version)) {
QUIC_BUG << "Failed to write Google version extension for " << in;
return false;
}
- CBB versions;
if (in.perspective == Perspective::IS_SERVER) {
- if (!CBB_add_u8_length_prefixed(&google_version_params, &versions)) {
+ if (!writer.WriteUInt8(sizeof(QuicVersionLabel) *
+ in.supported_versions.size())) {
QUIC_BUG << "Failed to write versions length for " << in;
return false;
}
- for (QuicVersionLabel version : in.supported_versions) {
- if (!CBB_add_u32(&versions, version)) {
+ for (QuicVersionLabel version_label : in.supported_versions) {
+ if (!writer.WriteUInt32(version_label)) {
QUIC_BUG << "Failed to write supported version for " << in;
return false;
}
}
}
- auto custom_parameters = std::make_unique<CBB[]>(in.custom_parameters.size());
- int i = 0;
for (const auto& kv : in.custom_parameters) {
- CBB* custom_parameter = &custom_parameters[i++];
- QUIC_BUG_IF(kv.first < 0xff00) << "custom_parameters should not be used "
- "for non-private use parameters";
- if (!CBB_add_u16(&params, kv.first) ||
- !CBB_add_u16_length_prefixed(&params, custom_parameter) ||
- !CBB_add_bytes(custom_parameter,
- reinterpret_cast<const uint8_t*>(kv.second.data()),
- kv.second.size())) {
- QUIC_BUG << "Failed to write custom parameter "
- << static_cast<int>(kv.first);
+ QUIC_BUG_IF(static_cast<uint64_t>(kv.first) < 0xff00)
+ << "custom_parameters should not be used "
+ "for non-private use parameters";
+ if (!WriteTransportParameterId(&writer, kv.first, version) ||
+ !WriteTransportParameterStringPiece(&writer, kv.second, version)) {
+ QUIC_BUG << "Failed to write custom parameter " << kv.first;
return false;
}
}
- if (!CBB_flush(cbb.get())) {
- QUIC_BUG << "Failed to flush CBB for " << in;
- return false;
+ if (!version.HasVarIntTransportParams()) {
+ // Fill in the length prefix at the start of the transport parameters.
+ if (writer.length() < sizeof(uint16_t) ||
+ writer.length() - sizeof(uint16_t) >
+ std::numeric_limits<uint16_t>::max()) {
+ QUIC_BUG << "Cannot write length " << writer.length() << " for " << in;
+ return false;
+ }
+ const uint16_t length_prefix = writer.length() - sizeof(uint16_t);
+ QuicDataWriter length_prefix_writer(out->size(),
+ reinterpret_cast<char*>(out->data()));
+ if (!length_prefix_writer.WriteUInt16(length_prefix)) {
+ QUIC_BUG << "Failed to write length prefix for " << in;
+ return false;
+ }
}
- out->resize(CBB_len(cbb.get()));
- memcpy(out->data(), CBB_data(cbb.get()), CBB_len(cbb.get()));
- QUIC_DLOG(INFO) << "Serialized " << in << " as " << CBB_len(cbb.get())
+
+ out->resize(writer.length());
+
+ QUIC_DLOG(INFO) << "Serialized " << in << " as " << writer.length()
<< " bytes";
return true;
}
@@ -578,198 +686,192 @@ bool ParseTransportParameters(ParsedQuicVersion version,
Perspective perspective,
const uint8_t* in,
size_t in_len,
- TransportParameters* out) {
+ TransportParameters* out,
+ std::string* error_details) {
out->perspective = perspective;
- CBS cbs;
- CBS_init(&cbs, in, in_len);
+ QuicDataReader reader(reinterpret_cast<const char*>(in), in_len);
- CBS params;
- if (!CBS_get_u16_length_prefixed(&cbs, &params)) {
- QUIC_DLOG(ERROR) << "Failed to parse the number of transport parameters";
- return false;
+ if (!version.HasVarIntTransportParams()) {
+ uint16_t full_length;
+ if (!reader.ReadUInt16(&full_length)) {
+ *error_details = "Failed to parse the transport parameter full length";
+ return false;
+ }
+ if (full_length != reader.BytesRemaining()) {
+ *error_details =
+ quiche::QuicheStrCat("Invalid transport parameter full length ",
+ full_length, " != ", reader.BytesRemaining());
+ return false;
+ }
}
- while (CBS_len(&params) > 0) {
+ while (!reader.IsDoneReading()) {
TransportParameters::TransportParameterId param_id;
- CBS value;
- static_assert(sizeof(param_id) == sizeof(uint16_t), "bad size");
- if (!CBS_get_u16(&params, reinterpret_cast<uint16_t*>(&param_id))) {
- QUIC_DLOG(ERROR) << "Failed to parse transport parameter ID";
+ if (!ReadTransportParameterId(&reader, version, &param_id)) {
+ *error_details = "Failed to parse transport parameter ID";
return false;
}
- if (!CBS_get_u16_length_prefixed(&params, &value)) {
- QUIC_DLOG(ERROR) << "Failed to parse length of transport parameter "
- << TransportParameterIdToString(param_id);
+ quiche::QuicheStringPiece value;
+ if (!ReadTransportParameterLengthAndValue(&reader, version, &value)) {
+ *error_details =
+ "Failed to read length and value of transport parameter " +
+ TransportParameterIdToString(param_id);
return false;
}
+ QuicDataReader value_reader(value);
bool parse_success = true;
switch (param_id) {
case TransportParameters::kOriginalConnectionId: {
if (!out->original_connection_id.IsEmpty()) {
- QUIC_DLOG(ERROR) << "Received a second original connection ID";
+ *error_details = "Received a second original connection ID";
return false;
}
- const size_t connection_id_length = CBS_len(&value);
+ const size_t connection_id_length = value_reader.BytesRemaining();
if (!QuicUtils::IsConnectionIdLengthValidForVersion(
connection_id_length, version.transport_version)) {
- QUIC_DLOG(ERROR) << "Received original connection ID of "
- << "invalid length " << connection_id_length;
+ *error_details = quiche::QuicheStrCat(
+ "Received original connection ID of invalid length ",
+ connection_id_length);
return false;
}
- out->original_connection_id.set_length(
- static_cast<uint8_t>(connection_id_length));
- if (out->original_connection_id.length() != 0) {
- memcpy(out->original_connection_id.mutable_data(), CBS_data(&value),
- out->original_connection_id.length());
+ if (!value_reader.ReadConnectionId(&out->original_connection_id,
+ connection_id_length)) {
+ *error_details = "Failed to read original connection ID";
+ return false;
}
} break;
case TransportParameters::kIdleTimeout:
- parse_success = out->idle_timeout_milliseconds.ReadFromCbs(&value);
+ parse_success =
+ out->idle_timeout_milliseconds.Read(&value_reader, error_details);
break;
- case TransportParameters::kStatelessResetToken:
+ case TransportParameters::kStatelessResetToken: {
if (!out->stateless_reset_token.empty()) {
- QUIC_DLOG(ERROR) << "Received a second stateless reset token";
+ *error_details = "Received a second stateless reset token";
return false;
}
- if (CBS_len(&value) != kStatelessResetTokenLength) {
- QUIC_DLOG(ERROR) << "Received stateless reset token of "
- << "invalid length " << CBS_len(&value);
+ quiche::QuicheStringPiece stateless_reset_token =
+ value_reader.ReadRemainingPayload();
+ if (stateless_reset_token.length() != kStatelessResetTokenLength) {
+ *error_details = quiche::QuicheStrCat(
+ "Received stateless reset token of invalid length ",
+ stateless_reset_token.length());
return false;
}
- out->stateless_reset_token.assign(CBS_data(&value),
- CBS_data(&value) + CBS_len(&value));
- break;
+ out->stateless_reset_token.assign(
+ stateless_reset_token.data(),
+ stateless_reset_token.data() + stateless_reset_token.length());
+ } break;
case TransportParameters::kMaxPacketSize:
- parse_success = out->max_packet_size.ReadFromCbs(&value);
+ parse_success = out->max_packet_size.Read(&value_reader, error_details);
break;
case TransportParameters::kInitialMaxData:
- parse_success = out->initial_max_data.ReadFromCbs(&value);
+ parse_success =
+ out->initial_max_data.Read(&value_reader, error_details);
break;
case TransportParameters::kInitialMaxStreamDataBidiLocal:
- parse_success =
- out->initial_max_stream_data_bidi_local.ReadFromCbs(&value);
+ parse_success = out->initial_max_stream_data_bidi_local.Read(
+ &value_reader, error_details);
break;
case TransportParameters::kInitialMaxStreamDataBidiRemote:
- parse_success =
- out->initial_max_stream_data_bidi_remote.ReadFromCbs(&value);
+ parse_success = out->initial_max_stream_data_bidi_remote.Read(
+ &value_reader, error_details);
break;
case TransportParameters::kInitialMaxStreamDataUni:
- parse_success = out->initial_max_stream_data_uni.ReadFromCbs(&value);
+ parse_success =
+ out->initial_max_stream_data_uni.Read(&value_reader, error_details);
break;
case TransportParameters::kInitialMaxStreamsBidi:
- parse_success = out->initial_max_streams_bidi.ReadFromCbs(&value);
+ parse_success =
+ out->initial_max_streams_bidi.Read(&value_reader, error_details);
break;
case TransportParameters::kInitialMaxStreamsUni:
- parse_success = out->initial_max_streams_uni.ReadFromCbs(&value);
+ parse_success =
+ out->initial_max_streams_uni.Read(&value_reader, error_details);
break;
case TransportParameters::kAckDelayExponent:
- parse_success = out->ack_delay_exponent.ReadFromCbs(&value);
+ parse_success =
+ out->ack_delay_exponent.Read(&value_reader, error_details);
break;
case TransportParameters::kMaxAckDelay:
- parse_success = out->max_ack_delay.ReadFromCbs(&value);
+ parse_success = out->max_ack_delay.Read(&value_reader, error_details);
break;
case TransportParameters::kDisableMigration:
if (out->disable_migration) {
- QUIC_DLOG(ERROR) << "Received a second disable migration";
- return false;
- }
- if (CBS_len(&value) != 0) {
- QUIC_DLOG(ERROR) << "Received disable migration of invalid length "
- << CBS_len(&value);
+ *error_details = "Received a second disable migration";
return false;
}
out->disable_migration = true;
break;
case TransportParameters::kPreferredAddress: {
+ TransportParameters::PreferredAddress preferred_address;
uint16_t ipv4_port, ipv6_port;
in_addr ipv4_address;
in6_addr ipv6_address;
- if (!CBS_copy_bytes(&value, reinterpret_cast<uint8_t*>(&ipv4_address),
- sizeof(ipv4_address)) ||
- !CBS_get_u16(&value, &ipv4_port) ||
- !CBS_copy_bytes(&value, reinterpret_cast<uint8_t*>(&ipv6_address),
- sizeof(ipv6_address)) ||
- !CBS_get_u16(&value, &ipv6_port)) {
- QUIC_DLOG(ERROR) << "Failed to parse preferred address IPs and ports";
+ preferred_address.stateless_reset_token.resize(
+ kStatelessResetTokenLength);
+ if (!value_reader.ReadBytes(&ipv4_address, sizeof(ipv4_address)) ||
+ !value_reader.ReadUInt16(&ipv4_port) ||
+ !value_reader.ReadBytes(&ipv6_address, sizeof(ipv6_address)) ||
+ !value_reader.ReadUInt16(&ipv6_port) ||
+ !value_reader.ReadLengthPrefixedConnectionId(
+ &preferred_address.connection_id) ||
+ !value_reader.ReadBytes(&preferred_address.stateless_reset_token[0],
+ kStatelessResetTokenLength)) {
+ *error_details = "Failed to read preferred address";
return false;
}
- TransportParameters::PreferredAddress preferred_address;
preferred_address.ipv4_socket_address =
QuicSocketAddress(QuicIpAddress(ipv4_address), ipv4_port);
preferred_address.ipv6_socket_address =
QuicSocketAddress(QuicIpAddress(ipv6_address), ipv6_port);
if (!preferred_address.ipv4_socket_address.host().IsIPv4() ||
!preferred_address.ipv6_socket_address.host().IsIPv6()) {
- QUIC_DLOG(ERROR) << "Received preferred addresses of bad families "
- << preferred_address;
- return false;
- }
- CBS connection_id_cbs;
- if (!CBS_get_u8_length_prefixed(&value, &connection_id_cbs)) {
- QUIC_DLOG(ERROR)
- << "Failed to parse length of preferred address connection ID";
- return false;
- }
- const size_t connection_id_length = CBS_len(&connection_id_cbs);
- if (!QuicUtils::IsConnectionIdLengthValidForVersion(
- connection_id_length, version.transport_version)) {
- QUIC_DLOG(ERROR) << "Received preferred address connection ID of "
- << "invalid length " << connection_id_length;
- return false;
- }
- preferred_address.connection_id.set_length(
- static_cast<uint8_t>(connection_id_length));
- if (preferred_address.connection_id.length() > 0 &&
- !CBS_copy_bytes(&connection_id_cbs,
- reinterpret_cast<uint8_t*>(
- preferred_address.connection_id.mutable_data()),
- preferred_address.connection_id.length())) {
- QUIC_DLOG(ERROR) << "Failed to read preferred address connection ID";
+ *error_details = "Received preferred addresses of bad families " +
+ preferred_address.ToString();
return false;
}
- if (CBS_len(&value) != kStatelessResetTokenLength) {
- QUIC_DLOG(ERROR) << "Received preferred address with "
- << "invalid remaining length " << CBS_len(&value);
+ if (!QuicUtils::IsConnectionIdValidForVersion(
+ preferred_address.connection_id, version.transport_version)) {
+ *error_details = "Received invalid preferred address connection ID " +
+ preferred_address.ToString();
return false;
}
- preferred_address.stateless_reset_token.assign(
- CBS_data(&value), CBS_data(&value) + CBS_len(&value));
out->preferred_address =
std::make_unique<TransportParameters::PreferredAddress>(
preferred_address);
} break;
case TransportParameters::kActiveConnectionIdLimit:
- parse_success = out->active_connection_id_limit.ReadFromCbs(&value);
+ parse_success =
+ out->active_connection_id_limit.Read(&value_reader, error_details);
break;
case TransportParameters::kMaxDatagramFrameSize:
- parse_success = out->max_datagram_frame_size.ReadFromCbs(&value);
+ parse_success =
+ out->max_datagram_frame_size.Read(&value_reader, error_details);
break;
case TransportParameters::kGoogleQuicParam: {
if (out->google_quic_params) {
- QUIC_DLOG(ERROR) << "Received a second Google parameter";
+ *error_details = "Received a second Google parameter";
return false;
}
- QuicStringPiece serialized_params(
- reinterpret_cast<const char*>(CBS_data(&value)), CBS_len(&value));
- out->google_quic_params = CryptoFramer::ParseMessage(serialized_params);
+ out->google_quic_params =
+ CryptoFramer::ParseMessage(value_reader.ReadRemainingPayload());
} break;
case TransportParameters::kGoogleQuicVersion: {
- if (!CBS_get_u32(&value, &out->version)) {
- QUIC_DLOG(ERROR) << "Failed to parse Google version extension";
+ if (!value_reader.ReadUInt32(&out->version)) {
+ *error_details = "Failed to read Google version extension version";
return false;
}
if (perspective == Perspective::IS_SERVER) {
- CBS versions;
- if (!CBS_get_u8_length_prefixed(&value, &versions) ||
- CBS_len(&versions) % 4 != 0) {
- QUIC_DLOG(ERROR)
- << "Failed to parse Google supported versions length";
+ uint8_t versions_length;
+ if (!value_reader.ReadUInt8(&versions_length)) {
+ *error_details = "Failed to parse Google supported versions length";
return false;
}
- while (CBS_len(&versions) > 0) {
+ const uint8_t num_versions = versions_length / sizeof(uint32_t);
+ for (uint8_t i = 0; i < num_versions; ++i) {
QuicVersionLabel version;
- if (!CBS_get_u32(&versions, &version)) {
- QUIC_DLOG(ERROR) << "Failed to parse Google supported version";
+ if (!value_reader.ReadUInt32(&version)) {
+ *error_details = "Failed to parse Google supported version";
return false;
}
out->supported_versions.push_back(version);
@@ -777,24 +879,37 @@ bool ParseTransportParameters(ParsedQuicVersion version,
}
} break;
default:
- out->custom_parameters[param_id] = std::string(
- reinterpret_cast<const char*>(CBS_data(&value)), CBS_len(&value));
+ if (out->custom_parameters.find(param_id) !=
+ out->custom_parameters.end()) {
+ *error_details = "Received a second unknown parameter" +
+ TransportParameterIdToString(param_id);
+ return false;
+ }
+ out->custom_parameters[param_id] =
+ std::string(value_reader.ReadRemainingPayload());
break;
}
if (!parse_success) {
+ DCHECK(!error_details->empty());
+ return false;
+ }
+ if (!value_reader.IsDoneReading()) {
+ *error_details = quiche::QuicheStrCat(
+ "Received unexpected ", value_reader.BytesRemaining(),
+ " bytes after parsing ", TransportParameterIdToString(param_id));
return false;
}
}
- const bool ok = out->AreValid();
- if (ok) {
- QUIC_DLOG(INFO) << "Parsed transport parameters " << *out << " from "
- << in_len << " bytes";
- } else {
- QUIC_DLOG(ERROR) << "Transport parameter validity check failed " << *out
- << " from " << in_len << " bytes";
+ if (!out->AreValid(error_details)) {
+ DCHECK(!error_details->empty());
+ return false;
}
- return ok;
+
+ QUIC_DLOG(INFO) << "Parsed transport parameters " << *out << " from "
+ << in_len << " bytes";
+
+ return true;
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.h b/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.h
index c5ec1a4f71b..831caecd1a9 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.h
@@ -8,13 +8,14 @@
#include <memory>
#include <vector>
-#include "third_party/boringssl/src/include/openssl/bytestring.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h"
#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
+#include "net/third_party/quiche/src/quic/core/quic_data_reader.h"
#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -24,7 +25,7 @@ namespace quic {
// This struct currently uses the values from draft 20.
struct QUIC_EXPORT_PRIVATE TransportParameters {
// The identifier used to differentiate transport parameters.
- enum TransportParameterId : uint16_t;
+ enum TransportParameterId : uint64_t;
// A map used to specify custom parameters.
using ParameterMap = QuicUnorderedMap<TransportParameterId, std::string>;
// Represents an individual QUIC transport parameter that only encodes a
@@ -45,10 +46,12 @@ struct QUIC_EXPORT_PRIVATE TransportParameters {
// Writes to a crypto byte buffer, used during serialization. Does not write
// anything if the value is equal to the parameter's default value.
// Returns whether the write was successful.
- bool WriteToCbb(CBB* parent_cbb) const;
+ bool Write(QuicDataWriter* writer, ParsedQuicVersion version) const;
// Reads from a crypto byte string, used during parsing.
// Returns whether the read was successful.
- bool ReadFromCbs(CBS* const value_cbs);
+ // On failure, this method will write a human-readable error message to
+ // |error_details|.
+ bool Read(QuicDataReader* reader, std::string* error_details);
// operator<< allows easily logging integer transport parameters.
friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
std::ostream& os,
@@ -78,7 +81,7 @@ struct QUIC_EXPORT_PRIVATE TransportParameters {
// Maximum value of this transport parameter, as per IETF specification.
const uint64_t max_value_;
// Ensures this parameter is not parsed twice in the same message.
- bool has_been_read_from_cbs_;
+ bool has_been_read_;
};
// Represents the preferred_address transport parameter that a server can
@@ -178,8 +181,9 @@ struct QUIC_EXPORT_PRIVATE TransportParameters {
std::unique_ptr<CryptoHandshakeMessage> google_quic_params;
// Validates whether transport parameters are valid according to
- // the specification.
- bool AreValid() const;
+ // the specification. If the transport parameters are not valid, this method
+ // will write a human-readable error message to |error_details|.
+ bool AreValid(std::string* error_details) const;
// Custom parameters that may be specific to application protocol.
ParameterMap custom_parameters;
@@ -203,12 +207,15 @@ QUIC_EXPORT_PRIVATE bool SerializeTransportParameters(
// parsed parameters into |*out|. Input is read from |in| for |in_len| bytes.
// |perspective| indicates whether the input came from a client or a server.
// This method returns true if the input was successfully parsed.
+// On failure, this method will write a human-readable error message to
+// |error_details|.
// TODO(nharper): Write fuzz tests for this method.
QUIC_EXPORT_PRIVATE bool ParseTransportParameters(ParsedQuicVersion version,
Perspective perspective,
const uint8_t* in,
size_t in_len,
- TransportParameters* out);
+ TransportParameters* out,
+ std::string* error_details);
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters_test.cc
index 61a6e0d4d6b..bbcba74efb8 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters_test.cc
@@ -7,12 +7,13 @@
#include <cstring>
#include <utility>
-#include "third_party/boringssl/src/include/openssl/mem.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ip_address.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
@@ -21,7 +22,6 @@ namespace {
using testing::Pair;
using testing::UnorderedElementsAre;
-const ParsedQuicVersion kVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99);
const QuicVersionLabel kFakeVersionLabel = 0x01234567;
const QuicVersionLabel kFakeVersionLabel2 = 0x89ABCDEF;
const uint64_t kFakeIdleTimeoutMilliseconds = 12012;
@@ -101,11 +101,31 @@ CreateFakePreferredAddress() {
preferred_address);
}
+std::vector<ParsedQuicVersion> AllSupportedTlsVersions() {
+ std::vector<ParsedQuicVersion> tls_versions;
+ for (const ParsedQuicVersion& version : AllSupportedVersions()) {
+ if (version.handshake_protocol == PROTOCOL_TLS1_3) {
+ tls_versions.push_back(version);
+ }
+ }
+ return tls_versions;
+}
+
} // namespace
-class TransportParametersTest : public QuicTest {};
+class TransportParametersTest : public QuicTestWithParam<ParsedQuicVersion> {
+ protected:
+ TransportParametersTest() : version_(GetParam()) {}
+
+ ParsedQuicVersion version_;
+};
+
+INSTANTIATE_TEST_SUITE_P(TransportParametersTests,
+ TransportParametersTest,
+ ::testing::ValuesIn(AllSupportedTlsVersions()),
+ ::testing::PrintToStringParamName());
-TEST_F(TransportParametersTest, RoundTripClient) {
+TEST_P(TransportParametersTest, RoundTripClient) {
TransportParameters orig_params;
orig_params.perspective = Perspective::IS_CLIENT;
orig_params.version = kFakeVersionLabel;
@@ -129,13 +149,15 @@ TEST_F(TransportParametersTest, RoundTripClient) {
orig_params.custom_parameters[kCustomParameter2] = kCustomParameter2Value;
std::vector<uint8_t> serialized;
- ASSERT_TRUE(SerializeTransportParameters(kVersion, orig_params, &serialized));
+ ASSERT_TRUE(SerializeTransportParameters(version_, orig_params, &serialized));
TransportParameters new_params;
- ASSERT_TRUE(ParseTransportParameters(kVersion, Perspective::IS_CLIENT,
+ std::string error_details;
+ ASSERT_TRUE(ParseTransportParameters(version_, Perspective::IS_CLIENT,
serialized.data(), serialized.size(),
- &new_params));
-
+ &new_params, &error_details))
+ << error_details;
+ EXPECT_TRUE(error_details.empty());
EXPECT_EQ(Perspective::IS_CLIENT, new_params.perspective);
EXPECT_EQ(kFakeVersionLabel, new_params.version);
EXPECT_TRUE(new_params.supported_versions.empty());
@@ -166,7 +188,7 @@ TEST_F(TransportParametersTest, RoundTripClient) {
Pair(kCustomParameter2, kCustomParameter2Value)));
}
-TEST_F(TransportParametersTest, RoundTripServer) {
+TEST_P(TransportParametersTest, RoundTripServer) {
TransportParameters orig_params;
orig_params.perspective = Perspective::IS_SERVER;
orig_params.version = kFakeVersionLabel;
@@ -193,13 +215,15 @@ TEST_F(TransportParametersTest, RoundTripServer) {
kFakeActiveConnectionIdLimit);
std::vector<uint8_t> serialized;
- ASSERT_TRUE(SerializeTransportParameters(kVersion, orig_params, &serialized));
+ ASSERT_TRUE(SerializeTransportParameters(version_, orig_params, &serialized));
TransportParameters new_params;
- ASSERT_TRUE(ParseTransportParameters(kVersion, Perspective::IS_SERVER,
+ std::string error_details;
+ ASSERT_TRUE(ParseTransportParameters(version_, Perspective::IS_SERVER,
serialized.data(), serialized.size(),
- &new_params));
-
+ &new_params, &error_details))
+ << error_details;
+ EXPECT_TRUE(error_details.empty());
EXPECT_EQ(Perspective::IS_SERVER, new_params.perspective);
EXPECT_EQ(kFakeVersionLabel, new_params.version);
EXPECT_EQ(2u, new_params.supported_versions.size());
@@ -239,50 +263,76 @@ TEST_F(TransportParametersTest, RoundTripServer) {
EXPECT_EQ(0u, new_params.custom_parameters.size());
}
-TEST_F(TransportParametersTest, IsValid) {
+TEST_P(TransportParametersTest, AreValid) {
{
TransportParameters params;
+ std::string error_details;
params.perspective = Perspective::IS_CLIENT;
- EXPECT_TRUE(params.AreValid());
+ EXPECT_TRUE(params.AreValid(&error_details));
+ EXPECT_TRUE(error_details.empty());
}
{
TransportParameters params;
+ std::string error_details;
params.perspective = Perspective::IS_CLIENT;
- EXPECT_TRUE(params.AreValid());
+ EXPECT_TRUE(params.AreValid(&error_details));
+ EXPECT_TRUE(error_details.empty());
params.idle_timeout_milliseconds.set_value(kFakeIdleTimeoutMilliseconds);
- EXPECT_TRUE(params.AreValid());
+ EXPECT_TRUE(params.AreValid(&error_details));
+ EXPECT_TRUE(error_details.empty());
params.idle_timeout_milliseconds.set_value(601000);
- EXPECT_TRUE(params.AreValid());
+ EXPECT_TRUE(params.AreValid(&error_details));
+ EXPECT_TRUE(error_details.empty());
}
{
TransportParameters params;
+ std::string error_details;
params.perspective = Perspective::IS_CLIENT;
- EXPECT_TRUE(params.AreValid());
- params.max_packet_size.set_value(0);
- EXPECT_FALSE(params.AreValid());
- params.max_packet_size.set_value(1199);
- EXPECT_FALSE(params.AreValid());
+ EXPECT_TRUE(params.AreValid(&error_details));
+ EXPECT_TRUE(error_details.empty());
params.max_packet_size.set_value(1200);
- EXPECT_TRUE(params.AreValid());
+ EXPECT_TRUE(params.AreValid(&error_details));
+ EXPECT_TRUE(error_details.empty());
params.max_packet_size.set_value(65535);
- EXPECT_TRUE(params.AreValid());
+ EXPECT_TRUE(params.AreValid(&error_details));
+ EXPECT_TRUE(error_details.empty());
params.max_packet_size.set_value(9999999);
- EXPECT_TRUE(params.AreValid());
+ EXPECT_TRUE(params.AreValid(&error_details));
+ EXPECT_TRUE(error_details.empty());
+ params.max_packet_size.set_value(0);
+ error_details = "";
+ EXPECT_FALSE(params.AreValid(&error_details));
+ EXPECT_EQ(
+ error_details,
+ "Invalid transport parameters [Client max_packet_size 0 (Invalid)]");
+ params.max_packet_size.set_value(1199);
+ error_details = "";
+ EXPECT_FALSE(params.AreValid(&error_details));
+ EXPECT_EQ(
+ error_details,
+ "Invalid transport parameters [Client max_packet_size 1199 (Invalid)]");
}
{
TransportParameters params;
+ std::string error_details;
params.perspective = Perspective::IS_CLIENT;
- EXPECT_TRUE(params.AreValid());
+ EXPECT_TRUE(params.AreValid(&error_details));
+ EXPECT_TRUE(error_details.empty());
params.ack_delay_exponent.set_value(0);
- EXPECT_TRUE(params.AreValid());
+ EXPECT_TRUE(params.AreValid(&error_details));
+ EXPECT_TRUE(error_details.empty());
params.ack_delay_exponent.set_value(20);
- EXPECT_TRUE(params.AreValid());
+ EXPECT_TRUE(params.AreValid(&error_details));
+ EXPECT_TRUE(error_details.empty());
params.ack_delay_exponent.set_value(21);
- EXPECT_FALSE(params.AreValid());
+ EXPECT_FALSE(params.AreValid(&error_details));
+ EXPECT_EQ(error_details,
+ "Invalid transport parameters [Client ack_delay_exponent 21 "
+ "(Invalid)]");
}
}
-TEST_F(TransportParametersTest, NoClientParamsWithStatelessResetToken) {
+TEST_P(TransportParametersTest, NoClientParamsWithStatelessResetToken) {
TransportParameters orig_params;
orig_params.perspective = Perspective::IS_CLIENT;
orig_params.version = kFakeVersionLabel;
@@ -291,12 +341,17 @@ TEST_F(TransportParametersTest, NoClientParamsWithStatelessResetToken) {
orig_params.max_packet_size.set_value(kFakeMaxPacketSize);
std::vector<uint8_t> out;
- EXPECT_FALSE(SerializeTransportParameters(kVersion, orig_params, &out));
+ bool ok;
+ EXPECT_QUIC_BUG(
+ ok = SerializeTransportParameters(version_, orig_params, &out),
+ "Not serializing invalid transport parameters: Client cannot send "
+ "stateless reset token");
+ EXPECT_FALSE(ok);
}
-TEST_F(TransportParametersTest, ParseClientParams) {
+TEST_P(TransportParametersTest, ParseClientParams) {
// clang-format off
- const uint8_t kClientParams[] = {
+ const uint8_t kClientParamsOld[] = {
0x00, 0x49, // length of the parameters array that follows
// idle_timeout
0x00, 0x01, // parameter id
@@ -350,13 +405,74 @@ TEST_F(TransportParametersTest, ParseClientParams) {
0x00, 0x04, // length
0x01, 0x23, 0x45, 0x67, // initial version
};
+ const uint8_t kClientParams[] = {
+ // idle_timeout
+ 0x01, // parameter id
+ 0x02, // length
+ 0x6e, 0xec, // value
+ // max_packet_size
+ 0x03, // parameter id
+ 0x02, // length
+ 0x63, 0x29, // value
+ // initial_max_data
+ 0x04, // parameter id
+ 0x02, // length
+ 0x40, 0x65, // value
+ // initial_max_stream_data_bidi_local
+ 0x05, // parameter id
+ 0x02, // length
+ 0x47, 0xD1, // value
+ // initial_max_stream_data_bidi_remote
+ 0x06, // parameter id
+ 0x02, // length
+ 0x47, 0xD2, // value
+ // initial_max_stream_data_uni
+ 0x07, // parameter id
+ 0x02, // length
+ 0x4B, 0xB8, // value
+ // initial_max_streams_bidi
+ 0x08, // parameter id
+ 0x01, // length
+ 0x15, // value
+ // initial_max_streams_uni
+ 0x09, // parameter id
+ 0x01, // length
+ 0x16, // value
+ // ack_delay_exponent
+ 0x0a, // parameter id
+ 0x01, // length
+ 0x0a, // value
+ // max_ack_delay
+ 0x0b, // parameter id
+ 0x01, // length
+ 0x33, // value
+ // disable_migration
+ 0x0c, // parameter id
+ 0x00, // length
+ // active_connection_id_limit
+ 0x0e, // parameter id
+ 0x01, // length
+ 0x34, // value
+ // Google version extension
+ 0x80, 0x00, 0x47, 0x52, // parameter id
+ 0x04, // length
+ 0x01, 0x23, 0x45, 0x67, // initial version
+ };
// clang-format on
-
+ const uint8_t* client_params =
+ reinterpret_cast<const uint8_t*>(kClientParams);
+ size_t client_params_length = QUICHE_ARRAYSIZE(kClientParams);
+ if (!version_.HasVarIntTransportParams()) {
+ client_params = reinterpret_cast<const uint8_t*>(kClientParamsOld);
+ client_params_length = QUICHE_ARRAYSIZE(kClientParamsOld);
+ }
TransportParameters new_params;
- ASSERT_TRUE(
- ParseTransportParameters(kVersion, Perspective::IS_CLIENT, kClientParams,
- QUIC_ARRAYSIZE(kClientParams), &new_params));
-
+ std::string error_details;
+ ASSERT_TRUE(ParseTransportParameters(version_, Perspective::IS_CLIENT,
+ client_params, client_params_length,
+ &new_params, &error_details))
+ << error_details;
+ EXPECT_TRUE(error_details.empty());
EXPECT_EQ(Perspective::IS_CLIENT, new_params.perspective);
EXPECT_EQ(kFakeVersionLabel, new_params.version);
EXPECT_TRUE(new_params.supported_versions.empty());
@@ -383,19 +499,18 @@ TEST_F(TransportParametersTest, ParseClientParams) {
new_params.active_connection_id_limit.value());
}
-TEST_F(TransportParametersTest, ParseClientParamsFailsWithStatelessResetToken) {
- TransportParameters out_params;
-
+TEST_P(TransportParametersTest,
+ ParseClientParamsFailsWithFullStatelessResetToken) {
// clang-format off
- const uint8_t kClientParamsWithFullToken[] = {
+ const uint8_t kClientParamsWithFullTokenOld[] = {
0x00, 0x26, // length parameters array that follows
// idle_timeout
0x00, 0x01, // parameter id
0x00, 0x02, // length
0x6e, 0xec, // value
// stateless_reset_token
- 0x00, 0x02,
- 0x00, 0x10,
+ 0x00, 0x02, // parameter id
+ 0x00, 0x10, // length
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
// max_packet_size
@@ -407,21 +522,53 @@ TEST_F(TransportParametersTest, ParseClientParamsFailsWithStatelessResetToken) {
0x00, 0x02, // length
0x40, 0x65, // value
};
+ const uint8_t kClientParamsWithFullToken[] = {
+ // idle_timeout
+ 0x01, // parameter id
+ 0x02, // length
+ 0x6e, 0xec, // value
+ // stateless_reset_token
+ 0x02, // parameter id
+ 0x10, // length
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
+ // max_packet_size
+ 0x03, // parameter id
+ 0x02, // length
+ 0x63, 0x29, // value
+ // initial_max_data
+ 0x04, // parameter id
+ 0x02, // length
+ 0x40, 0x65, // value
+ };
// clang-format on
+ const uint8_t* client_params =
+ reinterpret_cast<const uint8_t*>(kClientParamsWithFullToken);
+ size_t client_params_length = QUICHE_ARRAYSIZE(kClientParamsWithFullToken);
+ if (!version_.HasVarIntTransportParams()) {
+ client_params =
+ reinterpret_cast<const uint8_t*>(kClientParamsWithFullTokenOld);
+ client_params_length = QUICHE_ARRAYSIZE(kClientParamsWithFullTokenOld);
+ }
+ TransportParameters out_params;
+ std::string error_details;
+ EXPECT_FALSE(ParseTransportParameters(version_, Perspective::IS_CLIENT,
+ client_params, client_params_length,
+ &out_params, &error_details));
+ EXPECT_EQ(error_details, "Client cannot send stateless reset token");
+}
- EXPECT_FALSE(ParseTransportParameters(
- kVersion, Perspective::IS_CLIENT, kClientParamsWithFullToken,
- QUIC_ARRAYSIZE(kClientParamsWithFullToken), &out_params));
-
+TEST_P(TransportParametersTest,
+ ParseClientParamsFailsWithEmptyStatelessResetToken) {
// clang-format off
- const uint8_t kClientParamsWithEmptyToken[] = {
+ const uint8_t kClientParamsWithEmptyTokenOld[] = {
0x00, 0x16, // length parameters array that follows
// idle_timeout
0x00, 0x01, // parameter id
0x00, 0x02, // length
0x6e, 0xec, // value
// stateless_reset_token
- 0x00, 0x02,
+ 0x00, 0x02, // parameter id
0x00, 0x00,
// max_packet_size
0x00, 0x03, // parameter id
@@ -432,24 +579,49 @@ TEST_F(TransportParametersTest, ParseClientParamsFailsWithStatelessResetToken) {
0x00, 0x02, // length
0x40, 0x65, // value
};
+ const uint8_t kClientParamsWithEmptyToken[] = {
+ // idle_timeout
+ 0x01, // parameter id
+ 0x02, // length
+ 0x6e, 0xec, // value
+ // stateless_reset_token
+ 0x02, // parameter id
+ 0x00, // length
+ // max_packet_size
+ 0x03, // parameter id
+ 0x02, // length
+ 0x63, 0x29, // value
+ // initial_max_data
+ 0x04, // parameter id
+ 0x02, // length
+ 0x40, 0x65, // value
+ };
// clang-format on
-
- EXPECT_FALSE(ParseTransportParameters(
- kVersion, Perspective::IS_CLIENT, kClientParamsWithEmptyToken,
- QUIC_ARRAYSIZE(kClientParamsWithEmptyToken), &out_params));
+ const uint8_t* client_params =
+ reinterpret_cast<const uint8_t*>(kClientParamsWithEmptyToken);
+ size_t client_params_length = QUICHE_ARRAYSIZE(kClientParamsWithEmptyToken);
+ if (!version_.HasVarIntTransportParams()) {
+ client_params =
+ reinterpret_cast<const uint8_t*>(kClientParamsWithEmptyTokenOld);
+ client_params_length = QUICHE_ARRAYSIZE(kClientParamsWithEmptyTokenOld);
+ }
+ TransportParameters out_params;
+ std::string error_details;
+ EXPECT_FALSE(ParseTransportParameters(version_, Perspective::IS_CLIENT,
+ client_params, client_params_length,
+ &out_params, &error_details));
+ EXPECT_EQ(error_details,
+ "Received stateless reset token of invalid length 0");
}
-TEST_F(TransportParametersTest, ParseClientParametersRepeated) {
+TEST_P(TransportParametersTest, ParseClientParametersRepeated) {
// clang-format off
- const uint8_t kClientParamsRepeated[] = {
- 0x00, 0x16, // length parameters array that follows
+ const uint8_t kClientParamsRepeatedOld[] = {
+ 0x00, 0x12, // length parameters array that follows
// idle_timeout
0x00, 0x01, // parameter id
0x00, 0x02, // length
0x6e, 0xec, // value
- // stateless_reset_token
- 0x00, 0x02,
- 0x00, 0x00,
// max_packet_size
0x00, 0x03, // parameter id
0x00, 0x02, // length
@@ -459,16 +631,39 @@ TEST_F(TransportParametersTest, ParseClientParametersRepeated) {
0x00, 0x02, // length
0x6e, 0xec, // value
};
+ const uint8_t kClientParamsRepeated[] = {
+ // idle_timeout
+ 0x01, // parameter id
+ 0x02, // length
+ 0x6e, 0xec, // value
+ // max_packet_size
+ 0x03, // parameter id
+ 0x02, // length
+ 0x63, 0x29, // value
+ // idle_timeout (repeated)
+ 0x01, // parameter id
+ 0x02, // length
+ 0x6e, 0xec, // value
+ };
// clang-format on
+ const uint8_t* client_params =
+ reinterpret_cast<const uint8_t*>(kClientParamsRepeated);
+ size_t client_params_length = QUICHE_ARRAYSIZE(kClientParamsRepeated);
+ if (!version_.HasVarIntTransportParams()) {
+ client_params = reinterpret_cast<const uint8_t*>(kClientParamsRepeatedOld);
+ client_params_length = QUICHE_ARRAYSIZE(kClientParamsRepeatedOld);
+ }
TransportParameters out_params;
- EXPECT_FALSE(ParseTransportParameters(
- kVersion, Perspective::IS_CLIENT, kClientParamsRepeated,
- QUIC_ARRAYSIZE(kClientParamsRepeated), &out_params));
+ std::string error_details;
+ EXPECT_FALSE(ParseTransportParameters(version_, Perspective::IS_CLIENT,
+ client_params, client_params_length,
+ &out_params, &error_details));
+ EXPECT_EQ(error_details, "Received a second idle_timeout");
}
-TEST_F(TransportParametersTest, ParseServerParams) {
+TEST_P(TransportParametersTest, ParseServerParams) {
// clang-format off
- const uint8_t kServerParams[] = {
+ const uint8_t kServerParamsOld[] = {
0x00, 0xa7, // length of parameters array that follows
// original_connection_id
0x00, 0x00, // parameter id
@@ -479,8 +674,8 @@ TEST_F(TransportParametersTest, ParseServerParams) {
0x00, 0x02, // length
0x6e, 0xec, // value
// stateless_reset_token
- 0x00, 0x02,
- 0x00, 0x10,
+ 0x00, 0x02, // parameter id
+ 0x00, 0x10, // length
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
// max_packet_size
@@ -546,13 +741,98 @@ TEST_F(TransportParametersTest, ParseServerParams) {
0x01, 0x23, 0x45, 0x67,
0x89, 0xab, 0xcd, 0xef,
};
+ const uint8_t kServerParams[] = {
+ // original_connection_id
+ 0x00, // parameter id
+ 0x08, // length
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x37,
+ // idle_timeout
+ 0x01, // parameter id
+ 0x02, // length
+ 0x6e, 0xec, // value
+ // stateless_reset_token
+ 0x02, // parameter id
+ 0x10, // length
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
+ // max_packet_size
+ 0x03, // parameter id
+ 0x02, // length
+ 0x63, 0x29, // value
+ // initial_max_data
+ 0x04, // parameter id
+ 0x02, // length
+ 0x40, 0x65, // value
+ // initial_max_stream_data_bidi_local
+ 0x05, // parameter id
+ 0x02, // length
+ 0x47, 0xD1, // value
+ // initial_max_stream_data_bidi_remote
+ 0x06, // parameter id
+ 0x02, // length
+ 0x47, 0xD2, // value
+ // initial_max_stream_data_uni
+ 0x07, // parameter id
+ 0x02, // length
+ 0x4B, 0xB8, // value
+ // initial_max_streams_bidi
+ 0x08, // parameter id
+ 0x01, // length
+ 0x15, // value
+ // initial_max_streams_uni
+ 0x09, // parameter id
+ 0x01, // length
+ 0x16, // value
+ // ack_delay_exponent
+ 0x0a, // parameter id
+ 0x01, // length
+ 0x0a, // value
+ // max_ack_delay
+ 0x0b, // parameter id
+ 0x01, // length
+ 0x33, // value
+ // disable_migration
+ 0x0c, // parameter id
+ 0x00, // length
+ // preferred_address
+ 0x0d, // parameter id
+ 0x31, // length
+ 0x41, 0x42, 0x43, 0x44, // IPv4 address
+ 0x48, 0x84, // IPv4 port
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, // IPv6 address
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x63, 0x36, // IPv6 port
+ 0x08, // connection ID length
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xEF, // connection ID
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, // stateless reset token
+ 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
+ // active_connection_id_limit
+ 0x0e, // parameter id
+ 0x01, // length
+ 0x34, // value
+ // Google version extension
+ 0x80, 0x00, 0x47, 0x52, // parameter id
+ 0x0d, // length
+ 0x01, 0x23, 0x45, 0x67, // negotiated_version
+ 0x08, // length of supported versions array
+ 0x01, 0x23, 0x45, 0x67,
+ 0x89, 0xab, 0xcd, 0xef,
+ };
// clang-format on
-
+ const uint8_t* server_params =
+ reinterpret_cast<const uint8_t*>(kServerParams);
+ size_t server_params_length = QUICHE_ARRAYSIZE(kServerParams);
+ if (!version_.HasVarIntTransportParams()) {
+ server_params = reinterpret_cast<const uint8_t*>(kServerParamsOld);
+ server_params_length = QUICHE_ARRAYSIZE(kServerParamsOld);
+ }
TransportParameters new_params;
- ASSERT_TRUE(
- ParseTransportParameters(kVersion, Perspective::IS_SERVER, kServerParams,
- QUIC_ARRAYSIZE(kServerParams), &new_params));
-
+ std::string error_details;
+ ASSERT_TRUE(ParseTransportParameters(version_, Perspective::IS_SERVER,
+ server_params, server_params_length,
+ &new_params, &error_details))
+ << error_details;
+ EXPECT_TRUE(error_details.empty());
EXPECT_EQ(Perspective::IS_SERVER, new_params.perspective);
EXPECT_EQ(kFakeVersionLabel, new_params.version);
EXPECT_EQ(2u, new_params.supported_versions.size());
@@ -591,9 +871,9 @@ TEST_F(TransportParametersTest, ParseServerParams) {
new_params.active_connection_id_limit.value());
}
-TEST_F(TransportParametersTest, ParseServerParametersRepeated) {
+TEST_P(TransportParametersTest, ParseServerParametersRepeated) {
// clang-format off
- const uint8_t kServerParamsRepeated[] = {
+ const uint8_t kServerParamsRepeatedOld[] = {
0x00, 0x2c, // length of parameters array that follows
// original_connection_id
0x00, 0x00, // parameter id
@@ -604,8 +884,8 @@ TEST_F(TransportParametersTest, ParseServerParametersRepeated) {
0x00, 0x02, // length
0x6e, 0xec, // value
// stateless_reset_token
- 0x00, 0x02,
- 0x00, 0x10,
+ 0x00, 0x02, // parameter id
+ 0x00, 0x10, // length
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
// idle_timeout (repeated)
@@ -613,15 +893,42 @@ TEST_F(TransportParametersTest, ParseServerParametersRepeated) {
0x00, 0x02, // length
0x6e, 0xec, // value
};
+ const uint8_t kServerParamsRepeated[] = {
+ // original_connection_id
+ 0x00, // parameter id
+ 0x08, // length
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x37,
+ // idle_timeout
+ 0x01, // parameter id
+ 0x02, // length
+ 0x6e, 0xec, // value
+ // stateless_reset_token
+ 0x02, // parameter id
+ 0x10, // length
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+ // idle_timeout (repeated)
+ 0x01, // parameter id
+ 0x02, // length
+ 0x6e, 0xec, // value
+ };
// clang-format on
-
+ const uint8_t* server_params =
+ reinterpret_cast<const uint8_t*>(kServerParamsRepeated);
+ size_t server_params_length = QUICHE_ARRAYSIZE(kServerParamsRepeated);
+ if (!version_.HasVarIntTransportParams()) {
+ server_params = reinterpret_cast<const uint8_t*>(kServerParamsRepeatedOld);
+ server_params_length = QUICHE_ARRAYSIZE(kServerParamsRepeatedOld);
+ }
TransportParameters out_params;
- EXPECT_FALSE(ParseTransportParameters(
- kVersion, Perspective::IS_SERVER, kServerParamsRepeated,
- QUIC_ARRAYSIZE(kServerParamsRepeated), &out_params));
+ std::string error_details;
+ EXPECT_FALSE(ParseTransportParameters(version_, Perspective::IS_SERVER,
+ server_params, server_params_length,
+ &out_params, &error_details));
+ EXPECT_EQ(error_details, "Received a second idle_timeout");
}
-TEST_F(TransportParametersTest, CryptoHandshakeMessageRoundtrip) {
+TEST_P(TransportParametersTest, CryptoHandshakeMessageRoundtrip) {
TransportParameters orig_params;
orig_params.perspective = Perspective::IS_CLIENT;
orig_params.version = kFakeVersionLabel;
@@ -634,22 +941,24 @@ TEST_F(TransportParametersTest, CryptoHandshakeMessageRoundtrip) {
orig_params.google_quic_params->SetValue(1337, kTestValue);
std::vector<uint8_t> serialized;
- ASSERT_TRUE(SerializeTransportParameters(kVersion, orig_params, &serialized));
+ ASSERT_TRUE(SerializeTransportParameters(version_, orig_params, &serialized));
TransportParameters new_params;
- ASSERT_TRUE(ParseTransportParameters(kVersion, Perspective::IS_CLIENT,
+ std::string error_details;
+ ASSERT_TRUE(ParseTransportParameters(version_, Perspective::IS_CLIENT,
serialized.data(), serialized.size(),
- &new_params));
-
+ &new_params, &error_details))
+ << error_details;
+ EXPECT_TRUE(error_details.empty());
ASSERT_NE(new_params.google_quic_params.get(), nullptr);
EXPECT_EQ(new_params.google_quic_params->tag(),
orig_params.google_quic_params->tag());
- QuicStringPiece test_string;
+ quiche::QuicheStringPiece test_string;
EXPECT_TRUE(new_params.google_quic_params->GetStringPiece(42, &test_string));
EXPECT_EQ(test_string, kTestString);
uint32_t test_value;
- EXPECT_EQ(new_params.google_quic_params->GetUint32(1337, &test_value),
- QUIC_NO_ERROR);
+ EXPECT_THAT(new_params.google_quic_params->GetUint32(1337, &test_value),
+ IsQuicNoError());
EXPECT_EQ(test_value, kTestValue);
EXPECT_EQ(kFakeVersionLabel, new_params.version);
EXPECT_EQ(kFakeMaxPacketSize, new_params.max_packet_size.value());
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_blocked_frame.h b/chromium/net/third_party/quiche/src/quic/core/frames/quic_blocked_frame.h
index a4be66411d3..30dcdf4ca05 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_blocked_frame.h
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_blocked_frame.h
@@ -30,13 +30,9 @@ struct QUIC_EXPORT_PRIVATE QuicBlockedFrame {
// and non-zero when sent.
QuicControlFrameId control_frame_id;
- // The stream this frame applies to. 0 is a special case meaning the overall
- // connection rather than a specific stream.
- //
- // For IETF QUIC, the stream_id controls whether an IETF QUIC
- // BLOCKED or STREAM_BLOCKED frame is generated.
- // If stream_id is 0 then a BLOCKED frame is generated and transmitted,
- // if non-0, a STREAM_BLOCKED.
+ // 0 is a special case meaning the connection is blocked, rather than a
+ // stream. So stream_id 0 corresponds to a BLOCKED frame and non-0
+ // corresponds to a STREAM_BLOCKED.
// TODO(fkastenholz): This should be converted to use
// QuicUtils::GetInvalidStreamId to get the correct invalid stream id value
// and not rely on 0.
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_connection_close_frame.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_connection_close_frame.cc
index 88c110938e0..35aedf4a292 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_connection_close_frame.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_connection_close_frame.cc
@@ -7,7 +7,6 @@
#include <memory>
#include "net/third_party/quiche/src/quic/core/quic_constants.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
namespace quic {
QuicConnectionCloseFrame::QuicConnectionCloseFrame()
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_crypto_frame.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_crypto_frame.cc
index fafbba85b6b..d750da76939 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_crypto_frame.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_crypto_frame.cc
@@ -5,6 +5,7 @@
#include "net/third_party/quiche/src/quic/core/frames/quic_crypto_frame.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -18,7 +19,7 @@ QuicCryptoFrame::QuicCryptoFrame(EncryptionLevel level,
QuicCryptoFrame::QuicCryptoFrame(EncryptionLevel level,
QuicStreamOffset offset,
- QuicStringPiece data)
+ quiche::QuicheStringPiece data)
: QuicCryptoFrame(level, offset, data.data(), data.length()) {}
QuicCryptoFrame::QuicCryptoFrame(EncryptionLevel level,
@@ -34,7 +35,8 @@ QuicCryptoFrame::~QuicCryptoFrame() {}
std::ostream& operator<<(std::ostream& os,
const QuicCryptoFrame& stream_frame) {
- os << "{ offset: " << stream_frame.offset
+ os << "{ level: " << static_cast<int>(stream_frame.level)
+ << ", offset: " << stream_frame.offset
<< ", length: " << stream_frame.data_length << " }\n";
return os;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_crypto_frame.h b/chromium/net/third_party/quiche/src/quic/core/frames/quic_crypto_frame.h
index a3968fe7f27..28434cb6362 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_crypto_frame.h
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_crypto_frame.h
@@ -11,7 +11,7 @@
#include "net/third_party/quiche/src/quic/core/quic_buffer_allocator.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -22,7 +22,7 @@ struct QUIC_EXPORT_PRIVATE QuicCryptoFrame {
QuicPacketLength data_length);
QuicCryptoFrame(EncryptionLevel level,
QuicStreamOffset offset,
- QuicStringPiece data);
+ quiche::QuicheStringPiece data);
~QuicCryptoFrame();
friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.cc
index e640179c460..d40202f1930 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.cc
@@ -4,6 +4,7 @@
#include "net/third_party/quiche/src/quic/core/frames/quic_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_buffer_allocator.h"
#include "net/third_party/quiche/src/quic/core/quic_constants.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
@@ -18,6 +19,9 @@ QuicFrame::QuicFrame(QuicPaddingFrame padding_frame)
QuicFrame::QuicFrame(QuicStreamFrame stream_frame)
: stream_frame(stream_frame) {}
+QuicFrame::QuicFrame(QuicHandshakeDoneFrame handshake_done_frame)
+ : handshake_done_frame(handshake_done_frame) {}
+
QuicFrame::QuicFrame(QuicCryptoFrame* crypto_frame)
: type(CRYPTO_FRAME), crypto_frame(crypto_frame) {}
@@ -88,6 +92,7 @@ void DeleteFrame(QuicFrame* frame) {
case STOP_WAITING_FRAME:
case STREAMS_BLOCKED_FRAME:
case STREAM_FRAME:
+ case HANDSHAKE_DONE_FRAME:
break;
case ACK_FRAME:
delete frame->ack_frame;
@@ -158,6 +163,7 @@ bool IsControlFrame(QuicFrameType type) {
case MAX_STREAMS_FRAME:
case PING_FRAME:
case STOP_SENDING_FRAME:
+ case HANDSHAKE_DONE_FRAME:
return true;
default:
return false;
@@ -182,6 +188,8 @@ QuicControlFrameId GetControlFrameId(const QuicFrame& frame) {
return frame.ping_frame.control_frame_id;
case STOP_SENDING_FRAME:
return frame.stop_sending_frame->control_frame_id;
+ case HANDSHAKE_DONE_FRAME:
+ return frame.handshake_done_frame.control_frame_id;
default:
return kInvalidControlFrameId;
}
@@ -213,6 +221,9 @@ void SetControlFrameId(QuicControlFrameId control_frame_id, QuicFrame* frame) {
case STOP_SENDING_FRAME:
frame->stop_sending_frame->control_frame_id = control_frame_id;
return;
+ case HANDSHAKE_DONE_FRAME:
+ frame->handshake_done_frame.control_frame_id = control_frame_id;
+ return;
default:
QUIC_BUG
<< "Try to set control frame id of a frame without control frame id";
@@ -246,6 +257,10 @@ QuicFrame CopyRetransmittableControlFrame(const QuicFrame& frame) {
case MAX_STREAMS_FRAME:
copy = QuicFrame(QuicMaxStreamsFrame(frame.max_streams_frame));
break;
+ case HANDSHAKE_DONE_FRAME:
+ copy = QuicFrame(
+ QuicHandshakeDoneFrame(frame.handshake_done_frame.control_frame_id));
+ break;
default:
QUIC_BUG << "Try to copy a non-retransmittable control frame: " << frame;
copy = QuicFrame(QuicPingFrame(kInvalidControlFrameId));
@@ -319,10 +334,11 @@ QuicFrame CopyQuicFrame(QuicBufferAllocator* allocator,
copy.message_frame->data = frame.message_frame->data;
copy.message_frame->message_length = frame.message_frame->message_length;
for (const auto& slice : frame.message_frame->message_data) {
- QuicMemSlice copy_slice(allocator, slice.length());
- memcpy(const_cast<char*>(copy_slice.data()), slice.data(),
- slice.length());
- copy.message_frame->message_data.push_back(std::move(copy_slice));
+ QuicUniqueBufferPtr buffer =
+ MakeUniqueBuffer(allocator, slice.length());
+ memcpy(buffer.get(), slice.data(), slice.length());
+ copy.message_frame->message_data.push_back(
+ QuicMemSlice(std::move(buffer), slice.length()));
}
break;
case NEW_TOKEN_FRAME:
@@ -332,6 +348,10 @@ QuicFrame CopyQuicFrame(QuicBufferAllocator* allocator,
copy = QuicFrame(
new QuicRetireConnectionIdFrame(*frame.retire_connection_id_frame));
break;
+ case HANDSHAKE_DONE_FRAME:
+ copy = QuicFrame(
+ QuicHandshakeDoneFrame(frame.handshake_done_frame.control_frame_id));
+ break;
default:
QUIC_BUG << "Cannot copy frame: " << frame;
copy = QuicFrame(QuicPingFrame(kInvalidControlFrameId));
@@ -428,6 +448,9 @@ std::ostream& operator<<(std::ostream& os, const QuicFrame& frame) {
case NEW_TOKEN_FRAME:
os << "type { NEW_TOKEN_FRAME }" << *(frame.new_token_frame);
break;
+ case HANDSHAKE_DONE_FRAME:
+ os << "type { HANDSHAKE_DONE_FRAME } " << frame.handshake_done_frame;
+ break;
default: {
QUIC_LOG(ERROR) << "Unknown frame type: " << frame.type;
break;
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.h b/chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.h
index 226cbfb2d83..756b69f1db0 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.h
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.h
@@ -13,6 +13,7 @@
#include "net/third_party/quiche/src/quic/core/frames/quic_connection_close_frame.h"
#include "net/third_party/quiche/src/quic/core/frames/quic_crypto_frame.h"
#include "net/third_party/quiche/src/quic/core/frames/quic_goaway_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_handshake_done_frame.h"
#include "net/third_party/quiche/src/quic/core/frames/quic_max_streams_frame.h"
#include "net/third_party/quiche/src/quic/core/frames/quic_message_frame.h"
#include "net/third_party/quiche/src/quic/core/frames/quic_mtu_discovery_frame.h"
@@ -45,6 +46,7 @@ struct QUIC_EXPORT_PRIVATE QuicFrame {
explicit QuicFrame(QuicStopWaitingFrame frame);
explicit QuicFrame(QuicStreamsBlockedFrame frame);
explicit QuicFrame(QuicStreamFrame stream_frame);
+ explicit QuicFrame(QuicHandshakeDoneFrame handshake_done_frame);
explicit QuicFrame(QuicAckFrame* frame);
explicit QuicFrame(QuicRstStreamFrame* frame);
@@ -76,6 +78,7 @@ struct QUIC_EXPORT_PRIVATE QuicFrame {
QuicStopWaitingFrame stop_waiting_frame;
QuicStreamsBlockedFrame streams_blocked_frame;
QuicStreamFrame stream_frame;
+ QuicHandshakeDoneFrame handshake_done_frame;
// Out of line frames.
struct {
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_frames_test.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_frames_test.cc
index 1764e170f03..7450adb5d2c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_frames_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_frames_test.cc
@@ -234,6 +234,17 @@ TEST_F(QuicFramesTest, PingFrameToString) {
EXPECT_TRUE(IsControlFrame(frame.type));
}
+TEST_F(QuicFramesTest, HandshakeDoneFrameToString) {
+ QuicHandshakeDoneFrame handshake_done;
+ QuicFrame frame(handshake_done);
+ SetControlFrameId(6, &frame);
+ EXPECT_EQ(6u, GetControlFrameId(frame));
+ std::ostringstream stream;
+ stream << frame.handshake_done_frame;
+ EXPECT_EQ("{ control_frame_id: 6 }\n", stream.str());
+ EXPECT_TRUE(IsControlFrame(frame.type));
+}
+
TEST_F(QuicFramesTest, StreamFrameToString) {
QuicStreamFrame frame;
frame.stream_id = 1;
@@ -546,6 +557,9 @@ TEST_F(QuicFramesTest, CopyQuicFrames) {
case RETIRE_CONNECTION_ID_FRAME:
frames.push_back(QuicFrame(new QuicRetireConnectionIdFrame()));
break;
+ case HANDSHAKE_DONE_FRAME:
+ frames.push_back(QuicFrame(QuicHandshakeDoneFrame()));
+ break;
default:
ASSERT_TRUE(false)
<< "Please fix CopyQuicFrames if a new frame type is added.";
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_handshake_done_frame.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_handshake_done_frame.cc
new file mode 100644
index 00000000000..6f411a50188
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_handshake_done_frame.cc
@@ -0,0 +1,25 @@
+// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/frames/quic_handshake_done_frame.h"
+
+namespace quic {
+
+QuicHandshakeDoneFrame::QuicHandshakeDoneFrame()
+ : QuicInlinedFrame(HANDSHAKE_DONE_FRAME),
+ control_frame_id(kInvalidControlFrameId) {}
+
+QuicHandshakeDoneFrame::QuicHandshakeDoneFrame(
+ QuicControlFrameId control_frame_id)
+ : QuicInlinedFrame(HANDSHAKE_DONE_FRAME),
+ control_frame_id(control_frame_id) {}
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicHandshakeDoneFrame& handshake_done_frame) {
+ os << "{ control_frame_id: " << handshake_done_frame.control_frame_id
+ << " }\n";
+ return os;
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_handshake_done_frame.h b/chromium/net/third_party/quiche/src/quic/core/frames/quic_handshake_done_frame.h
new file mode 100644
index 00000000000..48aa3c774a3
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_handshake_done_frame.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_HANDSHAKE_DONE_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_HANDSHAKE_DONE_FRAME_H_
+
+#include "net/third_party/quiche/src/quic/core/frames/quic_inlined_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+
+namespace quic {
+
+// A HANDSHAKE_DONE frame contains no payload, and it is retransmittable,
+// and ACK'd just like other normal frames.
+struct QUIC_EXPORT_PRIVATE QuicHandshakeDoneFrame
+ : public QuicInlinedFrame<QuicHandshakeDoneFrame> {
+ QuicHandshakeDoneFrame();
+ explicit QuicHandshakeDoneFrame(QuicControlFrameId control_frame_id);
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicHandshakeDoneFrame& handshake_done_frame);
+
+ // A unique identifier of this control frame. 0 when this frame is received,
+ // and non-zero when sent.
+ QuicControlFrameId control_frame_id;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_HANDSHAKE_DONE_FRAME_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_max_streams_frame.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_max_streams_frame.cc
index 21dce5bf706..6301e72c28f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_max_streams_frame.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_max_streams_frame.cc
@@ -9,6 +9,7 @@ namespace quic {
QuicMaxStreamsFrame::QuicMaxStreamsFrame()
: QuicInlinedFrame(MAX_STREAMS_FRAME),
control_frame_id(kInvalidControlFrameId),
+ stream_count(0),
unidirectional(false) {}
QuicMaxStreamsFrame::QuicMaxStreamsFrame(QuicControlFrameId control_frame_id,
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_message_frame.h b/chromium/net/third_party/quiche/src/quic/core/frames/quic_message_frame.h
index 78dafe39243..5f285135e10 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_message_frame.h
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_message_frame.h
@@ -10,7 +10,6 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice_span.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_new_token_frame.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_new_token_frame.cc
index 51d03e769bd..2dfb97f9017 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_new_token_frame.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_new_token_frame.cc
@@ -6,7 +6,7 @@
#include "net/third_party/quiche/src/quic/core/quic_constants.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
@@ -19,7 +19,7 @@ QuicNewTokenFrame::QuicNewTokenFrame(QuicControlFrameId control_frame_id,
std::ostream& operator<<(std::ostream& os, const QuicNewTokenFrame& s) {
os << "{ control_frame_id: " << s.control_frame_id
- << ", token: " << QuicTextUtils::HexEncode(s.token) << " }\n";
+ << ", token: " << quiche::QuicheTextUtils::HexEncode(s.token) << " }\n";
return os;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_new_token_frame.h b/chromium/net/third_party/quiche/src/quic/core/frames/quic_new_token_frame.h
index 5a063a3d7cf..0491477a2dd 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_new_token_frame.h
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_new_token_frame.h
@@ -11,7 +11,6 @@
#include "net/third_party/quiche/src/quic/core/quic_buffer_allocator.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_path_challenge_frame.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_path_challenge_frame.cc
index feaa71c4414..998ae483c07 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_path_challenge_frame.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_path_challenge_frame.cc
@@ -6,7 +6,7 @@
#include "net/third_party/quiche/src/quic/core/quic_constants.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
@@ -25,7 +25,7 @@ QuicPathChallengeFrame::~QuicPathChallengeFrame() {}
std::ostream& operator<<(std::ostream& os,
const QuicPathChallengeFrame& frame) {
os << "{ control_frame_id: " << frame.control_frame_id << ", data: "
- << QuicTextUtils::HexEncode(
+ << quiche::QuicheTextUtils::HexEncode(
reinterpret_cast<const char*>(frame.data_buffer.data()),
frame.data_buffer.size())
<< " }\n";
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_path_response_frame.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_path_response_frame.cc
index bf36ab4ff8d..e652698ab03 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_path_response_frame.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_path_response_frame.cc
@@ -6,7 +6,7 @@
#include "net/third_party/quiche/src/quic/core/quic_constants.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
@@ -24,7 +24,7 @@ QuicPathResponseFrame::~QuicPathResponseFrame() {}
std::ostream& operator<<(std::ostream& os, const QuicPathResponseFrame& frame) {
os << "{ control_frame_id: " << frame.control_frame_id << ", data: "
- << QuicTextUtils::HexEncode(
+ << quiche::QuicheTextUtils::HexEncode(
reinterpret_cast<const char*>(frame.data_buffer.data()),
frame.data_buffer.size())
<< " }\n";
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_frame.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_frame.cc
index d0e65d20d13..54a5252bb7d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_frame.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_frame.cc
@@ -5,6 +5,7 @@
#include "net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -14,7 +15,7 @@ QuicStreamFrame::QuicStreamFrame()
QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id,
bool fin,
QuicStreamOffset offset,
- QuicStringPiece data)
+ quiche::QuicheStringPiece data)
: QuicStreamFrame(stream_id, fin, offset, data.data(), data.length()) {}
QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id,
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h b/chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h
index 5c5323b2d57..fc78ff9df7f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h
@@ -12,7 +12,7 @@
#include "net/third_party/quiche/src/quic/core/quic_buffer_allocator.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -22,7 +22,7 @@ struct QUIC_EXPORT_PRIVATE QuicStreamFrame
QuicStreamFrame(QuicStreamId stream_id,
bool fin,
QuicStreamOffset offset,
- QuicStringPiece data);
+ quiche::QuicheStringPiece data);
QuicStreamFrame(QuicStreamId stream_id,
bool fin,
QuicStreamOffset offset,
diff --git a/chromium/net/third_party/quiche/src/quic/core/handshaker_delegate_interface.h b/chromium/net/third_party/quiche/src/quic/core/handshaker_delegate_interface.h
index 9eae32ab8cf..0e8e0454483 100644
--- a/chromium/net/third_party/quiche/src/quic/core/handshaker_delegate_interface.h
+++ b/chromium/net/third_party/quiche/src/quic/core/handshaker_delegate_interface.h
@@ -17,16 +17,27 @@ class QUIC_EXPORT_PRIVATE HandshakerDelegateInterface {
public:
virtual ~HandshakerDelegateInterface() {}
- // Called when new keys are available.
- virtual void OnNewKeysAvailable(EncryptionLevel level,
- std::unique_ptr<QuicDecrypter> decrypter,
- bool set_alternative_decrypter,
- bool latch_once_used,
- std::unique_ptr<QuicEncrypter> encrypter) = 0;
-
- // Called to set default encryption level to |level|.
+ // Called when new decryption key of |level| is available. Returns true if
+ // decrypter is set successfully, otherwise, returns false.
+ virtual bool OnNewDecryptionKeyAvailable(
+ EncryptionLevel level,
+ std::unique_ptr<QuicDecrypter> decrypter,
+ bool set_alternative_decrypter,
+ bool latch_once_used) = 0;
+
+ // Called when new encryption key of |level| is available.
+ virtual void OnNewEncryptionKeyAvailable(
+ EncryptionLevel level,
+ std::unique_ptr<QuicEncrypter> encrypter) = 0;
+
+ // Called to set default encryption level to |level|. Only used in QUIC
+ // crypto.
virtual void SetDefaultEncryptionLevel(EncryptionLevel level) = 0;
+ // Called when both 1-RTT read and write keys are available. Only used in TLS
+ // handshake.
+ virtual void OnOneRttKeysAvailable() = 0;
+
// Called to discard old decryption keys to stop processing packets of
// encryption |level|.
virtual void DiscardOldDecryptionKey(EncryptionLevel level) = 0;
@@ -38,13 +49,10 @@ class QUIC_EXPORT_PRIVATE HandshakerDelegateInterface {
// Called to neuter ENCRYPTION_INITIAL data (without discarding initial keys).
virtual void NeuterUnencryptedData() = 0;
- // Called to neuter data of HANDSHAKE_DATA packet number space. In QUIC
- // crypto, this is called 1) when a client switches to forward secure
+ // Called to neuter data of HANDSHAKE_DATA packet number space. Only used in
+ // QUIC crypto. This is called 1) when a client switches to forward secure
// encryption level and 2) a server successfully processes a forward secure
- // packet. Temporarily use this method in TLS handshake when both endpoints
- // switch to forward secure encryption level.
- // TODO(fayang): use DiscardOldEncryptionKey instead of this method in TLS
- // handshake when handshake key discarding settles down.
+ // packet.
virtual void NeuterHandshakeData() = 0;
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/end_to_end_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/end_to_end_test.cc
index df2b458d588..cec0ceb9fff 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/end_to_end_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/end_to_end_test.cc
@@ -31,12 +31,8 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_port_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_sleep.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test_loopback.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
-#include "net/quic/platform/impl/quic_socket_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/bad_packet_writer.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/packet_dropping_test_writer.h"
@@ -65,6 +61,9 @@
#include "net/third_party/quiche/src/quic/tools/quic_server.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_client_stream.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_server_stream.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
using spdy::kV3LowestPriority;
using spdy::SpdyFramer;
@@ -85,13 +84,11 @@ struct TestParams {
TestParams(const ParsedQuicVersionVector& client_supported_versions,
const ParsedQuicVersionVector& server_supported_versions,
ParsedQuicVersion negotiated_version,
- QuicTag congestion_control_tag,
- QuicTag priority_tag)
+ QuicTag congestion_control_tag)
: client_supported_versions(client_supported_versions),
server_supported_versions(server_supported_versions),
negotiated_version(negotiated_version),
- congestion_control_tag(congestion_control_tag),
- priority_tag(priority_tag) {}
+ congestion_control_tag(congestion_control_tag) {}
friend std::ostream& operator<<(std::ostream& os, const TestParams& p) {
os << "{ server_supported_versions: "
@@ -101,8 +98,7 @@ struct TestParams {
os << " negotiated_version: "
<< ParsedQuicVersionToString(p.negotiated_version);
os << " congestion_control_tag: "
- << QuicTagToString(p.congestion_control_tag);
- os << " priority_tag: " << QuicTagToString(p.priority_tag) << " }";
+ << QuicTagToString(p.congestion_control_tag) << " }";
return os;
}
@@ -110,17 +106,15 @@ struct TestParams {
ParsedQuicVersionVector server_supported_versions;
ParsedQuicVersion negotiated_version;
QuicTag congestion_control_tag;
- QuicTag priority_tag;
};
// Used by ::testing::PrintToStringParamName().
std::string PrintToString(const TestParams& p) {
- std::string rv = QuicStrCat(
+ std::string rv = quiche::QuicheStrCat(
ParsedQuicVersionToString(p.negotiated_version), "_Server_",
ParsedQuicVersionVectorToString(p.server_supported_versions), "_Client_",
ParsedQuicVersionVectorToString(p.client_supported_versions), "_",
- QuicTagToString(p.congestion_control_tag), "_",
- QuicTagToString(p.priority_tag));
+ QuicTagToString(p.congestion_control_tag));
std::replace(rv.begin(), rv.end(), ',', '_');
std::replace(rv.begin(), rv.end(), ' ', '_');
return rv;
@@ -128,7 +122,6 @@ std::string PrintToString(const TestParams& p) {
// Constructs various test permutations.
std::vector<TestParams> GetTestParams(bool use_tls_handshake) {
- QuicFlagSaver flags;
// Divide the versions into buckets in which the intra-frame format
// is compatible. When clients encounter QUIC version negotiation
// they simply retransmit all packets using the new version's
@@ -137,7 +130,6 @@ std::vector<TestParams> GetTestParams(bool use_tls_handshake) {
// handshake protocol). So these tests need to ensure that clients are never
// attempting to do 0-RTT across incompatible versions. Chromium only
// supports a single version at a time anyway. :)
- SetQuicReloadableFlag(quic_supports_tls_handshake, use_tls_handshake);
ParsedQuicVersionVector all_supported_versions =
FilterSupportedVersions(AllSupportedVersions());
@@ -150,6 +142,9 @@ std::vector<TestParams> GetTestParams(bool use_tls_handshake) {
ParsedQuicVersionVector version_buckets[3];
for (const ParsedQuicVersion& version : all_supported_versions) {
+ if (!use_tls_handshake && version.handshake_protocol == PROTOCOL_TLS1_3) {
+ continue;
+ }
if (!QuicVersionUsesCryptoFrames(version.transport_version)) {
version_buckets[0].push_back(version);
} else if (version.handshake_protocol == PROTOCOL_QUIC_CRYPTO) {
@@ -160,8 +155,7 @@ std::vector<TestParams> GetTestParams(bool use_tls_handshake) {
}
std::vector<TestParams> params;
- for (const QuicTag congestion_control_tag :
- {kRENO, kTBBR, kQBIC, kTPCC, kB2ON}) {
+ for (const QuicTag congestion_control_tag : {kRENO, kTBBR, kQBIC, kB2ON}) {
if (!GetQuicReloadableFlag(quic_allow_client_enabled_bbr_v2) &&
congestion_control_tag == kB2ON) {
continue;
@@ -170,32 +164,27 @@ std::vector<TestParams> GetTestParams(bool use_tls_handshake) {
if (FilterSupportedVersions(client_versions).empty()) {
continue;
}
- for (const QuicTag priority_tag :
- {/*no tag*/ static_cast<QuicTag>(0), kH2PR, kFIFO, kLIFO}) {
- // Add an entry for server and client supporting all versions.
- params.push_back(TestParams(client_versions, all_supported_versions,
- client_versions.front(),
- congestion_control_tag, priority_tag));
-
- // Test client supporting all versions and server supporting
- // 1 version. Simulate an old server and exercise version
- // downgrade in the client. Protocol negotiation should
- // occur. Skip the i = 0 case because it is essentially the
- // same as the default case.
- for (size_t i = 1; i < client_versions.size(); ++i) {
- ParsedQuicVersionVector server_supported_versions;
- server_supported_versions.push_back(client_versions[i]);
- if (FilterSupportedVersions(server_supported_versions).empty()) {
- continue;
- }
- params.push_back(TestParams(client_versions,
- server_supported_versions,
- server_supported_versions.front(),
- congestion_control_tag, priority_tag));
- } // End of inner version loop.
- } // End of priority_tag loop.
- } // End of outer version loop.
- } // End of congestion_control_tag loop.
+ // Add an entry for server and client supporting all versions.
+ params.push_back(TestParams(client_versions, all_supported_versions,
+ client_versions.front(),
+ congestion_control_tag));
+ // Test client supporting all versions and server supporting
+ // 1 version. Simulate an old server and exercise version
+ // downgrade in the client. Protocol negotiation should
+ // occur. Skip the i = 0 case because it is essentially the
+ // same as the default case.
+ for (size_t i = 1; i < client_versions.size(); ++i) {
+ ParsedQuicVersionVector server_supported_versions;
+ server_supported_versions.push_back(client_versions[i]);
+ if (FilterSupportedVersions(server_supported_versions).empty()) {
+ continue;
+ }
+ params.push_back(TestParams(client_versions, server_supported_versions,
+ server_supported_versions.front(),
+ congestion_control_tag));
+ } // End of inner version loop.
+ } // End of outer version loop.
+ } // End of congestion_control_tag loop.
return params;
}
@@ -245,9 +234,7 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
negotiated_version_(UnsupportedQuicVersion()),
chlo_multiplier_(0),
stream_factory_(nullptr),
- support_server_push_(false),
expected_server_connection_id_length_(kQuicDefaultConnectionIdLength) {
- SetQuicReloadableFlag(quic_supports_tls_handshake, true);
client_supported_versions_ = GetParam().client_supported_versions;
server_supported_versions_ = GetParam().server_supported_versions;
negotiated_version_ = GetParam().negotiated_version;
@@ -293,9 +280,7 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
}
client->UseConnectionIdLength(override_server_connection_id_length_);
client->UseClientConnectionIdLength(override_client_connection_id_length_);
- if (support_server_push_) {
- client->client()->SetMaxAllowedPushId(kMaxQuicStreamId);
- }
+ client->client()->set_connection_debug_visitor(connection_debug_visitor_);
client->Connect();
return client;
}
@@ -391,17 +376,11 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
// TODO(nimia): Consider setting the congestion control algorithm for the
// client as well according to the test parameter.
copt.push_back(GetParam().congestion_control_tag);
- if (GetParam().congestion_control_tag == kTPCC &&
- GetQuicReloadableFlag(quic_enable_pcc3)) {
- copt.push_back(kTPCC);
- }
- copt.push_back(GetParam().priority_tag);
- if (GetQuicReloadableFlag(quic_enable_pto)) {
- copt.push_back(k2PTO);
- }
+ copt.push_back(k2PTO);
if (VersionHasIetfQuicFrames(negotiated_version_.transport_version)) {
copt.push_back(kILD0);
}
+ copt.push_back(kPLE1);
client_config_.SetConnectionOptionsToSend(copt);
// Start the server first, because CreateQuicClient() attempts
@@ -435,6 +414,7 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
void TearDown() override {
ASSERT_TRUE(initialized_) << "You must call Initialize() in every test "
<< "case. Otherwise, your test will leak memory.";
+ GetClientConnection()->set_debug_visitor(nullptr);
StopServer();
}
@@ -476,9 +456,9 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
}
}
- void AddToCache(QuicStringPiece path,
+ void AddToCache(quiche::QuicheStringPiece path,
int response_code,
- QuicStringPiece body) {
+ quiche::QuicheStringPiece body) {
memory_cache_backend_.AddSimpleResponse(server_hostname_, path,
response_code, body);
}
@@ -602,6 +582,7 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
QuicMemoryCacheBackend memory_cache_backend_;
std::unique_ptr<ServerThread> server_thread_;
std::unique_ptr<QuicTestClient> client_;
+ QuicConnectionDebugVisitor* connection_debug_visitor_ = nullptr;
PacketDroppingTestWriter* client_writer_;
PacketDroppingTestWriter* server_writer_;
QuicConfig client_config_;
@@ -612,7 +593,6 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
ParsedQuicVersion negotiated_version_;
size_t chlo_multiplier_;
QuicTestServer::StreamFactory* stream_factory_;
- bool support_server_push_;
std::string pre_shared_key_client_;
std::string pre_shared_key_server_;
int override_server_connection_id_length_ = -1;
@@ -659,12 +639,8 @@ TEST_P(EndToEndTest, SimpleRequestResponse) {
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
- int expected_num_client_hellos = 2;
- if (ServerSendsVersionNegotiation()) {
- ++expected_num_client_hellos;
- }
- EXPECT_EQ(expected_num_client_hellos,
- client_->client()->GetNumSentClientHellos());
+ EXPECT_FALSE(client_->client()->EarlyDataAccepted());
+ EXPECT_FALSE(client_->client()->ReceivedInchoateReject());
if (VersionUsesHttp3(GetClientConnection()->transport_version())) {
EXPECT_TRUE(QuicSpdySessionPeer::GetSendControlStream(GetClientSession()));
EXPECT_TRUE(
@@ -681,6 +657,21 @@ TEST_P(EndToEndTestWithTls, SimpleRequestResponse) {
EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
}
+TEST_P(EndToEndTestWithTls, HandshakeConfirmed) {
+ ASSERT_TRUE(Initialize());
+ if (!GetParam().negotiated_version.HasHandshakeDone()) {
+ return;
+ }
+ EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
+ EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+ // Verify handshake state.
+ EXPECT_EQ(HANDSHAKE_CONFIRMED, GetClientSession()->GetHandshakeState());
+ server_thread_->Pause();
+ EXPECT_EQ(HANDSHAKE_CONFIRMED, GetServerSession()->GetHandshakeState());
+ server_thread_->Resume();
+ client_->Disconnect();
+}
+
TEST_P(EndToEndTestWithTls, SendAndReceiveCoalescedPackets) {
ASSERT_TRUE(Initialize());
if (!GetClientConnection()->version().CanSendCoalescedPackets()) {
@@ -706,12 +697,8 @@ TEST_P(EndToEndTest, SimpleRequestResponseWithAckDelayChange) {
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
- int expected_num_client_hellos = 2;
- if (ServerSendsVersionNegotiation()) {
- ++expected_num_client_hellos;
- }
- EXPECT_EQ(expected_num_client_hellos,
- client_->client()->GetNumSentClientHellos());
+ EXPECT_FALSE(client_->client()->EarlyDataAccepted());
+ EXPECT_FALSE(client_->client()->ReceivedInchoateReject());
if (GetQuicReloadableFlag(quic_negotiate_ack_delay_time)) {
EXPECT_EQ(kDefaultDelayedAckTimeMs + 100u,
GetSentPacketManagerFromFirstServerSession()
@@ -736,13 +723,9 @@ TEST_P(EndToEndTest, SimpleRequestResponseWithAckExponentChange) {
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
- int expected_num_client_hellos = 2;
- if (ServerSendsVersionNegotiation()) {
- ++expected_num_client_hellos;
- }
- EXPECT_EQ(expected_num_client_hellos,
- client_->client()->GetNumSentClientHellos());
+ EXPECT_FALSE(client_->client()->EarlyDataAccepted());
+ EXPECT_FALSE(client_->client()->ReceivedInchoateReject());
if (VersionHasIetfQuicFrames(
GetParam().negotiated_version.transport_version)) {
// Should be only for IETF QUIC.
@@ -761,13 +744,17 @@ TEST_P(EndToEndTest, SimpleRequestResponseWithAckExponentChange) {
TEST_P(EndToEndTest, SimpleRequestResponseForcedVersionNegotiation) {
client_supported_versions_.insert(client_supported_versions_.begin(),
QuicVersionReservedForNegotiation());
+ testing::NiceMock<MockQuicConnectionDebugVisitor> visitor;
+ connection_debug_visitor_ = &visitor;
+ EXPECT_CALL(visitor, OnVersionNegotiationPacket(testing::_)).Times(1);
ASSERT_TRUE(Initialize());
ASSERT_TRUE(ServerSendsVersionNegotiation());
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
- EXPECT_EQ(3, client_->client()->GetNumSentClientHellos());
+ EXPECT_FALSE(client_->client()->EarlyDataAccepted());
+ EXPECT_FALSE(client_->client()->ReceivedInchoateReject());
}
TEST_P(EndToEndTestWithTls, ForcedVersionNegotiation) {
@@ -781,8 +768,7 @@ TEST_P(EndToEndTestWithTls, ForcedVersionNegotiation) {
}
TEST_P(EndToEndTest, SimpleRequestResponseZeroConnectionID) {
- if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
- GetParam().negotiated_version.transport_version)) {
+ if (!GetParam().negotiated_version.AllowsVariableLengthConnectionIds()) {
ASSERT_TRUE(Initialize());
return;
}
@@ -792,20 +778,15 @@ TEST_P(EndToEndTest, SimpleRequestResponseZeroConnectionID) {
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
- int expected_num_client_hellos = 2;
- if (ServerSendsVersionNegotiation()) {
- ++expected_num_client_hellos;
- }
- EXPECT_EQ(expected_num_client_hellos,
- client_->client()->GetNumSentClientHellos());
+ EXPECT_FALSE(client_->client()->EarlyDataAccepted());
+ EXPECT_FALSE(client_->client()->ReceivedInchoateReject());
EXPECT_EQ(GetClientConnection()->connection_id(),
QuicUtils::CreateZeroConnectionId(
GetParam().negotiated_version.transport_version));
}
TEST_P(EndToEndTestWithTls, ZeroConnectionID) {
- if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
- GetParam().negotiated_version.transport_version)) {
+ if (!GetParam().negotiated_version.AllowsVariableLengthConnectionIds()) {
ASSERT_TRUE(Initialize());
return;
}
@@ -821,8 +802,7 @@ TEST_P(EndToEndTestWithTls, ZeroConnectionID) {
}
TEST_P(EndToEndTestWithTls, BadConnectionIdLength) {
- if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
- GetParam().negotiated_version.transport_version)) {
+ if (!GetParam().negotiated_version.AllowsVariableLengthConnectionIds()) {
ASSERT_TRUE(Initialize());
return;
}
@@ -840,8 +820,7 @@ TEST_P(EndToEndTestWithTls, BadConnectionIdLength) {
// Tests a very long (16-byte) initial destination connection ID to make
// sure the dispatcher properly replaces it with an 8-byte one.
TEST_P(EndToEndTestWithTls, LongBadConnectionIdLength) {
- if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
- GetParam().negotiated_version.transport_version)) {
+ if (!GetParam().negotiated_version.AllowsVariableLengthConnectionIds()) {
ASSERT_TRUE(Initialize());
return;
}
@@ -892,8 +871,7 @@ TEST_P(EndToEndTestWithTls, ForcedVersionNegotiationAndClientConnectionId) {
}
TEST_P(EndToEndTestWithTls, ForcedVersionNegotiationAndBadConnectionIdLength) {
- if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
- GetParam().negotiated_version.transport_version)) {
+ if (!GetParam().negotiated_version.AllowsVariableLengthConnectionIds()) {
ASSERT_TRUE(Initialize());
return;
}
@@ -915,8 +893,7 @@ TEST_P(EndToEndTestWithTls, ForcedVersionNegotiationAndBadConnectionIdLength) {
// connection ID.
TEST_P(EndToEndTestWithTls, ForcedVersNegoAndClientCIDAndLongCID) {
if (!GetParam().negotiated_version.SupportsClientConnectionIds() ||
- !QuicUtils::VariableLengthConnectionIdAllowedForVersion(
- GetParam().negotiated_version.transport_version)) {
+ !GetParam().negotiated_version.AllowsVariableLengthConnectionIds()) {
ASSERT_TRUE(Initialize());
return;
}
@@ -941,8 +918,7 @@ TEST_P(EndToEndTestWithTls, ForcedVersNegoAndClientCIDAndLongCID) {
}
TEST_P(EndToEndTest, MixGoodAndBadConnectionIdLengths) {
- if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
- GetParam().negotiated_version.transport_version)) {
+ if (!GetParam().negotiated_version.AllowsVariableLengthConnectionIds()) {
ASSERT_TRUE(Initialize());
return;
}
@@ -982,8 +958,7 @@ TEST_P(EndToEndTest, MixGoodAndBadConnectionIdLengths) {
}
TEST_P(EndToEndTestWithTls, SimpleRequestResponseWithIetfDraftSupport) {
- if (GetParam().negotiated_version.transport_version != QUIC_VERSION_99 ||
- GetParam().negotiated_version.handshake_protocol != PROTOCOL_TLS1_3) {
+ if (!GetParam().negotiated_version.HasIetfQuicFrames()) {
ASSERT_TRUE(Initialize());
return;
}
@@ -1000,11 +975,8 @@ TEST_P(EndToEndTest, SimpleRequestResponseWithLargeReject) {
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
- if (ServerSendsVersionNegotiation()) {
- EXPECT_EQ(4, client_->client()->GetNumSentClientHellos());
- } else {
- EXPECT_EQ(3, client_->client()->GetNumSentClientHellos());
- }
+ EXPECT_FALSE(client_->client()->EarlyDataAccepted());
+ EXPECT_TRUE(client_->client()->ReceivedInchoateReject());
}
TEST_P(EndToEndTestWithTls, SimpleRequestResponsev6) {
@@ -1098,8 +1070,7 @@ TEST_P(EndToEndTestWithTls, MultipleRequestResponse) {
}
TEST_P(EndToEndTest, MultipleRequestResponseZeroConnectionID) {
- if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
- GetParam().negotiated_version.transport_version)) {
+ if (!GetParam().negotiated_version.AllowsVariableLengthConnectionIds()) {
ASSERT_TRUE(Initialize());
return;
}
@@ -1359,14 +1330,10 @@ TEST_P(EndToEndTest, LargePostZeroRTTFailure) {
EXPECT_EQ(kFooResponseBody,
client_->SendCustomSynchronousRequest(headers, body));
- // The same session is used for both hellos, so the number of hellos sent on
- // that session is 2.
- EXPECT_EQ(2, GetClientSession()->GetNumSentClientHellos());
- if (ServerSendsVersionNegotiation()) {
- EXPECT_EQ(3, client_->client()->GetNumSentClientHellos());
- } else {
- EXPECT_EQ(2, client_->client()->GetNumSentClientHellos());
- }
+ EXPECT_FALSE(GetClientSession()->EarlyDataAccepted());
+ EXPECT_FALSE(GetClientSession()->ReceivedInchoateReject());
+ EXPECT_FALSE(client_->client()->EarlyDataAccepted());
+ EXPECT_FALSE(client_->client()->ReceivedInchoateReject());
client_->Disconnect();
@@ -1377,12 +1344,8 @@ TEST_P(EndToEndTest, LargePostZeroRTTFailure) {
EXPECT_EQ(kFooResponseBody,
client_->SendCustomSynchronousRequest(headers, body));
- EXPECT_EQ(1, GetClientSession()->GetNumSentClientHellos());
- if (ServerSendsVersionNegotiation()) {
- EXPECT_EQ(2, client_->client()->GetNumSentClientHellos());
- } else {
- EXPECT_EQ(1, client_->client()->GetNumSentClientHellos());
- }
+ EXPECT_TRUE(GetClientSession()->EarlyDataAccepted());
+ EXPECT_TRUE(client_->client()->EarlyDataAccepted());
client_->Disconnect();
@@ -1396,14 +1359,10 @@ TEST_P(EndToEndTest, LargePostZeroRTTFailure) {
ASSERT_TRUE(client_->client()->connected());
EXPECT_EQ(kFooResponseBody,
client_->SendCustomSynchronousRequest(headers, body));
- // The same session is used for both hellos, so the number of hellos sent on
- // that session is 2.
- EXPECT_EQ(2, GetClientSession()->GetNumSentClientHellos());
- if (ServerSendsVersionNegotiation()) {
- EXPECT_EQ(3, client_->client()->GetNumSentClientHellos());
- } else {
- EXPECT_EQ(2, client_->client()->GetNumSentClientHellos());
- }
+ EXPECT_FALSE(GetClientSession()->EarlyDataAccepted());
+ EXPECT_FALSE(GetClientSession()->ReceivedInchoateReject());
+ EXPECT_FALSE(client_->client()->EarlyDataAccepted());
+ EXPECT_FALSE(client_->client()->ReceivedInchoateReject());
VerifyCleanConnection(false);
}
@@ -1414,14 +1373,10 @@ TEST_P(EndToEndTest, SynchronousRequestZeroRTTFailure) {
ASSERT_TRUE(Initialize());
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
- // The same session is used for both hellos, so the number of hellos sent on
- // that session is 2.
- EXPECT_EQ(2, GetClientSession()->GetNumSentClientHellos());
- if (ServerSendsVersionNegotiation()) {
- EXPECT_EQ(3, client_->client()->GetNumSentClientHellos());
- } else {
- EXPECT_EQ(2, client_->client()->GetNumSentClientHellos());
- }
+ EXPECT_FALSE(GetClientSession()->EarlyDataAccepted());
+ EXPECT_FALSE(GetClientSession()->ReceivedInchoateReject());
+ EXPECT_FALSE(client_->client()->EarlyDataAccepted());
+ EXPECT_FALSE(client_->client()->ReceivedInchoateReject());
client_->Disconnect();
@@ -1431,12 +1386,8 @@ TEST_P(EndToEndTest, SynchronousRequestZeroRTTFailure) {
ASSERT_TRUE(client_->client()->connected());
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
- EXPECT_EQ(1, GetClientSession()->GetNumSentClientHellos());
- if (ServerSendsVersionNegotiation()) {
- EXPECT_EQ(2, client_->client()->GetNumSentClientHellos());
- } else {
- EXPECT_EQ(1, client_->client()->GetNumSentClientHellos());
- }
+ EXPECT_TRUE(GetClientSession()->EarlyDataAccepted());
+ EXPECT_TRUE(client_->client()->EarlyDataAccepted());
client_->Disconnect();
@@ -1450,12 +1401,10 @@ TEST_P(EndToEndTest, SynchronousRequestZeroRTTFailure) {
ASSERT_TRUE(client_->client()->connected());
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
- EXPECT_EQ(2, GetClientSession()->GetNumSentClientHellos());
- if (ServerSendsVersionNegotiation()) {
- EXPECT_EQ(3, client_->client()->GetNumSentClientHellos());
- } else {
- EXPECT_EQ(2, client_->client()->GetNumSentClientHellos());
- }
+ EXPECT_FALSE(GetClientSession()->EarlyDataAccepted());
+ EXPECT_FALSE(GetClientSession()->ReceivedInchoateReject());
+ EXPECT_FALSE(client_->client()->EarlyDataAccepted());
+ EXPECT_FALSE(client_->client()->ReceivedInchoateReject());
VerifyCleanConnection(false);
}
@@ -1474,14 +1423,10 @@ TEST_P(EndToEndTest, LargePostSynchronousRequest) {
EXPECT_EQ(kFooResponseBody,
client_->SendCustomSynchronousRequest(headers, body));
- // The same session is used for both hellos, so the number of hellos sent on
- // that session is 2.
- EXPECT_EQ(2, GetClientSession()->GetNumSentClientHellos());
- if (ServerSendsVersionNegotiation()) {
- EXPECT_EQ(3, client_->client()->GetNumSentClientHellos());
- } else {
- EXPECT_EQ(2, client_->client()->GetNumSentClientHellos());
- }
+ EXPECT_FALSE(GetClientSession()->EarlyDataAccepted());
+ EXPECT_FALSE(GetClientSession()->ReceivedInchoateReject());
+ EXPECT_FALSE(client_->client()->EarlyDataAccepted());
+ EXPECT_FALSE(client_->client()->ReceivedInchoateReject());
client_->Disconnect();
@@ -1492,12 +1437,8 @@ TEST_P(EndToEndTest, LargePostSynchronousRequest) {
EXPECT_EQ(kFooResponseBody,
client_->SendCustomSynchronousRequest(headers, body));
- EXPECT_EQ(1, GetClientSession()->GetNumSentClientHellos());
- if (ServerSendsVersionNegotiation()) {
- EXPECT_EQ(2, client_->client()->GetNumSentClientHellos());
- } else {
- EXPECT_EQ(1, client_->client()->GetNumSentClientHellos());
- }
+ EXPECT_TRUE(GetClientSession()->EarlyDataAccepted());
+ EXPECT_TRUE(client_->client()->EarlyDataAccepted());
client_->Disconnect();
@@ -1512,12 +1453,10 @@ TEST_P(EndToEndTest, LargePostSynchronousRequest) {
EXPECT_EQ(kFooResponseBody,
client_->SendCustomSynchronousRequest(headers, body));
- EXPECT_EQ(2, GetClientSession()->GetNumSentClientHellos());
- if (ServerSendsVersionNegotiation()) {
- EXPECT_EQ(3, client_->client()->GetNumSentClientHellos());
- } else {
- EXPECT_EQ(2, client_->client()->GetNumSentClientHellos());
- }
+ EXPECT_FALSE(GetClientSession()->EarlyDataAccepted());
+ EXPECT_FALSE(GetClientSession()->ReceivedInchoateReject());
+ EXPECT_FALSE(client_->client()->EarlyDataAccepted());
+ EXPECT_FALSE(client_->client()->ReceivedInchoateReject());
VerifyCleanConnection(false);
}
@@ -1732,12 +1671,11 @@ TEST_P(EndToEndTest, Timeout) {
}
}
-TEST_P(EndToEndTestWithTls, MaxIncomingDynamicStreamsLimitRespected) {
+TEST_P(EndToEndTestWithTls, MaxDynamicStreamsLimitRespected) {
// Set a limit on maximum number of incoming dynamic streams.
- // Make sure the limit is respected.
- const uint32_t kServerMaxIncomingDynamicStreams = 1;
- server_config_.SetMaxIncomingBidirectionalStreamsToSend(
- kServerMaxIncomingDynamicStreams);
+ // Make sure the limit is respected by the peer.
+ const uint32_t kServerMaxDynamicStreams = 1;
+ server_config_.SetMaxBidirectionalStreamsToSend(kServerMaxDynamicStreams);
ASSERT_TRUE(Initialize());
if (VersionHasIetfQuicFrames(
GetParam().negotiated_version.transport_version)) {
@@ -1776,18 +1714,14 @@ TEST_P(EndToEndTestWithTls, MaxIncomingDynamicStreamsLimitRespected) {
EXPECT_THAT(client_->connection_error(), IsQuicNoError());
}
-TEST_P(EndToEndTest, SetIndependentMaxIncomingDynamicStreamsLimits) {
- // Each endpoint can set max incoming dynamic streams independently.
- const uint32_t kClientMaxIncomingDynamicStreams = 4;
- const uint32_t kServerMaxIncomingDynamicStreams = 3;
- client_config_.SetMaxIncomingBidirectionalStreamsToSend(
- kClientMaxIncomingDynamicStreams);
- server_config_.SetMaxIncomingBidirectionalStreamsToSend(
- kServerMaxIncomingDynamicStreams);
- client_config_.SetMaxIncomingUnidirectionalStreamsToSend(
- kClientMaxIncomingDynamicStreams);
- server_config_.SetMaxIncomingUnidirectionalStreamsToSend(
- kServerMaxIncomingDynamicStreams);
+TEST_P(EndToEndTest, SetIndependentMaxDynamicStreamsLimits) {
+ // Each endpoint can set max dynamic streams independently.
+ const uint32_t kClientMaxDynamicStreams = 4;
+ const uint32_t kServerMaxDynamicStreams = 3;
+ client_config_.SetMaxBidirectionalStreamsToSend(kClientMaxDynamicStreams);
+ server_config_.SetMaxBidirectionalStreamsToSend(kServerMaxDynamicStreams);
+ client_config_.SetMaxUnidirectionalStreamsToSend(kClientMaxDynamicStreams);
+ server_config_.SetMaxUnidirectionalStreamsToSend(kServerMaxDynamicStreams);
ASSERT_TRUE(Initialize());
EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
@@ -1815,9 +1749,9 @@ TEST_P(EndToEndTest, SetIndependentMaxIncomingDynamicStreamsLimits) {
client_session->num_expected_unidirectional_static_streams()
: QuicSessionPeer::GetStreamIdManager(client_session)
->max_open_outgoing_streams();
- EXPECT_EQ(kServerMaxIncomingDynamicStreams,
+ EXPECT_EQ(kServerMaxDynamicStreams,
client_max_open_outgoing_bidirectional_streams);
- EXPECT_EQ(kServerMaxIncomingDynamicStreams,
+ EXPECT_EQ(kServerMaxDynamicStreams,
client_max_open_outgoing_unidirectional_streams);
server_thread_->Pause();
QuicSession* server_session = GetServerSession();
@@ -1836,9 +1770,9 @@ TEST_P(EndToEndTest, SetIndependentMaxIncomingDynamicStreamsLimits) {
server_session->num_expected_unidirectional_static_streams()
: QuicSessionPeer::GetStreamIdManager(server_session)
->max_open_outgoing_streams();
- EXPECT_EQ(kClientMaxIncomingDynamicStreams,
+ EXPECT_EQ(kClientMaxDynamicStreams,
server_max_open_outgoing_bidirectional_streams);
- EXPECT_EQ(kClientMaxIncomingDynamicStreams,
+ EXPECT_EQ(kClientMaxDynamicStreams,
server_max_open_outgoing_unidirectional_streams);
server_thread_->Resume();
@@ -1847,12 +1781,6 @@ TEST_P(EndToEndTest, SetIndependentMaxIncomingDynamicStreamsLimits) {
TEST_P(EndToEndTest, NegotiateCongestionControl) {
ASSERT_TRUE(Initialize());
- // For PCC, the underlying implementation may be a stub with a
- // different name-tag. Skip the rest of this test.
- if (GetParam().congestion_control_tag == kTPCC) {
- return;
- }
-
EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
CongestionControlType expected_congestion_control_type = kRenoBytes;
@@ -2756,15 +2684,13 @@ TEST_P(EndToEndTestWithTls, BadPacketHeaderTruncated) {
&packet[0], sizeof(packet),
client_->client()->network_helper()->GetLatestClientAddress().host(),
server_address_, nullptr);
- // Give the server time to process the packet.
- QuicSleep(QuicTime::Delta::FromMilliseconds(100));
- // Pause the server so we can access the server's internals without races.
- server_thread_->Pause();
- QuicDispatcher* dispatcher =
- QuicServerPeer::GetDispatcher(server_thread_->server());
- EXPECT_THAT(QuicDispatcherPeer::GetAndClearLastError(dispatcher),
- IsError(QUIC_INVALID_PACKET_HEADER));
- server_thread_->Resume();
+ EXPECT_TRUE(server_thread_->WaitUntil(
+ [&] {
+ return QuicDispatcherPeer::GetAndClearLastError(
+ QuicServerPeer::GetDispatcher(server_thread_->server())) ==
+ QUIC_INVALID_PACKET_HEADER;
+ },
+ QuicTime::Delta::FromSeconds(5)));
// The connection should not be terminated.
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
@@ -2807,15 +2733,14 @@ TEST_P(EndToEndTestWithTls, BadPacketHeaderFlags) {
&packet[0], sizeof(packet),
client_->client()->network_helper()->GetLatestClientAddress().host(),
server_address_, nullptr);
- // Give the server time to process the packet.
- QuicSleep(QuicTime::Delta::FromMilliseconds(100));
- // Pause the server so we can access the server's internals without races.
- server_thread_->Pause();
- QuicDispatcher* dispatcher =
- QuicServerPeer::GetDispatcher(server_thread_->server());
- EXPECT_THAT(QuicDispatcherPeer::GetAndClearLastError(dispatcher),
- IsError(QUIC_INVALID_PACKET_HEADER));
- server_thread_->Resume();
+
+ EXPECT_TRUE(server_thread_->WaitUntil(
+ [&] {
+ return QuicDispatcherPeer::GetAndClearLastError(
+ QuicServerPeer::GetDispatcher(server_thread_->server())) ==
+ QUIC_INVALID_PACKET_HEADER;
+ },
+ QuicTime::Delta::FromSeconds(5)));
// The connection should not be terminated.
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
@@ -2844,7 +2769,7 @@ TEST_P(EndToEndTestWithTls, BadEncryptedData) {
client_->client()->network_helper()->GetLatestClientAddress().host(),
server_address_, nullptr);
// Give the server time to process the packet.
- QuicSleep(QuicTime::Delta::FromMilliseconds(100));
+ QuicSleep(QuicTime::Delta::FromSeconds(1));
// This error is sent to the connection's OnError (which ignores it), so the
// dispatcher doesn't see it.
// Pause the server so we can access the server's internals without races.
@@ -2903,7 +2828,7 @@ class ServerStreamWithErrorResponseBody : public QuicSimpleServerStream {
SpdyHeaderBlock headers;
headers[":status"] = "500";
headers["content-length"] =
- QuicTextUtils::Uint64ToString(response_body_.size());
+ quiche::QuicheTextUtils::Uint64ToString(response_body_.size());
// This method must call CloseReadSide to cause the test case, StopReading
// is not sufficient.
QuicStreamPeer::CloseReadSide(this);
@@ -3122,7 +3047,8 @@ TEST_P(EndToEndTestWithTls, Trailers) {
SpdyHeaderBlock headers;
headers[":status"] = "200";
- headers["content-length"] = QuicTextUtils::Uint64ToString(kBody.size());
+ headers["content-length"] =
+ quiche::QuicheTextUtils::Uint64ToString(kBody.size());
SpdyHeaderBlock trailers;
trailers["some-trailing-header"] = "trailing-header-value";
@@ -3136,16 +3062,16 @@ TEST_P(EndToEndTestWithTls, Trailers) {
EXPECT_EQ(trailers, client_->response_trailers());
}
+// TODO(b/151749109): Test server push for IETF QUIC.
class EndToEndTestServerPush : public EndToEndTest {
protected:
const size_t kNumMaxStreams = 10;
EndToEndTestServerPush() : EndToEndTest() {
- client_config_.SetMaxIncomingBidirectionalStreamsToSend(kNumMaxStreams);
- server_config_.SetMaxIncomingBidirectionalStreamsToSend(kNumMaxStreams);
- client_config_.SetMaxIncomingUnidirectionalStreamsToSend(kNumMaxStreams);
- server_config_.SetMaxIncomingUnidirectionalStreamsToSend(kNumMaxStreams);
- support_server_push_ = true;
+ client_config_.SetMaxBidirectionalStreamsToSend(kNumMaxStreams);
+ server_config_.SetMaxBidirectionalStreamsToSend(kNumMaxStreams);
+ client_config_.SetMaxUnidirectionalStreamsToSend(kNumMaxStreams);
+ server_config_.SetMaxUnidirectionalStreamsToSend(kNumMaxStreams);
}
// Add a request with its response and |num_resources| push resources into
@@ -3173,11 +3099,12 @@ class EndToEndTestServerPush : public EndToEndTest {
std::string body =
use_large_response
? large_resource
- : QuicStrCat("This is server push response body for ", url);
+ : quiche::QuicheStrCat("This is server push response body for ",
+ url);
SpdyHeaderBlock response_headers;
response_headers[":status"] = "200";
response_headers["content-length"] =
- QuicTextUtils::Uint64ToString(body.size());
+ quiche::QuicheTextUtils::Uint64ToString(body.size());
push_resources.push_back(QuicBackendResponse::ServerPushInfo(
resource_url, std::move(response_headers), kV3LowestPriority, body));
}
@@ -3235,7 +3162,7 @@ TEST_P(EndToEndTestServerPush, ServerPush) {
for (const std::string& url : push_urls) {
QUIC_DVLOG(1) << "send request for pushed stream on url " << url;
std::string expected_body =
- QuicStrCat("This is server push response body for ", url);
+ quiche::QuicheStrCat("This is server push response body for ", url);
std::string response_body = client_->SendSynchronousRequest(url);
QUIC_DVLOG(1) << "response body " << response_body;
EXPECT_EQ(expected_body, response_body);
@@ -3250,7 +3177,6 @@ TEST_P(EndToEndTestServerPush, ServerPush) {
}
TEST_P(EndToEndTestServerPush, ServerPushUnderLimit) {
- SetQuicReloadableFlag(quic_send_max_push_id_with_settings, true);
// Tests that sending a request which has 4 push resources will trigger server
// to push those 4 resources and client can handle pushed resources and match
// them with requests later.
@@ -3288,7 +3214,7 @@ TEST_P(EndToEndTestServerPush, ServerPushUnderLimit) {
// as the responses are already in the client's cache.
QUIC_DVLOG(1) << "send request for pushed stream on url " << url;
std::string expected_body =
- QuicStrCat("This is server push response body for ", url);
+ quiche::QuicheStrCat("This is server push response body for ", url);
std::string response_body = client_->SendSynchronousRequest(url);
QUIC_DVLOG(1) << "response body " << response_body;
EXPECT_EQ(expected_body, response_body);
@@ -3327,7 +3253,8 @@ TEST_P(EndToEndTestServerPush, ServerPushOverLimitNonBlocking) {
const size_t kNumResources = 1 + kNumMaxStreams; // 11.
std::string push_urls[11];
for (size_t i = 0; i < kNumResources; ++i) {
- push_urls[i] = QuicStrCat("https://example.com/push_resources", i);
+ push_urls[i] =
+ quiche::QuicheStrCat("https://example.com/push_resources", i);
}
AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody,
push_urls, kNumResources, 0);
@@ -3344,8 +3271,9 @@ TEST_P(EndToEndTestServerPush, ServerPushOverLimitNonBlocking) {
for (const std::string& url : push_urls) {
// Sending subsequent requesets will not actually send anything on the wire,
// as the responses are already in the client's cache.
- EXPECT_EQ(QuicStrCat("This is server push response body for ", url),
- client_->SendSynchronousRequest(url));
+ EXPECT_EQ(
+ quiche::QuicheStrCat("This is server push response body for ", url),
+ client_->SendSynchronousRequest(url));
}
// Only 1 request should have been sent.
@@ -3356,7 +3284,6 @@ TEST_P(EndToEndTestServerPush, ServerPushOverLimitNonBlocking) {
}
TEST_P(EndToEndTestServerPush, ServerPushOverLimitWithBlocking) {
- SetQuicReloadableFlag(quic_send_max_push_id_with_settings, true);
// Tests that when server tries to send more large resources(large enough to
// be blocked by flow control window or congestion control window) than max
// open outgoing streams , server can open upto max number of outgoing
@@ -3385,7 +3312,7 @@ TEST_P(EndToEndTestServerPush, ServerPushOverLimitWithBlocking) {
const size_t kNumResources = kNumMaxStreams + 1;
std::string push_urls[11];
for (size_t i = 0; i < kNumResources; ++i) {
- push_urls[i] = QuicStrCat("http://example.com/push_resources", i);
+ push_urls[i] = quiche::QuicheStrCat("http://example.com/push_resources", i);
}
AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody,
push_urls, kNumResources, kBodySize);
@@ -3462,7 +3389,7 @@ TEST_P(EndToEndTest, DISABLED_TestHugePostWithPacketLoss) {
headers[":scheme"] = "https";
headers[":authority"] = server_hostname_;
headers["content-length"] =
- QuicTextUtils::Uint64ToString(request_body_size_bytes);
+ quiche::QuicheTextUtils::Uint64ToString(request_body_size_bytes);
client_->SendMessage(headers, "", /*fin=*/false);
@@ -3572,8 +3499,12 @@ TEST_P(EndToEndTest, WayTooLongRequestHeaders) {
client_->SendMessage(headers, "");
client_->WaitForResponse();
- EXPECT_THAT(client_->connection_error(),
- IsError(QUIC_HEADERS_STREAM_DATA_DECOMPRESS_FAILURE));
+
+ QuicErrorCode expected_error =
+ GetQuicReloadableFlag(spdy_enable_granular_decompress_errors)
+ ? QUIC_HPACK_INDEX_VARINT_ERROR
+ : QUIC_HEADERS_STREAM_DATA_DECOMPRESS_FAILURE;
+ EXPECT_THAT(client_->connection_error(), IsError(expected_error));
}
class WindowUpdateObserver : public QuicConnectionDebugVisitor {
@@ -3732,9 +3663,9 @@ TEST_P(EndToEndTest, LastPacketSentIsConnectivityProbing) {
TEST_P(EndToEndTest, PreSharedKey) {
client_config_.set_max_time_before_crypto_handshake(
- QuicTime::Delta::FromSeconds(1));
+ QuicTime::Delta::FromSeconds(5));
client_config_.set_max_idle_time_before_crypto_handshake(
- QuicTime::Delta::FromSeconds(1));
+ QuicTime::Delta::FromSeconds(5));
pre_shared_key_client_ = "foobar";
pre_shared_key_server_ = "foobar";
ASSERT_TRUE(Initialize());
@@ -3794,9 +3725,9 @@ TEST_P(EndToEndTest, RequestAndStreamRstInOnePacket) {
// (and the FIN) after the response body.
std::string response_body(1305, 'a');
SpdyHeaderBlock response_headers;
- response_headers[":status"] = QuicTextUtils::Uint64ToString(200);
+ response_headers[":status"] = quiche::QuicheTextUtils::Uint64ToString(200);
response_headers["content-length"] =
- QuicTextUtils::Uint64ToString(response_body.length());
+ quiche::QuicheTextUtils::Uint64ToString(response_body.length());
memory_cache_backend_.AddSpecialResponse(
server_hostname_, "/test_url", std::move(response_headers), response_body,
QuicBackendResponse::INCOMPLETE_RESPONSE);
@@ -3853,22 +3784,22 @@ TEST_P(EndToEndTest, SendMessages) {
ASSERT_LT(0, client_session->GetCurrentLargestMessagePayload());
std::string message_string(kMaxOutgoingPacketSize, 'a');
- QuicStringPiece message_buffer(message_string);
+ quiche::QuicheStringPiece message_buffer(message_string);
QuicRandom* random =
QuicConnectionPeer::GetHelper(client_connection)->GetRandomGenerator();
QuicMemSliceStorage storage(nullptr, 0, nullptr, 0);
{
QuicConnection::ScopedPacketFlusher flusher(client_session->connection());
// Verify the largest message gets successfully sent.
- EXPECT_EQ(
- MessageResult(MESSAGE_STATUS_SUCCESS, 1),
- client_session->SendMessage(MakeSpan(
- client_session->connection()
- ->helper()
- ->GetStreamSendBufferAllocator(),
- QuicStringPiece(message_buffer.data(),
- client_session->GetCurrentLargestMessagePayload()),
- &storage)));
+ EXPECT_EQ(MessageResult(MESSAGE_STATUS_SUCCESS, 1),
+ client_session->SendMessage(MakeSpan(
+ client_session->connection()
+ ->helper()
+ ->GetStreamSendBufferAllocator(),
+ quiche::QuicheStringPiece(
+ message_buffer.data(),
+ client_session->GetCurrentLargestMessagePayload()),
+ &storage)));
// Send more messages with size (0, largest_payload] until connection is
// write blocked.
const int kTestMaxNumberOfMessages = 100;
@@ -3881,7 +3812,8 @@ TEST_P(EndToEndTest, SendMessages) {
client_session->connection()
->helper()
->GetStreamSendBufferAllocator(),
- QuicStringPiece(message_buffer.data(), message_length), &storage));
+ quiche::QuicheStringPiece(message_buffer.data(), message_length),
+ &storage));
if (result.status == MESSAGE_STATUS_BLOCKED) {
// Connection is write blocked.
break;
@@ -3897,7 +3829,7 @@ TEST_P(EndToEndTest, SendMessages) {
client_session->connection()
->helper()
->GetStreamSendBufferAllocator(),
- QuicStringPiece(
+ quiche::QuicheStringPiece(
message_buffer.data(),
client_session->GetCurrentLargestMessagePayload() + 1),
&storage))
@@ -3999,17 +3931,11 @@ TEST_P(EndToEndPacketReorderingTest, Buffer0RttRequest) {
EXPECT_EQ(kBarResponseBody, client_->response_body());
QuicConnectionStats client_stats = GetClientConnection()->GetStats();
EXPECT_EQ(0u, client_stats.packets_lost);
- if (ServerSendsVersionNegotiation()) {
- EXPECT_EQ(2, client_->client()->GetNumSentClientHellos());
- } else {
- EXPECT_EQ(1, client_->client()->GetNumSentClientHellos());
- }
+ EXPECT_TRUE(client_->client()->EarlyDataAccepted());
}
-// Test that STOP_SENDING makes it to the other side. Set up a client & server,
-// create a stream (do not close it), and then send a STOP_SENDING from one
-// side. The other side should get a call to QuicStream::OnStopSending.
-// (aside, test cribbed from RequestAndStreamRstInOnePacket)
+// Test that STOP_SENDING makes it to the peer. Create a stream and send a
+// STOP_SENDING. The receiver should get a call to QuicStream::OnStopSending.
TEST_P(EndToEndTest, SimpleStopSendingTest) {
const uint16_t kStopSendingTestCode = 123;
ASSERT_TRUE(Initialize());
@@ -4021,14 +3947,11 @@ TEST_P(EndToEndTest, SimpleStopSendingTest) {
QuicConnection* client_connection = client_session->connection();
ASSERT_NE(nullptr, client_connection);
- // STOP_SENDING will cause the server to not to send the trailer
- // (and the FIN) after the response body. Instead, it sends a STOP_SENDING
- // frame for the stream.
std::string response_body(1305, 'a');
SpdyHeaderBlock response_headers;
- response_headers[":status"] = QuicTextUtils::Uint64ToString(200);
+ response_headers[":status"] = quiche::QuicheTextUtils::Uint64ToString(200);
response_headers["content-length"] =
- QuicTextUtils::Uint64ToString(response_body.length());
+ quiche::QuicheTextUtils::Uint64ToString(response_body.length());
memory_cache_backend_.AddStopSendingResponse(
server_hostname_, "/test_url", std::move(response_headers), response_body,
kStopSendingTestCode);
@@ -4050,14 +3973,13 @@ TEST_P(EndToEndTest, SimpleStopSendingTest) {
// Wait for the connection to become idle.
client_->WaitForDelayedAcks();
- // The real expectation is the test does not crash or timeout.
EXPECT_THAT(client_->connection_error(), IsQuicNoError());
- // And that the stop-sending code is received.
QuicSimpleClientStream* client_stream =
static_cast<QuicSimpleClientStream*>(client_->latest_created_stream());
ASSERT_NE(nullptr, client_stream);
- // Make sure we have the correct stream
+ // Ensure the stream has been write closed upon receiving STOP_SENDING.
EXPECT_EQ(stream_id, client_stream->id());
+ EXPECT_TRUE(client_stream->write_side_closed());
EXPECT_EQ(kStopSendingTestCode,
static_cast<uint16_t>(client_stream->stream_error()));
}
@@ -4249,17 +4171,15 @@ TEST_P(EndToEndTest, TestMaxPushId) {
EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
static_cast<QuicSpdySession*>(client_->client()->session())
- ->SetMaxAllowedPushId(kMaxQuicStreamId);
+ ->SetMaxPushId(kMaxQuicStreamId);
client_->SendSynchronousRequest("/foo");
- EXPECT_EQ(kMaxQuicStreamId,
- static_cast<QuicSpdySession*>(client_->client()->session())
- ->max_allowed_push_id());
+ EXPECT_TRUE(static_cast<QuicSpdySession*>(client_->client()->session())
+ ->CanCreatePushStreamWithId(kMaxQuicStreamId));
- EXPECT_EQ(
- kMaxQuicStreamId,
- static_cast<QuicSpdySession*>(GetServerSession())->max_allowed_push_id());
+ EXPECT_TRUE(static_cast<QuicSpdySession*>(GetServerSession())
+ ->CanCreatePushStreamWithId(kMaxQuicStreamId));
}
TEST_P(EndToEndTest, CustomTransportParameters) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/http_decoder.cc b/chromium/net/third_party/quiche/src/quic/core/http/http_decoder.cc
index 41632a9a6c2..87f9919d296 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/http_decoder.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/http_decoder.cc
@@ -11,6 +11,7 @@
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_fallthrough.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -127,8 +128,7 @@ bool HttpDecoder::ReadFrameLength(QuicDataReader* reader) {
}
if (current_frame_length_ > MaxFrameLength(current_frame_type_)) {
- // TODO(b/124216424): Use HTTP_EXCESSIVE_LOAD.
- RaiseError(QUIC_INVALID_FRAME_DATA, "Frame is too large");
+ RaiseError(QUIC_HTTP_FRAME_TOO_LARGE, "Frame is too large.");
return false;
}
@@ -140,13 +140,12 @@ bool HttpDecoder::ReadFrameLength(QuicDataReader* reader) {
switch (current_frame_type_) {
case static_cast<uint64_t>(HttpFrameType::DATA):
- continue_processing = visitor_->OnDataFrameStart(header_length);
+ continue_processing =
+ visitor_->OnDataFrameStart(header_length, current_frame_length_);
break;
case static_cast<uint64_t>(HttpFrameType::HEADERS):
- continue_processing = visitor_->OnHeadersFrameStart(header_length);
- break;
- case static_cast<uint64_t>(HttpFrameType::PRIORITY):
- continue_processing = visitor_->OnPriorityFrameStart(header_length);
+ continue_processing =
+ visitor_->OnHeadersFrameStart(header_length, current_frame_length_);
break;
case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH):
break;
@@ -157,7 +156,8 @@ bool HttpDecoder::ReadFrameLength(QuicDataReader* reader) {
// This edge case needs to be handled here, because ReadFramePayload()
// does not get called if |current_frame_length_| is zero.
if (current_frame_length_ == 0) {
- RaiseError(QUIC_INVALID_FRAME_DATA, "Corrupt PUSH_PROMISE frame.");
+ RaiseError(QUIC_HTTP_FRAME_ERROR,
+ "PUSH_PROMISE frame with empty payload.");
return false;
}
continue_processing = visitor_->OnPushPromiseFrameStart(header_length);
@@ -166,11 +166,12 @@ bool HttpDecoder::ReadFrameLength(QuicDataReader* reader) {
break;
case static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID):
break;
- case static_cast<uint64_t>(HttpFrameType::DUPLICATE_PUSH):
+ case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE):
+ continue_processing = visitor_->OnPriorityUpdateFrameStart(header_length);
break;
default:
- continue_processing =
- visitor_->OnUnknownFrameStart(current_frame_type_, header_length);
+ continue_processing = visitor_->OnUnknownFrameStart(
+ current_frame_type_, header_length, current_frame_length_);
break;
}
@@ -190,7 +191,7 @@ bool HttpDecoder::ReadFramePayload(QuicDataReader* reader) {
case static_cast<uint64_t>(HttpFrameType::DATA): {
QuicByteCount bytes_to_read = std::min<QuicByteCount>(
remaining_frame_length_, reader->BytesRemaining());
- QuicStringPiece payload;
+ quiche::QuicheStringPiece payload;
bool success = reader->ReadStringPiece(&payload, bytes_to_read);
DCHECK(success);
DCHECK(!payload.empty());
@@ -201,7 +202,7 @@ bool HttpDecoder::ReadFramePayload(QuicDataReader* reader) {
case static_cast<uint64_t>(HttpFrameType::HEADERS): {
QuicByteCount bytes_to_read = std::min<QuicByteCount>(
remaining_frame_length_, reader->BytesRemaining());
- QuicStringPiece payload;
+ quiche::QuicheStringPiece payload;
bool success = reader->ReadStringPiece(&payload, bytes_to_read);
DCHECK(success);
DCHECK(!payload.empty());
@@ -209,12 +210,6 @@ bool HttpDecoder::ReadFramePayload(QuicDataReader* reader) {
remaining_frame_length_ -= payload.length();
break;
}
- case static_cast<uint64_t>(HttpFrameType::PRIORITY): {
- // TODO(rch): avoid buffering if the entire frame is present, and
- // instead parse directly out of |reader|.
- BufferFramePayload(reader);
- break;
- }
case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH): {
BufferFramePayload(reader);
break;
@@ -230,7 +225,8 @@ bool HttpDecoder::ReadFramePayload(QuicDataReader* reader) {
DCHECK_EQ(0u, current_push_id_length_);
current_push_id_length_ = reader->PeekVarInt62Length();
if (current_push_id_length_ > remaining_frame_length_) {
- RaiseError(QUIC_INVALID_FRAME_DATA, "PUSH_PROMISE frame malformed.");
+ RaiseError(QUIC_HTTP_FRAME_ERROR,
+ "Unable to read PUSH_PROMISE push_id.");
return false;
}
if (current_push_id_length_ > reader->BytesRemaining()) {
@@ -243,8 +239,9 @@ bool HttpDecoder::ReadFramePayload(QuicDataReader* reader) {
bool success = reader->ReadVarInt62(&push_id);
DCHECK(success);
remaining_frame_length_ -= current_push_id_length_;
- if (!visitor_->OnPushPromiseFramePushId(push_id,
- current_push_id_length_)) {
+ if (!visitor_->OnPushPromiseFramePushId(
+ push_id, current_push_id_length_,
+ current_frame_length_ - current_push_id_length_)) {
continue_processing = false;
current_push_id_length_ = 0;
break;
@@ -261,8 +258,9 @@ bool HttpDecoder::ReadFramePayload(QuicDataReader* reader) {
bool success = push_id_reader.ReadVarInt62(&push_id);
DCHECK(success);
- if (!visitor_->OnPushPromiseFramePushId(push_id,
- current_push_id_length_)) {
+ if (!visitor_->OnPushPromiseFramePushId(
+ push_id, current_push_id_length_,
+ current_frame_length_ - current_push_id_length_)) {
continue_processing = false;
current_push_id_length_ = 0;
break;
@@ -277,7 +275,7 @@ bool HttpDecoder::ReadFramePayload(QuicDataReader* reader) {
if (bytes_to_read == 0) {
break;
}
- QuicStringPiece payload;
+ quiche::QuicheStringPiece payload;
bool success = reader->ReadStringPiece(&payload, bytes_to_read);
DCHECK(success);
DCHECK(!payload.empty());
@@ -293,14 +291,16 @@ bool HttpDecoder::ReadFramePayload(QuicDataReader* reader) {
BufferFramePayload(reader);
break;
}
- case static_cast<uint64_t>(HttpFrameType::DUPLICATE_PUSH): {
+ case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE): {
+ // TODO(bnc): Avoid buffering if the entire frame is present, and
+ // instead parse directly out of |reader|.
BufferFramePayload(reader);
break;
}
default: {
QuicByteCount bytes_to_read = std::min<QuicByteCount>(
remaining_frame_length_, reader->BytesRemaining());
- QuicStringPiece payload;
+ quiche::QuicheStringPiece payload;
bool success = reader->ReadStringPiece(&payload, bytes_to_read);
DCHECK(success);
DCHECK(!payload.empty());
@@ -331,27 +331,16 @@ bool HttpDecoder::FinishParsing() {
continue_processing = visitor_->OnHeadersFrameEnd();
break;
}
- case static_cast<uint64_t>(HttpFrameType::PRIORITY): {
- // TODO(rch): avoid buffering if the entire frame is present, and
- // instead parse directly out of |reader|.
- PriorityFrame frame;
- QuicDataReader reader(buffer_.data(), current_frame_length_);
- if (!ParsePriorityFrame(&reader, &frame)) {
- return false;
- }
- continue_processing = visitor_->OnPriorityFrame(frame);
- break;
- }
case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH): {
CancelPushFrame frame;
QuicDataReader reader(buffer_.data(), current_frame_length_);
if (!reader.ReadVarInt62(&frame.push_id)) {
- // TODO(b/124216424): Use HTTP_MALFORMED_FRAME.
- RaiseError(QUIC_INVALID_FRAME_DATA, "Unable to read push_id");
+ RaiseError(QUIC_HTTP_FRAME_ERROR,
+ "Unable to read CANCEL_PUSH push_id.");
return false;
}
if (!reader.IsDoneReading()) {
- RaiseError(QUIC_INVALID_FRAME_DATA,
+ RaiseError(QUIC_HTTP_FRAME_ERROR,
"Superfluous data in CANCEL_PUSH frame.");
return false;
}
@@ -380,13 +369,11 @@ bool HttpDecoder::FinishParsing() {
"QuicStreamId from uint32_t to uint64_t.");
uint64_t stream_id;
if (!reader.ReadVarInt62(&stream_id)) {
- // TODO(b/124216424): Use HTTP_MALFORMED_FRAME.
- RaiseError(QUIC_INVALID_FRAME_DATA, "Unable to read GOAWAY stream_id");
+ RaiseError(QUIC_HTTP_FRAME_ERROR, "Unable to read GOAWAY stream_id.");
return false;
}
if (!reader.IsDoneReading()) {
- RaiseError(QUIC_INVALID_FRAME_DATA,
- "Superfluous data in GOAWAY frame.");
+ RaiseError(QUIC_HTTP_FRAME_ERROR, "Superfluous data in GOAWAY frame.");
return false;
}
frame.stream_id = static_cast<QuicStreamId>(stream_id);
@@ -397,32 +384,27 @@ bool HttpDecoder::FinishParsing() {
QuicDataReader reader(buffer_.data(), current_frame_length_);
MaxPushIdFrame frame;
if (!reader.ReadVarInt62(&frame.push_id)) {
- // TODO(b/124216424): Use HTTP_MALFORMED_FRAME.
- RaiseError(QUIC_INVALID_FRAME_DATA, "Unable to read push_id");
+ RaiseError(QUIC_HTTP_FRAME_ERROR,
+ "Unable to read MAX_PUSH_ID push_id.");
return false;
}
if (!reader.IsDoneReading()) {
- RaiseError(QUIC_INVALID_FRAME_DATA,
+ RaiseError(QUIC_HTTP_FRAME_ERROR,
"Superfluous data in MAX_PUSH_ID frame.");
return false;
}
continue_processing = visitor_->OnMaxPushIdFrame(frame);
break;
}
- case static_cast<uint64_t>(HttpFrameType::DUPLICATE_PUSH): {
+ case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE): {
+ // TODO(bnc): Avoid buffering if the entire frame is present, and
+ // instead parse directly out of |reader|.
+ PriorityUpdateFrame frame;
QuicDataReader reader(buffer_.data(), current_frame_length_);
- DuplicatePushFrame frame;
- if (!reader.ReadVarInt62(&frame.push_id)) {
- // TODO(b/124216424): Use HTTP_MALFORMED_FRAME.
- RaiseError(QUIC_INVALID_FRAME_DATA, "Unable to read push_id");
- return false;
- }
- if (!reader.IsDoneReading()) {
- RaiseError(QUIC_INVALID_FRAME_DATA,
- "Superfluous data in DUPLICATE_PUSH frame.");
+ if (!ParsePriorityUpdateFrame(&reader, &frame)) {
return false;
}
- continue_processing = visitor_->OnDuplicatePushFrame(frame);
+ continue_processing = visitor_->OnPriorityUpdateFrame(frame);
break;
}
default: {
@@ -440,7 +422,7 @@ bool HttpDecoder::FinishParsing() {
void HttpDecoder::DiscardFramePayload(QuicDataReader* reader) {
QuicByteCount bytes_to_read = std::min<QuicByteCount>(
remaining_frame_length_, reader->BytesRemaining());
- QuicStringPiece payload;
+ quiche::QuicheStringPiece payload;
bool success = reader->ReadStringPiece(&payload, bytes_to_read);
DCHECK(success);
remaining_frame_length_ -= payload.length();
@@ -507,83 +489,62 @@ void HttpDecoder::RaiseError(QuicErrorCode error, std::string error_detail) {
visitor_->OnError(this);
}
-bool HttpDecoder::ParsePriorityFrame(QuicDataReader* reader,
- PriorityFrame* frame) {
- uint8_t flags;
- if (!reader->ReadUInt8(&flags)) {
- // TODO(b/124216424): Use HTTP_MALFORMED_FRAME.
- RaiseError(QUIC_INVALID_FRAME_DATA, "Unable to read PRIORITY frame flags.");
- return false;
- }
-
- // Assign two most significant bits to prioritized_type.
- frame->prioritized_type = static_cast<PriorityElementType>((flags >> 6) & 3);
- // Assign the next two most significant bits to dependency type.
- frame->dependency_type = static_cast<PriorityElementType>((flags >> 4) & 3);
- frame->exclusive = flags & kPriorityExclusiveBit;
- // TODO(bnc): Close connection with HTTP_MALFORMED_FRAME
- // if lowest three bits are not all zero.
-
- if (frame->prioritized_type != ROOT_OF_TREE &&
- !reader->ReadVarInt62(&frame->prioritized_element_id)) {
- // TODO(b/124216424): Use HTTP_MALFORMED_FRAME.
- RaiseError(QUIC_INVALID_FRAME_DATA,
- "Unable to read prioritized_element_id.");
- return false;
- }
- if (frame->dependency_type != ROOT_OF_TREE &&
- !reader->ReadVarInt62(&frame->element_dependency_id)) {
- // TODO(b/124216424): Use HTTP_MALFORMED_FRAME.
- RaiseError(QUIC_INVALID_FRAME_DATA,
- "Unable to read element_dependency_id.");
- return false;
- }
- if (!reader->ReadUInt8(&frame->weight)) {
- // TODO(b/124216424): Use HTTP_MALFORMED_FRAME.
- RaiseError(QUIC_INVALID_FRAME_DATA,
- "Unable to read PRIORITY frame weight.");
- return false;
- }
- if (!reader->IsDoneReading()) {
- // TODO(b/124216424): Use HTTP_MALFORMED_FRAME.
- RaiseError(QUIC_INVALID_FRAME_DATA, "Superfluous data in PRIORITY frame.");
- return false;
- }
- return true;
-}
-
bool HttpDecoder::ParseSettingsFrame(QuicDataReader* reader,
SettingsFrame* frame) {
while (!reader->IsDoneReading()) {
uint64_t id;
if (!reader->ReadVarInt62(&id)) {
- // TODO(b/124216424): Use HTTP_MALFORMED_FRAME.
- RaiseError(QUIC_INVALID_FRAME_DATA,
- "Unable to read settings frame identifier");
+ RaiseError(QUIC_HTTP_FRAME_ERROR, "Unable to read setting identifier.");
return false;
}
uint64_t content;
if (!reader->ReadVarInt62(&content)) {
- // TODO(b/124216424): Use HTTP_MALFORMED_FRAME.
- RaiseError(QUIC_INVALID_FRAME_DATA,
- "Unable to read settings frame content");
+ RaiseError(QUIC_HTTP_FRAME_ERROR, "Unable to read setting value.");
return false;
}
auto result = frame->values.insert({id, content});
if (!result.second) {
- // TODO(b/124216424): Use HTTP_SETTINGS_ERROR.
- RaiseError(QUIC_INVALID_FRAME_DATA, "Duplicate SETTINGS identifier.");
+ RaiseError(QUIC_HTTP_DUPLICATE_SETTING_IDENTIFIER,
+ "Duplicate setting identifier.");
return false;
}
}
return true;
}
+bool HttpDecoder::ParsePriorityUpdateFrame(QuicDataReader* reader,
+ PriorityUpdateFrame* frame) {
+ uint8_t prioritized_element_type;
+ if (!reader->ReadUInt8(&prioritized_element_type)) {
+ RaiseError(QUIC_HTTP_FRAME_ERROR,
+ "Unable to read prioritized element type.");
+ return false;
+ }
+
+ if (prioritized_element_type != REQUEST_STREAM &&
+ prioritized_element_type != PUSH_STREAM) {
+ RaiseError(QUIC_HTTP_FRAME_ERROR, "Invalid prioritized element type.");
+ return false;
+ }
+
+ frame->prioritized_element_type =
+ static_cast<PrioritizedElementType>(prioritized_element_type);
+
+ if (!reader->ReadVarInt62(&frame->prioritized_element_id)) {
+ RaiseError(QUIC_HTTP_FRAME_ERROR, "Unable to read prioritized element id.");
+ return false;
+ }
+
+ quiche::QuicheStringPiece priority_field_value =
+ reader->ReadRemainingPayload();
+ frame->priority_field_value =
+ std::string(priority_field_value.data(), priority_field_value.size());
+
+ return true;
+}
+
QuicByteCount HttpDecoder::MaxFrameLength(uint64_t frame_type) {
switch (frame_type) {
- case static_cast<uint64_t>(HttpFrameType::PRIORITY):
- return kPriorityFirstByteLength + VARIABLE_LENGTH_INTEGER_LENGTH_8 * 2 +
- kPriorityWeightLength;
case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH):
return sizeof(PushId);
case static_cast<uint64_t>(HttpFrameType::SETTINGS):
@@ -593,8 +554,9 @@ QuicByteCount HttpDecoder::MaxFrameLength(uint64_t frame_type) {
return VARIABLE_LENGTH_INTEGER_LENGTH_8;
case static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID):
return sizeof(PushId);
- case static_cast<uint64_t>(HttpFrameType::DUPLICATE_PUSH):
- return sizeof(PushId);
+ case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE):
+ // This limit is arbitrary.
+ return 1024 * 1024;
default:
// Other frames require no data buffering, so it's safe to have no limit.
return std::numeric_limits<QuicByteCount>::max();
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/http_decoder.h b/chromium/net/third_party/quiche/src/quic/core/http/http_decoder.h
index 862c5ded15a..3650bef572e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/http_decoder.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/http_decoder.h
@@ -11,7 +11,7 @@
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -39,13 +39,6 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
// On*FrameStart() methods are called after the frame header is completely
// processed. At that point it is safe to consume |header_length| bytes.
- // Called when a PRIORITY frame has been received.
- // |header_length| contains PRIORITY frame length and payload length.
- virtual bool OnPriorityFrameStart(QuicByteCount header_length) = 0;
-
- // Called when a PRIORITY frame has been successfully parsed.
- virtual bool OnPriorityFrame(const PriorityFrame& frame) = 0;
-
// Called when a CANCEL_PUSH frame has been successfully parsed.
virtual bool OnCancelPushFrame(const CancelPushFrame& frame) = 0;
@@ -61,52 +54,66 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
// Called when a SETTINGS frame has been successfully parsed.
virtual bool OnSettingsFrame(const SettingsFrame& frame) = 0;
- // Called when a DUPLICATE_PUSH frame has been successfully parsed.
- virtual bool OnDuplicatePushFrame(const DuplicatePushFrame& frame) = 0;
-
// Called when a DATA frame has been received.
- // |header_length| contains DATA frame length and payload length.
- virtual bool OnDataFrameStart(QuicByteCount header_length) = 0;
+ // |header_length| and |payload_length| are the length of DATA frame header
+ // and payload, respectively.
+ virtual bool OnDataFrameStart(QuicByteCount header_length,
+ QuicByteCount payload_length) = 0;
// Called when part of the payload of a DATA frame has been read. May be
// called multiple times for a single frame. |payload| is guaranteed to be
// non-empty.
- virtual bool OnDataFramePayload(QuicStringPiece payload) = 0;
+ virtual bool OnDataFramePayload(quiche::QuicheStringPiece payload) = 0;
// Called when a DATA frame has been completely processed.
virtual bool OnDataFrameEnd() = 0;
// Called when a HEADERS frame has been received.
- // |header_length| contains HEADERS frame length and payload length.
- virtual bool OnHeadersFrameStart(QuicByteCount header_length) = 0;
+ // |header_length| and |payload_length| are the length of HEADERS frame
+ // header and payload, respectively.
+ virtual bool OnHeadersFrameStart(QuicByteCount header_length,
+ QuicByteCount payload_length) = 0;
// Called when part of the payload of a HEADERS frame has been read. May be
// called multiple times for a single frame. |payload| is guaranteed to be
// non-empty.
- virtual bool OnHeadersFramePayload(QuicStringPiece payload) = 0;
+ virtual bool OnHeadersFramePayload(quiche::QuicheStringPiece payload) = 0;
// Called when a HEADERS frame has been completely processed.
- // |frame_len| is the length of the HEADERS frame payload.
virtual bool OnHeadersFrameEnd() = 0;
// Called when a PUSH_PROMISE frame has been received.
virtual bool OnPushPromiseFrameStart(QuicByteCount header_length) = 0;
// Called when the Push ID field of a PUSH_PROMISE frame has been parsed.
// Called exactly once for a valid PUSH_PROMISE frame.
- virtual bool OnPushPromiseFramePushId(PushId push_id,
- QuicByteCount push_id_length) = 0;
+ // |push_id_length| is the length of the push ID field.
+ // |header_block_length| is the length of the compressed header block.
+ virtual bool OnPushPromiseFramePushId(
+ PushId push_id,
+ QuicByteCount push_id_length,
+ QuicByteCount header_block_length) = 0;
// Called when part of the header block of a PUSH_PROMISE frame has been
// read. May be called multiple times for a single frame. |payload| is
// guaranteed to be non-empty.
- virtual bool OnPushPromiseFramePayload(QuicStringPiece payload) = 0;
+ virtual bool OnPushPromiseFramePayload(
+ quiche::QuicheStringPiece payload) = 0;
// Called when a PUSH_PROMISE frame has been completely processed.
virtual bool OnPushPromiseFrameEnd() = 0;
+ // Called when a PRIORITY_UPDATE frame has been received.
+ // |header_length| contains PRIORITY_UPDATE frame length and payload length.
+ virtual bool OnPriorityUpdateFrameStart(QuicByteCount header_length) = 0;
+
+ // Called when a PRIORITY_UPDATE frame has been successfully parsed.
+ virtual bool OnPriorityUpdateFrame(const PriorityUpdateFrame& frame) = 0;
+
// Called when a frame of unknown type |frame_type| has been received.
// Frame type might be reserved, Visitor must make sure to ignore.
- // |header_length| contains frame length and payload length.
+ // |header_length| and |payload_length| are the length of the frame header
+ // and payload, respectively.
virtual bool OnUnknownFrameStart(uint64_t frame_type,
- QuicByteCount header_length) = 0;
+ QuicByteCount header_length,
+ QuicByteCount payload_length) = 0;
// Called when part of the payload of the unknown frame has been read. May
// be called multiple times for a single frame. |payload| is guaranteed to
// be non-empty.
- virtual bool OnUnknownFramePayload(QuicStringPiece payload) = 0;
+ virtual bool OnUnknownFramePayload(quiche::QuicheStringPiece payload) = 0;
// Called when the unknown frame has been completely processed.
virtual bool OnUnknownFrameEnd() = 0;
};
@@ -180,12 +187,13 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
// Sets |error_| and |error_detail_| accordingly.
void RaiseError(QuicErrorCode error, std::string error_detail);
- // Parses the payload of a PRIORITY frame from |reader| into |frame|.
- bool ParsePriorityFrame(QuicDataReader* reader, PriorityFrame* frame);
-
// Parses the payload of a SETTINGS frame from |reader| into |frame|.
bool ParseSettingsFrame(QuicDataReader* reader, SettingsFrame* frame);
+ // Parses the payload of a PRIORITY_UPDATE frame from |reader| into |frame|.
+ bool ParsePriorityUpdateFrame(QuicDataReader* reader,
+ PriorityUpdateFrame* frame);
+
// Returns the max frame size of a given |frame_type|.
QuicByteCount MaxFrameLength(uint64_t frame_type);
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/http_decoder_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/http_decoder_test.cc
index 751ca5876bb..2e8885c9dd7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/http_decoder_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/http_decoder_test.cc
@@ -11,11 +11,12 @@
#include "net/third_party/quiche/src/quic/core/http/http_frames.h"
#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
using ::testing::_;
using ::testing::Eq;
@@ -40,57 +41,65 @@ class MockVisitor : public HttpDecoder::Visitor {
// Called if an error is detected.
MOCK_METHOD1(OnError, void(HttpDecoder* decoder));
- MOCK_METHOD1(OnPriorityFrameStart, bool(QuicByteCount header_length));
- MOCK_METHOD1(OnPriorityFrame, bool(const PriorityFrame& frame));
MOCK_METHOD1(OnCancelPushFrame, bool(const CancelPushFrame& frame));
MOCK_METHOD1(OnMaxPushIdFrame, bool(const MaxPushIdFrame& frame));
MOCK_METHOD1(OnGoAwayFrame, bool(const GoAwayFrame& frame));
MOCK_METHOD1(OnSettingsFrameStart, bool(QuicByteCount header_length));
MOCK_METHOD1(OnSettingsFrame, bool(const SettingsFrame& frame));
- MOCK_METHOD1(OnDuplicatePushFrame, bool(const DuplicatePushFrame& frame));
- MOCK_METHOD1(OnDataFrameStart, bool(QuicByteCount header_length));
- MOCK_METHOD1(OnDataFramePayload, bool(QuicStringPiece payload));
+ MOCK_METHOD2(OnDataFrameStart,
+ bool(QuicByteCount header_length, QuicByteCount payload_length));
+ MOCK_METHOD1(OnDataFramePayload, bool(quiche::QuicheStringPiece payload));
MOCK_METHOD0(OnDataFrameEnd, bool());
- MOCK_METHOD1(OnHeadersFrameStart, bool(QuicByteCount header_length));
- MOCK_METHOD1(OnHeadersFramePayload, bool(QuicStringPiece payload));
+ MOCK_METHOD2(OnHeadersFrameStart,
+ bool(QuicByteCount header_length, QuicByteCount payload_length));
+ MOCK_METHOD1(OnHeadersFramePayload, bool(quiche::QuicheStringPiece payload));
MOCK_METHOD0(OnHeadersFrameEnd, bool());
MOCK_METHOD1(OnPushPromiseFrameStart, bool(QuicByteCount header_length));
- MOCK_METHOD2(OnPushPromiseFramePushId,
- bool(PushId push_id, QuicByteCount push_id_length));
- MOCK_METHOD1(OnPushPromiseFramePayload, bool(QuicStringPiece payload));
+ MOCK_METHOD3(OnPushPromiseFramePushId,
+ bool(PushId push_id,
+ QuicByteCount push_id_length,
+ QuicByteCount header_block_length));
+ MOCK_METHOD1(OnPushPromiseFramePayload,
+ bool(quiche::QuicheStringPiece payload));
MOCK_METHOD0(OnPushPromiseFrameEnd, bool());
- MOCK_METHOD2(OnUnknownFrameStart, bool(uint64_t, QuicByteCount));
- MOCK_METHOD1(OnUnknownFramePayload, bool(QuicStringPiece));
+ MOCK_METHOD1(OnPriorityUpdateFrameStart, bool(QuicByteCount header_length));
+ MOCK_METHOD1(OnPriorityUpdateFrame, bool(const PriorityUpdateFrame& frame));
+
+ MOCK_METHOD3(OnUnknownFrameStart,
+ bool(uint64_t frame_type,
+ QuicByteCount header_length,
+ QuicByteCount payload_length));
+ MOCK_METHOD1(OnUnknownFramePayload, bool(quiche::QuicheStringPiece payload));
MOCK_METHOD0(OnUnknownFrameEnd, bool());
};
class HttpDecoderTest : public QuicTest {
public:
HttpDecoderTest() : decoder_(&visitor_) {
- ON_CALL(visitor_, OnPriorityFrameStart(_)).WillByDefault(Return(true));
- ON_CALL(visitor_, OnPriorityFrame(_)).WillByDefault(Return(true));
ON_CALL(visitor_, OnCancelPushFrame(_)).WillByDefault(Return(true));
ON_CALL(visitor_, OnMaxPushIdFrame(_)).WillByDefault(Return(true));
ON_CALL(visitor_, OnGoAwayFrame(_)).WillByDefault(Return(true));
ON_CALL(visitor_, OnSettingsFrameStart(_)).WillByDefault(Return(true));
ON_CALL(visitor_, OnSettingsFrame(_)).WillByDefault(Return(true));
- ON_CALL(visitor_, OnDuplicatePushFrame(_)).WillByDefault(Return(true));
- ON_CALL(visitor_, OnDataFrameStart(_)).WillByDefault(Return(true));
+ ON_CALL(visitor_, OnDataFrameStart(_, _)).WillByDefault(Return(true));
ON_CALL(visitor_, OnDataFramePayload(_)).WillByDefault(Return(true));
ON_CALL(visitor_, OnDataFrameEnd()).WillByDefault(Return(true));
- ON_CALL(visitor_, OnHeadersFrameStart(_)).WillByDefault(Return(true));
+ ON_CALL(visitor_, OnHeadersFrameStart(_, _)).WillByDefault(Return(true));
ON_CALL(visitor_, OnHeadersFramePayload(_)).WillByDefault(Return(true));
ON_CALL(visitor_, OnHeadersFrameEnd()).WillByDefault(Return(true));
ON_CALL(visitor_, OnPushPromiseFrameStart(_)).WillByDefault(Return(true));
- ON_CALL(visitor_, OnPushPromiseFramePushId(_, _))
+ ON_CALL(visitor_, OnPushPromiseFramePushId(_, _, _))
.WillByDefault(Return(true));
ON_CALL(visitor_, OnPushPromiseFramePayload(_)).WillByDefault(Return(true));
ON_CALL(visitor_, OnPushPromiseFrameEnd()).WillByDefault(Return(true));
- ON_CALL(visitor_, OnUnknownFrameStart(_, _)).WillByDefault(Return(true));
+ ON_CALL(visitor_, OnPriorityUpdateFrameStart(_))
+ .WillByDefault(Return(true));
+ ON_CALL(visitor_, OnPriorityUpdateFrame(_)).WillByDefault(Return(true));
+ ON_CALL(visitor_, OnUnknownFrameStart(_, _, _)).WillByDefault(Return(true));
ON_CALL(visitor_, OnUnknownFramePayload(_)).WillByDefault(Return(true));
ON_CALL(visitor_, OnUnknownFrameEnd()).WillByDefault(Return(true));
}
@@ -101,13 +110,13 @@ class HttpDecoderTest : public QuicTest {
}
// Process |input| in a single call to HttpDecoder::ProcessInput().
- QuicByteCount ProcessInput(QuicStringPiece input) {
+ QuicByteCount ProcessInput(quiche::QuicheStringPiece input) {
return decoder_.ProcessInput(input.data(), input.size());
}
// Feed |input| to |decoder_| one character at a time,
// verifying that each character gets processed.
- void ProcessInputCharByChar(QuicStringPiece input) {
+ void ProcessInputCharByChar(quiche::QuicheStringPiece input) {
for (char c : input) {
EXPECT_EQ(1u, decoder_.ProcessInput(&c, 1));
}
@@ -115,8 +124,10 @@ class HttpDecoderTest : public QuicTest {
// Append garbage to |input|, then process it in a single call to
// HttpDecoder::ProcessInput(). Verify that garbage is not read.
- QuicByteCount ProcessInputWithGarbageAppended(QuicStringPiece input) {
- std::string input_with_garbage_appended = QuicStrCat(input, "blahblah");
+ QuicByteCount ProcessInputWithGarbageAppended(
+ quiche::QuicheStringPiece input) {
+ std::string input_with_garbage_appended =
+ quiche::QuicheStrCat(input, "blahblah");
QuicByteCount processed_bytes = ProcessInput(input_with_garbage_appended);
// Guaranteed by HttpDecoder::ProcessInput() contract.
@@ -144,7 +155,7 @@ TEST_F(HttpDecoderTest, UnknownFrame) {
const QuicByteCount payload_lengths[] = {0, 14, 100};
const uint64_t frame_types[] = {
0x21, 0x40, 0x5f, 0x7e, 0x9d, // some reserved frame types
- 0x06, 0x0f, 0x14 // some unknown, not reserved frame types
+ 0x06, 0x6f, 0x14 // some unknown, not reserved frame types
};
for (auto payload_length : payload_lengths) {
@@ -164,7 +175,8 @@ TEST_F(HttpDecoderTest, UnknownFrame) {
writer.WriteStringPiece(data);
}
- EXPECT_CALL(visitor_, OnUnknownFrameStart(frame_type, header_length));
+ EXPECT_CALL(visitor_, OnUnknownFrameStart(frame_type, header_length,
+ payload_length));
if (payload_length > 0) {
EXPECT_CALL(visitor_, OnUnknownFramePayload(Eq(data)));
}
@@ -181,7 +193,7 @@ TEST_F(HttpDecoderTest, UnknownFrame) {
TEST_F(HttpDecoderTest, CancelPush) {
InSequence s;
- std::string input = QuicTextUtils::HexDecode(
+ std::string input = quiche::QuicheTextUtils::HexDecode(
"03" // type (CANCEL_PUSH)
"01" // length
"01"); // Push Id
@@ -208,17 +220,17 @@ TEST_F(HttpDecoderTest, CancelPush) {
TEST_F(HttpDecoderTest, PushPromiseFrame) {
InSequence s;
- std::string input =
- QuicStrCat(QuicTextUtils::HexDecode("05" // type (PUSH PROMISE)
- "0f" // length
- "C000000000000101"), // push id 257
- "Headers"); // headers
+ std::string input = quiche::QuicheStrCat(
+ quiche::QuicheTextUtils::HexDecode("05" // type (PUSH PROMISE)
+ "0f" // length
+ "C000000000000101"), // push id 257
+ "Headers"); // headers
// Visitor pauses processing.
EXPECT_CALL(visitor_, OnPushPromiseFrameStart(2)).WillOnce(Return(false));
- EXPECT_CALL(visitor_, OnPushPromiseFramePushId(257, 8))
+ EXPECT_CALL(visitor_, OnPushPromiseFramePushId(257, 8, 7))
.WillOnce(Return(false));
- QuicStringPiece remaining_input(input);
+ quiche::QuicheStringPiece remaining_input(input);
QuicByteCount processed_bytes =
ProcessInputWithGarbageAppended(remaining_input);
EXPECT_EQ(2u, processed_bytes);
@@ -227,7 +239,8 @@ TEST_F(HttpDecoderTest, PushPromiseFrame) {
EXPECT_EQ(8u, processed_bytes);
remaining_input = remaining_input.substr(processed_bytes);
- EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("Headers")))
+ EXPECT_CALL(visitor_,
+ OnPushPromiseFramePayload(quiche::QuicheStringPiece("Headers")))
.WillOnce(Return(false));
processed_bytes = ProcessInputWithGarbageAppended(remaining_input);
EXPECT_EQ(remaining_input.size(), processed_bytes);
@@ -239,8 +252,9 @@ TEST_F(HttpDecoderTest, PushPromiseFrame) {
// Process the full frame.
EXPECT_CALL(visitor_, OnPushPromiseFrameStart(2));
- EXPECT_CALL(visitor_, OnPushPromiseFramePushId(257, 8));
- EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("Headers")));
+ EXPECT_CALL(visitor_, OnPushPromiseFramePushId(257, 8, 7));
+ EXPECT_CALL(visitor_,
+ OnPushPromiseFramePayload(quiche::QuicheStringPiece("Headers")));
EXPECT_CALL(visitor_, OnPushPromiseFrameEnd());
EXPECT_EQ(input.size(), ProcessInput(input));
EXPECT_THAT(decoder_.error(), IsQuicNoError());
@@ -248,14 +262,21 @@ TEST_F(HttpDecoderTest, PushPromiseFrame) {
// Process the frame incrementally.
EXPECT_CALL(visitor_, OnPushPromiseFrameStart(2));
- EXPECT_CALL(visitor_, OnPushPromiseFramePushId(257, 8));
- EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("H")));
- EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("e")));
- EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("a")));
- EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("d")));
- EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("e")));
- EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("r")));
- EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("s")));
+ EXPECT_CALL(visitor_, OnPushPromiseFramePushId(257, 8, 7));
+ EXPECT_CALL(visitor_,
+ OnPushPromiseFramePayload(quiche::QuicheStringPiece("H")));
+ EXPECT_CALL(visitor_,
+ OnPushPromiseFramePayload(quiche::QuicheStringPiece("e")));
+ EXPECT_CALL(visitor_,
+ OnPushPromiseFramePayload(quiche::QuicheStringPiece("a")));
+ EXPECT_CALL(visitor_,
+ OnPushPromiseFramePayload(quiche::QuicheStringPiece("d")));
+ EXPECT_CALL(visitor_,
+ OnPushPromiseFramePayload(quiche::QuicheStringPiece("e")));
+ EXPECT_CALL(visitor_,
+ OnPushPromiseFramePayload(quiche::QuicheStringPiece("r")));
+ EXPECT_CALL(visitor_,
+ OnPushPromiseFramePayload(quiche::QuicheStringPiece("s")));
EXPECT_CALL(visitor_, OnPushPromiseFrameEnd());
ProcessInputCharByChar(input);
EXPECT_THAT(decoder_.error(), IsQuicNoError());
@@ -263,8 +284,9 @@ TEST_F(HttpDecoderTest, PushPromiseFrame) {
// Process push id incrementally and append headers with last byte of push id.
EXPECT_CALL(visitor_, OnPushPromiseFrameStart(2));
- EXPECT_CALL(visitor_, OnPushPromiseFramePushId(257, 8));
- EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("Headers")));
+ EXPECT_CALL(visitor_, OnPushPromiseFramePushId(257, 8, 7));
+ EXPECT_CALL(visitor_,
+ OnPushPromiseFramePayload(quiche::QuicheStringPiece("Headers")));
EXPECT_CALL(visitor_, OnPushPromiseFrameEnd());
ProcessInputCharByChar(input.substr(0, 9));
EXPECT_EQ(8u, ProcessInput(input.substr(9)));
@@ -275,7 +297,7 @@ TEST_F(HttpDecoderTest, PushPromiseFrame) {
TEST_F(HttpDecoderTest, CorruptPushPromiseFrame) {
InSequence s;
- std::string input = QuicTextUtils::HexDecode(
+ std::string input = quiche::QuicheTextUtils::HexDecode(
"05" // type (PUSH_PROMISE)
"01" // length
"40"); // first byte of two-byte varint push id
@@ -287,8 +309,8 @@ TEST_F(HttpDecoderTest, CorruptPushPromiseFrame) {
decoder.ProcessInput(input.data(), input.size());
- EXPECT_THAT(decoder.error(), IsError(QUIC_INVALID_FRAME_DATA));
- EXPECT_EQ("PUSH_PROMISE frame malformed.", decoder.error_detail());
+ EXPECT_THAT(decoder.error(), IsError(QUIC_HTTP_FRAME_ERROR));
+ EXPECT_EQ("Unable to read PUSH_PROMISE push_id.", decoder.error_detail());
}
{
HttpDecoder decoder(&visitor_);
@@ -299,14 +321,14 @@ TEST_F(HttpDecoderTest, CorruptPushPromiseFrame) {
decoder.ProcessInput(&c, 1);
}
- EXPECT_THAT(decoder.error(), IsError(QUIC_INVALID_FRAME_DATA));
- EXPECT_EQ("PUSH_PROMISE frame malformed.", decoder.error_detail());
+ EXPECT_THAT(decoder.error(), IsError(QUIC_HTTP_FRAME_ERROR));
+ EXPECT_EQ("Unable to read PUSH_PROMISE push_id.", decoder.error_detail());
}
}
TEST_F(HttpDecoderTest, MaxPushId) {
InSequence s;
- std::string input = QuicTextUtils::HexDecode(
+ std::string input = quiche::QuicheTextUtils::HexDecode(
"0D" // type (MAX_PUSH_ID)
"01" // length
"01"); // Push Id
@@ -331,146 +353,9 @@ TEST_F(HttpDecoderTest, MaxPushId) {
EXPECT_EQ("", decoder_.error_detail());
}
-TEST_F(HttpDecoderTest, DuplicatePush) {
- InSequence s;
- std::string input = QuicTextUtils::HexDecode(
- "0E" // type (DUPLICATE_PUSH)
- "01" // length
- "01"); // Push Id
-
- // Visitor pauses processing.
- EXPECT_CALL(visitor_, OnDuplicatePushFrame(DuplicatePushFrame({1})))
- .WillOnce(Return(false));
- EXPECT_EQ(input.size(), ProcessInputWithGarbageAppended(input));
- EXPECT_THAT(decoder_.error(), IsQuicNoError());
- EXPECT_EQ("", decoder_.error_detail());
-
- // Process the full frame.
- EXPECT_CALL(visitor_, OnDuplicatePushFrame(DuplicatePushFrame({1})));
- EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_THAT(decoder_.error(), IsQuicNoError());
- EXPECT_EQ("", decoder_.error_detail());
-
- // Process the frame incrementally.
- EXPECT_CALL(visitor_, OnDuplicatePushFrame(DuplicatePushFrame({1})));
- ProcessInputCharByChar(input);
- EXPECT_THAT(decoder_.error(), IsQuicNoError());
- EXPECT_EQ("", decoder_.error_detail());
-}
-
-TEST_F(HttpDecoderTest, PriorityFrame) {
- InSequence s;
- std::string input = QuicTextUtils::HexDecode(
- "02" // type (PRIORITY)
- "04" // length
- "08" // request stream, request stream, exclusive
- "03" // prioritized_element_id
- "04" // element_dependency_id
- "FF"); // weight
-
- PriorityFrame frame;
- frame.prioritized_type = REQUEST_STREAM;
- frame.dependency_type = REQUEST_STREAM;
- frame.exclusive = true;
- frame.prioritized_element_id = 0x03;
- frame.element_dependency_id = 0x04;
- frame.weight = 0xFF;
-
- // Visitor pauses processing.
- EXPECT_CALL(visitor_, OnPriorityFrameStart(2)).WillOnce(Return(false));
- QuicStringPiece remaining_input(input);
- QuicByteCount processed_bytes =
- ProcessInputWithGarbageAppended(remaining_input);
- EXPECT_EQ(2u, processed_bytes);
- remaining_input = remaining_input.substr(processed_bytes);
-
- EXPECT_CALL(visitor_, OnPriorityFrame(frame)).WillOnce(Return(false));
- processed_bytes = ProcessInputWithGarbageAppended(remaining_input);
- EXPECT_EQ(remaining_input.size(), processed_bytes);
- EXPECT_THAT(decoder_.error(), IsQuicNoError());
- EXPECT_EQ("", decoder_.error_detail());
-
- // Process the full frame.
- EXPECT_CALL(visitor_, OnPriorityFrameStart(2));
- EXPECT_CALL(visitor_, OnPriorityFrame(frame));
- EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_THAT(decoder_.error(), IsQuicNoError());
- EXPECT_EQ("", decoder_.error_detail());
-
- // Process the frame incrementally.
- EXPECT_CALL(visitor_, OnPriorityFrameStart(2));
- EXPECT_CALL(visitor_, OnPriorityFrame(frame));
- ProcessInputCharByChar(input);
- EXPECT_THAT(decoder_.error(), IsQuicNoError());
- EXPECT_EQ("", decoder_.error_detail());
-
- std::string input2 = QuicTextUtils::HexDecode(
- "02" // type (PRIORITY)
- "02" // length
- "f8" // root of tree, root of tree, exclusive
- "FF"); // weight
- PriorityFrame frame2;
- frame2.prioritized_type = ROOT_OF_TREE;
- frame2.dependency_type = ROOT_OF_TREE;
- frame2.exclusive = true;
- frame2.weight = 0xFF;
-
- EXPECT_CALL(visitor_, OnPriorityFrameStart(2));
- EXPECT_CALL(visitor_, OnPriorityFrame(frame2));
- EXPECT_EQ(input2.size(), ProcessInput(input2));
- EXPECT_THAT(decoder_.error(), IsQuicNoError());
- EXPECT_EQ("", decoder_.error_detail());
-}
-
-// Regression test for https://crbug.com/981291 and https://crbug.com/981646.
-TEST_F(HttpDecoderTest, CorruptPriorityFrame) {
- const char* const payload1 =
- "\x01" // request stream, request stream, exclusive
- "\x03" // prioritized_element_id
- "\x04" // element_dependency_id
- "\xFF" // weight
- "\xFF"; // superfluous data
- const char* const payload2 =
- "\xf1" // root of tree, root of tree, exclusive
- "\xFF" // weight
- "\xFF"; // superfluous data
- struct {
- const char* const payload;
- size_t payload_length;
- const char* const error_message;
- } kTestData[] = {
- {payload1, 0, "Unable to read PRIORITY frame flags."},
- {payload1, 1, "Unable to read prioritized_element_id."},
- {payload1, 2, "Unable to read element_dependency_id."},
- {payload1, 3, "Unable to read PRIORITY frame weight."},
- {payload1, 5, "Superfluous data in PRIORITY frame."},
- {payload2, 0, "Unable to read PRIORITY frame flags."},
- {payload2, 1, "Unable to read PRIORITY frame weight."},
- {payload2, 3, "Superfluous data in PRIORITY frame."},
- };
-
- for (const auto& test_data : kTestData) {
- std::string input;
- input.push_back(2u); // type PRIORITY
- input.push_back(test_data.payload_length);
- size_t header_length = input.size();
- input.append(test_data.payload, test_data.payload_length);
-
- HttpDecoder decoder(&visitor_);
- EXPECT_CALL(visitor_, OnPriorityFrameStart(header_length));
- EXPECT_CALL(visitor_, OnError(&decoder));
-
- QuicByteCount processed_bytes =
- decoder.ProcessInput(input.data(), input.size());
- EXPECT_EQ(input.size(), processed_bytes);
- EXPECT_THAT(decoder.error(), IsError(QUIC_INVALID_FRAME_DATA));
- EXPECT_EQ(test_data.error_message, decoder.error_detail());
- }
-}
-
TEST_F(HttpDecoderTest, SettingsFrame) {
InSequence s;
- std::string input = QuicTextUtils::HexDecode(
+ std::string input = quiche::QuicheTextUtils::HexDecode(
"04" // type (SETTINGS)
"07" // length
"01" // identifier (SETTINGS_QPACK_MAX_TABLE_CAPACITY)
@@ -486,7 +371,7 @@ TEST_F(HttpDecoderTest, SettingsFrame) {
frame.values[256] = 4;
// Visitor pauses processing.
- QuicStringPiece remaining_input(input);
+ quiche::QuicheStringPiece remaining_input(input);
EXPECT_CALL(visitor_, OnSettingsFrameStart(2)).WillOnce(Return(false));
QuicByteCount processed_bytes =
ProcessInputWithGarbageAppended(remaining_input);
@@ -524,10 +409,10 @@ TEST_F(HttpDecoderTest, CorruptSettingsFrame) {
size_t payload_length;
const char* const error_message;
} kTestData[] = {
- {1, "Unable to read settings frame identifier"},
- {5, "Unable to read settings frame content"},
- {7, "Unable to read settings frame identifier"},
- {12, "Unable to read settings frame content"},
+ {1, "Unable to read setting identifier."},
+ {5, "Unable to read setting value."},
+ {7, "Unable to read setting identifier."},
+ {12, "Unable to read setting value."},
};
for (const auto& test_data : kTestData) {
@@ -544,13 +429,13 @@ TEST_F(HttpDecoderTest, CorruptSettingsFrame) {
QuicByteCount processed_bytes =
decoder.ProcessInput(input.data(), input.size());
EXPECT_EQ(input.size(), processed_bytes);
- EXPECT_THAT(decoder.error(), IsError(QUIC_INVALID_FRAME_DATA));
+ EXPECT_THAT(decoder.error(), IsError(QUIC_HTTP_FRAME_ERROR));
EXPECT_EQ(test_data.error_message, decoder.error_detail());
}
}
TEST_F(HttpDecoderTest, DuplicateSettingsIdentifier) {
- std::string input = QuicTextUtils::HexDecode(
+ std::string input = quiche::QuicheTextUtils::HexDecode(
"04" // type (SETTINGS)
"04" // length
"01" // identifier
@@ -563,25 +448,27 @@ TEST_F(HttpDecoderTest, DuplicateSettingsIdentifier) {
EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_THAT(decoder_.error(), IsError(QUIC_INVALID_FRAME_DATA));
- EXPECT_EQ("Duplicate SETTINGS identifier.", decoder_.error_detail());
+ EXPECT_THAT(decoder_.error(),
+ IsError(QUIC_HTTP_DUPLICATE_SETTING_IDENTIFIER));
+ EXPECT_EQ("Duplicate setting identifier.", decoder_.error_detail());
}
TEST_F(HttpDecoderTest, DataFrame) {
InSequence s;
- std::string input = QuicStrCat(QuicTextUtils::HexDecode("00" // type (DATA)
- "05"), // length
- "Data!"); // data
+ std::string input = quiche::QuicheStrCat(
+ quiche::QuicheTextUtils::HexDecode("00" // type (DATA)
+ "05"), // length
+ "Data!"); // data
// Visitor pauses processing.
- EXPECT_CALL(visitor_, OnDataFrameStart(2)).WillOnce(Return(false));
- QuicStringPiece remaining_input(input);
+ EXPECT_CALL(visitor_, OnDataFrameStart(2, 5)).WillOnce(Return(false));
+ quiche::QuicheStringPiece remaining_input(input);
QuicByteCount processed_bytes =
ProcessInputWithGarbageAppended(remaining_input);
EXPECT_EQ(2u, processed_bytes);
remaining_input = remaining_input.substr(processed_bytes);
- EXPECT_CALL(visitor_, OnDataFramePayload(QuicStringPiece("Data!")))
+ EXPECT_CALL(visitor_, OnDataFramePayload(quiche::QuicheStringPiece("Data!")))
.WillOnce(Return(false));
processed_bytes = ProcessInputWithGarbageAppended(remaining_input);
EXPECT_EQ(remaining_input.size(), processed_bytes);
@@ -592,20 +479,20 @@ TEST_F(HttpDecoderTest, DataFrame) {
EXPECT_EQ("", decoder_.error_detail());
// Process the full frame.
- EXPECT_CALL(visitor_, OnDataFrameStart(2));
- EXPECT_CALL(visitor_, OnDataFramePayload(QuicStringPiece("Data!")));
+ EXPECT_CALL(visitor_, OnDataFrameStart(2, 5));
+ EXPECT_CALL(visitor_, OnDataFramePayload(quiche::QuicheStringPiece("Data!")));
EXPECT_CALL(visitor_, OnDataFrameEnd());
EXPECT_EQ(input.size(), ProcessInput(input));
EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the frame incrementally.
- EXPECT_CALL(visitor_, OnDataFrameStart(2));
- EXPECT_CALL(visitor_, OnDataFramePayload(QuicStringPiece("D")));
- EXPECT_CALL(visitor_, OnDataFramePayload(QuicStringPiece("a")));
- EXPECT_CALL(visitor_, OnDataFramePayload(QuicStringPiece("t")));
- EXPECT_CALL(visitor_, OnDataFramePayload(QuicStringPiece("a")));
- EXPECT_CALL(visitor_, OnDataFramePayload(QuicStringPiece("!")));
+ EXPECT_CALL(visitor_, OnDataFrameStart(2, 5));
+ EXPECT_CALL(visitor_, OnDataFramePayload(quiche::QuicheStringPiece("D")));
+ EXPECT_CALL(visitor_, OnDataFramePayload(quiche::QuicheStringPiece("a")));
+ EXPECT_CALL(visitor_, OnDataFramePayload(quiche::QuicheStringPiece("t")));
+ EXPECT_CALL(visitor_, OnDataFramePayload(quiche::QuicheStringPiece("a")));
+ EXPECT_CALL(visitor_, OnDataFramePayload(quiche::QuicheStringPiece("!")));
EXPECT_CALL(visitor_, OnDataFrameEnd());
ProcessInputCharByChar(input);
EXPECT_THAT(decoder_.error(), IsQuicNoError());
@@ -626,14 +513,14 @@ TEST_F(HttpDecoderTest, FrameHeaderPartialDelivery) {
EXPECT_EQ("", decoder_.error_detail());
// Send the rest of the header.
- EXPECT_CALL(visitor_, OnDataFrameStart(3));
+ EXPECT_CALL(visitor_, OnDataFrameStart(3, input.length()));
EXPECT_EQ(header_length - 1,
decoder_.ProcessInput(header.data() + 1, header_length - 1));
EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Send data.
- EXPECT_CALL(visitor_, OnDataFramePayload(QuicStringPiece(input)));
+ EXPECT_CALL(visitor_, OnDataFramePayload(quiche::QuicheStringPiece(input)));
EXPECT_CALL(visitor_, OnDataFrameEnd());
EXPECT_EQ(2048u, decoder_.ProcessInput(input.data(), 2048));
EXPECT_THAT(decoder_.error(), IsQuicNoError());
@@ -653,7 +540,8 @@ TEST_F(HttpDecoderTest, PartialDeliveryOfLargeFrameType) {
writer.WriteVarInt62(frame_type);
writer.WriteVarInt62(payload_length);
- EXPECT_CALL(visitor_, OnUnknownFrameStart(frame_type, header_length));
+ EXPECT_CALL(visitor_,
+ OnUnknownFrameStart(frame_type, header_length, payload_length));
EXPECT_CALL(visitor_, OnUnknownFrameEnd());
auto raw_input = input.get();
@@ -669,7 +557,7 @@ TEST_F(HttpDecoderTest, PartialDeliveryOfLargeFrameType) {
TEST_F(HttpDecoderTest, GoAway) {
InSequence s;
- std::string input = QuicTextUtils::HexDecode(
+ std::string input = quiche::QuicheTextUtils::HexDecode(
"07" // type (GOAWAY)
"01" // length
"01"); // StreamId
@@ -696,20 +584,21 @@ TEST_F(HttpDecoderTest, GoAway) {
TEST_F(HttpDecoderTest, HeadersFrame) {
InSequence s;
- std::string input =
- QuicStrCat(QuicTextUtils::HexDecode("01" // type (HEADERS)
- "07"), // length
- "Headers"); // headers
+ std::string input = quiche::QuicheStrCat(
+ quiche::QuicheTextUtils::HexDecode("01" // type (HEADERS)
+ "07"), // length
+ "Headers"); // headers
// Visitor pauses processing.
- EXPECT_CALL(visitor_, OnHeadersFrameStart(2)).WillOnce(Return(false));
- QuicStringPiece remaining_input(input);
+ EXPECT_CALL(visitor_, OnHeadersFrameStart(2, 7)).WillOnce(Return(false));
+ quiche::QuicheStringPiece remaining_input(input);
QuicByteCount processed_bytes =
ProcessInputWithGarbageAppended(remaining_input);
EXPECT_EQ(2u, processed_bytes);
remaining_input = remaining_input.substr(processed_bytes);
- EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("Headers")))
+ EXPECT_CALL(visitor_,
+ OnHeadersFramePayload(quiche::QuicheStringPiece("Headers")))
.WillOnce(Return(false));
processed_bytes = ProcessInputWithGarbageAppended(remaining_input);
EXPECT_EQ(remaining_input.size(), processed_bytes);
@@ -720,22 +609,23 @@ TEST_F(HttpDecoderTest, HeadersFrame) {
EXPECT_EQ("", decoder_.error_detail());
// Process the full frame.
- EXPECT_CALL(visitor_, OnHeadersFrameStart(2));
- EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("Headers")));
+ EXPECT_CALL(visitor_, OnHeadersFrameStart(2, 7));
+ EXPECT_CALL(visitor_,
+ OnHeadersFramePayload(quiche::QuicheStringPiece("Headers")));
EXPECT_CALL(visitor_, OnHeadersFrameEnd());
EXPECT_EQ(input.size(), ProcessInput(input));
EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the frame incrementally.
- EXPECT_CALL(visitor_, OnHeadersFrameStart(2));
- EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("H")));
- EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("e")));
- EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("a")));
- EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("d")));
- EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("e")));
- EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("r")));
- EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("s")));
+ EXPECT_CALL(visitor_, OnHeadersFrameStart(2, 7));
+ EXPECT_CALL(visitor_, OnHeadersFramePayload(quiche::QuicheStringPiece("H")));
+ EXPECT_CALL(visitor_, OnHeadersFramePayload(quiche::QuicheStringPiece("e")));
+ EXPECT_CALL(visitor_, OnHeadersFramePayload(quiche::QuicheStringPiece("a")));
+ EXPECT_CALL(visitor_, OnHeadersFramePayload(quiche::QuicheStringPiece("d")));
+ EXPECT_CALL(visitor_, OnHeadersFramePayload(quiche::QuicheStringPiece("e")));
+ EXPECT_CALL(visitor_, OnHeadersFramePayload(quiche::QuicheStringPiece("r")));
+ EXPECT_CALL(visitor_, OnHeadersFramePayload(quiche::QuicheStringPiece("s")));
EXPECT_CALL(visitor_, OnHeadersFrameEnd());
ProcessInputCharByChar(input);
EXPECT_THAT(decoder_.error(), IsQuicNoError());
@@ -744,12 +634,12 @@ TEST_F(HttpDecoderTest, HeadersFrame) {
TEST_F(HttpDecoderTest, EmptyDataFrame) {
InSequence s;
- std::string input = QuicTextUtils::HexDecode(
+ std::string input = quiche::QuicheTextUtils::HexDecode(
"00" // type (DATA)
"00"); // length
// Visitor pauses processing.
- EXPECT_CALL(visitor_, OnDataFrameStart(2)).WillOnce(Return(false));
+ EXPECT_CALL(visitor_, OnDataFrameStart(2, 0)).WillOnce(Return(false));
EXPECT_EQ(input.size(), ProcessInputWithGarbageAppended(input));
EXPECT_CALL(visitor_, OnDataFrameEnd()).WillOnce(Return(false));
@@ -758,14 +648,14 @@ TEST_F(HttpDecoderTest, EmptyDataFrame) {
EXPECT_EQ("", decoder_.error_detail());
// Process the full frame.
- EXPECT_CALL(visitor_, OnDataFrameStart(2));
+ EXPECT_CALL(visitor_, OnDataFrameStart(2, 0));
EXPECT_CALL(visitor_, OnDataFrameEnd());
EXPECT_EQ(input.size(), ProcessInput(input));
EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the frame incrementally.
- EXPECT_CALL(visitor_, OnDataFrameStart(2));
+ EXPECT_CALL(visitor_, OnDataFrameStart(2, 0));
EXPECT_CALL(visitor_, OnDataFrameEnd());
ProcessInputCharByChar(input);
EXPECT_THAT(decoder_.error(), IsQuicNoError());
@@ -774,12 +664,12 @@ TEST_F(HttpDecoderTest, EmptyDataFrame) {
TEST_F(HttpDecoderTest, EmptyHeadersFrame) {
InSequence s;
- std::string input = QuicTextUtils::HexDecode(
+ std::string input = quiche::QuicheTextUtils::HexDecode(
"01" // type (HEADERS)
"00"); // length
// Visitor pauses processing.
- EXPECT_CALL(visitor_, OnHeadersFrameStart(2)).WillOnce(Return(false));
+ EXPECT_CALL(visitor_, OnHeadersFrameStart(2, 0)).WillOnce(Return(false));
EXPECT_EQ(input.size(), ProcessInputWithGarbageAppended(input));
EXPECT_CALL(visitor_, OnHeadersFrameEnd()).WillOnce(Return(false));
@@ -788,14 +678,14 @@ TEST_F(HttpDecoderTest, EmptyHeadersFrame) {
EXPECT_EQ("", decoder_.error_detail());
// Process the full frame.
- EXPECT_CALL(visitor_, OnHeadersFrameStart(2));
+ EXPECT_CALL(visitor_, OnHeadersFrameStart(2, 0));
EXPECT_CALL(visitor_, OnHeadersFrameEnd());
EXPECT_EQ(input.size(), ProcessInput(input));
EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the frame incrementally.
- EXPECT_CALL(visitor_, OnHeadersFrameStart(2));
+ EXPECT_CALL(visitor_, OnHeadersFrameStart(2, 0));
EXPECT_CALL(visitor_, OnHeadersFrameEnd());
ProcessInputCharByChar(input);
EXPECT_THAT(decoder_.error(), IsQuicNoError());
@@ -804,14 +694,15 @@ TEST_F(HttpDecoderTest, EmptyHeadersFrame) {
TEST_F(HttpDecoderTest, PushPromiseFrameNoHeaders) {
InSequence s;
- std::string input = QuicTextUtils::HexDecode(
+ std::string input = quiche::QuicheTextUtils::HexDecode(
"05" // type (PUSH_PROMISE)
"01" // length
"01"); // Push Id
// Visitor pauses processing.
EXPECT_CALL(visitor_, OnPushPromiseFrameStart(2));
- EXPECT_CALL(visitor_, OnPushPromiseFramePushId(1, 1)).WillOnce(Return(false));
+ EXPECT_CALL(visitor_, OnPushPromiseFramePushId(1, 1, 0))
+ .WillOnce(Return(false));
EXPECT_EQ(input.size(), ProcessInputWithGarbageAppended(input));
EXPECT_CALL(visitor_, OnPushPromiseFrameEnd()).WillOnce(Return(false));
@@ -821,7 +712,7 @@ TEST_F(HttpDecoderTest, PushPromiseFrameNoHeaders) {
// Process the full frame.
EXPECT_CALL(visitor_, OnPushPromiseFrameStart(2));
- EXPECT_CALL(visitor_, OnPushPromiseFramePushId(1, 1));
+ EXPECT_CALL(visitor_, OnPushPromiseFramePushId(1, 1, 0));
EXPECT_CALL(visitor_, OnPushPromiseFrameEnd());
EXPECT_EQ(input.size(), ProcessInput(input));
EXPECT_THAT(decoder_.error(), IsQuicNoError());
@@ -829,7 +720,7 @@ TEST_F(HttpDecoderTest, PushPromiseFrameNoHeaders) {
// Process the frame incrementally.
EXPECT_CALL(visitor_, OnPushPromiseFrameStart(2));
- EXPECT_CALL(visitor_, OnPushPromiseFramePushId(1, 1));
+ EXPECT_CALL(visitor_, OnPushPromiseFramePushId(1, 1, 0));
EXPECT_CALL(visitor_, OnPushPromiseFrameEnd());
ProcessInputCharByChar(input);
EXPECT_THAT(decoder_.error(), IsQuicNoError());
@@ -837,15 +728,15 @@ TEST_F(HttpDecoderTest, PushPromiseFrameNoHeaders) {
}
TEST_F(HttpDecoderTest, MalformedFrameWithOverlyLargePayload) {
- std::string input = QuicTextUtils::HexDecode(
+ std::string input = quiche::QuicheTextUtils::HexDecode(
"03" // type (CANCEL_PUSH)
"10" // length
"15"); // malformed payload
// Process the full frame.
EXPECT_CALL(visitor_, OnError(&decoder_));
EXPECT_EQ(2u, ProcessInput(input));
- EXPECT_THAT(decoder_.error(), IsError(QUIC_INVALID_FRAME_DATA));
- EXPECT_EQ("Frame is too large", decoder_.error_detail());
+ EXPECT_THAT(decoder_.error(), IsError(QUIC_HTTP_FRAME_TOO_LARGE));
+ EXPECT_EQ("Frame is too large.", decoder_.error_detail());
}
TEST_F(HttpDecoderTest, MalformedSettingsFrame) {
@@ -858,34 +749,35 @@ TEST_F(HttpDecoderTest, MalformedSettingsFrame) {
writer.WriteStringPiece("Malformed payload");
EXPECT_CALL(visitor_, OnError(&decoder_));
- EXPECT_EQ(5u, decoder_.ProcessInput(input, QUIC_ARRAYSIZE(input)));
- EXPECT_THAT(decoder_.error(), IsError(QUIC_INVALID_FRAME_DATA));
- EXPECT_EQ("Frame is too large", decoder_.error_detail());
+ EXPECT_EQ(5u, decoder_.ProcessInput(input, QUICHE_ARRAYSIZE(input)));
+ EXPECT_THAT(decoder_.error(), IsError(QUIC_HTTP_FRAME_TOO_LARGE));
+ EXPECT_EQ("Frame is too large.", decoder_.error_detail());
}
TEST_F(HttpDecoderTest, HeadersPausedThenData) {
InSequence s;
- std::string input =
- QuicStrCat(QuicTextUtils::HexDecode("01" // type (HEADERS)
- "07"), // length
- "Headers", // headers
- QuicTextUtils::HexDecode("00" // type (DATA)
- "05"), // length
- "Data!"); // data
+ std::string input = quiche::QuicheStrCat(
+ quiche::QuicheTextUtils::HexDecode("01" // type (HEADERS)
+ "07"), // length
+ "Headers", // headers
+ quiche::QuicheTextUtils::HexDecode("00" // type (DATA)
+ "05"), // length
+ "Data!"); // data
// Visitor pauses processing, maybe because header decompression is blocked.
- EXPECT_CALL(visitor_, OnHeadersFrameStart(2));
- EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("Headers")));
+ EXPECT_CALL(visitor_, OnHeadersFrameStart(2, 7));
+ EXPECT_CALL(visitor_,
+ OnHeadersFramePayload(quiche::QuicheStringPiece("Headers")));
EXPECT_CALL(visitor_, OnHeadersFrameEnd()).WillOnce(Return(false));
- QuicStringPiece remaining_input(input);
+ quiche::QuicheStringPiece remaining_input(input);
QuicByteCount processed_bytes =
ProcessInputWithGarbageAppended(remaining_input);
EXPECT_EQ(9u, processed_bytes);
remaining_input = remaining_input.substr(processed_bytes);
// Process DATA frame.
- EXPECT_CALL(visitor_, OnDataFrameStart(2));
- EXPECT_CALL(visitor_, OnDataFramePayload(QuicStringPiece("Data!")));
+ EXPECT_CALL(visitor_, OnDataFrameStart(2, 5));
+ EXPECT_CALL(visitor_, OnDataFramePayload(quiche::QuicheStringPiece("Data!")));
EXPECT_CALL(visitor_, OnDataFrameEnd());
processed_bytes = ProcessInput(remaining_input);
@@ -904,7 +796,7 @@ TEST_F(HttpDecoderTest, CorruptFrame) {
} kTestData[] = {{"\x03" // type (CANCEL_PUSH)
"\x01" // length
"\x40", // first byte of two-byte varint push id
- "Unable to read push_id"},
+ "Unable to read CANCEL_PUSH push_id."},
{"\x03" // type (CANCEL_PUSH)
"\x04" // length
"\x05" // valid push id
@@ -913,25 +805,16 @@ TEST_F(HttpDecoderTest, CorruptFrame) {
{"\x0D" // type (MAX_PUSH_ID)
"\x01" // length
"\x40", // first byte of two-byte varint push id
- "Unable to read push_id"},
+ "Unable to read MAX_PUSH_ID push_id."},
{"\x0D" // type (MAX_PUSH_ID)
"\x04" // length
"\x05" // valid push id
"foo", // superfluous data
"Superfluous data in MAX_PUSH_ID frame."},
- {"\x0E" // type (DUPLICATE_PUSH)
- "\x01" // length
- "\x40", // first byte of two-byte varint push id
- "Unable to read push_id"},
- {"\x0E" // type (DUPLICATE_PUSH)
- "\x04" // length
- "\x05" // valid push id
- "foo", // superfluous data
- "Superfluous data in DUPLICATE_PUSH frame."},
{"\x07" // type (GOAWAY)
"\x01" // length
"\x40", // first byte of two-byte varint stream id
- "Unable to read GOAWAY stream_id"},
+ "Unable to read GOAWAY stream_id."},
{"\x07" // type (GOAWAY)
"\x04" // length
"\x05" // valid stream id
@@ -943,38 +826,38 @@ TEST_F(HttpDecoderTest, CorruptFrame) {
HttpDecoder decoder(&visitor_);
EXPECT_CALL(visitor_, OnError(&decoder));
- QuicStringPiece input(test_data.input);
+ quiche::QuicheStringPiece input(test_data.input);
decoder.ProcessInput(input.data(), input.size());
- EXPECT_THAT(decoder.error(), IsError(QUIC_INVALID_FRAME_DATA));
+ EXPECT_THAT(decoder.error(), IsError(QUIC_HTTP_FRAME_ERROR));
EXPECT_EQ(test_data.error_message, decoder.error_detail());
}
{
HttpDecoder decoder(&visitor_);
EXPECT_CALL(visitor_, OnError(&decoder));
- QuicStringPiece input(test_data.input);
+ quiche::QuicheStringPiece input(test_data.input);
for (auto c : input) {
decoder.ProcessInput(&c, 1);
}
- EXPECT_THAT(decoder.error(), IsError(QUIC_INVALID_FRAME_DATA));
+ EXPECT_THAT(decoder.error(), IsError(QUIC_HTTP_FRAME_ERROR));
EXPECT_EQ(test_data.error_message, decoder.error_detail());
}
}
}
TEST_F(HttpDecoderTest, EmptyCancelPushFrame) {
- std::string input = QuicTextUtils::HexDecode(
+ std::string input = quiche::QuicheTextUtils::HexDecode(
"03" // type (CANCEL_PUSH)
"00"); // frame length
EXPECT_CALL(visitor_, OnError(&decoder_));
EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_THAT(decoder_.error(), IsError(QUIC_INVALID_FRAME_DATA));
- EXPECT_EQ("Unable to read push_id", decoder_.error_detail());
+ EXPECT_THAT(decoder_.error(), IsError(QUIC_HTTP_FRAME_ERROR));
+ EXPECT_EQ("Unable to read CANCEL_PUSH push_id.", decoder_.error_detail());
}
TEST_F(HttpDecoderTest, EmptySettingsFrame) {
- std::string input = QuicTextUtils::HexDecode(
+ std::string input = quiche::QuicheTextUtils::HexDecode(
"04" // type (SETTINGS)
"00"); // frame length
@@ -990,47 +873,36 @@ TEST_F(HttpDecoderTest, EmptySettingsFrame) {
// Regression test for https://crbug.com/1001823.
TEST_F(HttpDecoderTest, EmptyPushPromiseFrame) {
- std::string input = QuicTextUtils::HexDecode(
+ std::string input = quiche::QuicheTextUtils::HexDecode(
"05" // type (PUSH_PROMISE)
"00"); // frame length
EXPECT_CALL(visitor_, OnError(&decoder_));
EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_THAT(decoder_.error(), IsError(QUIC_INVALID_FRAME_DATA));
- EXPECT_EQ("Corrupt PUSH_PROMISE frame.", decoder_.error_detail());
+ EXPECT_THAT(decoder_.error(), IsError(QUIC_HTTP_FRAME_ERROR));
+ EXPECT_EQ("PUSH_PROMISE frame with empty payload.", decoder_.error_detail());
}
TEST_F(HttpDecoderTest, EmptyGoAwayFrame) {
- std::string input = QuicTextUtils::HexDecode(
+ std::string input = quiche::QuicheTextUtils::HexDecode(
"07" // type (GOAWAY)
"00"); // frame length
EXPECT_CALL(visitor_, OnError(&decoder_));
EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_THAT(decoder_.error(), IsError(QUIC_INVALID_FRAME_DATA));
- EXPECT_EQ("Unable to read GOAWAY stream_id", decoder_.error_detail());
+ EXPECT_THAT(decoder_.error(), IsError(QUIC_HTTP_FRAME_ERROR));
+ EXPECT_EQ("Unable to read GOAWAY stream_id.", decoder_.error_detail());
}
TEST_F(HttpDecoderTest, EmptyMaxPushIdFrame) {
- std::string input = QuicTextUtils::HexDecode(
+ std::string input = quiche::QuicheTextUtils::HexDecode(
"0d" // type (MAX_PUSH_ID)
"00"); // frame length
EXPECT_CALL(visitor_, OnError(&decoder_));
EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_THAT(decoder_.error(), IsError(QUIC_INVALID_FRAME_DATA));
- EXPECT_EQ("Unable to read push_id", decoder_.error_detail());
-}
-
-TEST_F(HttpDecoderTest, EmptyDuplicatePushFrame) {
- std::string input = QuicTextUtils::HexDecode(
- "0e" // type (DUPLICATE_PUSH)
- "00"); // frame length
-
- EXPECT_CALL(visitor_, OnError(&decoder_));
- EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_THAT(decoder_.error(), IsError(QUIC_INVALID_FRAME_DATA));
- EXPECT_EQ("Unable to read push_id", decoder_.error_detail());
+ EXPECT_THAT(decoder_.error(), IsError(QUIC_HTTP_FRAME_ERROR));
+ EXPECT_EQ("Unable to read MAX_PUSH_ID push_id.", decoder_.error_detail());
}
TEST_F(HttpDecoderTest, LargeStreamIdInGoAway) {
@@ -1045,6 +917,124 @@ TEST_F(HttpDecoderTest, LargeStreamIdInGoAway) {
EXPECT_EQ("", decoder_.error_detail());
}
+TEST_F(HttpDecoderTest, PriorityUpdateFrame) {
+ InSequence s;
+ std::string input1 = quiche::QuicheTextUtils::HexDecode(
+ "0f" // type (PRIORITY_UPDATE)
+ "02" // length
+ "00" // prioritized element type: REQUEST_STREAM
+ "03"); // prioritized element id
+
+ PriorityUpdateFrame priority_update1;
+ priority_update1.prioritized_element_type = REQUEST_STREAM;
+ priority_update1.prioritized_element_id = 0x03;
+
+ // Visitor pauses processing.
+ EXPECT_CALL(visitor_, OnPriorityUpdateFrameStart(2)).WillOnce(Return(false));
+ quiche::QuicheStringPiece remaining_input(input1);
+ QuicByteCount processed_bytes =
+ ProcessInputWithGarbageAppended(remaining_input);
+ EXPECT_EQ(2u, processed_bytes);
+ remaining_input = remaining_input.substr(processed_bytes);
+
+ EXPECT_CALL(visitor_, OnPriorityUpdateFrame(priority_update1))
+ .WillOnce(Return(false));
+ processed_bytes = ProcessInputWithGarbageAppended(remaining_input);
+ EXPECT_EQ(remaining_input.size(), processed_bytes);
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
+ EXPECT_EQ("", decoder_.error_detail());
+
+ // Process the full frame.
+ EXPECT_CALL(visitor_, OnPriorityUpdateFrameStart(2));
+ EXPECT_CALL(visitor_, OnPriorityUpdateFrame(priority_update1));
+ EXPECT_EQ(input1.size(), ProcessInput(input1));
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
+ EXPECT_EQ("", decoder_.error_detail());
+
+ // Process the frame incrementally.
+ EXPECT_CALL(visitor_, OnPriorityUpdateFrameStart(2));
+ EXPECT_CALL(visitor_, OnPriorityUpdateFrame(priority_update1));
+ ProcessInputCharByChar(input1);
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
+ EXPECT_EQ("", decoder_.error_detail());
+
+ std::string input2 = quiche::QuicheTextUtils::HexDecode(
+ "0f" // type (PRIORIRTY)
+ "05" // length
+ "80" // prioritized element type: PUSH_STREAM
+ "05" // prioritized element id
+ "666f6f"); // priority field value: "foo"
+
+ PriorityUpdateFrame priority_update2;
+ priority_update2.prioritized_element_type = PUSH_STREAM;
+ priority_update2.prioritized_element_id = 0x05;
+ priority_update2.priority_field_value = "foo";
+
+ // Visitor pauses processing.
+ EXPECT_CALL(visitor_, OnPriorityUpdateFrameStart(2)).WillOnce(Return(false));
+ remaining_input = input2;
+ processed_bytes = ProcessInputWithGarbageAppended(remaining_input);
+ EXPECT_EQ(2u, processed_bytes);
+ remaining_input = remaining_input.substr(processed_bytes);
+
+ EXPECT_CALL(visitor_, OnPriorityUpdateFrame(priority_update2))
+ .WillOnce(Return(false));
+ processed_bytes = ProcessInputWithGarbageAppended(remaining_input);
+ EXPECT_EQ(remaining_input.size(), processed_bytes);
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
+ EXPECT_EQ("", decoder_.error_detail());
+
+ // Process the full frame.
+ EXPECT_CALL(visitor_, OnPriorityUpdateFrameStart(2));
+ EXPECT_CALL(visitor_, OnPriorityUpdateFrame(priority_update2));
+ EXPECT_EQ(input2.size(), ProcessInput(input2));
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
+ EXPECT_EQ("", decoder_.error_detail());
+
+ // Process the frame incrementally.
+ EXPECT_CALL(visitor_, OnPriorityUpdateFrameStart(2));
+ EXPECT_CALL(visitor_, OnPriorityUpdateFrame(priority_update2));
+ ProcessInputCharByChar(input2);
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
+ EXPECT_EQ("", decoder_.error_detail());
+}
+
+TEST_F(HttpDecoderTest, CorruptPriorityUpdateFrame) {
+ std::string payload1 = quiche::QuicheTextUtils::HexDecode(
+ "80" // prioritized element type: PUSH_STREAM
+ "4005"); // prioritized element id
+ std::string payload2 = quiche::QuicheTextUtils::HexDecode(
+ "42"); // invalid prioritized element type
+ struct {
+ const char* const payload;
+ size_t payload_length;
+ const char* const error_message;
+ } kTestData[] = {
+ {payload1.data(), 0, "Unable to read prioritized element type."},
+ {payload1.data(), 1, "Unable to read prioritized element id."},
+ {payload1.data(), 2, "Unable to read prioritized element id."},
+ {payload2.data(), 1, "Invalid prioritized element type."},
+ };
+
+ for (const auto& test_data : kTestData) {
+ std::string input;
+ input.push_back(15u); // type PRIORITY_UPDATE
+ input.push_back(test_data.payload_length);
+ size_t header_length = input.size();
+ input.append(test_data.payload, test_data.payload_length);
+
+ HttpDecoder decoder(&visitor_);
+ EXPECT_CALL(visitor_, OnPriorityUpdateFrameStart(header_length));
+ EXPECT_CALL(visitor_, OnError(&decoder));
+
+ QuicByteCount processed_bytes =
+ decoder.ProcessInput(input.data(), input.size());
+ EXPECT_EQ(input.size(), processed_bytes);
+ EXPECT_THAT(decoder.error(), IsError(QUIC_HTTP_FRAME_ERROR));
+ EXPECT_EQ(test_data.error_message, decoder.error_detail());
+ }
+}
+
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/http_encoder.cc b/chromium/net/third_party/quiche/src/quic/core/http/http_encoder.cc
index 6bb25cf16fe..6066b2619b6 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/http_encoder.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/http_encoder.cc
@@ -3,43 +3,19 @@
// found in the LICENSE file.
#include "net/third_party/quiche/src/quic/core/http/http_encoder.h"
+#include <cstdint>
+#include <memory>
+#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
namespace quic {
namespace {
-// Set the first byte of a PRIORITY frame according to its fields.
-uint8_t SetPriorityFields(uint8_t num,
- PriorityElementType type,
- bool prioritized) {
- switch (type) {
- case REQUEST_STREAM:
- return num;
- case PUSH_STREAM:
- if (prioritized) {
- return num | (1 << 6);
- }
- return num | (1 << 4);
- case PLACEHOLDER:
- if (prioritized) {
- return num | (1 << 7);
- }
- return num | (1 << 5);
- case ROOT_OF_TREE:
- if (prioritized) {
- num = num | (1 << 6);
- return num | (1 << 7);
- }
- num = num | (1 << 4);
- return num | (1 << 5);
- default:
- QUIC_NOTREACHED();
- return num;
- }
-}
-
bool WriteFrameHeader(QuicByteCount length,
HttpFrameType type,
QuicDataWriter* writer) {
@@ -53,29 +29,6 @@ QuicByteCount GetTotalLength(QuicByteCount payload_length, HttpFrameType type) {
payload_length;
}
-// Write prioritized element id and element dependency id if needed.
-bool MaybeWriteIds(const PriorityFrame& priority, QuicDataWriter* writer) {
- if (priority.prioritized_type != ROOT_OF_TREE) {
- if (!writer->WriteVarInt62(priority.prioritized_element_id)) {
- return false;
- }
- } else {
- DCHECK_EQ(0u, priority.prioritized_element_id)
- << "Prioritized element id should be 0 when prioritized type is "
- "ROOT_OF_TREE";
- }
- if (priority.dependency_type != ROOT_OF_TREE) {
- if (!writer->WriteVarInt62(priority.element_dependency_id)) {
- return false;
- }
- } else {
- DCHECK_EQ(0u, priority.element_dependency_id)
- << "Element dependency id should be 0 when dependency type is "
- "ROOT_OF_TREE";
- }
- return true;
-}
-
} // namespace
// static
@@ -121,48 +74,6 @@ QuicByteCount HttpEncoder::SerializeHeadersFrameHeader(
}
// static
-QuicByteCount HttpEncoder::SerializePriorityFrame(
- const PriorityFrame& priority,
- std::unique_ptr<char[]>* output) {
- QuicByteCount payload_length =
- kPriorityFirstByteLength +
- (priority.prioritized_type == ROOT_OF_TREE
- ? 0
- : QuicDataWriter::GetVarInt62Len(priority.prioritized_element_id)) +
- (priority.dependency_type == ROOT_OF_TREE
- ? 0
- : QuicDataWriter::GetVarInt62Len(priority.element_dependency_id)) +
- kPriorityWeightLength;
- QuicByteCount total_length =
- GetTotalLength(payload_length, HttpFrameType::PRIORITY);
-
- output->reset(new char[total_length]);
- QuicDataWriter writer(total_length, output->get());
-
- if (!WriteFrameHeader(payload_length, HttpFrameType::PRIORITY, &writer)) {
- QUIC_DLOG(ERROR) << "Http encoder failed when attempting to serialize "
- "priority frame header.";
- return 0;
- }
-
- // Set the first byte of the payload.
- uint8_t firstByte = 0;
- firstByte = SetPriorityFields(firstByte, priority.prioritized_type, true);
- firstByte = SetPriorityFields(firstByte, priority.dependency_type, false);
- if (priority.exclusive) {
- firstByte |= kPriorityExclusiveBit;
- }
-
- if (writer.WriteUInt8(firstByte) && MaybeWriteIds(priority, &writer) &&
- writer.WriteUInt8(priority.weight)) {
- return total_length;
- }
- QUIC_DLOG(ERROR) << "Http encoder failed when attempting to serialize "
- "priority frame payload.";
- return 0;
-}
-
-// static
QuicByteCount HttpEncoder::SerializeCancelPushFrame(
const CancelPushFrame& cancel_push,
std::unique_ptr<char[]>* output) {
@@ -286,24 +197,77 @@ QuicByteCount HttpEncoder::SerializeMaxPushIdFrame(
}
// static
-QuicByteCount HttpEncoder::SerializeDuplicatePushFrame(
- const DuplicatePushFrame& duplicate_push,
+QuicByteCount HttpEncoder::SerializePriorityUpdateFrame(
+ const PriorityUpdateFrame& priority_update,
std::unique_ptr<char[]>* output) {
QuicByteCount payload_length =
- QuicDataWriter::GetVarInt62Len(duplicate_push.push_id);
+ kPriorityFirstByteLength +
+ QuicDataWriter::GetVarInt62Len(priority_update.prioritized_element_id) +
+ priority_update.priority_field_value.size();
QuicByteCount total_length =
- GetTotalLength(payload_length, HttpFrameType::DUPLICATE_PUSH);
+ GetTotalLength(payload_length, HttpFrameType::PRIORITY_UPDATE);
output->reset(new char[total_length]);
QuicDataWriter writer(total_length, output->get());
- if (WriteFrameHeader(payload_length, HttpFrameType::DUPLICATE_PUSH,
+ if (WriteFrameHeader(payload_length, HttpFrameType::PRIORITY_UPDATE,
&writer) &&
- writer.WriteVarInt62(duplicate_push.push_id)) {
+ writer.WriteUInt8(priority_update.prioritized_element_type) &&
+ writer.WriteVarInt62(priority_update.prioritized_element_id) &&
+ writer.WriteBytes(priority_update.priority_field_value.data(),
+ priority_update.priority_field_value.size())) {
return total_length;
}
+
+ QUIC_DLOG(ERROR) << "Http encoder failed when attempting to serialize "
+ "PRIORITY_UPDATE frame.";
+ return 0;
+}
+
+// static
+QuicByteCount HttpEncoder::SerializeGreasingFrame(
+ std::unique_ptr<char[]>* output) {
+ uint64_t frame_type;
+ QuicByteCount payload_length;
+ std::string payload;
+ if (!GetQuicFlag(FLAGS_quic_enable_http3_grease_randomness)) {
+ frame_type = 0x40;
+ payload_length = 1;
+ payload = "a";
+ } else {
+ uint32_t result;
+ QuicRandom::GetInstance()->RandBytes(&result, sizeof(result));
+ frame_type = 0x1fULL * static_cast<uint64_t>(result) + 0x21ULL;
+
+ // The payload length is random but within [0, 3];
+ payload_length = result % 4;
+
+ if (payload_length > 0) {
+ std::unique_ptr<char[]> buffer(new char[payload_length]);
+ QuicRandom::GetInstance()->RandBytes(buffer.get(), payload_length);
+ payload = std::string(buffer.get(), payload_length);
+ }
+ }
+ QuicByteCount total_length = QuicDataWriter::GetVarInt62Len(frame_type) +
+ QuicDataWriter::GetVarInt62Len(payload_length) +
+ payload_length;
+
+ output->reset(new char[total_length]);
+ QuicDataWriter writer(total_length, output->get());
+
+ bool success =
+ writer.WriteVarInt62(frame_type) && writer.WriteVarInt62(payload_length);
+
+ if (payload_length > 0) {
+ success &= writer.WriteBytes(payload.data(), payload_length);
+ }
+
+ if (success) {
+ return total_length;
+ }
+
QUIC_DLOG(ERROR) << "Http encoder failed when attempting to serialize "
- "duplicate push frame.";
+ "greasing frame.";
return 0;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/http_encoder.h b/chromium/net/third_party/quiche/src/quic/core/http/http_encoder.h
index 4420fc65b7b..4d6a54a283e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/http_encoder.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/http_encoder.h
@@ -5,6 +5,7 @@
#ifndef QUICHE_QUIC_CORE_HTTP_HTTP_ENCODER_H_
#define QUICHE_QUIC_CORE_HTTP_HTTP_ENCODER_H_
+#include <memory>
#include "net/third_party/quiche/src/quic/core/http/http_frames.h"
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
@@ -31,11 +32,6 @@ class QUIC_EXPORT_PRIVATE HttpEncoder {
QuicByteCount payload_length,
std::unique_ptr<char[]>* output);
- // Serializes a PRIORITY frame into a new buffer stored in |output|.
- // Returns the length of the buffer on success, or 0 otherwise.
- static QuicByteCount SerializePriorityFrame(const PriorityFrame& priority,
- std::unique_ptr<char[]>* output);
-
// Serializes a CANCEL_PUSH frame into a new buffer stored in |output|.
// Returns the length of the buffer on success, or 0 otherwise.
static QuicByteCount SerializeCancelPushFrame(
@@ -65,11 +61,15 @@ class QUIC_EXPORT_PRIVATE HttpEncoder {
const MaxPushIdFrame& max_push_id,
std::unique_ptr<char[]>* output);
- // Serialize a DUPLICATE_PUSH frame into a new buffer stored in |output|.
+ // Serializes a PRIORITY_UPDATE frame into a new buffer stored in |output|.
// Returns the length of the buffer on success, or 0 otherwise.
- static QuicByteCount SerializeDuplicatePushFrame(
- const DuplicatePushFrame& duplicate_push,
+ static QuicByteCount SerializePriorityUpdateFrame(
+ const PriorityUpdateFrame& priority_update,
std::unique_ptr<char[]>* output);
+
+ // Serializes a frame with reserved frame type specified in
+ // https://tools.ietf.org/html/draft-ietf-quic-http-25#section-7.2.9.
+ static QuicByteCount SerializeGreasingFrame(std::unique_ptr<char[]>* output);
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/http_encoder_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/http_encoder_test.cc
index 2df89bd4ae6..aad20e5d95e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/http_encoder_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/http_encoder_test.cc
@@ -4,9 +4,10 @@
#include "net/third_party/quiche/src/quic/core/http/http_encoder.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/test_tools/quiche_test_utils.h"
namespace quic {
namespace test {
@@ -19,9 +20,9 @@ TEST(HttpEncoderTest, SerializeDataFrameHeader) {
0x00,
// length
0x05};
- EXPECT_EQ(QUIC_ARRAYSIZE(output), length);
- CompareCharArraysWithHexError("DATA", buffer.get(), length, output,
- QUIC_ARRAYSIZE(output));
+ EXPECT_EQ(QUICHE_ARRAYSIZE(output), length);
+ quiche::test::CompareCharArraysWithHexError("DATA", buffer.get(), length,
+ output, QUICHE_ARRAYSIZE(output));
}
TEST(HttpEncoderTest, SerializeHeadersFrameHeader) {
@@ -32,76 +33,9 @@ TEST(HttpEncoderTest, SerializeHeadersFrameHeader) {
0x01,
// length
0x07};
- EXPECT_EQ(QUIC_ARRAYSIZE(output), length);
- CompareCharArraysWithHexError("HEADERS", buffer.get(), length, output,
- QUIC_ARRAYSIZE(output));
-}
-
-TEST(HttpEncoderTest, SerializePriorityFrame) {
- PriorityFrame priority;
- priority.prioritized_type = REQUEST_STREAM;
- priority.dependency_type = REQUEST_STREAM;
- priority.exclusive = true;
- priority.prioritized_element_id = 0x03;
- priority.element_dependency_id = 0x04;
- priority.weight = 0xFF;
- char output[] = {// type (PRIORITY)
- 0x2,
- // length
- 0x4,
- // request stream, request stream, exclusive
- 0x08,
- // prioritized_element_id
- 0x03,
- // element_dependency_id
- 0x04,
- // weight
- 0xFF};
-
- std::unique_ptr<char[]> buffer;
- uint64_t length = HttpEncoder::SerializePriorityFrame(priority, &buffer);
- EXPECT_EQ(QUIC_ARRAYSIZE(output), length);
- CompareCharArraysWithHexError("PRIORITY", buffer.get(), length, output,
- QUIC_ARRAYSIZE(output));
-
- PriorityFrame priority2;
- priority2.prioritized_type = ROOT_OF_TREE;
- priority2.dependency_type = REQUEST_STREAM;
- priority2.exclusive = true;
- priority2.element_dependency_id = 0x04;
- priority2.weight = 0xFF;
- char output2[] = {// type (PRIORIRTY)
- 0x2,
- // length
- 0x3,
- // root of tree, request stream, exclusive
- 0xc8,
- // element_dependency_id
- 0x04,
- // weight
- 0xff};
- length = HttpEncoder::SerializePriorityFrame(priority2, &buffer);
- EXPECT_EQ(QUIC_ARRAYSIZE(output2), length);
- CompareCharArraysWithHexError("PRIORITY", buffer.get(), length, output2,
- QUIC_ARRAYSIZE(output2));
-
- PriorityFrame priority3;
- priority3.prioritized_type = ROOT_OF_TREE;
- priority3.dependency_type = ROOT_OF_TREE;
- priority3.exclusive = true;
- priority3.weight = 0xFF;
- char output3[] = {// type (PRIORITY)
- 0x2,
- // length
- 0x2,
- // root of tree, root of tree, exclusive
- 0xf8,
- // weight
- 0xff};
- length = HttpEncoder::SerializePriorityFrame(priority3, &buffer);
- EXPECT_EQ(QUIC_ARRAYSIZE(output3), length);
- CompareCharArraysWithHexError("PRIORITY", buffer.get(), length, output3,
- QUIC_ARRAYSIZE(output3));
+ EXPECT_EQ(QUICHE_ARRAYSIZE(output), length);
+ quiche::test::CompareCharArraysWithHexError("HEADERS", buffer.get(), length,
+ output, QUICHE_ARRAYSIZE(output));
}
TEST(HttpEncoderTest, SerializeCancelPushFrame) {
@@ -115,9 +49,9 @@ TEST(HttpEncoderTest, SerializeCancelPushFrame) {
0x01};
std::unique_ptr<char[]> buffer;
uint64_t length = HttpEncoder::SerializeCancelPushFrame(cancel_push, &buffer);
- EXPECT_EQ(QUIC_ARRAYSIZE(output), length);
- CompareCharArraysWithHexError("CANCEL_PUSH", buffer.get(), length, output,
- QUIC_ARRAYSIZE(output));
+ EXPECT_EQ(QUICHE_ARRAYSIZE(output), length);
+ quiche::test::CompareCharArraysWithHexError(
+ "CANCEL_PUSH", buffer.get(), length, output, QUICHE_ARRAYSIZE(output));
}
TEST(HttpEncoderTest, SerializeSettingsFrame) {
@@ -143,9 +77,9 @@ TEST(HttpEncoderTest, SerializeSettingsFrame) {
0x04};
std::unique_ptr<char[]> buffer;
uint64_t length = HttpEncoder::SerializeSettingsFrame(settings, &buffer);
- EXPECT_EQ(QUIC_ARRAYSIZE(output), length);
- CompareCharArraysWithHexError("SETTINGS", buffer.get(), length, output,
- QUIC_ARRAYSIZE(output));
+ EXPECT_EQ(QUICHE_ARRAYSIZE(output), length);
+ quiche::test::CompareCharArraysWithHexError("SETTINGS", buffer.get(), length,
+ output, QUICHE_ARRAYSIZE(output));
}
TEST(HttpEncoderTest, SerializePushPromiseFrameWithOnlyPushId) {
@@ -161,9 +95,9 @@ TEST(HttpEncoderTest, SerializePushPromiseFrameWithOnlyPushId) {
std::unique_ptr<char[]> buffer;
uint64_t length = HttpEncoder::SerializePushPromiseFrameWithOnlyPushId(
push_promise, &buffer);
- EXPECT_EQ(QUIC_ARRAYSIZE(output), length);
- CompareCharArraysWithHexError("PUSH_PROMISE", buffer.get(), length, output,
- QUIC_ARRAYSIZE(output));
+ EXPECT_EQ(QUICHE_ARRAYSIZE(output), length);
+ quiche::test::CompareCharArraysWithHexError(
+ "PUSH_PROMISE", buffer.get(), length, output, QUICHE_ARRAYSIZE(output));
}
TEST(HttpEncoderTest, SerializeGoAwayFrame) {
@@ -177,9 +111,9 @@ TEST(HttpEncoderTest, SerializeGoAwayFrame) {
0x01};
std::unique_ptr<char[]> buffer;
uint64_t length = HttpEncoder::SerializeGoAwayFrame(goaway, &buffer);
- EXPECT_EQ(QUIC_ARRAYSIZE(output), length);
- CompareCharArraysWithHexError("GOAWAY", buffer.get(), length, output,
- QUIC_ARRAYSIZE(output));
+ EXPECT_EQ(QUICHE_ARRAYSIZE(output), length);
+ quiche::test::CompareCharArraysWithHexError("GOAWAY", buffer.get(), length,
+ output, QUICHE_ARRAYSIZE(output));
}
TEST(HttpEncoderTest, SerializeMaxPushIdFrame) {
@@ -193,26 +127,42 @@ TEST(HttpEncoderTest, SerializeMaxPushIdFrame) {
0x01};
std::unique_ptr<char[]> buffer;
uint64_t length = HttpEncoder::SerializeMaxPushIdFrame(max_push_id, &buffer);
- EXPECT_EQ(QUIC_ARRAYSIZE(output), length);
- CompareCharArraysWithHexError("MAX_PUSH_ID", buffer.get(), length, output,
- QUIC_ARRAYSIZE(output));
+ EXPECT_EQ(QUICHE_ARRAYSIZE(output), length);
+ quiche::test::CompareCharArraysWithHexError(
+ "MAX_PUSH_ID", buffer.get(), length, output, QUICHE_ARRAYSIZE(output));
}
-TEST(HttpEncoderTest, SerializeDuplicatePushFrame) {
- DuplicatePushFrame duplicate_push;
- duplicate_push.push_id = 0x1;
- char output[] = {// type (DUPLICATE_PUSH)
- 0x0E,
- // length
- 0x1,
- // Push Id
- 0x01};
+TEST(HttpEncoderTest, SerializePriorityUpdateFrame) {
+ PriorityUpdateFrame priority_update1;
+ priority_update1.prioritized_element_type = REQUEST_STREAM;
+ priority_update1.prioritized_element_id = 0x03;
+ char output1[] = {0x0f, // type (PRIORITY_UPDATE)
+ 0x02, // length
+ 0x00, // prioritized element type: REQUEST_STREAM
+ 0x03}; // prioritized element id
+
std::unique_ptr<char[]> buffer;
uint64_t length =
- HttpEncoder::SerializeDuplicatePushFrame(duplicate_push, &buffer);
- EXPECT_EQ(QUIC_ARRAYSIZE(output), length);
- CompareCharArraysWithHexError("DUPLICATE_PUSH", buffer.get(), length, output,
- QUIC_ARRAYSIZE(output));
+ HttpEncoder::SerializePriorityUpdateFrame(priority_update1, &buffer);
+ EXPECT_EQ(QUICHE_ARRAYSIZE(output1), length);
+ quiche::test::CompareCharArraysWithHexError("PRIORITY_UPDATE", buffer.get(),
+ length, output1,
+ QUICHE_ARRAYSIZE(output1));
+
+ PriorityUpdateFrame priority_update2;
+ priority_update2.prioritized_element_type = PUSH_STREAM;
+ priority_update2.prioritized_element_id = 0x05;
+ priority_update2.priority_field_value = "foo";
+ char output2[] = {0x0f, // type (PRIORIRTY)
+ 0x05, // length
+ 0x80, // prioritized element type: PUSH_STREAM
+ 0x05, // prioritized element id
+ 'f', 'o', 'o'}; // priority field value
+ length = HttpEncoder::SerializePriorityUpdateFrame(priority_update2, &buffer);
+ EXPECT_EQ(QUICHE_ARRAYSIZE(output2), length);
+ quiche::test::CompareCharArraysWithHexError("PRIORITY_UPDATE", buffer.get(),
+ length, output2,
+ QUICHE_ARRAYSIZE(output2));
}
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/http_frames.h b/chromium/net/third_party/quiche/src/quic/core/http/http_frames.h
index 215fa568d29..d7d875a11f1 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/http_frames.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/http_frames.h
@@ -11,9 +11,9 @@
#include "net/third_party/quiche/src/quic/core/http/spdy_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
namespace quic {
@@ -21,83 +21,31 @@ namespace quic {
enum class HttpFrameType : uint8_t {
DATA = 0x0,
HEADERS = 0x1,
- PRIORITY = 0X2,
CANCEL_PUSH = 0X3,
SETTINGS = 0x4,
PUSH_PROMISE = 0x5,
GOAWAY = 0x7,
MAX_PUSH_ID = 0xD,
- DUPLICATE_PUSH = 0xE
+ PRIORITY_UPDATE = 0XF,
};
-// 4.2.1. DATA
+// 7.2.1. DATA
//
// DATA frames (type=0x0) convey arbitrary, variable-length sequences of
// octets associated with an HTTP request or response payload.
struct QUIC_EXPORT_PRIVATE DataFrame {
- QuicStringPiece data;
+ quiche::QuicheStringPiece data;
};
-// 4.2.2. HEADERS
+// 7.2.2. HEADERS
//
// The HEADERS frame (type=0x1) is used to carry a header block,
// compressed using QPACK.
struct QUIC_EXPORT_PRIVATE HeadersFrame {
- QuicStringPiece headers;
+ quiche::QuicheStringPiece headers;
};
-// 4.2.3. PRIORITY
-//
-// The PRIORITY (type=0x02) frame specifies the sender-advised priority
-// of a stream
-
-// Length of the weight field of a priority frame.
-const QuicByteCount kPriorityWeightLength = 1;
-// Length of a priority frame's first byte.
-const QuicByteCount kPriorityFirstByteLength = 1;
-// The bit that indicates Priority frame is exclusive.
-const uint8_t kPriorityExclusiveBit = 8;
-
-enum PriorityElementType : uint8_t {
- REQUEST_STREAM = 0,
- PUSH_STREAM = 1,
- PLACEHOLDER = 2,
- ROOT_OF_TREE = 3
-};
-
-struct QUIC_EXPORT_PRIVATE PriorityFrame {
- PriorityElementType prioritized_type = REQUEST_STREAM;
- PriorityElementType dependency_type = REQUEST_STREAM;
- bool exclusive = false;
- uint64_t prioritized_element_id = 0;
- uint64_t element_dependency_id = 0;
- uint8_t weight = 0;
-
- bool operator==(const PriorityFrame& rhs) const {
- return prioritized_type == rhs.prioritized_type &&
- dependency_type == rhs.dependency_type &&
- exclusive == rhs.exclusive &&
- prioritized_element_id == rhs.prioritized_element_id &&
- element_dependency_id == rhs.element_dependency_id &&
- weight == rhs.weight;
- }
- std::string ToString() const {
- return QuicStrCat("Priority Frame : {prioritized_type: ", prioritized_type,
- ", dependency_type: ", dependency_type,
- ", exclusive: ", exclusive,
- ", prioritized_element_id: ", prioritized_element_id,
- ", element_dependency_id: ", element_dependency_id,
- ", weight: ", weight, "}");
- }
-
- friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
- const PriorityFrame& s) {
- os << s.ToString();
- return os;
- }
-};
-
-// 4.2.4. CANCEL_PUSH
+// 7.2.3. CANCEL_PUSH
//
// The CANCEL_PUSH frame (type=0x3) is used to request cancellation of
// server push prior to the push stream being created.
@@ -111,7 +59,7 @@ struct QUIC_EXPORT_PRIVATE CancelPushFrame {
}
};
-// 4.2.5. SETTINGS
+// 7.2.4. SETTINGS
//
// The SETTINGS frame (type=0x4) conveys configuration parameters that
// affect how endpoints communicate, such as preferences and constraints
@@ -129,7 +77,7 @@ struct QUIC_EXPORT_PRIVATE SettingsFrame {
std::string ToString() const {
std::string s;
for (auto it : values) {
- std::string setting = QuicStrCat(
+ std::string setting = quiche::QuicheStrCat(
SpdyUtils::H3SettingsToString(
static_cast<Http3AndQpackSettingsIdentifiers>(it.first)),
" = ", it.second, "; ");
@@ -144,20 +92,20 @@ struct QUIC_EXPORT_PRIVATE SettingsFrame {
}
};
-// 4.2.6. PUSH_PROMISE
+// 7.2.5. PUSH_PROMISE
//
// The PUSH_PROMISE frame (type=0x05) is used to carry a request header
// set from server to client, as in HTTP/2.
struct QUIC_EXPORT_PRIVATE PushPromiseFrame {
PushId push_id;
- QuicStringPiece headers;
+ quiche::QuicheStringPiece headers;
bool operator==(const PushPromiseFrame& rhs) const {
return push_id == rhs.push_id && headers == rhs.headers;
}
};
-// 4.2.7. GOAWAY
+// 7.2.6. GOAWAY
//
// The GOAWAY frame (type=0x7) is used to initiate graceful shutdown of
// a connection by a server.
@@ -169,7 +117,7 @@ struct QUIC_EXPORT_PRIVATE GoAwayFrame {
}
};
-// 4.2.8. MAX_PUSH_ID
+// 7.2.7. MAX_PUSH_ID
//
// The MAX_PUSH_ID frame (type=0xD) is used by clients to control the
// number of server pushes that the server can initiate.
@@ -181,16 +129,43 @@ struct QUIC_EXPORT_PRIVATE MaxPushIdFrame {
}
};
-// 4.2.9. DUPLICATE_PUSH
+// https://httpwg.org/http-extensions/draft-ietf-httpbis-priority.html
//
-// The DUPLICATE_PUSH frame (type=0xE) is used by servers to indicate
-// that an existing pushed resource is related to multiple client
-// requests.
-struct QUIC_EXPORT_PRIVATE DuplicatePushFrame {
- PushId push_id;
+// The PRIORITY_UPDATE (type=0x0f) frame specifies the sender-advised priority
+// of a stream
- bool operator==(const DuplicatePushFrame& rhs) const {
- return push_id == rhs.push_id;
+// Length of a priority frame's first byte.
+const QuicByteCount kPriorityFirstByteLength = 1;
+
+enum PrioritizedElementType : uint8_t {
+ REQUEST_STREAM = 0x00,
+ PUSH_STREAM = 0x80,
+};
+
+struct QUIC_EXPORT_PRIVATE PriorityUpdateFrame {
+ PrioritizedElementType prioritized_element_type = REQUEST_STREAM;
+ uint64_t prioritized_element_id = 0;
+ std::string priority_field_value;
+
+ bool operator==(const PriorityUpdateFrame& rhs) const {
+ return std::tie(prioritized_element_type, prioritized_element_id,
+ priority_field_value) ==
+ std::tie(rhs.prioritized_element_type, rhs.prioritized_element_id,
+ rhs.priority_field_value);
+ }
+ std::string ToString() const {
+ return quiche::QuicheStrCat(
+ "Priority Frame : {prioritized_element_type: ",
+ static_cast<int>(prioritized_element_type),
+ ", prioritized_element_id: ", prioritized_element_id,
+ ", priority_field_value: ", priority_field_value, "}");
+ }
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const PriorityUpdateFrame& s) {
+ os << s.ToString();
+ return os;
}
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_header_list.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_header_list.cc
index cba3e587ab3..cbf60ceb252 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_header_list.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_header_list.cc
@@ -9,6 +9,7 @@
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
namespace quic {
@@ -35,7 +36,8 @@ void QuicHeaderList::OnHeaderBlockStart() {
<< "OnHeaderBlockStart called more than once!";
}
-void QuicHeaderList::OnHeader(QuicStringPiece name, QuicStringPiece value) {
+void QuicHeaderList::OnHeader(quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value) {
// Avoid infinite buffering of headers. No longer store headers
// once the current headers are over the limit.
if (current_header_list_size_ < max_header_list_size_) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_header_list.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_header_list.h
index cc6e7bc210d..0ed8ae8c4a9 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_header_list.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_header_list.h
@@ -10,10 +10,10 @@
#include <string>
#include <utility>
+#include "net/third_party/quiche/src/quic/core/quic_circular_deque.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "net/third_party/quiche/src/spdy/core/spdy_header_block.h"
#include "net/third_party/quiche/src/spdy/core/spdy_headers_handler_interface.h"
@@ -23,7 +23,7 @@ namespace quic {
class QUIC_EXPORT_PRIVATE QuicHeaderList
: public spdy::SpdyHeadersHandlerInterface {
public:
- using ListType = QuicDeque<std::pair<std::string, std::string>>;
+ using ListType = QuicCircularDeque<std::pair<std::string, std::string>>;
using value_type = ListType::value_type;
using const_iterator = ListType::const_iterator;
@@ -36,7 +36,8 @@ class QUIC_EXPORT_PRIVATE QuicHeaderList
// From SpdyHeadersHandlerInteface.
void OnHeaderBlockStart() override;
- void OnHeader(QuicStringPiece name, QuicStringPiece value) override;
+ void OnHeader(quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value) override;
void OnHeaderBlockEnd(size_t uncompressed_header_bytes,
size_t compressed_header_bytes) override;
@@ -51,16 +52,15 @@ class QUIC_EXPORT_PRIVATE QuicHeaderList
}
size_t compressed_header_bytes() const { return compressed_header_bytes_; }
+ // Deprecated. TODO(b/145909215): remove.
void set_max_header_list_size(size_t max_header_list_size) {
max_header_list_size_ = max_header_list_size;
}
- size_t max_header_list_size() const { return max_header_list_size_; }
-
std::string DebugString() const;
private:
- QuicDeque<std::pair<std::string, std::string>> header_list_;
+ QuicCircularDeque<std::pair<std::string, std::string>> header_list_;
// The limit on the size of the header list (defined by spec as name + value +
// overhead for each header field). Headers over this limit will not be
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream.cc
index 394d42a98ae..8157daec788 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream.cc
@@ -6,9 +6,9 @@
#include "net/third_party/quiche/src/quic/core/http/quic_spdy_session.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
namespace quic {
@@ -60,6 +60,7 @@ bool QuicHeadersStream::OnStreamFrameAcked(QuicStreamOffset offset,
QuicByteCount data_length,
bool fin_acked,
QuicTime::Delta ack_delay_time,
+ QuicTime receive_timestamp,
QuicByteCount* newly_acked_length) {
QuicIntervalSet<QuicStreamOffset> newly_acked(offset, offset + data_length);
newly_acked.Difference(bytes_acked());
@@ -85,8 +86,8 @@ bool QuicHeadersStream::OnStreamFrameAcked(QuicStreamOffset offset,
if (header.unacked_length < header_length) {
QUIC_BUG << "Unsent stream data is acked. unacked_length: "
<< header.unacked_length << " acked_length: " << header_length;
- CloseConnectionWithDetails(QUIC_INTERNAL_ERROR,
- "Unsent stream data is acked");
+ OnUnrecoverableError(QUIC_INTERNAL_ERROR,
+ "Unsent stream data is acked");
return false;
}
if (header.ack_listener != nullptr && header_length > 0) {
@@ -104,7 +105,8 @@ bool QuicHeadersStream::OnStreamFrameAcked(QuicStreamOffset offset,
unacked_headers_.pop_front();
}
return QuicStream::OnStreamFrameAcked(offset, data_length, fin_acked,
- ack_delay_time, newly_acked_length);
+ ack_delay_time, receive_timestamp,
+ newly_acked_length);
}
void QuicHeadersStream::OnStreamFrameRetransmitted(QuicStreamOffset offset,
@@ -153,4 +155,9 @@ void QuicHeadersStream::OnDataBuffered(
}
}
+void QuicHeadersStream::OnStreamReset(const QuicRstStreamFrame& /*frame*/) {
+ stream_delegate()->OnStreamError(QUIC_INVALID_STREAM_ID,
+ "Attempt to reset headers stream");
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream.h
index d07c85f17e8..3786ddf9c3a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream.h
@@ -43,12 +43,15 @@ class QUIC_EXPORT_PRIVATE QuicHeadersStream : public QuicStream {
QuicByteCount data_length,
bool fin_acked,
QuicTime::Delta ack_delay_time,
+ QuicTime receive_timestamp,
QuicByteCount* newly_acked_length) override;
void OnStreamFrameRetransmitted(QuicStreamOffset offset,
QuicByteCount data_length,
bool fin_retransmitted) override;
+ void OnStreamReset(const QuicRstStreamFrame& frame) override;
+
private:
friend class test::QuicHeadersStreamPeer;
@@ -88,7 +91,7 @@ class QUIC_EXPORT_PRIVATE QuicHeadersStream : public QuicStream {
QuicSpdySession* spdy_session_;
// Headers that have not been fully acked.
- QuicDeque<CompressedHeaderInfo> unacked_headers_;
+ QuicCircularDeque<CompressedHeaderInfo> unacked_headers_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream_test.cc
index 4cf11cc2976..9395a708225 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream_test.cc
@@ -18,14 +18,14 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.h"
#include "net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
@@ -128,7 +128,7 @@ class MockVisitor : public SpdyFramerVisitorInterface {
MOCK_METHOD2(OnContinuation, void(SpdyStreamId stream_id, bool end));
MOCK_METHOD3(OnAltSvc,
void(SpdyStreamId stream_id,
- QuicStringPiece origin,
+ quiche::QuicheStringPiece origin,
const SpdyAltSvcWireFormat::AlternativeServiceVector&
altsvc_vector));
MOCK_METHOD4(OnPriority,
@@ -163,7 +163,7 @@ struct TestParams {
// Used by ::testing::PrintToStringParamName().
std::string PrintToString(const TestParams& tp) {
- return QuicStrCat(
+ return quiche::QuicheStrCat(
ParsedQuicVersionToString(tp.version), "_",
(tp.perspective == Perspective::IS_CLIENT ? "client" : "server"));
}
@@ -244,7 +244,7 @@ class QuicHeadersStreamTest : public QuicTestWithParam<TestParams> {
return true;
}
- void SaveHeaderDataStringPiece(QuicStringPiece data) {
+ void SaveHeaderDataStringPiece(quiche::QuicheStringPiece data) {
saved_header_data_.append(data.data(), data.length());
}
@@ -286,11 +286,10 @@ class QuicHeadersStreamTest : public QuicTestWithParam<TestParams> {
SpdyPriority priority,
bool is_request) {
// Write the headers and capture the outgoing data
- EXPECT_CALL(session_, WritevData(headers_stream_,
- QuicUtils::GetHeadersStreamId(
+ EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId(
connection_->transport_version()),
- _, _, NO_FIN))
- .WillOnce(WithArgs<2>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
+ _, _, NO_FIN, _, _))
+ .WillOnce(WithArgs<1>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
QuicSpdySessionPeer::WriteHeadersOnHeadersStream(
&session_, stream_id, headers_.Clone(), fin,
spdy::SpdyStreamPrecedence(priority), nullptr);
@@ -404,18 +403,15 @@ TEST_P(QuicHeadersStreamTest, WriteHeaders) {
}
TEST_P(QuicHeadersStreamTest, WritePushPromises) {
- session_.SetMaxAllowedPushId(kMaxQuicStreamId);
-
for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_;
stream_id += next_stream_id_) {
QuicStreamId promised_stream_id = NextPromisedStreamId();
if (perspective() == Perspective::IS_SERVER) {
// Write the headers and capture the outgoing data
- EXPECT_CALL(session_, WritevData(headers_stream_,
- QuicUtils::GetHeadersStreamId(
+ EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId(
connection_->transport_version()),
- _, _, NO_FIN))
- .WillOnce(WithArgs<2>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
+ _, _, NO_FIN, _, _))
+ .WillOnce(WithArgs<1>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
session_.WritePushPromise(stream_id, promised_stream_id,
headers_.Clone());
@@ -646,7 +642,7 @@ TEST_P(QuicHeadersStreamTest, RespectHttp2SettingsFrameSupportedFields) {
stream_frame_.data_length = frame.size();
headers_stream_->OnStreamFrame(stream_frame_);
EXPECT_EQ(kTestHeaderTableSize, QuicSpdySessionPeer::GetSpdyFramer(&session_)
- .header_encoder_table_size());
+ ->header_encoder_table_size());
}
TEST_P(QuicHeadersStreamTest, RespectHttp2SettingsFrameUnsupportedFields) {
@@ -661,30 +657,34 @@ TEST_P(QuicHeadersStreamTest, RespectHttp2SettingsFrameUnsupportedFields) {
SpdySerializedFrame frame(framer_->SerializeFrame(data));
EXPECT_CALL(
*connection_,
- CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
- QuicStrCat("Unsupported field of HTTP/2 SETTINGS frame: ",
- SETTINGS_MAX_CONCURRENT_STREAMS),
- _));
+ CloseConnection(
+ QUIC_INVALID_HEADERS_STREAM_DATA,
+ quiche::QuicheStrCat("Unsupported field of HTTP/2 SETTINGS frame: ",
+ SETTINGS_MAX_CONCURRENT_STREAMS),
+ _));
EXPECT_CALL(
*connection_,
- CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
- QuicStrCat("Unsupported field of HTTP/2 SETTINGS frame: ",
- SETTINGS_INITIAL_WINDOW_SIZE),
- _));
+ CloseConnection(
+ QUIC_INVALID_HEADERS_STREAM_DATA,
+ quiche::QuicheStrCat("Unsupported field of HTTP/2 SETTINGS frame: ",
+ SETTINGS_INITIAL_WINDOW_SIZE),
+ _));
if (session_.perspective() == Perspective::IS_CLIENT) {
- EXPECT_CALL(*connection_,
- CloseConnection(
- QUIC_INVALID_HEADERS_STREAM_DATA,
- QuicStrCat("Unsupported field of HTTP/2 SETTINGS frame: ",
- SETTINGS_ENABLE_PUSH),
- _));
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(
+ QUIC_INVALID_HEADERS_STREAM_DATA,
+ quiche::QuicheStrCat("Unsupported field of HTTP/2 SETTINGS frame: ",
+ SETTINGS_ENABLE_PUSH),
+ _));
}
EXPECT_CALL(
*connection_,
- CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
- QuicStrCat("Unsupported field of HTTP/2 SETTINGS frame: ",
- SETTINGS_MAX_FRAME_SIZE),
- _));
+ CloseConnection(
+ QUIC_INVALID_HEADERS_STREAM_DATA,
+ quiche::QuicheStrCat("Unsupported field of HTTP/2 SETTINGS frame: ",
+ SETTINGS_MAX_FRAME_SIZE),
+ _));
stream_frame_.data_buffer = frame.data();
stream_frame_.data_length = frame.size();
headers_stream_->OnStreamFrame(stream_frame_);
@@ -823,11 +823,10 @@ TEST_P(QuicHeadersStreamTest, HpackEncoderDebugVisitor) {
}
TEST_P(QuicHeadersStreamTest, AckSentData) {
- EXPECT_CALL(session_, WritevData(headers_stream_,
- QuicUtils::GetHeadersStreamId(
+ EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId(
connection_->transport_version()),
- _, _, NO_FIN))
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+ _, _, NO_FIN, _, _))
+ .WillRepeatedly(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
InSequence s;
QuicReferenceCountedPointer<MockAckListener> ack_listener1(
new MockAckListener());
@@ -859,39 +858,44 @@ TEST_P(QuicHeadersStreamTest, AckSentData) {
EXPECT_CALL(*ack_listener3, OnPacketAcked(7, _));
EXPECT_CALL(*ack_listener2, OnPacketAcked(7, _));
EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
- 21, 7, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ 21, 7, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
+ &newly_acked_length));
EXPECT_EQ(7u, newly_acked_length);
EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
- 28, 7, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ 28, 7, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
+ &newly_acked_length));
EXPECT_EQ(7u, newly_acked_length);
EXPECT_CALL(*ack_listener3, OnPacketAcked(7, _));
EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
- 35, 7, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ 35, 7, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
+ &newly_acked_length));
EXPECT_EQ(7u, newly_acked_length);
EXPECT_CALL(*ack_listener1, OnPacketAcked(7, _));
EXPECT_CALL(*ack_listener1, OnPacketAcked(7, _));
EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
- 0, 7, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ 0, 7, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
+ &newly_acked_length));
EXPECT_EQ(7u, newly_acked_length);
EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
- 7, 7, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ 7, 7, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
+ &newly_acked_length));
EXPECT_EQ(7u, newly_acked_length);
// Unsent data is acked.
EXPECT_CALL(*ack_listener2, OnPacketAcked(7, _));
EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
- 14, 10, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ 14, 10, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
+ &newly_acked_length));
EXPECT_EQ(7u, newly_acked_length);
}
TEST_P(QuicHeadersStreamTest, FrameContainsMultipleHeaders) {
// In this test, a stream frame can contain multiple headers.
- EXPECT_CALL(session_, WritevData(headers_stream_,
- QuicUtils::GetHeadersStreamId(
+ EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId(
connection_->transport_version()),
- _, _, NO_FIN))
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+ _, _, NO_FIN, _, _))
+ .WillRepeatedly(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
InSequence s;
QuicReferenceCountedPointer<MockAckListener> ack_listener1(
new MockAckListener());
@@ -918,28 +922,30 @@ TEST_P(QuicHeadersStreamTest, FrameContainsMultipleHeaders) {
EXPECT_CALL(*ack_listener3, OnPacketAcked(7, _));
EXPECT_CALL(*ack_listener2, OnPacketAcked(2, _));
EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
- 17, 13, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ 17, 13, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
+ &newly_acked_length));
EXPECT_EQ(13u, newly_acked_length);
EXPECT_CALL(*ack_listener2, OnPacketAcked(5, _));
EXPECT_CALL(*ack_listener3, OnPacketAcked(7, _));
EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
- 30, 12, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ 30, 12, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
+ &newly_acked_length));
EXPECT_EQ(12u, newly_acked_length);
EXPECT_CALL(*ack_listener1, OnPacketAcked(14, _));
EXPECT_CALL(*ack_listener2, OnPacketAcked(3, _));
EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
- 0, 17, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ 0, 17, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
+ &newly_acked_length));
EXPECT_EQ(17u, newly_acked_length);
}
TEST_P(QuicHeadersStreamTest, HeadersGetAckedMultipleTimes) {
- EXPECT_CALL(session_, WritevData(headers_stream_,
- QuicUtils::GetHeadersStreamId(
+ EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId(
connection_->transport_version()),
- _, _, NO_FIN))
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+ _, _, NO_FIN, _, _))
+ .WillRepeatedly(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
InSequence s;
QuicReferenceCountedPointer<MockAckListener> ack_listener1(
new MockAckListener());
@@ -960,7 +966,8 @@ TEST_P(QuicHeadersStreamTest, HeadersGetAckedMultipleTimes) {
QuicByteCount newly_acked_length = 0;
EXPECT_CALL(*ack_listener2, OnPacketAcked(5, _));
EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
- 15, 5, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ 15, 5, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
+ &newly_acked_length));
EXPECT_EQ(5u, newly_acked_length);
EXPECT_CALL(*ack_listener1, OnPacketAcked(9, _));
@@ -968,24 +975,28 @@ TEST_P(QuicHeadersStreamTest, HeadersGetAckedMultipleTimes) {
EXPECT_CALL(*ack_listener2, OnPacketAcked(1, _));
EXPECT_CALL(*ack_listener3, OnPacketAcked(4, _));
EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
- 5, 20, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ 5, 20, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
+ &newly_acked_length));
EXPECT_EQ(15u, newly_acked_length);
// Duplicate ack.
EXPECT_FALSE(headers_stream_->OnStreamFrameAcked(
- 10, 7, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ 10, 7, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
+ &newly_acked_length));
EXPECT_EQ(0u, newly_acked_length);
EXPECT_CALL(*ack_listener1, OnPacketAcked(5, _));
EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
- 0, 12, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ 0, 12, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
+ &newly_acked_length));
EXPECT_EQ(5u, newly_acked_length);
EXPECT_CALL(*ack_listener3, OnPacketAcked(3, _));
EXPECT_CALL(*ack_listener2, OnPacketAcked(7, _));
EXPECT_CALL(*ack_listener3, OnPacketAcked(7, _));
EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
- 22, 20, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ 22, 20, false, QuicTime::Delta::Zero(), QuicTime::Zero(),
+ &newly_acked_length));
EXPECT_EQ(17u, newly_acked_length);
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.cc
index c949fa77c7f..17c6ecc55cc 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.cc
@@ -10,252 +10,289 @@
#include "net/third_party/quiche/src/quic/core/http/http_decoder.h"
#include "net/third_party/quiche/src/quic/core/http/quic_spdy_session.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
-// Visitor of HttpDecoder that passes data frame to QuicSpdyStream and closes
-// the connection on unexpected frames.
-class QuicReceiveControlStream::HttpDecoderVisitor
- : public HttpDecoder::Visitor {
- public:
- explicit HttpDecoderVisitor(QuicReceiveControlStream* stream)
- : stream_(stream) {}
- HttpDecoderVisitor(const HttpDecoderVisitor&) = delete;
- HttpDecoderVisitor& operator=(const HttpDecoderVisitor&) = delete;
-
- void OnError(HttpDecoder* /*decoder*/) override {
- stream_->session()->connection()->CloseConnection(
- QUIC_HTTP_DECODER_ERROR, "Http decoder internal error",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- }
+QuicReceiveControlStream::QuicReceiveControlStream(
+ PendingStream* pending,
+ QuicSpdySession* spdy_session)
+ : QuicStream(pending, READ_UNIDIRECTIONAL, /*is_static=*/true),
+ settings_frame_received_(false),
+ decoder_(this),
+ spdy_session_(spdy_session) {
+ sequencer()->set_level_triggered(true);
+}
- bool OnPriorityFrameStart(QuicByteCount header_length) override {
- if (stream_->session()->perspective() == Perspective::IS_CLIENT) {
- stream_->session()->connection()->CloseConnection(
- QUIC_HTTP_DECODER_ERROR, "Server must not send Priority frames.",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- return false;
- }
- return stream_->OnPriorityFrameStart(header_length);
- }
+QuicReceiveControlStream::~QuicReceiveControlStream() {}
- bool OnPriorityFrame(const PriorityFrame& frame) override {
- if (stream_->session()->perspective() == Perspective::IS_CLIENT) {
- stream_->session()->connection()->CloseConnection(
- QUIC_HTTP_DECODER_ERROR, "Server must not send Priority frames.",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- return false;
- }
- return stream_->OnPriorityFrame(frame);
- }
+void QuicReceiveControlStream::OnStreamReset(
+ const QuicRstStreamFrame& /*frame*/) {
+ stream_delegate()->OnStreamError(
+ QUIC_HTTP_CLOSED_CRITICAL_STREAM,
+ "RESET_STREAM received for receive control stream");
+}
- bool OnCancelPushFrame(const CancelPushFrame& /*frame*/) override {
- CloseConnectionOnWrongFrame("Cancel Push");
- return false;
- }
+void QuicReceiveControlStream::OnDataAvailable() {
+ iovec iov;
+ while (!reading_stopped() && decoder_.error() == QUIC_NO_ERROR &&
+ sequencer()->GetReadableRegion(&iov)) {
+ DCHECK(!sequencer()->IsClosed());
- bool OnMaxPushIdFrame(const MaxPushIdFrame& frame) override {
- if (stream_->session()->perspective() == Perspective::IS_SERVER) {
- QuicSpdySession* spdy_session =
- static_cast<QuicSpdySession*>(stream_->session());
- spdy_session->SetMaxAllowedPushId(frame.push_id);
- return true;
- }
- CloseConnectionOnWrongFrame("Max Push Id");
- return false;
- }
+ QuicByteCount processed_bytes = decoder_.ProcessInput(
+ reinterpret_cast<const char*>(iov.iov_base), iov.iov_len);
+ sequencer()->MarkConsumed(processed_bytes);
- bool OnGoAwayFrame(const GoAwayFrame& frame) override {
- QuicSpdySession* spdy_session =
- static_cast<QuicSpdySession*>(stream_->session());
- if (spdy_session->perspective() == Perspective::IS_SERVER) {
- CloseConnectionOnWrongFrame("Go Away");
- return false;
+ if (!session()->connection()->connected()) {
+ return;
}
- spdy_session->OnHttp3GoAway(frame.stream_id);
- return true;
- }
- bool OnSettingsFrameStart(QuicByteCount header_length) override {
- return stream_->OnSettingsFrameStart(header_length);
+ // The only reason QuicReceiveControlStream pauses HttpDecoder is an error,
+ // in which case the connection would have already been closed.
+ DCHECK_EQ(iov.iov_len, processed_bytes);
}
+}
- bool OnSettingsFrame(const SettingsFrame& frame) override {
- return stream_->OnSettingsFrame(frame);
- }
+void QuicReceiveControlStream::OnError(HttpDecoder* decoder) {
+ OnUnrecoverableError(decoder->error(), decoder->error_detail());
+}
- bool OnDuplicatePushFrame(const DuplicatePushFrame& /*frame*/) override {
- CloseConnectionOnWrongFrame("Duplicate Push");
- return false;
+bool QuicReceiveControlStream::OnCancelPushFrame(const CancelPushFrame& frame) {
+ if (spdy_session()->debug_visitor()) {
+ spdy_session()->debug_visitor()->OnCancelPushFrameReceived(frame);
}
- bool OnDataFrameStart(QuicByteCount /*header_length*/) override {
- CloseConnectionOnWrongFrame("Data");
+ if (!settings_frame_received_) {
+ stream_delegate()->OnStreamError(
+ QUIC_HTTP_MISSING_SETTINGS_FRAME,
+ "CANCEL_PUSH frame received before SETTINGS.");
return false;
}
- bool OnDataFramePayload(QuicStringPiece /*payload*/) override {
- CloseConnectionOnWrongFrame("Data");
- return false;
- }
+ // TODO(b/151841240): Handle CANCEL_PUSH frames instead of ignoring them.
+ return true;
+}
- bool OnDataFrameEnd() override {
- CloseConnectionOnWrongFrame("Data");
- return false;
+bool QuicReceiveControlStream::OnMaxPushIdFrame(const MaxPushIdFrame& frame) {
+ if (spdy_session()->debug_visitor()) {
+ spdy_session()->debug_visitor()->OnMaxPushIdFrameReceived(frame);
}
- bool OnHeadersFrameStart(QuicByteCount /*header_length*/) override {
- CloseConnectionOnWrongFrame("Headers");
+ if (!settings_frame_received_) {
+ stream_delegate()->OnStreamError(
+ QUIC_HTTP_MISSING_SETTINGS_FRAME,
+ "MAX_PUSH_ID frame received before SETTINGS.");
return false;
}
- bool OnHeadersFramePayload(QuicStringPiece /*payload*/) override {
- CloseConnectionOnWrongFrame("Headers");
+ if (spdy_session()->perspective() == Perspective::IS_CLIENT) {
+ OnWrongFrame("Max Push Id");
return false;
}
- bool OnHeadersFrameEnd() override {
- CloseConnectionOnWrongFrame("Headers");
- return false;
- }
+ // TODO(b/124216424): Signal error if received push ID is smaller than a
+ // previously received value.
+ spdy_session()->OnMaxPushIdFrame(frame.push_id);
+ return true;
+}
- bool OnPushPromiseFrameStart(QuicByteCount /*header_length*/) override {
- CloseConnectionOnWrongFrame("Push Promise");
- return false;
+bool QuicReceiveControlStream::OnGoAwayFrame(const GoAwayFrame& frame) {
+ if (spdy_session()->debug_visitor()) {
+ spdy_session()->debug_visitor()->OnGoAwayFrameReceived(frame);
}
- bool OnPushPromiseFramePushId(PushId /*push_id*/,
- QuicByteCount /*push_id_length*/) override {
- CloseConnectionOnWrongFrame("Push Promise");
+ if (!settings_frame_received_) {
+ stream_delegate()->OnStreamError(QUIC_HTTP_MISSING_SETTINGS_FRAME,
+ "GOAWAY frame received before SETTINGS.");
return false;
}
- bool OnPushPromiseFramePayload(QuicStringPiece /*payload*/) override {
- CloseConnectionOnWrongFrame("Push Promise");
+ if (spdy_session()->perspective() == Perspective::IS_SERVER) {
+ OnWrongFrame("Go Away");
return false;
}
- bool OnPushPromiseFrameEnd() override {
- CloseConnectionOnWrongFrame("Push Promise");
+ spdy_session()->OnHttp3GoAway(frame.stream_id);
+ return true;
+}
+
+bool QuicReceiveControlStream::OnSettingsFrameStart(
+ QuicByteCount /*header_length*/) {
+ if (settings_frame_received_) {
+ stream_delegate()->OnStreamError(
+ QUIC_HTTP_INVALID_FRAME_SEQUENCE_ON_CONTROL_STREAM,
+ "Settings frames are received twice.");
return false;
}
- bool OnUnknownFrameStart(uint64_t /* frame_type */,
- QuicByteCount /* header_length */) override {
- // Ignore unknown frame types.
- return true;
- }
+ settings_frame_received_ = true;
- bool OnUnknownFramePayload(QuicStringPiece /* payload */) override {
- // Ignore unknown frame types.
- return true;
- }
+ return true;
+}
- bool OnUnknownFrameEnd() override {
- // Ignore unknown frame types.
- return true;
+bool QuicReceiveControlStream::OnSettingsFrame(const SettingsFrame& frame) {
+ QUIC_DVLOG(1) << "Control Stream " << id()
+ << " received settings frame: " << frame;
+ if (spdy_session_->debug_visitor() != nullptr) {
+ spdy_session_->debug_visitor()->OnSettingsFrameReceived(frame);
}
-
- private:
- void CloseConnectionOnWrongFrame(QuicStringPiece frame_type) {
- // TODO(renjietang): Change to HTTP/3 error type.
- stream_->session()->connection()->CloseConnection(
- QUIC_HTTP_DECODER_ERROR,
- QuicStrCat(frame_type, " frame received on control stream"),
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ for (const auto& setting : frame.values) {
+ spdy_session_->OnSetting(setting.first, setting.second);
}
+ return true;
+}
- QuicReceiveControlStream* stream_;
-};
+bool QuicReceiveControlStream::OnDataFrameStart(QuicByteCount /*header_length*/,
+ QuicByteCount
+ /*payload_length*/) {
+ OnWrongFrame("Data");
+ return false;
+}
-QuicReceiveControlStream::QuicReceiveControlStream(PendingStream* pending)
- : QuicStream(pending, READ_UNIDIRECTIONAL, /*is_static=*/true),
- settings_frame_received_(false),
- http_decoder_visitor_(std::make_unique<HttpDecoderVisitor>(this)),
- decoder_(http_decoder_visitor_.get()) {
- sequencer()->set_level_triggered(true);
+bool QuicReceiveControlStream::OnDataFramePayload(
+ quiche::QuicheStringPiece /*payload*/) {
+ OnWrongFrame("Data");
+ return false;
}
-QuicReceiveControlStream::~QuicReceiveControlStream() {}
+bool QuicReceiveControlStream::OnDataFrameEnd() {
+ OnWrongFrame("Data");
+ return false;
+}
-void QuicReceiveControlStream::OnStreamReset(
- const QuicRstStreamFrame& /*frame*/) {
- // TODO(renjietang) Change the error code to H/3 specific
- // HTTP_CLOSED_CRITICAL_STREAM.
- session()->connection()->CloseConnection(
- QUIC_INVALID_STREAM_ID, "Attempt to reset receive control stream",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+bool QuicReceiveControlStream::OnHeadersFrameStart(
+ QuicByteCount /*header_length*/,
+ QuicByteCount
+ /*payload_length*/) {
+ OnWrongFrame("Headers");
+ return false;
}
-void QuicReceiveControlStream::OnDataAvailable() {
- iovec iov;
- while (!reading_stopped() && decoder_.error() == QUIC_NO_ERROR &&
- sequencer()->GetReadableRegion(&iov)) {
- DCHECK(!sequencer()->IsClosed());
+bool QuicReceiveControlStream::OnHeadersFramePayload(
+ quiche::QuicheStringPiece /*payload*/) {
+ OnWrongFrame("Headers");
+ return false;
+}
- QuicByteCount processed_bytes = decoder_.ProcessInput(
- reinterpret_cast<const char*>(iov.iov_base), iov.iov_len);
- sequencer()->MarkConsumed(processed_bytes);
+bool QuicReceiveControlStream::OnHeadersFrameEnd() {
+ OnWrongFrame("Headers");
+ return false;
+}
- if (!session()->connection()->connected()) {
- return;
- }
+bool QuicReceiveControlStream::OnPushPromiseFrameStart(
+ QuicByteCount /*header_length*/) {
+ OnWrongFrame("Push Promise");
+ return false;
+}
- // The only reason QuicReceiveControlStream pauses HttpDecoder is an error,
- // in which case the connection would have already been closed.
- DCHECK_EQ(iov.iov_len, processed_bytes);
- }
+bool QuicReceiveControlStream::OnPushPromiseFramePushId(
+ PushId /*push_id*/,
+ QuicByteCount /*push_id_length*/,
+ QuicByteCount /*header_block_length*/) {
+ OnWrongFrame("Push Promise");
+ return false;
}
-bool QuicReceiveControlStream::OnSettingsFrameStart(
- QuicByteCount /* header_length */) {
- if (settings_frame_received_) {
- // TODO(renjietang): Change error code to HTTP_UNEXPECTED_FRAME.
- session()->connection()->CloseConnection(
- QUIC_INVALID_STREAM_ID, "Settings frames are received twice.",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+bool QuicReceiveControlStream::OnPushPromiseFramePayload(
+ quiche::QuicheStringPiece /*payload*/) {
+ OnWrongFrame("Push Promise");
+ return false;
+}
+
+bool QuicReceiveControlStream::OnPushPromiseFrameEnd() {
+ OnWrongFrame("Push Promise");
+ return false;
+}
+
+bool QuicReceiveControlStream::OnPriorityUpdateFrameStart(
+ QuicByteCount /*header_length*/) {
+ if (!settings_frame_received_) {
+ stream_delegate()->OnStreamError(
+ QUIC_HTTP_MISSING_SETTINGS_FRAME,
+ "PRIORITY_UPDATE frame received before SETTINGS.");
return false;
}
+ return true;
+}
- settings_frame_received_ = true;
+bool QuicReceiveControlStream::OnPriorityUpdateFrame(
+ const PriorityUpdateFrame& frame) {
+ if (spdy_session()->debug_visitor()) {
+ spdy_session()->debug_visitor()->OnPriorityUpdateFrameReceived(frame);
+ }
+
+ // TODO(b/147306124): Use a proper structured headers parser instead.
+ for (auto key_value :
+ quiche::QuicheTextUtils::Split(frame.priority_field_value, ',')) {
+ auto key_and_value = quiche::QuicheTextUtils::Split(key_value, '=');
+ if (key_and_value.size() != 2) {
+ continue;
+ }
+
+ quiche::QuicheStringPiece key = key_and_value[0];
+ quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&key);
+ if (key != "u") {
+ continue;
+ }
+ quiche::QuicheStringPiece value = key_and_value[1];
+ int urgency;
+ if (!quiche::QuicheTextUtils::StringToInt(value, &urgency) || urgency < 0 ||
+ urgency > 7) {
+ stream_delegate()->OnStreamError(
+ QUIC_INVALID_STREAM_ID,
+ "Invalid value for PRIORITY_UPDATE urgency parameter.");
+ return false;
+ }
+
+ if (frame.prioritized_element_type == REQUEST_STREAM) {
+ return spdy_session_->OnPriorityUpdateForRequestStream(
+ frame.prioritized_element_id, urgency);
+ } else {
+ return spdy_session_->OnPriorityUpdateForPushStream(
+ frame.prioritized_element_id, urgency);
+ }
+ }
+
+ // Ignore frame if no urgency parameter can be parsed.
return true;
}
-bool QuicReceiveControlStream::OnSettingsFrame(const SettingsFrame& settings) {
- QUIC_DVLOG(1) << "Control Stream " << id()
- << " received settings frame: " << settings;
- QuicSpdySession* spdy_session = static_cast<QuicSpdySession*>(session());
- if (spdy_session->debug_visitor() != nullptr) {
- spdy_session->debug_visitor()->OnSettingsFrameReceived(settings);
+bool QuicReceiveControlStream::OnUnknownFrameStart(
+ uint64_t frame_type,
+ QuicByteCount /*header_length*/,
+ QuicByteCount payload_length) {
+ if (spdy_session()->debug_visitor()) {
+ spdy_session()->debug_visitor()->OnUnknownFrameReceived(id(), frame_type,
+ payload_length);
}
- for (const auto& setting : settings.values) {
- spdy_session->OnSetting(setting.first, setting.second);
+
+ if (!settings_frame_received_) {
+ stream_delegate()->OnStreamError(QUIC_HTTP_MISSING_SETTINGS_FRAME,
+ "Unknown frame received before SETTINGS.");
+ return false;
}
+
return true;
}
-bool QuicReceiveControlStream::OnPriorityFrameStart(
- QuicByteCount /* header_length */) {
- DCHECK_EQ(Perspective::IS_SERVER, session()->perspective());
+bool QuicReceiveControlStream::OnUnknownFramePayload(
+ quiche::QuicheStringPiece /*payload*/) {
+ // Ignore unknown frame types.
return true;
}
-bool QuicReceiveControlStream::OnPriorityFrame(const PriorityFrame& priority) {
- DCHECK_EQ(Perspective::IS_SERVER, session()->perspective());
- if (!GetQuicFlag(FLAGS_quic_allow_http3_priority)) {
- return true;
- }
- QuicStream* stream =
- session()->GetOrCreateStream(priority.prioritized_element_id);
- // It's possible that the client sends a Priority frame for a request stream
- // that the server is not permitted to open. In that case, simply drop the
- // frame.
- if (stream) {
- stream->SetPriority(spdy::SpdyStreamPrecedence(priority.weight));
- }
+bool QuicReceiveControlStream::OnUnknownFrameEnd() {
+ // Ignore unknown frame types.
return true;
}
+void QuicReceiveControlStream::OnWrongFrame(
+ quiche::QuicheStringPiece frame_type) {
+ OnUnrecoverableError(
+ QUIC_HTTP_FRAME_UNEXPECTED_ON_CONTROL_STREAM,
+ quiche::QuicheStrCat(frame_type, " frame received on control stream"));
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.h
index 84217ce8fd2..7fd02b495f6 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.h
@@ -16,9 +16,12 @@ class QuicSpdySession;
// 3.2.1 Control Stream.
// The receive control stream is peer initiated and is read only.
-class QUIC_EXPORT_PRIVATE QuicReceiveControlStream : public QuicStream {
+class QUIC_EXPORT_PRIVATE QuicReceiveControlStream
+ : public QuicStream,
+ public HttpDecoder::Visitor {
public:
- explicit QuicReceiveControlStream(PendingStream* pending);
+ explicit QuicReceiveControlStream(PendingStream* pending,
+ QuicSpdySession* spdy_session);
QuicReceiveControlStream(const QuicReceiveControlStream&) = delete;
QuicReceiveControlStream& operator=(const QuicReceiveControlStream&) = delete;
~QuicReceiveControlStream() override;
@@ -30,24 +33,47 @@ class QUIC_EXPORT_PRIVATE QuicReceiveControlStream : public QuicStream {
// Implementation of QuicStream.
void OnDataAvailable() override;
+ // HttpDecoderVisitor implementation.
+ void OnError(HttpDecoder* decoder) override;
+ bool OnCancelPushFrame(const CancelPushFrame& frame) override;
+ bool OnMaxPushIdFrame(const MaxPushIdFrame& frame) override;
+ bool OnGoAwayFrame(const GoAwayFrame& frame) override;
+ bool OnSettingsFrameStart(QuicByteCount header_length) override;
+ bool OnSettingsFrame(const SettingsFrame& frame) override;
+ bool OnDataFrameStart(QuicByteCount header_length,
+ QuicByteCount payload_length) override;
+ bool OnDataFramePayload(quiche::QuicheStringPiece payload) override;
+ bool OnDataFrameEnd() override;
+ bool OnHeadersFrameStart(QuicByteCount header_length,
+ QuicByteCount payload_length) override;
+ bool OnHeadersFramePayload(quiche::QuicheStringPiece payload) override;
+ bool OnHeadersFrameEnd() override;
+ bool OnPushPromiseFrameStart(QuicByteCount header_length) override;
+ bool OnPushPromiseFramePushId(PushId push_id,
+ QuicByteCount push_id_length,
+ QuicByteCount header_block_length) override;
+ bool OnPushPromiseFramePayload(quiche::QuicheStringPiece payload) override;
+ bool OnPushPromiseFrameEnd() override;
+ bool OnPriorityUpdateFrameStart(QuicByteCount header_length) override;
+ bool OnPriorityUpdateFrame(const PriorityUpdateFrame& frame) override;
+ bool OnUnknownFrameStart(uint64_t frame_type,
+ QuicByteCount header_length,
+ QuicByteCount payload_length) override;
+ bool OnUnknownFramePayload(quiche::QuicheStringPiece payload) override;
+ bool OnUnknownFrameEnd() override;
+
void SetUnblocked() { sequencer()->SetUnblocked(); }
- private:
- class HttpDecoderVisitor;
+ QuicSpdySession* spdy_session() { return spdy_session_; }
- // Called from HttpDecoderVisitor.
- bool OnSettingsFrameStart(QuicByteCount header_length);
- bool OnSettingsFrame(const SettingsFrame& settings);
- bool OnPriorityFrameStart(QuicByteCount header_length);
- // TODO(renjietang): Decode Priority in HTTP/3 style.
- bool OnPriorityFrame(const PriorityFrame& priority);
+ private:
+ void OnWrongFrame(quiche::QuicheStringPiece frame_type);
// False until a SETTINGS frame is received.
bool settings_frame_received_;
- // HttpDecoder and its visitor.
- std::unique_ptr<HttpDecoderVisitor> http_decoder_visitor_;
HttpDecoder decoder_;
+ QuicSpdySession* const spdy_session_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream_test.cc
index 8418766a97a..b7517b50ec0 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream_test.cc
@@ -5,15 +5,21 @@
#include "net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.h"
#include "net/third_party/quiche/src/quic/core/http/http_constants.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_header_table.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
+
+class QpackEncoder;
+
namespace test {
namespace {
@@ -43,7 +49,7 @@ struct TestParams {
// Used by ::testing::PrintToStringParamName().
std::string PrintToString(const TestParams& tp) {
- return QuicStrCat(
+ return quiche::QuicheStrCat(
ParsedQuicVersionToString(tp.version), "_",
(tp.perspective == Perspective::IS_CLIENT ? "client" : "server"));
}
@@ -88,7 +94,7 @@ class QuicReceiveControlStreamTest : public QuicTestWithParam<TestParams> {
session_.transport_version(), 3);
char type[] = {kControlStream};
- QuicStreamFrame data1(id, false, 0, QuicStringPiece(type, 1));
+ QuicStreamFrame data1(id, false, 0, quiche::QuicheStringPiece(type, 1));
session_.OnStreamFrame(data1);
receive_control_stream_ =
@@ -109,10 +115,12 @@ class QuicReceiveControlStreamTest : public QuicTestWithParam<TestParams> {
return std::string(buffer.get(), settings_frame_length);
}
- std::string PriorityFrame(const PriorityFrame& frame) {
+ std::string SerializePriorityUpdateFrame(
+ const PriorityUpdateFrame& priority_update) {
std::unique_ptr<char[]> priority_buffer;
QuicByteCount priority_frame_length =
- HttpEncoder::SerializePriorityFrame(frame, &priority_buffer);
+ HttpEncoder::SerializePriorityUpdateFrame(priority_update,
+ &priority_buffer);
return std::string(priority_buffer.get(), priority_frame_length);
}
@@ -139,7 +147,8 @@ TEST_P(QuicReceiveControlStreamTest, ResetControlStream) {
QuicRstStreamFrame rst_frame(kInvalidControlFrameId,
receive_control_stream_->id(),
QUIC_STREAM_CANCELLED, 1234);
- EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID, _, _));
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_HTTP_CLOSED_CRITICAL_STREAM, _, _));
receive_control_stream_->OnStreamReset(rst_frame);
}
@@ -147,11 +156,24 @@ TEST_P(QuicReceiveControlStreamTest, ReceiveSettings) {
SettingsFrame settings;
settings.values[3] = 2;
settings.values[SETTINGS_MAX_HEADER_LIST_SIZE] = 5;
+ settings.values[SETTINGS_QPACK_BLOCKED_STREAMS] = 12;
+ settings.values[SETTINGS_QPACK_MAX_TABLE_CAPACITY] = 37;
std::string data = EncodeSettings(settings);
QuicStreamFrame frame(receive_control_stream_->id(), false, 1, data);
- EXPECT_NE(5u, session_.max_outbound_header_list_size());
+
+ QpackEncoder* qpack_encoder = session_.qpack_encoder();
+ QpackHeaderTable* header_table =
+ QpackEncoderPeer::header_table(qpack_encoder);
+ EXPECT_EQ(std::numeric_limits<size_t>::max(),
+ session_.max_outbound_header_list_size());
+ EXPECT_EQ(0u, QpackEncoderPeer::maximum_blocked_streams(qpack_encoder));
+ EXPECT_EQ(0u, header_table->maximum_dynamic_table_capacity());
+
receive_control_stream_->OnStreamFrame(frame);
+
EXPECT_EQ(5u, session_.max_outbound_header_list_size());
+ EXPECT_EQ(12u, QpackEncoderPeer::maximum_blocked_streams(qpack_encoder));
+ EXPECT_EQ(37u, header_table->maximum_dynamic_table_capacity());
}
// Regression test for https://crbug.com/982648.
@@ -165,34 +187,36 @@ TEST_P(QuicReceiveControlStreamTest, ReceiveSettingsTwice) {
std::string settings_frame = EncodeSettings(settings);
- EXPECT_EQ(1u, NumBytesConsumed());
+ QuicStreamOffset offset = 1;
+ EXPECT_EQ(offset, NumBytesConsumed());
// Receive first SETTINGS frame.
receive_control_stream_->OnStreamFrame(
- QuicStreamFrame(receive_control_stream_->id(), /* fin = */ false,
- /* offset = */ 1, settings_frame));
+ QuicStreamFrame(receive_control_stream_->id(), /* fin = */ false, offset,
+ settings_frame));
+ offset += settings_frame.length();
// First SETTINGS frame is consumed.
- EXPECT_EQ(settings_frame.size() + 1, NumBytesConsumed());
+ EXPECT_EQ(offset, NumBytesConsumed());
// Second SETTINGS frame causes the connection to be closed.
- EXPECT_CALL(*connection_,
- CloseConnection(QUIC_INVALID_STREAM_ID,
- "Settings frames are received twice.", _))
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_HTTP_INVALID_FRAME_SEQUENCE_ON_CONTROL_STREAM,
+ "Settings frames are received twice.", _))
.WillOnce(
Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _));
EXPECT_CALL(session_, OnConnectionClosed(_, _));
// Receive second SETTINGS frame.
- receive_control_stream_->OnStreamFrame(QuicStreamFrame(
- receive_control_stream_->id(), /* fin = */ false,
- /* offset = */ settings_frame.size() + 1, settings_frame));
+ receive_control_stream_->OnStreamFrame(
+ QuicStreamFrame(receive_control_stream_->id(), /* fin = */ false, offset,
+ settings_frame));
// Frame header of second SETTINGS frame is consumed, but not frame payload.
QuicByteCount settings_frame_header_length = 2;
- EXPECT_EQ(settings_frame.size() + settings_frame_header_length + 1,
- NumBytesConsumed());
+ EXPECT_EQ(offset + settings_frame_header_length, NumBytesConsumed());
}
TEST_P(QuicReceiveControlStreamTest, ReceiveSettingsFragments) {
@@ -212,51 +236,68 @@ TEST_P(QuicReceiveControlStreamTest, ReceiveSettingsFragments) {
}
TEST_P(QuicReceiveControlStreamTest, ReceiveWrongFrame) {
- DuplicatePushFrame dup;
- dup.push_id = 0x1;
+ // DATA frame header without payload.
std::unique_ptr<char[]> buffer;
QuicByteCount header_length =
- HttpEncoder::SerializeDuplicatePushFrame(dup, &buffer);
+ HttpEncoder::SerializeDataFrameHeader(/* payload_length = */ 2, &buffer);
std::string data = std::string(buffer.get(), header_length);
QuicStreamFrame frame(receive_control_stream_->id(), false, 1, data);
- EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_DECODER_ERROR, _, _));
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_HTTP_FRAME_UNEXPECTED_ON_CONTROL_STREAM, _, _));
receive_control_stream_->OnStreamFrame(frame);
}
-TEST_P(QuicReceiveControlStreamTest, ReceivePriorityFrame) {
- if (perspective() == Perspective::IS_CLIENT) {
- return;
- }
- SetQuicFlag(FLAGS_quic_allow_http3_priority, true);
- struct PriorityFrame frame;
- frame.prioritized_type = REQUEST_STREAM;
- frame.dependency_type = ROOT_OF_TREE;
- frame.prioritized_element_id = stream_->id();
- frame.weight = 1;
- std::string serialized_frame = PriorityFrame(frame);
- QuicStreamFrame data(receive_control_stream_->id(), false, 1,
- serialized_frame);
-
- EXPECT_EQ(3u, stream_->precedence().spdy3_priority());
+TEST_P(QuicReceiveControlStreamTest,
+ ReceivePriorityUpdateFrameBeforeSettingsFrame) {
+ std::string serialized_frame = SerializePriorityUpdateFrame({});
+ QuicStreamFrame data(receive_control_stream_->id(), /* fin = */ false,
+ /* offset = */ 1, serialized_frame);
+
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_HTTP_MISSING_SETTINGS_FRAME,
+ "PRIORITY_UPDATE frame received before SETTINGS.", _))
+ .WillOnce(
+ Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
+ EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _));
+ EXPECT_CALL(session_, OnConnectionClosed(_, _));
+
receive_control_stream_->OnStreamFrame(data);
- EXPECT_EQ(1u, stream_->precedence().spdy3_priority());
}
TEST_P(QuicReceiveControlStreamTest, ReceiveGoAwayFrame) {
- GoAwayFrame goaway;
- goaway.stream_id = 0x00;
+ StrictMock<MockHttp3DebugVisitor> debug_visitor;
+ session_.set_debug_visitor(&debug_visitor);
+
+ QuicStreamOffset offset = 1;
+
+ // Receive SETTINGS frame.
+ SettingsFrame settings;
+ std::string settings_frame = EncodeSettings(settings);
+ EXPECT_CALL(debug_visitor, OnSettingsFrameReceived(settings));
+ receive_control_stream_->OnStreamFrame(
+ QuicStreamFrame(receive_control_stream_->id(), /* fin = */ false, offset,
+ settings_frame));
+ offset += settings_frame.length();
+
+ GoAwayFrame goaway{/* stream_id = */ 0};
std::unique_ptr<char[]> buffer;
QuicByteCount header_length =
HttpEncoder::SerializeGoAwayFrame(goaway, &buffer);
std::string data = std::string(buffer.get(), header_length);
- QuicStreamFrame frame(receive_control_stream_->id(), false, 1, data);
+ QuicStreamFrame frame(receive_control_stream_->id(), false, offset, data);
EXPECT_FALSE(session_.http3_goaway_received());
+ EXPECT_CALL(debug_visitor, OnGoAwayFrameReceived(goaway));
+
if (perspective() == Perspective::IS_SERVER) {
- EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_DECODER_ERROR, _, _));
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_HTTP_FRAME_UNEXPECTED_ON_CONTROL_STREAM, _, _));
}
receive_control_stream_->OnStreamFrame(frame);
@@ -274,8 +315,9 @@ TEST_P(QuicReceiveControlStreamTest, PushPromiseOnControlStreamShouldClose) {
push_promise, &buffer);
QuicStreamFrame frame(receive_control_stream_->id(), false, 1, buffer.get(),
length);
- // TODO(lassey) Check for HTTP_WRONG_STREAM error code.
- EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_DECODER_ERROR, _, _))
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_HTTP_FRAME_UNEXPECTED_ON_CONTROL_STREAM, _, _))
.WillOnce(
Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _));
@@ -285,18 +327,97 @@ TEST_P(QuicReceiveControlStreamTest, PushPromiseOnControlStreamShouldClose) {
// Regression test for b/137554973: unknown frames should be consumed.
TEST_P(QuicReceiveControlStreamTest, ConsumeUnknownFrame) {
- std::string unknown_frame = QuicTextUtils::HexDecode(
+ EXPECT_EQ(1u, NumBytesConsumed());
+
+ QuicStreamOffset offset = 1;
+
+ // Receive SETTINGS frame.
+ std::string settings_frame = EncodeSettings({});
+ receive_control_stream_->OnStreamFrame(
+ QuicStreamFrame(receive_control_stream_->id(), /* fin = */ false, offset,
+ settings_frame));
+ offset += settings_frame.length();
+
+ // SETTINGS frame is consumed.
+ EXPECT_EQ(offset, NumBytesConsumed());
+
+ // Receive unknown frame.
+ std::string unknown_frame = quiche::QuicheTextUtils::HexDecode(
"21" // reserved frame type
"03" // payload length
"666f6f"); // payload "foo"
- EXPECT_EQ(1u, NumBytesConsumed());
+ receive_control_stream_->OnStreamFrame(QuicStreamFrame(
+ receive_control_stream_->id(), /* fin = */ false, offset, unknown_frame));
+ offset += unknown_frame.size();
+
+ // Unknown frame is consumed.
+ EXPECT_EQ(offset, NumBytesConsumed());
+}
+
+TEST_P(QuicReceiveControlStreamTest, ReceiveUnknownFrame) {
+ StrictMock<MockHttp3DebugVisitor> debug_visitor;
+ session_.set_debug_visitor(&debug_visitor);
+
+ const QuicStreamId id = receive_control_stream_->id();
+ QuicStreamOffset offset = 1;
+
+ // Receive SETTINGS frame.
+ SettingsFrame settings;
+ std::string settings_frame = EncodeSettings(settings);
+ EXPECT_CALL(debug_visitor, OnSettingsFrameReceived(settings));
+ receive_control_stream_->OnStreamFrame(
+ QuicStreamFrame(id, /* fin = */ false, offset, settings_frame));
+ offset += settings_frame.length();
+
+ // Receive unknown frame.
+ std::string unknown_frame = quiche::QuicheTextUtils::HexDecode(
+ "21" // reserved frame type
+ "03" // payload length
+ "666f6f"); // payload "foo"
+
+ EXPECT_CALL(debug_visitor, OnUnknownFrameReceived(id, /* frame_type = */ 0x21,
+ /* payload_length = */ 3));
+ receive_control_stream_->OnStreamFrame(
+ QuicStreamFrame(id, /* fin = */ false, offset, unknown_frame));
+}
+
+TEST_P(QuicReceiveControlStreamTest, CancelPushFrameBeforeSettings) {
+ std::string cancel_push_frame = quiche::QuicheTextUtils::HexDecode(
+ "03" // type CANCEL_PUSH
+ "01" // payload length
+ "01"); // push ID
+
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_HTTP_MISSING_SETTINGS_FRAME,
+ "CANCEL_PUSH frame received before SETTINGS.", _))
+ .WillOnce(
+ Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
+ EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _));
+ EXPECT_CALL(session_, OnConnectionClosed(_, _));
receive_control_stream_->OnStreamFrame(
QuicStreamFrame(receive_control_stream_->id(), /* fin = */ false,
- /* offset = */ 1, unknown_frame));
+ /* offset = */ 1, cancel_push_frame));
+}
+
+TEST_P(QuicReceiveControlStreamTest, UnknownFrameBeforeSettings) {
+ std::string unknown_frame = quiche::QuicheTextUtils::HexDecode(
+ "21" // reserved frame type
+ "03" // payload length
+ "666f6f"); // payload "foo"
- EXPECT_EQ(unknown_frame.size() + 1, NumBytesConsumed());
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_HTTP_MISSING_SETTINGS_FRAME,
+ "Unknown frame received before SETTINGS.", _))
+ .WillOnce(
+ Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
+ EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _));
+ EXPECT_CALL(session_, OnConnectionClosed(_, _));
+
+ receive_control_stream_->OnStreamFrame(
+ QuicStreamFrame(receive_control_stream_->id(), /* fin = */ false,
+ /* offset = */ 1, unknown_frame));
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream.cc
index ed7cd7ffb40..64c306a4431 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream.cc
@@ -3,37 +3,44 @@
// found in the LICENSE file.
#include "net/third_party/quiche/src/quic/core/http/quic_send_control_stream.h"
+#include <cstdint>
#include <memory>
+#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
#include "net/third_party/quiche/src/quic/core/http/http_constants.h"
#include "net/third_party/quiche/src/quic/core/http/quic_spdy_session.h"
#include "net/third_party/quiche/src/quic/core/quic_session.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
QuicSendControlStream::QuicSendControlStream(
QuicStreamId id,
- QuicSession* session,
+ QuicSpdySession* spdy_session,
uint64_t qpack_maximum_dynamic_table_capacity,
uint64_t qpack_maximum_blocked_streams,
uint64_t max_inbound_header_list_size)
- : QuicStream(id, session, /*is_static = */ true, WRITE_UNIDIRECTIONAL),
+ : QuicStream(id, spdy_session, /*is_static = */ true, WRITE_UNIDIRECTIONAL),
settings_sent_(false),
qpack_maximum_dynamic_table_capacity_(
qpack_maximum_dynamic_table_capacity),
qpack_maximum_blocked_streams_(qpack_maximum_blocked_streams),
- max_inbound_header_list_size_(max_inbound_header_list_size) {}
+ max_inbound_header_list_size_(max_inbound_header_list_size),
+ spdy_session_(spdy_session) {}
void QuicSendControlStream::OnStreamReset(const QuicRstStreamFrame& /*frame*/) {
- // TODO(renjietang) Change the error code to H/3 specific
- // HTTP_CLOSED_CRITICAL_STREAM.
- session()->connection()->CloseConnection(
- QUIC_INVALID_STREAM_ID, "Attempt to reset send control stream",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ QUIC_BUG << "OnStreamReset() called for write unidirectional stream.";
+}
+
+bool QuicSendControlStream::OnStopSending(uint16_t /* code */) {
+ stream_delegate()->OnStreamError(
+ QUIC_HTTP_CLOSED_CRITICAL_STREAM,
+ "STOP_SENDING received for send control stream");
+ return false;
}
void QuicSendControlStream::MaybeSendSettingsFrame() {
@@ -44,10 +51,10 @@ void QuicSendControlStream::MaybeSendSettingsFrame() {
QuicConnection::ScopedPacketFlusher flusher(session()->connection());
// Send the stream type on so the peer knows about this stream.
char data[sizeof(kControlStream)];
- QuicDataWriter writer(QUIC_ARRAYSIZE(data), data);
+ QuicDataWriter writer(QUICHE_ARRAYSIZE(data), data);
writer.WriteVarInt62(kControlStream);
- WriteOrBufferData(QuicStringPiece(writer.data(), writer.length()), false,
- nullptr);
+ WriteOrBufferData(quiche::QuicheStringPiece(writer.data(), writer.length()),
+ false, nullptr);
SettingsFrame settings;
settings.values[SETTINGS_QPACK_MAX_TABLE_CAPACITY] =
@@ -56,49 +63,80 @@ void QuicSendControlStream::MaybeSendSettingsFrame() {
qpack_maximum_blocked_streams_;
settings.values[SETTINGS_MAX_HEADER_LIST_SIZE] =
max_inbound_header_list_size_;
+ // https://tools.ietf.org/html/draft-ietf-quic-http-25#section-7.2.4.1
+ // specifies that setting identifiers of 0x1f * N + 0x21 are reserved and
+ // greasing should be attempted.
+ if (!GetQuicFlag(FLAGS_quic_enable_http3_grease_randomness)) {
+ settings.values[0x40] = 20;
+ } else {
+ uint32_t result;
+ QuicRandom::GetInstance()->RandBytes(&result, sizeof(result));
+ uint64_t setting_id = 0x1fULL * static_cast<uint64_t>(result) + 0x21ULL;
+ QuicRandom::GetInstance()->RandBytes(&result, sizeof(result));
+ settings.values[setting_id] = result;
+ }
std::unique_ptr<char[]> buffer;
QuicByteCount frame_length =
HttpEncoder::SerializeSettingsFrame(settings, &buffer);
QUIC_DVLOG(1) << "Control stream " << id() << " is writing settings frame "
<< settings;
- QuicSpdySession* spdy_session = static_cast<QuicSpdySession*>(session());
- if (spdy_session->debug_visitor() != nullptr) {
- spdy_session->debug_visitor()->OnSettingsFrameSent(settings);
+ if (spdy_session_->debug_visitor()) {
+ spdy_session_->debug_visitor()->OnSettingsFrameSent(settings);
}
- WriteOrBufferData(QuicStringPiece(buffer.get(), frame_length),
+ WriteOrBufferData(quiche::QuicheStringPiece(buffer.get(), frame_length),
/*fin = */ false, nullptr);
settings_sent_ = true;
+
+ // https://tools.ietf.org/html/draft-ietf-quic-http-25#section-7.2.9
+ // specifies that a reserved frame type has no semantic meaning and should be
+ // discarded. A greasing frame is added here.
+ std::unique_ptr<char[]> grease;
+ QuicByteCount grease_length = HttpEncoder::SerializeGreasingFrame(&grease);
+ WriteOrBufferData(quiche::QuicheStringPiece(grease.get(), grease_length),
+ /*fin = */ false, nullptr);
}
-void QuicSendControlStream::WritePriority(const PriorityFrame& priority) {
+void QuicSendControlStream::WritePriorityUpdate(
+ const PriorityUpdateFrame& priority_update) {
QuicConnection::ScopedPacketFlusher flusher(session()->connection());
MaybeSendSettingsFrame();
+
+ if (spdy_session_->debug_visitor()) {
+ spdy_session_->debug_visitor()->OnPriorityUpdateFrameSent(priority_update);
+ }
+
std::unique_ptr<char[]> buffer;
QuicByteCount frame_length =
- HttpEncoder::SerializePriorityFrame(priority, &buffer);
- QUIC_DVLOG(1) << "Control Stream " << id() << " is writing " << priority;
- WriteOrBufferData(QuicStringPiece(buffer.get(), frame_length), false,
- nullptr);
+ HttpEncoder::SerializePriorityUpdateFrame(priority_update, &buffer);
+ QUIC_DVLOG(1) << "Control Stream " << id() << " is writing "
+ << priority_update;
+ WriteOrBufferData(quiche::QuicheStringPiece(buffer.get(), frame_length),
+ false, nullptr);
}
void QuicSendControlStream::SendMaxPushIdFrame(PushId max_push_id) {
+ DCHECK_EQ(Perspective::IS_CLIENT, session()->perspective());
QuicConnection::ScopedPacketFlusher flusher(session()->connection());
-
MaybeSendSettingsFrame();
+
MaxPushIdFrame frame;
frame.push_id = max_push_id;
+ if (spdy_session_->debug_visitor()) {
+ spdy_session_->debug_visitor()->OnMaxPushIdFrameSent(frame);
+ }
+
std::unique_ptr<char[]> buffer;
QuicByteCount frame_length =
HttpEncoder::SerializeMaxPushIdFrame(frame, &buffer);
- WriteOrBufferData(QuicStringPiece(buffer.get(), frame_length),
+ WriteOrBufferData(quiche::QuicheStringPiece(buffer.get(), frame_length),
/*fin = */ false, nullptr);
}
void QuicSendControlStream::SendGoAway(QuicStreamId stream_id) {
QuicConnection::ScopedPacketFlusher flusher(session()->connection());
-
MaybeSendSettingsFrame();
+
GoAwayFrame frame;
// If the peer hasn't created any stream yet. Use stream id 0 to indicate no
// request is accepted.
@@ -107,11 +145,15 @@ void QuicSendControlStream::SendGoAway(QuicStreamId stream_id) {
stream_id = 0;
}
frame.stream_id = stream_id;
+ if (spdy_session_->debug_visitor()) {
+ spdy_session_->debug_visitor()->OnGoAwayFrameSent(stream_id);
+ }
+
std::unique_ptr<char[]> buffer;
QuicByteCount frame_length =
HttpEncoder::SerializeGoAwayFrame(frame, &buffer);
- WriteOrBufferData(QuicStringPiece(buffer.get(), frame_length), false,
- nullptr);
+ WriteOrBufferData(quiche::QuicheStringPiece(buffer.get(), frame_length),
+ false, nullptr);
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream.h
index ac946d35a6f..03bd1f747aa 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream.h
@@ -9,19 +9,20 @@
#include "net/third_party/quiche/src/quic/core/quic_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
namespace quic {
-class QuicSession;
+class QuicSpdySession;
-// 3.2.1 Control Stream.
+// 6.2.1 Control Stream.
// The send control stream is self initiated and is write only.
class QUIC_EXPORT_PRIVATE QuicSendControlStream : public QuicStream {
public:
// |session| can't be nullptr, and the ownership is not passed. The stream can
// only be accessed through the session.
QuicSendControlStream(QuicStreamId id,
- QuicSession* session,
+ QuicSpdySession* session,
uint64_t qpack_maximum_dynamic_table_capacity,
uint64_t qpack_maximum_blocked_streams,
uint64_t max_inbound_header_list_size);
@@ -29,21 +30,25 @@ class QUIC_EXPORT_PRIVATE QuicSendControlStream : public QuicStream {
QuicSendControlStream& operator=(const QuicSendControlStream&) = delete;
~QuicSendControlStream() override = default;
- // Overriding QuicStream::OnStreamReset to make sure control stream is never
+ // Overriding QuicStream::OnStopSending() to make sure control stream is never
// closed before connection.
void OnStreamReset(const QuicRstStreamFrame& frame) override;
+ bool OnStopSending(uint16_t code) override;
// Send SETTINGS frame if it hasn't been sent yet. Settings frame must be the
// first frame sent on this stream.
void MaybeSendSettingsFrame();
- // Construct a MAX_PUSH_ID frame and send it on this stream.
+ // Send a MAX_PUSH_ID frame on this stream, and a SETTINGS frame beforehand if
+ // one has not been already sent. Must only be called for a client.
void SendMaxPushIdFrame(PushId max_push_id);
- // Send |Priority| on this stream. It must be sent after settings.
- void WritePriority(const PriorityFrame& priority);
+ // Send a PRIORITY_UPDATE frame on this stream, and a SETTINGS frame
+ // beforehand if one has not been already sent.
+ void WritePriorityUpdate(const PriorityUpdateFrame& priority_update);
- // Serialize a GOAWAY frame from |stream_id| and send it on this stream.
+ // Send a GOAWAY frame on this stream, and a SETTINGS frame beforehand if one
+ // has not been already sent.
void SendGoAway(QuicStreamId stream_id);
// The send control stream is write unidirectional, so this method should
@@ -60,6 +65,8 @@ class QUIC_EXPORT_PRIVATE QuicSendControlStream : public QuicStream {
const uint64_t qpack_maximum_blocked_streams_;
// SETTINGS_MAX_HEADER_LIST_SIZE value to send.
const uint64_t max_inbound_header_list_size_;
+
+ QuicSpdySession* const spdy_session_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream_test.cc
index de2e705e8c6..fb53b841234 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream_test.cc
@@ -6,10 +6,12 @@
#include <utility>
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
namespace test {
@@ -17,6 +19,7 @@ namespace test {
namespace {
using ::testing::_;
+using ::testing::AnyNumber;
using ::testing::Invoke;
using ::testing::StrictMock;
@@ -43,7 +46,7 @@ struct TestParams {
// Used by ::testing::PrintToStringParamName().
std::string PrintToString(const TestParams& tp) {
- return QuicStrCat(
+ return quiche::QuicheStrCat(
ParsedQuicVersionToString(tp.version), "_",
(tp.perspective == Perspective::IS_CLIENT ? "client" : "server"));
}
@@ -71,8 +74,8 @@ class QuicSendControlStreamTest : public QuicTestWithParam<TestParams> {
perspective(),
SupportedVersions(GetParam().version))),
session_(connection_) {
- ON_CALL(session_, WritevData(_, _, _, _, _))
- .WillByDefault(Invoke(MockQuicSession::ConsumeData));
+ ON_CALL(session_, WritevData(_, _, _, _, _, _))
+ .WillByDefault(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
}
void Initialize() {
@@ -82,8 +85,7 @@ class QuicSendControlStreamTest : public QuicTestWithParam<TestParams> {
session_.config(), kMinimumFlowControlSendWindow);
QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesUnidirectional(
session_.config(), kMinimumFlowControlSendWindow);
- QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams(
- session_.config(), 3);
+ QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(session_.config(), 3);
session_.OnConfigNegotiated();
}
@@ -102,6 +104,7 @@ INSTANTIATE_TEST_SUITE_P(Tests,
::testing::PrintToStringParamName());
TEST_P(QuicSendControlStreamTest, WriteSettings) {
+ SetQuicFlag(FLAGS_quic_enable_http3_grease_randomness, false);
session_.set_qpack_maximum_dynamic_table_capacity(255);
session_.set_qpack_maximum_blocked_streams(16);
session_.set_max_inbound_header_list_size(1024);
@@ -109,75 +112,85 @@ TEST_P(QuicSendControlStreamTest, WriteSettings) {
Initialize();
testing::InSequence s;
- std::string expected_write_data = QuicTextUtils::HexDecode(
+ std::string expected_write_data = quiche::QuicheTextUtils::HexDecode(
"00" // stream type: control stream
"04" // frame type: SETTINGS frame
- "08" // frame length
+ "0b" // frame length
"01" // SETTINGS_QPACK_MAX_TABLE_CAPACITY
"40ff" // 255
"06" // SETTINGS_MAX_HEADER_LIST_SIZE
"4400" // 1024
"07" // SETTINGS_QPACK_BLOCKED_STREAMS
- "10"); // 16
+ "10" // 16
+ "4040" // 0x40 as the reserved settings id
+ "14" // 20
+ "4040" // 0x40 as the reserved frame type
+ "01" // 1 byte frame length
+ "61"); // payload "a"
auto buffer = std::make_unique<char[]>(expected_write_data.size());
QuicDataWriter writer(expected_write_data.size(), buffer.get());
// A lambda to save and consume stream data when QuicSession::WritevData() is
// called.
- auto save_write_data = [&writer](QuicStream* stream, QuicStreamId /*id*/,
- size_t write_length, QuicStreamOffset offset,
- StreamSendingState /*state*/) {
- stream->WriteStreamData(offset, write_length, &writer);
- return QuicConsumedData(/* bytes_consumed = */ write_length,
- /* fin_consumed = */ false);
- };
-
- EXPECT_CALL(session_, WritevData(send_control_stream_, _, 1, _, _))
+ auto save_write_data =
+ [&writer, this](QuicStreamId /*id*/, size_t write_length,
+ QuicStreamOffset offset, StreamSendingState /*state*/,
+ TransmissionType /*type*/,
+ quiche::QuicheOptional<EncryptionLevel> /*level*/) {
+ send_control_stream_->WriteStreamData(offset, write_length, &writer);
+ return QuicConsumedData(/* bytes_consumed = */ write_length,
+ /* fin_consumed = */ false);
+ };
+
+ EXPECT_CALL(session_, WritevData(send_control_stream_->id(), 1, _, _, _, _))
.WillOnce(Invoke(save_write_data));
- EXPECT_CALL(session_, WritevData(send_control_stream_, _,
- expected_write_data.size() - 1, _, _))
+ EXPECT_CALL(session_, WritevData(send_control_stream_->id(),
+ expected_write_data.size() - 5, _, _, _, _))
+ .WillOnce(Invoke(save_write_data));
+ EXPECT_CALL(session_, WritevData(send_control_stream_->id(), 4, _, _, _, _))
.WillOnce(Invoke(save_write_data));
send_control_stream_->MaybeSendSettingsFrame();
EXPECT_EQ(expected_write_data,
- QuicStringPiece(writer.data(), writer.length()));
+ quiche::QuicheStringPiece(writer.data(), writer.length()));
}
TEST_P(QuicSendControlStreamTest, WriteSettingsOnlyOnce) {
Initialize();
testing::InSequence s;
- EXPECT_CALL(session_, WritevData(send_control_stream_, _, 1, _, _));
- EXPECT_CALL(session_, WritevData(send_control_stream_, _, _, _, _));
+ EXPECT_CALL(session_, WritevData(send_control_stream_->id(), 1, _, _, _, _));
+ EXPECT_CALL(session_, WritevData(send_control_stream_->id(), _, _, _, _, _))
+ .Times(2);
send_control_stream_->MaybeSendSettingsFrame();
- // No data should be written the sencond time MaybeSendSettingsFrame() is
+ // No data should be written the second time MaybeSendSettingsFrame() is
// called.
send_control_stream_->MaybeSendSettingsFrame();
}
+// Send stream type and SETTINGS frame if WritePriorityUpdate() is called first.
TEST_P(QuicSendControlStreamTest, WritePriorityBeforeSettings) {
Initialize();
testing::InSequence s;
- // The first write will trigger the control stream to write stream type and a
- // Settings frame before the Priority frame.
- EXPECT_CALL(session_, WritevData(send_control_stream_, _, _, _, _)).Times(3);
- PriorityFrame frame;
- send_control_stream_->WritePriority(frame);
+ // The first write will trigger the control stream to write stream type, a
+ // SETTINGS frame, and a greased frame before the PRIORITY_UPDATE frame.
+ EXPECT_CALL(session_, WritevData(send_control_stream_->id(), _, _, _, _, _))
+ .Times(4);
+ PriorityUpdateFrame frame;
+ send_control_stream_->WritePriorityUpdate(frame);
- EXPECT_CALL(session_, WritevData(send_control_stream_, _, _, _, _));
- send_control_stream_->WritePriority(frame);
+ EXPECT_CALL(session_, WritevData(send_control_stream_->id(), _, _, _, _, _));
+ send_control_stream_->WritePriorityUpdate(frame);
}
-TEST_P(QuicSendControlStreamTest, ResetControlStream) {
+TEST_P(QuicSendControlStreamTest, CloseControlStream) {
Initialize();
- QuicRstStreamFrame rst_frame(kInvalidControlFrameId,
- send_control_stream_->id(),
- QUIC_STREAM_CANCELLED, 1234);
- EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID, _, _));
- send_control_stream_->OnStreamReset(rst_frame);
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_HTTP_CLOSED_CRITICAL_STREAM, _, _));
+ send_control_stream_->OnStopSending(QUIC_STREAM_CANCELLED);
}
TEST_P(QuicSendControlStreamTest, ReceiveDataOnSendControlStream) {
@@ -189,6 +202,22 @@ TEST_P(QuicSendControlStreamTest, ReceiveDataOnSendControlStream) {
send_control_stream_->OnStreamFrame(frame);
}
+TEST_P(QuicSendControlStreamTest, SendGoAway) {
+ Initialize();
+
+ StrictMock<MockHttp3DebugVisitor> debug_visitor;
+ session_.set_debug_visitor(&debug_visitor);
+
+ QuicStreamId stream_id = 4;
+
+ EXPECT_CALL(session_, WritevData(send_control_stream_->id(), _, _, _, _, _))
+ .Times(AnyNumber());
+ EXPECT_CALL(debug_visitor, OnSettingsFrameSent(_));
+ EXPECT_CALL(debug_visitor, OnGoAwayFrameSent(stream_id));
+
+ send_control_stream_->SendGoAway(stream_id);
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.cc
index 5805fc90aeb..759c5a55a89 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.cc
@@ -22,7 +22,7 @@ QuicServerSessionBase::QuicServerSessionBase(
const ParsedQuicVersionVector& supported_versions,
QuicConnection* connection,
Visitor* visitor,
- QuicCryptoServerStream::Helper* helper,
+ QuicCryptoServerStreamBase::Helper* helper,
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache)
: QuicSpdySession(connection, visitor, config, supported_versions),
@@ -36,8 +36,8 @@ QuicServerSessionBase::QuicServerSessionBase(
QuicServerSessionBase::~QuicServerSessionBase() {}
void QuicServerSessionBase::Initialize() {
- crypto_stream_.reset(
- CreateQuicCryptoServerStream(crypto_config_, compressed_certs_cache_));
+ crypto_stream_ =
+ CreateQuicCryptoServerStream(crypto_config_, compressed_certs_cache_);
QuicSpdySession::Initialize();
}
@@ -201,6 +201,17 @@ bool QuicServerSessionBase::ShouldCreateIncomingStream(QuicStreamId id) {
return false;
}
+ if (GetQuicReloadableFlag(quic_create_incoming_stream_bug)) {
+ if (QuicUtils::IsServerInitiatedStreamId(transport_version(), id)) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_create_incoming_stream_bug, 1, 2);
+ QUIC_BUG << "ShouldCreateIncomingStream called with server initiated "
+ "stream ID.";
+ return false;
+ } else {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_create_incoming_stream_bug, 2, 2);
+ }
+ }
+
if (QuicUtils::IsServerInitiatedStreamId(transport_version(), id)) {
QUIC_DLOG(INFO) << "Invalid incoming even stream_id:" << id;
connection()->CloseConnection(
@@ -222,16 +233,6 @@ bool QuicServerSessionBase::ShouldCreateOutgoingBidirectionalStream() {
return false;
}
- if (!GetQuicReloadableFlag(quic_use_common_stream_check) &&
- !VersionHasIetfQuicFrames(transport_version())) {
- if (GetNumOpenOutgoingStreams() >=
- stream_id_manager().max_open_outgoing_streams()) {
- QUIC_VLOG(1) << "No more streams should be created. "
- << "Already " << GetNumOpenOutgoingStreams() << " open.";
- return false;
- }
- }
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_common_stream_check, 2, 2);
return CanOpenNextOutgoingBidirectionalStream();
}
@@ -246,16 +247,6 @@ bool QuicServerSessionBase::ShouldCreateOutgoingUnidirectionalStream() {
return false;
}
- if (!GetQuicReloadableFlag(quic_use_common_stream_check) &&
- !VersionHasIetfQuicFrames(transport_version())) {
- if (GetNumOpenOutgoingStreams() >=
- stream_id_manager().max_open_outgoing_streams()) {
- QUIC_VLOG(1) << "No more streams should be created. "
- << "Already " << GetNumOpenOutgoingStreams() << " open.";
- return false;
- }
- }
-
return CanOpenNextOutgoingUnidirectionalStream();
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.h
index 672bb0c4590..bf7a5bbb693 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.h
@@ -15,7 +15,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/quic_compressed_certs_cache.h"
#include "net/third_party/quiche/src/quic/core/http/quic_spdy_session.h"
-#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
+#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
@@ -38,7 +38,7 @@ class QUIC_EXPORT_PRIVATE QuicServerSessionBase : public QuicSpdySession {
const ParsedQuicVersionVector& supported_versions,
QuicConnection* connection,
QuicSession::Visitor* visitor,
- QuicCryptoServerStream::Helper* helper,
+ QuicCryptoServerStreamBase::Helper* helper,
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache);
QuicServerSessionBase(const QuicServerSessionBase&) = delete;
@@ -86,13 +86,14 @@ class QUIC_EXPORT_PRIVATE QuicServerSessionBase : public QuicSpdySession {
// possibly closing the connection, and returns false.
bool ShouldCreateIncomingStream(QuicStreamId id) override;
- virtual QuicCryptoServerStreamBase* CreateQuicCryptoServerStream(
+ virtual std::unique_ptr<QuicCryptoServerStreamBase>
+ CreateQuicCryptoServerStream(
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache) = 0;
const QuicCryptoServerConfig* crypto_config() { return crypto_config_; }
- QuicCryptoServerStream::Helper* stream_helper() { return helper_; }
+ QuicCryptoServerStreamBase::Helper* stream_helper() { return helper_; }
private:
friend class test::QuicServerSessionBasePeer;
@@ -108,7 +109,7 @@ class QUIC_EXPORT_PRIVATE QuicServerSessionBase : public QuicSpdySession {
// Pointer to the helper used to create crypto server streams. Must outlive
// streams created via CreateQuicCryptoServerStream.
- QuicCryptoServerStream::Helper* helper_;
+ QuicCryptoServerStreamBase::Helper* helper_;
// Whether bandwidth resumption is enabled for this connection.
bool bandwidth_resumption_enabled_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base_test.cc
index 9e8c749025b..98cdf4927fc 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base_test.cc
@@ -14,7 +14,9 @@
#include "net/third_party/quiche/src/quic/core/proto/cached_network_parameters_proto.h"
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
+#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
@@ -36,6 +38,7 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_server_stream.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
using testing::_;
using testing::StrictMock;
@@ -52,7 +55,7 @@ class TestServerSession : public QuicServerSessionBase {
TestServerSession(const QuicConfig& config,
QuicConnection* connection,
QuicSession::Visitor* visitor,
- QuicCryptoServerStream::Helper* helper,
+ QuicCryptoServerStreamBase::Helper* helper,
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache,
QuicSimpleServerBackend* quic_simple_server_backend)
@@ -65,7 +68,7 @@ class TestServerSession : public QuicServerSessionBase {
compressed_certs_cache),
quic_simple_server_backend_(quic_simple_server_backend) {}
- ~TestServerSession() override { delete connection(); }
+ ~TestServerSession() override { DeleteConnection(); }
protected:
QuicSpdyStream* CreateIncomingStream(QuicStreamId id) override {
@@ -102,11 +105,11 @@ class TestServerSession : public QuicServerSessionBase {
return stream;
}
- QuicCryptoServerStreamBase* CreateQuicCryptoServerStream(
+ std::unique_ptr<QuicCryptoServerStreamBase> CreateQuicCryptoServerStream(
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache) override {
- return new QuicCryptoServerStream(crypto_config, compressed_certs_cache,
- this, stream_helper());
+ return CreateCryptoServerStream(crypto_config, compressed_certs_cache, this,
+ stream_helper());
}
private:
@@ -128,12 +131,12 @@ class QuicServerSessionBaseTest : public QuicTestWithParam<ParsedQuicVersion> {
KeyExchangeSource::Default()),
compressed_certs_cache_(
QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) {
- config_.SetMaxIncomingBidirectionalStreamsToSend(kMaxStreamsForTest);
- config_.SetMaxIncomingUnidirectionalStreamsToSend(kMaxStreamsForTest);
- QuicConfigPeer::SetReceivedMaxIncomingBidirectionalStreams(
- &config_, kMaxStreamsForTest);
- QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams(
- &config_, kMaxStreamsForTest);
+ config_.SetMaxBidirectionalStreamsToSend(kMaxStreamsForTest);
+ config_.SetMaxUnidirectionalStreamsToSend(kMaxStreamsForTest);
+ QuicConfigPeer::SetReceivedMaxBidirectionalStreams(&config_,
+ kMaxStreamsForTest);
+ QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(&config_,
+ kMaxStreamsForTest);
config_.SetInitialStreamFlowControlWindowToSend(
kInitialStreamFlowControlWindowForTest);
config_.SetInitialSessionFlowControlWindowToSend(
@@ -150,12 +153,7 @@ class QuicServerSessionBaseTest : public QuicTestWithParam<ParsedQuicVersion> {
handshake_message_ = crypto_config_.AddDefaultConfig(
QuicRandom::GetInstance(), &clock,
QuicCryptoServerConfig::ConfigOptions());
- SetQuicReloadableFlag(quic_supports_tls_handshake, true);
session_->Initialize();
- if (!GetQuicReloadableFlag(quic_version_negotiated_by_default_at_server)) {
- QuicSessionPeer::GetMutableCryptoStream(session_.get())
- ->OnSuccessfulVersionNegotiation(supported_versions.front());
- }
QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(
session_->config(), kMinimumFlowControlSendWindow);
session_->OnConfigNegotiated();
@@ -236,7 +234,7 @@ TEST_P(QuicServerSessionBaseTest, CloseStreamDueToReset) {
// Open a stream, then reset it.
// Send two bytes of payload to open it.
QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
- QuicStringPiece("HT"));
+ quiche::QuicheStringPiece("HT"));
session_->OnStreamFrame(data1);
EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams());
@@ -295,7 +293,7 @@ TEST_P(QuicServerSessionBaseTest, NeverOpenStreamDueToReset) {
// Send two bytes of payload.
QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
- QuicStringPiece("HT"));
+ quiche::QuicheStringPiece("HT"));
session_->OnStreamFrame(data1);
// The stream should never be opened, now that the reset is received.
@@ -306,9 +304,9 @@ TEST_P(QuicServerSessionBaseTest, NeverOpenStreamDueToReset) {
TEST_P(QuicServerSessionBaseTest, AcceptClosedStream) {
// Send (empty) compressed headers followed by two bytes of data.
QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
- QuicStringPiece("\1\0\0\0\0\0\0\0HT"));
+ quiche::QuicheStringPiece("\1\0\0\0\0\0\0\0HT"));
QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(1), false, 0,
- QuicStringPiece("\2\0\0\0\0\0\0\0HT"));
+ quiche::QuicheStringPiece("\2\0\0\0\0\0\0\0HT"));
session_->OnStreamFrame(frame1);
session_->OnStreamFrame(frame2);
EXPECT_EQ(2u, session_->GetNumOpenIncomingStreams());
@@ -337,9 +335,9 @@ TEST_P(QuicServerSessionBaseTest, AcceptClosedStream) {
// past the reset point of stream 3. As it's a closed stream we just drop the
// data on the floor, but accept the packet because it has data for stream 5.
QuicStreamFrame frame3(GetNthClientInitiatedBidirectionalId(0), false, 2,
- QuicStringPiece("TP"));
+ quiche::QuicheStringPiece("TP"));
QuicStreamFrame frame4(GetNthClientInitiatedBidirectionalId(1), false, 2,
- QuicStringPiece("TP"));
+ quiche::QuicheStringPiece("TP"));
session_->OnStreamFrame(frame3);
session_->OnStreamFrame(frame4);
// The stream should never be opened, now that the reset is received.
@@ -440,7 +438,11 @@ TEST_P(QuicServerSessionBaseTest, MaxAvailableBidirectionalStreams) {
TEST_P(QuicServerSessionBaseTest, GetEvenIncomingError) {
// Incoming streams on the server session must be odd.
- EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID, _, _));
+ const QuicErrorCode expected_error =
+ VersionHasIetfQuicFrames(transport_version())
+ ? QUIC_HTTP_STREAM_WRONG_DIRECTION
+ : QUIC_INVALID_STREAM_ID;
+ EXPECT_CALL(*connection_, CloseConnection(expected_error, _, _));
EXPECT_EQ(nullptr, QuicServerSessionBasePeer::GetOrCreateStream(
session_.get(),
session_->next_outgoing_unidirectional_stream_id()));
@@ -465,7 +467,7 @@ class MockQuicCryptoServerStream : public QuicCryptoServerStream {
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache,
QuicServerSessionBase* session,
- QuicCryptoServerStream::Helper* helper)
+ QuicCryptoServerStreamBase::Helper* helper)
: QuicCryptoServerStream(crypto_config,
compressed_certs_cache,
session,
@@ -479,6 +481,20 @@ class MockQuicCryptoServerStream : public QuicCryptoServerStream {
void(const CachedNetworkParameters* cached_network_parameters));
};
+class MockTlsServerHandshaker : public TlsServerHandshaker {
+ public:
+ explicit MockTlsServerHandshaker(QuicServerSessionBase* session,
+ SSL_CTX* ssl_ctx,
+ ProofSource* proof_source)
+ : TlsServerHandshaker(session, ssl_ctx, proof_source) {}
+ MockTlsServerHandshaker(const MockTlsServerHandshaker&) = delete;
+ MockTlsServerHandshaker& operator=(const MockTlsServerHandshaker&) = delete;
+ ~MockTlsServerHandshaker() override {}
+
+ MOCK_METHOD1(SendServerConfigUpdate,
+ void(const CachedNetworkParameters* cached_network_parameters));
+};
+
TEST_P(QuicServerSessionBaseTest, BandwidthEstimates) {
// Test that bandwidth estimate updates are sent to the client, only when
// bandwidth resumption is enabled, the bandwidth estimate has changed
@@ -505,10 +521,22 @@ TEST_P(QuicServerSessionBaseTest, BandwidthEstimates) {
/*is_static=*/true);
}
QuicServerSessionBasePeer::SetCryptoStream(session_.get(), nullptr);
- MockQuicCryptoServerStream* crypto_stream =
- new MockQuicCryptoServerStream(&crypto_config_, &compressed_certs_cache_,
- session_.get(), &stream_helper_);
- QuicServerSessionBasePeer::SetCryptoStream(session_.get(), crypto_stream);
+ MockQuicCryptoServerStream* quic_crypto_stream = nullptr;
+ MockTlsServerHandshaker* tls_server_stream = nullptr;
+ if (session_->connection()->version().handshake_protocol ==
+ PROTOCOL_QUIC_CRYPTO) {
+ quic_crypto_stream = new MockQuicCryptoServerStream(
+ &crypto_config_, &compressed_certs_cache_, session_.get(),
+ &stream_helper_);
+ QuicServerSessionBasePeer::SetCryptoStream(session_.get(),
+ quic_crypto_stream);
+ } else {
+ tls_server_stream =
+ new MockTlsServerHandshaker(session_.get(), crypto_config_.ssl_ctx(),
+ crypto_config_.proof_source());
+ QuicServerSessionBasePeer::SetCryptoStream(session_.get(),
+ tls_server_stream);
+ }
if (!VersionUsesHttp3(transport_version())) {
session_->RegisterStreamPriority(
QuicUtils::GetHeadersStreamId(connection_->transport_version()),
@@ -592,9 +620,15 @@ TEST_P(QuicServerSessionBaseTest, BandwidthEstimates) {
session_->connection()->clock()->WallNow().ToUNIXSeconds());
expected_network_params.set_serving_region(serving_region);
- EXPECT_CALL(*crypto_stream,
- SendServerConfigUpdate(EqualsProto(expected_network_params)))
- .Times(1);
+ if (quic_crypto_stream) {
+ EXPECT_CALL(*quic_crypto_stream,
+ SendServerConfigUpdate(EqualsProto(expected_network_params)))
+ .Times(1);
+ } else {
+ EXPECT_CALL(*tls_server_stream,
+ SendServerConfigUpdate(EqualsProto(expected_network_params)))
+ .Times(1);
+ }
EXPECT_CALL(*connection_, OnSendConnectionState(_)).Times(1);
session_->OnCongestionWindowChange(now);
}
@@ -622,8 +656,9 @@ TEST_P(QuicServerSessionBaseTest, BandwidthResumptionExperiment) {
connection_->AdvanceTime(
QuicTime::Delta::FromSeconds(kNumSecondsPerHour + 1));
- QuicCryptoServerStream* crypto_stream = static_cast<QuicCryptoServerStream*>(
- QuicSessionPeer::GetMutableCryptoStream(session_.get()));
+ QuicCryptoServerStreamBase* crypto_stream =
+ static_cast<QuicCryptoServerStreamBase*>(
+ QuicSessionPeer::GetMutableCryptoStream(session_.get()));
// No effect if no CachedNetworkParameters provided.
EXPECT_CALL(*connection_, ResumeConnectionState(_, _)).Times(0);
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.cc
index da3336d26a0..07b9c7aac84 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.cc
@@ -56,27 +56,11 @@ bool QuicSpdyClientSession::ShouldCreateOutgoingBidirectionalStream() {
bool goaway_received = VersionUsesHttp3(transport_version())
? http3_goaway_received()
: QuicSession::goaway_received();
- if (!GetQuicReloadableFlag(quic_use_common_stream_check) &&
- !VersionHasIetfQuicFrames(transport_version())) {
- if (GetNumOpenOutgoingStreams() >=
- stream_id_manager().max_open_outgoing_streams()) {
- QUIC_DLOG(INFO) << "Failed to create a new outgoing stream. "
- << "Already " << GetNumOpenOutgoingStreams() << " open.";
- return false;
- }
- if (goaway_received && respect_goaway_) {
- QUIC_DLOG(INFO) << "Failed to create a new outgoing stream. "
- << "Already received goaway.";
- return false;
- }
- return true;
- }
if (goaway_received && respect_goaway_) {
QUIC_DLOG(INFO) << "Failed to create a new outgoing stream. "
<< "Already received goaway.";
return false;
}
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_common_stream_check, 1, 2);
return CanOpenNextOutgoingBidirectionalStream();
}
@@ -126,6 +110,14 @@ int QuicSpdyClientSession::GetNumSentClientHellos() const {
return crypto_stream_->num_sent_client_hellos();
}
+bool QuicSpdyClientSession::EarlyDataAccepted() const {
+ return crypto_stream_->EarlyDataAccepted();
+}
+
+bool QuicSpdyClientSession::ReceivedInchoateReject() const {
+ return crypto_stream_->ReceivedInchoateReject();
+}
+
int QuicSpdyClientSession::GetNumReceivedServerConfigUpdates() const {
return crypto_stream_->num_scup_messages_received();
}
@@ -143,9 +135,19 @@ bool QuicSpdyClientSession::ShouldCreateIncomingStream(QuicStreamId id) {
<< "Already received goaway.";
return false;
}
- if (QuicUtils::IsClientInitiatedStreamId(transport_version(), id) ||
- (VersionHasIetfQuicFrames(transport_version()) &&
- QuicUtils::IsBidirectionalStreamId(id))) {
+
+ if (GetQuicReloadableFlag(quic_create_incoming_stream_bug)) {
+ if (QuicUtils::IsClientInitiatedStreamId(transport_version(), id)) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_create_incoming_stream_bug, 1, 2);
+ QUIC_BUG << "ShouldCreateIncomingStream called with client initiated "
+ "stream ID.";
+ return false;
+ } else {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_create_incoming_stream_bug, 2, 2);
+ }
+ }
+
+ if (QuicUtils::IsClientInitiatedStreamId(transport_version(), id)) {
QUIC_LOG(WARNING) << "Received invalid push stream id " << id;
connection()->CloseConnection(
QUIC_INVALID_STREAM_ID,
@@ -153,6 +155,16 @@ bool QuicSpdyClientSession::ShouldCreateIncomingStream(QuicStreamId id) {
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return false;
}
+
+ if (VersionHasIetfQuicFrames(transport_version()) &&
+ QuicUtils::IsBidirectionalStreamId(id)) {
+ connection()->CloseConnection(
+ QUIC_HTTP_SERVER_INITIATED_BIDIRECTIONAL_STREAM,
+ "Server created bidirectional stream.",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
+ }
+
return true;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.h
index b3def0aca29..e8171baf8a1 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.h
@@ -57,8 +57,22 @@ class QUIC_NO_EXPORT QuicSpdyClientSession : public QuicSpdyClientSessionBase {
// than the number of round-trips needed for the handshake.
int GetNumSentClientHellos() const;
+ // Returns true if early data (0-RTT data) was sent and the server accepted
+ // it.
+ bool EarlyDataAccepted() const;
+
+ // Returns true if the handshake was delayed one round trip by the server
+ // because the server wanted proof the client controls its source address
+ // before progressing further. In Google QUIC, this would be due to an
+ // inchoate REJ in the QUIC Crypto handshake; in IETF QUIC this would be due
+ // to a Retry packet.
+ // TODO(nharper): Consider a better name for this method.
+ bool ReceivedInchoateReject() const;
+
int GetNumReceivedServerConfigUpdates() const;
+ using QuicSession::CanOpenNextOutgoingBidirectionalStream;
+
void set_respect_goaway(bool respect_goaway) {
respect_goaway_ = respect_goaway;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_base.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_base.cc
index 7dd2aec34e7..b8dae4903b2 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_base.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_base.cc
@@ -32,7 +32,7 @@ QuicSpdyClientSessionBase::~QuicSpdyClientSessionBase() {
QUIC_DVLOG(1) << "erase stream " << it.first << " url " << it.second->url();
push_promise_index_->promised_by_url()->erase(it.second->url());
}
- delete connection();
+ DeleteConnection();
}
void QuicSpdyClientSessionBase::OnConfigNegotiated() {
@@ -85,7 +85,7 @@ void QuicSpdyClientSessionBase::OnPromiseHeaderList(
}
if (VersionUsesHttp3(transport_version()) &&
- promised_stream_id > max_allowed_push_id()) {
+ !CanCreatePushStreamWithId(promised_stream_id)) {
connection()->CloseConnection(
QUIC_INVALID_STREAM_ID,
"Received push stream id higher than MAX_PUSH_ID.",
@@ -94,7 +94,7 @@ void QuicSpdyClientSessionBase::OnPromiseHeaderList(
}
largest_promised_stream_id_ = promised_stream_id;
- QuicSpdyStream* stream = GetSpdyDataStream(stream_id);
+ QuicSpdyStream* stream = GetOrCreateSpdyDataStream(stream_id);
if (!stream) {
// It's quite possible to receive headers after a stream has been reset.
return;
@@ -203,14 +203,14 @@ void QuicSpdyClientSessionBase::ResetPromised(
QuicRstStreamErrorCode error_code) {
DCHECK(QuicUtils::IsServerInitiatedStreamId(transport_version(), id));
SendRstStream(id, error_code, 0);
- if (!IsOpenStream(id)) {
+ if (!IsOpenStream(id) && !IsClosedStream(id)) {
MaybeIncreaseLargestPeerStreamId(id);
}
}
void QuicSpdyClientSessionBase::CloseStreamInner(QuicStreamId stream_id,
- bool locally_reset) {
- QuicSpdySession::CloseStreamInner(stream_id, locally_reset);
+ bool rst_sent) {
+ QuicSpdySession::CloseStreamInner(stream_id, rst_sent);
if (!VersionUsesHttp3(transport_version())) {
headers_stream()->MaybeReleaseSequencerBuffer();
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_base.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_base.h
index 3ca3499e8c7..7d4ba01141a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_base.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_base.h
@@ -103,7 +103,7 @@ class QUIC_EXPORT_PRIVATE QuicSpdyClientSessionBase
void ResetPromised(QuicStreamId id, QuicRstStreamErrorCode error_code);
// Release headers stream's sequencer buffer if it's empty.
- void CloseStreamInner(QuicStreamId stream_id, bool locally_reset) override;
+ void CloseStreamInner(QuicStreamId stream_id, bool rst_sent) override;
// Returns true if there are no active requests and no promised streams.
bool ShouldReleaseHeadersStreamSequencerBuffer() override;
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_test.cc
index 7c4d914da98..da05a15f6d6 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_test.cc
@@ -14,10 +14,9 @@
#include "net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.h"
#include "net/third_party/quiche/src/quic/core/http/spdy_server_push_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_quic_spdy_client_stream.h"
@@ -28,6 +27,9 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_session_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
using spdy::SpdyHeaderBlock;
using testing::_;
@@ -84,7 +86,6 @@ class QuicSpdyClientSessionTest : public QuicTestWithParam<ParsedQuicVersion> {
QuicUtils::GetInvalidStreamId(GetParam().transport_version)),
associated_stream_id_(
QuicUtils::GetInvalidStreamId(GetParam().transport_version)) {
- SetQuicReloadableFlag(quic_supports_tls_handshake, true);
Initialize();
// Advance the time, because timers do not like uninitialized times.
connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
@@ -156,14 +157,12 @@ class QuicSpdyClientSessionTest : public QuicTestWithParam<ParsedQuicVersion> {
session_->GetMutableCryptoStream());
QuicConfig config = DefaultQuicConfig();
if (VersionHasIetfQuicFrames(connection_->transport_version())) {
- config.SetMaxIncomingUnidirectionalStreamsToSend(
+ config.SetMaxUnidirectionalStreamsToSend(
server_max_incoming_streams +
session_->num_expected_unidirectional_static_streams());
- config.SetMaxIncomingBidirectionalStreamsToSend(
- server_max_incoming_streams);
+ config.SetMaxBidirectionalStreamsToSend(server_max_incoming_streams);
} else {
- config.SetMaxIncomingBidirectionalStreamsToSend(
- server_max_incoming_streams);
+ config.SetMaxBidirectionalStreamsToSend(server_max_incoming_streams);
}
std::unique_ptr<QuicCryptoServerConfig> crypto_config =
crypto_test_utils::CryptoServerConfigForTesting();
@@ -233,10 +232,10 @@ TEST_P(QuicSpdyClientSessionTest, NoEncryptionAfterInitialEncryption) {
EXPECT_TRUE(session_->CreateOutgoingBidirectionalStream() == nullptr);
// Verify that no data may be send on existing streams.
char data[] = "hello world";
- QuicConsumedData consumed = session_->WritevData(
- stream, stream->id(), QUIC_ARRAYSIZE(data), 0, NO_FIN);
- EXPECT_FALSE(consumed.fin_consumed);
- EXPECT_EQ(0u, consumed.bytes_consumed);
+ EXPECT_QUIC_BUG(
+ session_->WritevData(stream->id(), QUICHE_ARRAYSIZE(data), 0, NO_FIN,
+ NOT_RETRANSMISSION, QuicheNullOpt),
+ "Client: Try to send data of stream");
}
TEST_P(QuicSpdyClientSessionTest, MaxNumStreamsWithNoFinOrRst) {
@@ -428,7 +427,7 @@ TEST_P(QuicSpdyClientSessionTest, OnStreamHeaderListWithStaticStream) {
connection_->transport_version(), 3);
char type[] = {0x00};
- QuicStreamFrame data1(id, false, 0, QuicStringPiece(type, 1));
+ QuicStreamFrame data1(id, false, 0, quiche::QuicheStringPiece(type, 1));
session_->OnStreamFrame(data1);
} else {
id = QuicUtils::GetHeadersStreamId(connection_->transport_version());
@@ -458,7 +457,7 @@ TEST_P(QuicSpdyClientSessionTest, OnPromiseHeaderListWithStaticStream) {
connection_->transport_version(), 3);
char type[] = {0x00};
- QuicStreamFrame data1(id, false, 0, QuicStringPiece(type, 1));
+ QuicStreamFrame data1(id, false, 0, quiche::QuicheStringPiece(type, 1));
session_->OnStreamFrame(data1);
} else {
id = QuicUtils::GetHeadersStreamId(connection_->transport_version());
@@ -584,8 +583,10 @@ TEST_P(QuicSpdyClientSessionTest, PushPromiseOnPromiseHeaders) {
// Initialize crypto before the client session will create a stream.
CompleteCryptoHandshake();
- session_->SetMaxAllowedPushId(GetNthServerInitiatedUnidirectionalStreamId(
- connection_->transport_version(), 10));
+ if (VersionHasIetfQuicFrames(connection_->transport_version())) {
+ session_->SetMaxPushId(GetNthServerInitiatedUnidirectionalStreamId(
+ connection_->transport_version(), 10));
+ }
MockQuicSpdyClientStream* stream = static_cast<MockQuicSpdyClientStream*>(
session_->CreateOutgoingBidirectionalStream());
@@ -604,9 +605,9 @@ TEST_P(QuicSpdyClientSessionTest, PushPromiseStreamIdTooHigh) {
session_.get(), std::make_unique<QuicSpdyClientStream>(
stream_id, session_.get(), BIDIRECTIONAL));
- session_->SetMaxAllowedPushId(GetNthServerInitiatedUnidirectionalStreamId(
- connection_->transport_version(), 10));
if (VersionHasIetfQuicFrames(connection_->transport_version())) {
+ session_->SetMaxPushId(GetNthServerInitiatedUnidirectionalStreamId(
+ connection_->transport_version(), 10));
// TODO(b/136295430) Use PushId to represent Push IDs instead of
// QuicStreamId.
EXPECT_CALL(
@@ -645,8 +646,10 @@ TEST_P(QuicSpdyClientSessionTest, PushPromiseOutOfOrder) {
// Initialize crypto before the client session will create a stream.
CompleteCryptoHandshake();
- session_->SetMaxAllowedPushId(GetNthServerInitiatedUnidirectionalStreamId(
- connection_->transport_version(), 10));
+ if (VersionHasIetfQuicFrames(connection_->transport_version())) {
+ session_->SetMaxPushId(GetNthServerInitiatedUnidirectionalStreamId(
+ connection_->transport_version(), 10));
+ }
MockQuicSpdyClientStream* stream = static_cast<MockQuicSpdyClientStream*>(
session_->CreateOutgoingBidirectionalStream());
@@ -745,7 +748,7 @@ TEST_P(QuicSpdyClientSessionTest, PushPromiseDuplicateUrl) {
TEST_P(QuicSpdyClientSessionTest, ReceivingPromiseEnhanceYourCalm) {
for (size_t i = 0u; i < session_->get_max_promises(); i++) {
- push_promise_[":path"] = QuicStringPrintf("/bar%zu", i);
+ push_promise_[":path"] = quiche::QuicheStringPrintf("/bar%zu", i);
QuicStreamId id =
promised_stream_id_ +
@@ -763,7 +766,7 @@ TEST_P(QuicSpdyClientSessionTest, ReceivingPromiseEnhanceYourCalm) {
// One more promise, this should be refused.
int i = session_->get_max_promises();
- push_promise_[":path"] = QuicStringPrintf("/bar%d", i);
+ push_promise_[":path"] = quiche::QuicheStringPrintf("/bar%d", i);
QuicStreamId id =
promised_stream_id_ +
@@ -896,7 +899,9 @@ TEST_P(QuicSpdyClientSessionTest, PushPromiseInvalidHost) {
TEST_P(QuicSpdyClientSessionTest,
TryToCreateServerInitiatedBidirectionalStream) {
if (VersionHasIetfQuicFrames(connection_->transport_version())) {
- EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID, _, _));
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_HTTP_SERVER_INITIATED_BIDIRECTIONAL_STREAM, _, _));
} else {
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
}
@@ -913,7 +918,9 @@ TEST_P(QuicSpdyClientSessionTest, TooManyPushPromises) {
session_.get(), std::make_unique<QuicSpdyClientStream>(
stream_id, session_.get(), BIDIRECTIONAL));
- session_->SetMaxAllowedPushId(kMaxQuicStreamId);
+ if (VersionHasIetfQuicFrames(connection_->transport_version())) {
+ session_->SetMaxPushId(kMaxQuicStreamId);
+ }
EXPECT_CALL(*connection_, OnStreamReset(_, QUIC_REFUSED_STREAM));
@@ -923,7 +930,7 @@ TEST_P(QuicSpdyClientSessionTest, TooManyPushPromises) {
connection_->transport_version(), promise_count);
auto headers = QuicHeaderList();
headers.OnHeaderBlockStart();
- headers.OnHeader(":path", QuicStrCat("/", promise_count));
+ headers.OnHeader(":path", quiche::QuicheStrCat("/", promise_count));
headers.OnHeader(":authority", "www.google.com");
headers.OnHeader(":method", "GET");
headers.OnHeader(":scheme", "https");
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.cc
index 5cbb79d234d..7232f76c755 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.cc
@@ -11,6 +11,7 @@
#include "net/third_party/quiche/src/quic/core/http/spdy_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_alarm.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
using spdy::SpdyHeaderBlock;
@@ -140,7 +141,7 @@ void QuicSpdyClientStream::OnBodyAvailable() {
}
size_t QuicSpdyClientStream::SendRequest(SpdyHeaderBlock headers,
- QuicStringPiece body,
+ quiche::QuicheStringPiece body,
bool fin) {
QuicConnection::ScopedPacketFlusher flusher(session_->connection());
bool send_fin_with_headers = fin && body.empty();
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.h
index 5cd27d4a6b8..dfb9270ae78 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.h
@@ -10,7 +10,7 @@
#include "net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
namespace quic {
@@ -52,7 +52,7 @@ class QUIC_NO_EXPORT QuicSpdyClientStream : public QuicSpdyStream {
// Serializes the headers and body, sends it to the server, and
// returns the number of bytes sent.
size_t SendRequest(spdy::SpdyHeaderBlock headers,
- QuicStringPiece body,
+ quiche::QuicheStringPiece body,
bool fin);
// Returns the response data.
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream_test.cc
index dd1cadebbd8..50224cbde29 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream_test.cc
@@ -14,10 +14,10 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
using spdy::SpdyHeaderBlock;
using testing::_;
@@ -66,7 +66,6 @@ class QuicSpdyClientStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
connection_,
&push_promise_index_),
body_("hello world") {
- SetQuicReloadableFlag(quic_supports_tls_handshake, true);
session_.Initialize();
headers_[":status"] = "200";
@@ -213,7 +212,7 @@ TEST_P(QuicSpdyClientStreamTest, ReceivingTrailers) {
SpdyHeaderBlock trailer_block;
trailer_block["trailer key"] = "trailer value";
trailer_block[kFinalOffsetHeaderKey] =
- QuicTextUtils::Uint64ToString(body_.size());
+ quiche::QuicheTextUtils::Uint64ToString(body_.size());
auto trailers = AsHeaderList(trailer_block);
stream_->OnStreamHeaderList(true, trailers.uncompressed_header_bytes(),
trailers);
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.cc
index 3a3441bc416..11351438f3c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.cc
@@ -6,6 +6,7 @@
#include <algorithm>
#include <cstdint>
+#include <limits>
#include <string>
#include <utility>
@@ -22,8 +23,9 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_stack_trace.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
#include "net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.h"
using http2::Http2DecoderAdapter;
@@ -52,8 +54,8 @@ namespace quic {
namespace {
-// TODO(b/124216424): remove this once HTTP/3 error codes are adopted.
-const uint16_t kHttpUnknownStreamType = 0x0D;
+#define ENDPOINT \
+ (perspective() == Perspective::IS_SERVER ? "Server: " : "Client: ")
class HeaderTableDebugVisitor : public HpackHeaderTable::DebugVisitorInterface {
public:
@@ -134,18 +136,73 @@ class QuicSpdySession::SpdyFramerVisitor
}
void OnError(Http2DecoderAdapter::SpdyFramerError error) override {
- QuicErrorCode code = QUIC_INVALID_HEADERS_STREAM_DATA;
+ QuicErrorCode code;
switch (error) {
+ case Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_INDEX_VARINT_ERROR:
+ code = QUIC_HPACK_NAME_LENGTH_VARINT_ERROR;
+ break;
+ case Http2DecoderAdapter::SpdyFramerError::
+ SPDY_HPACK_NAME_LENGTH_VARINT_ERROR:
+ code = QUIC_HPACK_VALUE_LENGTH_VARINT_ERROR;
+ break;
+ case Http2DecoderAdapter::SpdyFramerError::
+ SPDY_HPACK_VALUE_LENGTH_VARINT_ERROR:
+ code = QUIC_HPACK_NAME_TOO_LONG;
+ break;
+ case Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_NAME_TOO_LONG:
+ code = QUIC_HPACK_VALUE_TOO_LONG;
+ break;
+ case Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_VALUE_TOO_LONG:
+ code = QUIC_HPACK_INDEX_VARINT_ERROR;
+ break;
+ case Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_NAME_HUFFMAN_ERROR:
+ code = QUIC_HPACK_NAME_HUFFMAN_ERROR;
+ break;
+ case Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_VALUE_HUFFMAN_ERROR:
+ code = QUIC_HPACK_VALUE_HUFFMAN_ERROR;
+ break;
+ case Http2DecoderAdapter::SpdyFramerError::
+ SPDY_HPACK_MISSING_DYNAMIC_TABLE_SIZE_UPDATE:
+ code = QUIC_HPACK_MISSING_DYNAMIC_TABLE_SIZE_UPDATE;
+ break;
+ case Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_INVALID_INDEX:
+ code = QUIC_HPACK_INVALID_INDEX;
+ break;
+ case Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_INVALID_NAME_INDEX:
+ code = QUIC_HPACK_INVALID_NAME_INDEX;
+ break;
+ case Http2DecoderAdapter::SpdyFramerError::
+ SPDY_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_NOT_ALLOWED:
+ code = QUIC_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_NOT_ALLOWED;
+ break;
+ case Http2DecoderAdapter::SpdyFramerError::
+ SPDY_HPACK_INITIAL_DYNAMIC_TABLE_SIZE_UPDATE_IS_ABOVE_LOW_WATER_MARK:
+ code = QUIC_HPACK_INITIAL_TABLE_SIZE_UPDATE_IS_ABOVE_LOW_WATER_MARK;
+ break;
+ case Http2DecoderAdapter::SpdyFramerError::
+ SPDY_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_IS_ABOVE_ACKNOWLEDGED_SETTING:
+ code = QUIC_HPACK_TABLE_SIZE_UPDATE_IS_ABOVE_ACKNOWLEDGED_SETTING;
+ break;
+ case Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_TRUNCATED_BLOCK:
+ code = QUIC_HPACK_TRUNCATED_BLOCK;
+ break;
+ case Http2DecoderAdapter::SpdyFramerError::SPDY_HPACK_FRAGMENT_TOO_LONG:
+ code = QUIC_HPACK_FRAGMENT_TOO_LONG;
+ break;
+ case Http2DecoderAdapter::SpdyFramerError::
+ SPDY_HPACK_COMPRESSED_HEADER_SIZE_EXCEEDS_LIMIT:
+ code = QUIC_HPACK_COMPRESSED_HEADER_SIZE_EXCEEDS_LIMIT;
+ break;
case Http2DecoderAdapter::SpdyFramerError::SPDY_DECOMPRESS_FAILURE:
code = QUIC_HEADERS_STREAM_DATA_DECOMPRESS_FAILURE;
break;
default:
- break;
+ code = QUIC_INVALID_HEADERS_STREAM_DATA;
}
- CloseConnection(
- QuicStrCat("SPDY framing error: ",
- Http2DecoderAdapter::SpdyFramerErrorToString(error)),
- code);
+ CloseConnection(quiche::QuicheStrCat(
+ "SPDY framing error: ",
+ Http2DecoderAdapter::SpdyFramerErrorToString(error)),
+ code);
}
void OnDataFrameHeader(SpdyStreamId /*stream_id*/,
@@ -207,8 +264,6 @@ class QuicSpdySession::SpdyFramerVisitor
session_->OnHeaders(
stream_id, has_priority,
spdy::SpdyStreamPrecedence(parent_stream_id, weight, exclusive), fin);
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_http2_priority_write_scheduler, 1,
- 3);
return;
}
@@ -228,7 +283,7 @@ class QuicSpdySession::SpdyFramerVisitor
SpdyStreamId promised_stream_id,
bool /*end*/) override {
DCHECK(!VersionUsesHttp3(session_->transport_version()));
- if (!session_->supports_push_promise()) {
+ if (session_->perspective() != Perspective::IS_CLIENT) {
CloseConnection("PUSH_PROMISE not supported.",
QUIC_INVALID_HEADERS_STREAM_DATA);
return;
@@ -252,8 +307,6 @@ class QuicSpdySession::SpdyFramerVisitor
if (session_->use_http2_priority_write_scheduler()) {
session_->OnPriority(
stream_id, spdy::SpdyStreamPrecedence(parent_id, weight, exclusive));
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_http2_priority_write_scheduler, 2,
- 3);
return;
}
SpdyPriority priority = Http2WeightToSpdy3Priority(weight);
@@ -334,18 +387,17 @@ QuicSpdySession::QuicSpdySession(
kDefaultQpackMaxDynamicTableCapacity),
qpack_maximum_blocked_streams_(kDefaultMaximumBlockedStreams),
max_inbound_header_list_size_(kDefaultMaxUncompressedHeaderSize),
- max_outbound_header_list_size_(kDefaultMaxUncompressedHeaderSize),
- server_push_enabled_(true),
+ max_outbound_header_list_size_(std::numeric_limits<size_t>::max()),
stream_id_(
QuicUtils::GetInvalidStreamId(connection->transport_version())),
promised_stream_id_(
QuicUtils::GetInvalidStreamId(connection->transport_version())),
fin_(false),
frame_len_(0),
- supports_push_promise_(perspective() == Perspective::IS_CLIENT),
spdy_framer_(SpdyFramer::ENABLE_COMPRESSION),
spdy_framer_visitor_(new SpdyFramerVisitor(this)),
- max_allowed_push_id_(0),
+ server_push_enabled_(true),
+ ietf_server_push_enabled_(false),
destruction_indicator_(123456789),
debug_visitor_(nullptr),
http3_goaway_received_(false),
@@ -395,8 +447,8 @@ void QuicSpdySession::Initialize() {
headers_stream_ = headers_stream.get();
ActivateStream(std::move(headers_stream));
} else {
- ConfigureMaxIncomingDynamicStreamsToSend(
- config()->GetMaxIncomingUnidirectionalStreamsToSend());
+ ConfigureMaxDynamicStreamsToSend(
+ config()->GetMaxUnidirectionalStreamsToSend());
qpack_encoder_ = std::make_unique<QpackEncoder>(this);
qpack_decoder_ =
std::make_unique<QpackDecoder>(qpack_maximum_dynamic_table_capacity_,
@@ -411,26 +463,28 @@ void QuicSpdySession::Initialize() {
2 * max_inbound_header_list_size_);
}
-void QuicSpdySession::OnDecoderStreamError(QuicStringPiece error_message) {
+void QuicSpdySession::OnDecoderStreamError(
+ quiche::QuicheStringPiece error_message) {
DCHECK(VersionUsesHttp3(transport_version()));
CloseConnectionWithDetails(
QUIC_QPACK_DECODER_STREAM_ERROR,
- QuicStrCat("Decoder stream error: ", error_message));
+ quiche::QuicheStrCat("Decoder stream error: ", error_message));
}
-void QuicSpdySession::OnEncoderStreamError(QuicStringPiece error_message) {
+void QuicSpdySession::OnEncoderStreamError(
+ quiche::QuicheStringPiece error_message) {
DCHECK(VersionUsesHttp3(transport_version()));
CloseConnectionWithDetails(
QUIC_QPACK_ENCODER_STREAM_ERROR,
- QuicStrCat("Encoder stream error: ", error_message));
+ quiche::QuicheStrCat("Encoder stream error: ", error_message));
}
void QuicSpdySession::OnStreamHeadersPriority(
QuicStreamId stream_id,
const spdy::SpdyStreamPrecedence& precedence) {
- QuicSpdyStream* stream = GetSpdyDataStream(stream_id);
+ QuicSpdyStream* stream = GetOrCreateSpdyDataStream(stream_id);
if (!stream) {
// It's quite possible to receive headers after a stream has been reset.
return;
@@ -448,7 +502,7 @@ void QuicSpdySession::OnStreamHeaderList(QuicStreamId stream_id,
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return;
}
- QuicSpdyStream* stream = GetSpdyDataStream(stream_id);
+ QuicSpdyStream* stream = GetOrCreateSpdyDataStream(stream_id);
if (stream == nullptr) {
// The stream no longer exists, but trailing headers may contain the final
// byte offset necessary for flow control and open stream accounting.
@@ -457,14 +511,16 @@ void QuicSpdySession::OnStreamHeaderList(QuicStreamId stream_id,
const std::string& header_key = header.first;
const std::string& header_value = header.second;
if (header_key == kFinalOffsetHeaderKey) {
- if (!QuicTextUtils::StringToSizeT(header_value, &final_byte_offset)) {
+ if (!quiche::QuicheTextUtils::StringToSizeT(header_value,
+ &final_byte_offset)) {
connection()->CloseConnection(
QUIC_INVALID_HEADERS_STREAM_DATA,
"Trailers are malformed (no final offset)",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return;
}
- QUIC_DVLOG(1) << "Received final byte offset in trailers for stream "
+ QUIC_DVLOG(1) << ENDPOINT
+ << "Received final byte offset in trailers for stream "
<< stream_id << ", which no longer exists.";
OnFinalByteOffsetReceived(stream_id, final_byte_offset);
}
@@ -479,7 +535,7 @@ void QuicSpdySession::OnStreamHeaderList(QuicStreamId stream_id,
void QuicSpdySession::OnPriorityFrame(
QuicStreamId stream_id,
const spdy::SpdyStreamPrecedence& precedence) {
- QuicSpdyStream* stream = GetSpdyDataStream(stream_id);
+ QuicSpdyStream* stream = GetOrCreateSpdyDataStream(stream_id);
if (!stream) {
// It's quite possible to receive a PRIORITY frame after a stream has been
// reset.
@@ -488,6 +544,64 @@ void QuicSpdySession::OnPriorityFrame(
stream->OnPriorityFrame(precedence);
}
+bool QuicSpdySession::OnPriorityUpdateForRequestStream(QuicStreamId stream_id,
+ int urgency) {
+ if (perspective() == Perspective::IS_CLIENT ||
+ !QuicUtils::IsBidirectionalStreamId(stream_id) ||
+ !QuicUtils::IsClientInitiatedStreamId(transport_version(), stream_id)) {
+ return true;
+ }
+
+ QuicStreamCount advertised_max_incoming_bidirectional_streams =
+ GetAdvertisedMaxIncomingBidirectionalStreams();
+ if (advertised_max_incoming_bidirectional_streams == 0 ||
+ stream_id > QuicUtils::GetFirstBidirectionalStreamId(
+ transport_version(), Perspective::IS_CLIENT) +
+ QuicUtils::StreamIdDelta(transport_version()) *
+ (advertised_max_incoming_bidirectional_streams - 1)) {
+ connection()->CloseConnection(
+ QUIC_INVALID_STREAM_ID,
+ "PRIORITY_UPDATE frame received for invalid stream.",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
+ }
+
+ if (MaybeSetStreamPriority(stream_id, spdy::SpdyStreamPrecedence(urgency))) {
+ return true;
+ }
+
+ if (IsClosedStream(stream_id)) {
+ return true;
+ }
+
+ buffered_stream_priorities_[stream_id] = urgency;
+
+ if (buffered_stream_priorities_.size() >
+ 10 * max_open_incoming_bidirectional_streams()) {
+ // This should never happen, because |buffered_stream_priorities_| should
+ // only contain entries for streams that are allowed to be open by the peer
+ // but have not been opened yet.
+ std::string error_message = quiche::QuicheStrCat(
+ "Too many stream priority values buffered: ",
+ buffered_stream_priorities_.size(),
+ ", which should not exceed the incoming stream limit of ",
+ max_open_incoming_bidirectional_streams());
+ QUIC_BUG << error_message;
+ connection()->CloseConnection(
+ QUIC_INTERNAL_ERROR, error_message,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
+ }
+
+ return true;
+}
+
+bool QuicSpdySession::OnPriorityUpdateForPushStream(QuicStreamId /*push_id*/,
+ int /*urgency*/) {
+ // TODO(b/147306124): Implement PRIORITY_UPDATE frames for pushed streams.
+ return true;
+}
+
size_t QuicSpdySession::ProcessHeaderData(const struct iovec& iov) {
QUIC_BUG_IF(destruction_indicator_ != 123456789)
<< "QuicSpdyStream use after free. " << destruction_indicator_
@@ -519,18 +633,15 @@ size_t QuicSpdySession::WritePriority(QuicStreamId id,
SpdyPriorityIR priority_frame(id, parent_stream_id, weight, exclusive);
SpdySerializedFrame frame(spdy_framer_.SerializeFrame(priority_frame));
headers_stream()->WriteOrBufferData(
- QuicStringPiece(frame.data(), frame.size()), false, nullptr);
+ quiche::QuicheStringPiece(frame.data(), frame.size()), false, nullptr);
return frame.size();
}
-void QuicSpdySession::WriteH3Priority(const PriorityFrame& priority) {
+void QuicSpdySession::WriteHttp3PriorityUpdate(
+ const PriorityUpdateFrame& priority_update) {
DCHECK(VersionUsesHttp3(transport_version()));
- DCHECK(GetQuicFlag(FLAGS_quic_allow_http3_priority));
- DCHECK(perspective() == Perspective::IS_CLIENT)
- << "Server must not send priority";
- QuicConnection::ScopedPacketFlusher flusher(connection());
- send_control_stream_->WritePriority(priority);
+ send_control_stream_->WritePriorityUpdate(priority_update);
}
void QuicSpdySession::OnHttp3GoAway(QuicStreamId stream_id) {
@@ -545,6 +656,22 @@ void QuicSpdySession::OnHttp3GoAway(QuicStreamId stream_id) {
http3_goaway_received_ = true;
}
+bool QuicSpdySession::OnStreamsBlockedFrame(
+ const QuicStreamsBlockedFrame& frame) {
+ if (!QuicSession::OnStreamsBlockedFrame(frame)) {
+ return false;
+ }
+
+ // The peer asked for stream space more than this implementation has. Send
+ // goaway.
+ if (perspective() == Perspective::IS_SERVER &&
+ frame.stream_count >= QuicUtils::GetMaxStreamCount()) {
+ DCHECK_EQ(frame.stream_count, QuicUtils::GetMaxStreamCount());
+ SendHttp3GoAway();
+ }
+ return true;
+}
+
void QuicSpdySession::SendHttp3GoAway() {
DCHECK_EQ(perspective(), Perspective::IS_SERVER);
DCHECK(VersionUsesHttp3(transport_version()));
@@ -561,13 +688,6 @@ void QuicSpdySession::WritePushPromise(QuicStreamId original_stream_id,
return;
}
- if (VersionUsesHttp3(transport_version()) &&
- promised_stream_id > max_allowed_push_id()) {
- QUIC_BUG
- << "Server shouldn't send push id higher than client's MAX_PUSH_ID.";
- return;
- }
-
if (!VersionUsesHttp3(transport_version())) {
SpdyPushPromiseIR push_promise(original_stream_id, promised_stream_id,
std::move(headers));
@@ -577,28 +697,45 @@ void QuicSpdySession::WritePushPromise(QuicStreamId original_stream_id,
SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise));
headers_stream()->WriteOrBufferData(
- QuicStringPiece(frame.data(), frame.size()), false, nullptr);
+ quiche::QuicheStringPiece(frame.data(), frame.size()), false, nullptr);
+ return;
+ }
+
+ if (!max_push_id_.has_value() || promised_stream_id > max_push_id_.value()) {
+ QUIC_BUG
+ << "Server shouldn't send push id higher than client's MAX_PUSH_ID.";
return;
}
// Encode header list.
std::string encoded_headers =
qpack_encoder_->EncodeHeaderList(original_stream_id, headers, nullptr);
+
+ if (debug_visitor_) {
+ debug_visitor_->OnPushPromiseFrameSent(original_stream_id,
+ promised_stream_id, headers);
+ }
+
PushPromiseFrame frame;
frame.push_id = promised_stream_id;
frame.headers = encoded_headers;
- QuicSpdyStream* stream = GetSpdyDataStream(original_stream_id);
+ QuicSpdyStream* stream = GetOrCreateSpdyDataStream(original_stream_id);
stream->WritePushPromise(frame);
}
+bool QuicSpdySession::server_push_enabled() const {
+ return VersionUsesHttp3(transport_version())
+ ? ietf_server_push_enabled_ && max_push_id_.has_value()
+ : server_push_enabled_;
+}
+
void QuicSpdySession::SendInitialData() {
if (!VersionUsesHttp3(transport_version())) {
return;
}
QuicConnection::ScopedPacketFlusher flusher(connection());
send_control_stream_->MaybeSendSettingsFrame();
- if (GetQuicReloadableFlag(quic_send_max_push_id_with_settings) &&
- perspective() == Perspective::IS_CLIENT && !http3_max_push_id_sent_) {
+ if (perspective() == Perspective::IS_CLIENT && !http3_max_push_id_sent_) {
SendMaxPushId();
http3_max_push_id_sent_ = true;
}
@@ -618,27 +755,56 @@ QpackDecoder* QuicSpdySession::qpack_decoder() {
return qpack_decoder_.get();
}
-QuicSpdyStream* QuicSpdySession::GetSpdyDataStream(
+void QuicSpdySession::OnStreamCreated(QuicSpdyStream* stream) {
+ auto it = buffered_stream_priorities_.find(stream->id());
+ if (it == buffered_stream_priorities_.end()) {
+ return;
+ }
+
+ stream->SetPriority(spdy::SpdyStreamPrecedence(it->second));
+ buffered_stream_priorities_.erase(it);
+}
+
+QuicSpdyStream* QuicSpdySession::GetOrCreateSpdyDataStream(
const QuicStreamId stream_id) {
QuicStream* stream = GetOrCreateStream(stream_id);
if (stream && stream->is_static()) {
- QUIC_BUG << "GetSpdyDataStream returns static stream";
+ QUIC_BUG << "GetOrCreateSpdyDataStream returns static stream " << stream_id
+ << " in version " << transport_version() << "\n"
+ << QuicStackTrace();
connection()->CloseConnection(
- QUIC_INVALID_STREAM_ID, "stream is static",
+ QUIC_INVALID_STREAM_ID,
+ quiche::QuicheStrCat("stream ", stream_id, " is static"),
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return nullptr;
}
return static_cast<QuicSpdyStream*>(stream);
}
-void QuicSpdySession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
- QuicSession::OnCryptoHandshakeEvent(event);
- SendInitialData();
+void QuicSpdySession::OnNewEncryptionKeyAvailable(
+ EncryptionLevel level,
+ std::unique_ptr<QuicEncrypter> encrypter) {
+ QuicSession::OnNewEncryptionKeyAvailable(level, std::move(encrypter));
+ if (GetQuicRestartFlag(quic_send_settings_on_write_key_available) &&
+ IsEncryptionEstablished()) {
+ // Send H3 SETTINGs once encryption is established.
+ QUIC_RESTART_FLAG_COUNT_N(quic_send_settings_on_write_key_available, 2, 2);
+ SendInitialData();
+ }
}
void QuicSpdySession::SetDefaultEncryptionLevel(quic::EncryptionLevel level) {
QuicSession::SetDefaultEncryptionLevel(level);
- SendInitialData();
+ if (!GetQuicRestartFlag(quic_send_settings_on_write_key_available)) {
+ SendInitialData();
+ }
+}
+
+void QuicSpdySession::OnOneRttKeysAvailable() {
+ QuicSession::OnOneRttKeysAvailable();
+ if (!GetQuicRestartFlag(quic_send_settings_on_write_key_available)) {
+ SendInitialData();
+ }
}
// True if there are open HTTP requests.
@@ -677,7 +843,7 @@ size_t QuicSpdySession::WriteHeadersOnHeadersStreamImpl(
}
SpdySerializedFrame frame(spdy_framer_.SerializeFrame(headers_frame));
headers_stream()->WriteOrBufferData(
- QuicStringPiece(frame.data(), frame.size()), false,
+ quiche::QuicheStringPiece(frame.data(), frame.size()), false,
std::move(ack_listener));
// Calculate compressed header block size without framing overhead.
@@ -713,6 +879,7 @@ void QuicSpdySession::OnSetting(uint64_t id, uint64_t value) {
switch (id) {
case SETTINGS_QPACK_MAX_TABLE_CAPACITY:
QUIC_DVLOG(1)
+ << ENDPOINT
<< "SETTINGS_QPACK_MAX_TABLE_CAPACITY received with value "
<< value;
// Communicate |value| to encoder, because it is used for encoding
@@ -724,17 +891,19 @@ void QuicSpdySession::OnSetting(uint64_t id, uint64_t value) {
std::min(value, qpack_maximum_dynamic_table_capacity_));
break;
case SETTINGS_MAX_HEADER_LIST_SIZE:
- QUIC_DVLOG(1) << "SETTINGS_MAX_HEADER_LIST_SIZE received with value "
+ QUIC_DVLOG(1) << ENDPOINT
+ << "SETTINGS_MAX_HEADER_LIST_SIZE received with value "
<< value;
max_outbound_header_list_size_ = value;
break;
case SETTINGS_QPACK_BLOCKED_STREAMS:
- QUIC_DVLOG(1) << "SETTINGS_QPACK_BLOCKED_STREAMS received with value "
+ QUIC_DVLOG(1) << ENDPOINT
+ << "SETTINGS_QPACK_BLOCKED_STREAMS received with value "
<< value;
qpack_encoder_->SetMaximumBlockedStreams(value);
break;
default:
- QUIC_DVLOG(1) << "Unknown setting identifier " << id
+ QUIC_DVLOG(1) << ENDPOINT << "Unknown setting identifier " << id
<< " received with value " << value;
// Ignore unknown settings.
break;
@@ -745,7 +914,8 @@ void QuicSpdySession::OnSetting(uint64_t id, uint64_t value) {
// SETTINGS frame received on the headers stream.
switch (id) {
case spdy::SETTINGS_HEADER_TABLE_SIZE:
- QUIC_DVLOG(1) << "SETTINGS_HEADER_TABLE_SIZE received with value "
+ QUIC_DVLOG(1) << ENDPOINT
+ << "SETTINGS_HEADER_TABLE_SIZE received with value "
<< value;
spdy_framer_.UpdateHeaderEncoderTableSize(value);
break;
@@ -753,42 +923,47 @@ void QuicSpdySession::OnSetting(uint64_t id, uint64_t value) {
if (perspective() == Perspective::IS_SERVER) {
// See rfc7540, Section 6.5.2.
if (value > 1) {
- QUIC_DLOG(ERROR) << "Invalid value " << value
+ QUIC_DLOG(ERROR) << ENDPOINT << "Invalid value " << value
<< " received for SETTINGS_ENABLE_PUSH.";
if (IsConnected()) {
CloseConnectionWithDetails(
QUIC_INVALID_HEADERS_STREAM_DATA,
- QuicStrCat("Invalid value for SETTINGS_ENABLE_PUSH: ", value));
+ quiche::QuicheStrCat("Invalid value for SETTINGS_ENABLE_PUSH: ",
+ value));
}
return;
}
- QUIC_DVLOG(1) << "SETTINGS_ENABLE_PUSH received with value " << value;
+ QUIC_DVLOG(1) << ENDPOINT << "SETTINGS_ENABLE_PUSH received with value "
+ << value;
server_push_enabled_ = value;
break;
} else {
QUIC_DLOG(ERROR)
+ << ENDPOINT
<< "Invalid SETTINGS_ENABLE_PUSH received by client with value "
<< value;
if (IsConnected()) {
CloseConnectionWithDetails(
QUIC_INVALID_HEADERS_STREAM_DATA,
- QuicStrCat("Unsupported field of HTTP/2 SETTINGS frame: ", id));
+ quiche::QuicheStrCat(
+ "Unsupported field of HTTP/2 SETTINGS frame: ", id));
}
}
break;
- // TODO(fayang): Need to support SETTINGS_MAX_HEADER_LIST_SIZE when
- // clients are actually sending it.
case spdy::SETTINGS_MAX_HEADER_LIST_SIZE:
- QUIC_DVLOG(1) << "SETTINGS_MAX_HEADER_LIST_SIZE received with value "
+ QUIC_DVLOG(1) << ENDPOINT
+ << "SETTINGS_MAX_HEADER_LIST_SIZE received with value "
<< value;
+ max_outbound_header_list_size_ = value;
break;
default:
- QUIC_DLOG(ERROR) << "Unknown setting identifier " << id
+ QUIC_DLOG(ERROR) << ENDPOINT << "Unknown setting identifier " << id
<< " received with value " << value;
if (IsConnected()) {
CloseConnectionWithDetails(
QUIC_INVALID_HEADERS_STREAM_DATA,
- QuicStrCat("Unsupported field of HTTP/2 SETTINGS frame: ", id));
+ quiche::QuicheStrCat("Unsupported field of HTTP/2 SETTINGS frame: ",
+ id));
}
}
}
@@ -844,8 +1019,8 @@ void QuicSpdySession::OnPriority(SpdyStreamId stream_id,
}
void QuicSpdySession::OnHeaderList(const QuicHeaderList& header_list) {
- QUIC_DVLOG(1) << "Received header list for stream " << stream_id_ << ": "
- << header_list.DebugString();
+ QUIC_DVLOG(1) << ENDPOINT << "Received header list for stream " << stream_id_
+ << ": " << header_list.DebugString();
// This code path is only executed for push promise in IETF QUIC.
if (VersionUsesHttp3(transport_version())) {
DCHECK(promised_stream_id_ !=
@@ -926,11 +1101,12 @@ bool QuicSpdySession::ProcessPendingStream(PendingStream* pending) {
CloseConnectionOnDuplicateHttp3UnidirectionalStreams("Control");
return false;
}
- auto receive_stream = std::make_unique<QuicReceiveControlStream>(pending);
+ auto receive_stream =
+ std::make_unique<QuicReceiveControlStream>(pending, this);
receive_control_stream_ = receive_stream.get();
ActivateStream(std::move(receive_stream));
receive_control_stream_->SetUnblocked();
- QUIC_DVLOG(1) << "Receive Control stream is created";
+ QUIC_DVLOG(1) << ENDPOINT << "Receive Control stream is created";
if (debug_visitor_ != nullptr) {
debug_visitor_->OnPeerControlStreamCreated(
receive_control_stream_->id());
@@ -952,7 +1128,7 @@ bool QuicSpdySession::ProcessPendingStream(PendingStream* pending) {
qpack_encoder_receive_stream_ = encoder_receive.get();
ActivateStream(std::move(encoder_receive));
qpack_encoder_receive_stream_->SetUnblocked();
- QUIC_DVLOG(1) << "Receive QPACK Encoder stream is created";
+ QUIC_DVLOG(1) << ENDPOINT << "Receive QPACK Encoder stream is created";
if (debug_visitor_ != nullptr) {
debug_visitor_->OnPeerQpackEncoderStreamCreated(
qpack_encoder_receive_stream_->id());
@@ -969,7 +1145,7 @@ bool QuicSpdySession::ProcessPendingStream(PendingStream* pending) {
qpack_decoder_receive_stream_ = decoder_receive.get();
ActivateStream(std::move(decoder_receive));
qpack_decoder_receive_stream_->SetUnblocked();
- QUIC_DVLOG(1) << "Receive QPACK Decoder stream is created";
+ QUIC_DVLOG(1) << ENDPOINT << "Receive QPACK Decoder stream is created";
if (debug_visitor_ != nullptr) {
debug_visitor_->OnPeerQpackDecoderStreamCreated(
qpack_decoder_receive_stream_->id());
@@ -977,7 +1153,10 @@ bool QuicSpdySession::ProcessPendingStream(PendingStream* pending) {
return true;
}
default:
- SendStopSending(kHttpUnknownStreamType, pending->id());
+ SendStopSending(
+ static_cast<QuicApplicationErrorCode>(
+ QuicHttp3ErrorCode::IETF_QUIC_HTTP3_STREAM_CREATION_ERROR),
+ pending->id());
pending->StopReading();
}
return false;
@@ -992,6 +1171,9 @@ void QuicSpdySession::MaybeInitializeHttp3UnidirectionalStreams() {
max_inbound_header_list_size_);
send_control_stream_ = send_control.get();
ActivateStream(std::move(send_control));
+ if (debug_visitor_) {
+ debug_visitor_->OnControlStreamCreated(send_control_stream_->id());
+ }
}
if (!qpack_decoder_send_stream_ &&
@@ -1002,6 +1184,10 @@ void QuicSpdySession::MaybeInitializeHttp3UnidirectionalStreams() {
ActivateStream(std::move(decoder_send));
qpack_decoder_->set_qpack_stream_sender_delegate(
qpack_decoder_send_stream_);
+ if (debug_visitor_) {
+ debug_visitor_->OnQpackDecoderStreamCreated(
+ qpack_decoder_send_stream_->id());
+ }
}
if (!qpack_encoder_send_stream_ &&
@@ -1012,6 +1198,10 @@ void QuicSpdySession::MaybeInitializeHttp3UnidirectionalStreams() {
ActivateStream(std::move(encoder_send));
qpack_encoder_->set_qpack_stream_sender_delegate(
qpack_encoder_send_stream_);
+ if (debug_visitor_) {
+ debug_visitor_->OnQpackEncoderStreamCreated(
+ qpack_encoder_send_stream_->id());
+ }
}
}
@@ -1021,41 +1211,83 @@ void QuicSpdySession::OnCanCreateNewOutgoingStream(bool unidirectional) {
}
}
-void QuicSpdySession::SetMaxAllowedPushId(QuicStreamId max_allowed_push_id) {
- if (!VersionUsesHttp3(transport_version())) {
- return;
+void QuicSpdySession::SetMaxPushId(QuicStreamId max_push_id) {
+ DCHECK(VersionUsesHttp3(transport_version()));
+ DCHECK_EQ(Perspective::IS_CLIENT, perspective());
+ if (max_push_id_.has_value()) {
+ DCHECK_GE(max_push_id, max_push_id_.value());
}
- QuicStreamId old_max_allowed_push_id = max_allowed_push_id_;
- max_allowed_push_id_ = max_allowed_push_id;
- QUIC_DVLOG(1) << "Setting max_allowed_push_id to: " << max_allowed_push_id_
- << " from: " << old_max_allowed_push_id;
+ ietf_server_push_enabled_ = true;
- if (perspective() == Perspective::IS_SERVER) {
- if (max_allowed_push_id_ > old_max_allowed_push_id) {
- OnCanCreateNewOutgoingStream(true);
- }
- return;
+ if (max_push_id_.has_value()) {
+ QUIC_DVLOG(1) << "Setting max_push_id to: " << max_push_id
+ << " from: " << max_push_id_.value();
+ } else {
+ QUIC_DVLOG(1) << "Setting max_push_id to: " << max_push_id
+ << " from unset";
}
+ max_push_id_ = max_push_id;
- DCHECK(perspective() == Perspective::IS_CLIENT);
- if (IsCryptoHandshakeConfirmed()) {
+ if (OneRttKeysAvailable()) {
SendMaxPushId();
}
}
+bool QuicSpdySession::OnMaxPushIdFrame(QuicStreamId max_push_id) {
+ DCHECK(VersionUsesHttp3(transport_version()));
+ DCHECK_EQ(Perspective::IS_SERVER, perspective());
+
+ if (max_push_id_.has_value()) {
+ QUIC_DVLOG(1) << "Setting max_push_id to: " << max_push_id
+ << " from: " << max_push_id_.value();
+ } else {
+ QUIC_DVLOG(1) << "Setting max_push_id to: " << max_push_id
+ << " from unset";
+ }
+ quiche::QuicheOptional<QuicStreamId> old_max_push_id = max_push_id_;
+ max_push_id_ = max_push_id;
+
+ if (!old_max_push_id.has_value() ||
+ max_push_id_.value() > old_max_push_id.value()) {
+ OnCanCreateNewOutgoingStream(true);
+ return true;
+ }
+
+ // Equal value is not considered an error.
+ return max_push_id_.value() >= old_max_push_id.value();
+}
+
void QuicSpdySession::SendMaxPushId() {
DCHECK(VersionUsesHttp3(transport_version()));
- send_control_stream_->SendMaxPushIdFrame(max_allowed_push_id_);
+ DCHECK_EQ(Perspective::IS_CLIENT, perspective());
+
+ if (max_push_id_.has_value()) {
+ send_control_stream_->SendMaxPushIdFrame(max_push_id_.value());
+ }
+}
+
+void QuicSpdySession::EnableServerPush() {
+ DCHECK(VersionUsesHttp3(transport_version()));
+ DCHECK_EQ(perspective(), Perspective::IS_SERVER);
+
+ ietf_server_push_enabled_ = true;
+}
+
+bool QuicSpdySession::CanCreatePushStreamWithId(QuicStreamId push_id) {
+ DCHECK(VersionUsesHttp3(transport_version()));
+
+ return ietf_server_push_enabled_ && max_push_id_.has_value() &&
+ max_push_id_.value() >= push_id;
}
void QuicSpdySession::CloseConnectionOnDuplicateHttp3UnidirectionalStreams(
- QuicStringPiece type) {
- QUIC_PEER_BUG << QuicStrCat("Received a duplicate ", type,
- " stream: Closing connection.");
- // TODO(b/124216424): Change to HTTP_STREAM_CREATION_ERROR.
- CloseConnectionWithDetails(QUIC_INVALID_STREAM_ID,
- QuicStrCat(type, " stream is received twice."));
+ quiche::QuicheStringPiece type) {
+ QUIC_PEER_BUG << quiche::QuicheStrCat("Received a duplicate ", type,
+ " stream: Closing connection.");
+ CloseConnectionWithDetails(
+ QUIC_HTTP_DUPLICATE_UNIDIRECTIONAL_STREAM,
+ quiche::QuicheStrCat(type, " stream is received twice."));
}
// static
@@ -1104,4 +1336,6 @@ void QuicSpdySession::LogHeaderCompressionRatioHistogram(
}
}
+#undef ENDPOINT // undef for jumbo builds
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.h
index 575d6641a61..93fa09d9762 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.h
@@ -24,7 +24,8 @@
#include "net/third_party/quiche/src/quic/core/quic_session.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_optional.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.h"
namespace quic {
@@ -60,20 +61,73 @@ class QUIC_EXPORT_PRIVATE Http3DebugVisitor {
virtual ~Http3DebugVisitor();
+ // TODO(https://crbug.com/1062700): Remove default implementation of all
+ // methods after Chrome's QuicHttp3Logger has overrides. This is to make sure
+ // QUICHE merge is not blocked on having to add those overrides, they can
+ // happen asynchronously.
+
+ // Creation of unidirectional streams.
+
+ // Called when locally-initiated control stream is created.
+ virtual void OnControlStreamCreated(QuicStreamId /*stream_id*/) {}
+ // Called when locally-initiated QPACK encoder stream is created.
+ virtual void OnQpackEncoderStreamCreated(QuicStreamId /*stream_id*/) {}
+ // Called when locally-initiated QPACK decoder stream is created.
+ virtual void OnQpackDecoderStreamCreated(QuicStreamId /*stream_id*/) {}
// Called when peer's control stream type is received.
virtual void OnPeerControlStreamCreated(QuicStreamId /*stream_id*/) = 0;
-
// Called when peer's QPACK encoder stream type is received.
virtual void OnPeerQpackEncoderStreamCreated(QuicStreamId /*stream_id*/) = 0;
-
// Called when peer's QPACK decoder stream type is received.
virtual void OnPeerQpackDecoderStreamCreated(QuicStreamId /*stream_id*/) = 0;
- // Called when SETTINGS frame is received.
+ // Incoming HTTP/3 frames on the control stream.
+ virtual void OnCancelPushFrameReceived(const CancelPushFrame& /*frame*/) {}
virtual void OnSettingsFrameReceived(const SettingsFrame& /*frame*/) = 0;
-
- // Called when SETTINGS frame is sent.
+ virtual void OnGoAwayFrameReceived(const GoAwayFrame& /*frame*/) {}
+ virtual void OnMaxPushIdFrameReceived(const MaxPushIdFrame& /*frame*/) {}
+ virtual void OnPriorityUpdateFrameReceived(
+ const PriorityUpdateFrame& /*frame*/) {}
+
+ // Incoming HTTP/3 frames on request or push streams.
+ virtual void OnDataFrameReceived(QuicStreamId /*stream_id*/,
+ QuicByteCount /*payload_length*/) {}
+ virtual void OnHeadersFrameReceived(
+ QuicStreamId /*stream_id*/,
+ QuicByteCount /*compressed_headers_length*/) {}
+ virtual void OnHeadersDecoded(QuicStreamId /*stream_id*/,
+ QuicHeaderList /*headers*/) {}
+ virtual void OnPushPromiseFrameReceived(QuicStreamId /*stream_id*/,
+ QuicStreamId /*push_id*/,
+ QuicByteCount
+ /*compressed_headers_length*/) {}
+ virtual void OnPushPromiseDecoded(QuicStreamId /*stream_id*/,
+ QuicStreamId /*push_id*/,
+ QuicHeaderList /*headers*/) {}
+
+ // Incoming HTTP/3 frames of unknown type on any stream.
+ virtual void OnUnknownFrameReceived(QuicStreamId /*stream_id*/,
+ uint64_t /*frame_type*/,
+ QuicByteCount /*payload_length*/) {}
+
+ // Outgoing HTTP/3 frames on the control stream.
virtual void OnSettingsFrameSent(const SettingsFrame& /*frame*/) = 0;
+ virtual void OnGoAwayFrameSent(QuicStreamId /*stream_id*/) {}
+ virtual void OnMaxPushIdFrameSent(const MaxPushIdFrame& /*frame*/) {}
+ virtual void OnPriorityUpdateFrameSent(const PriorityUpdateFrame& /*frame*/) {
+ }
+
+ // Outgoing HTTP/3 frames on request or push streams.
+ virtual void OnDataFrameSent(QuicStreamId /*stream_id*/,
+ QuicByteCount /*payload_length*/) {}
+ virtual void OnHeadersFrameSent(
+ QuicStreamId /*stream_id*/,
+ const spdy::SpdyHeaderBlock& /*header_block*/) {}
+ virtual void OnPushPromiseFrameSent(
+ QuicStreamId /*stream_id*/,
+ QuicStreamId
+ /*push_id*/,
+ const spdy::SpdyHeaderBlock& /*header_block*/) {}
};
// A QUIC session for HTTP.
@@ -95,10 +149,10 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
void Initialize() override;
// QpackEncoder::DecoderStreamErrorDelegate implementation.
- void OnDecoderStreamError(QuicStringPiece error_message) override;
+ void OnDecoderStreamError(quiche::QuicheStringPiece error_message) override;
// QpackDecoder::EncoderStreamErrorDelegate implementation.
- void OnEncoderStreamError(QuicStringPiece error_message) override;
+ void OnEncoderStreamError(quiche::QuicheStringPiece error_message) override;
// Called by |headers_stream_| when headers with a priority have been
// received for a stream. This method will only be called for server streams.
@@ -127,6 +181,14 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
virtual void OnPriorityFrame(QuicStreamId stream_id,
const spdy::SpdyStreamPrecedence& precedence);
+ // Called when an HTTP/3 PRIORITY_UPDATE frame has been received for a request
+ // stream. Returns false and closes connection if |stream_id| is invalid.
+ bool OnPriorityUpdateForRequestStream(QuicStreamId stream_id, int urgency);
+
+ // Called when an HTTP/3 PRIORITY_UPDATE frame has been received for a push
+ // stream. Returns false and closes connection if |push_id| is invalid.
+ bool OnPriorityUpdateForPushStream(QuicStreamId push_id, int urgency);
+
// Sends contents of |iov| to h2_deframer_, returns number of bytes processed.
size_t ProcessHeaderData(const struct iovec& iov);
@@ -141,21 +203,24 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
const spdy::SpdyStreamPrecedence& precedence,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
- // Writes a PRIORITY frame the to peer. Returns the size in bytes of the
- // resulting PRIORITY frame for QUIC_VERSION_43 and above. Otherwise, does
+ // Writes an HTTP/2 PRIORITY frame the to peer. Returns the size in bytes of
+ // the resulting PRIORITY frame for QUIC_VERSION_43 and above. Otherwise, does
// nothing and returns 0.
size_t WritePriority(QuicStreamId id,
QuicStreamId parent_stream_id,
int weight,
bool exclusive);
- // Writes a HTTP/3 PRIORITY frame to the peer.
- void WriteH3Priority(const PriorityFrame& priority);
+ // Writes an HTTP/3 PRIORITY_UPDATE frame to the peer.
+ void WriteHttp3PriorityUpdate(const PriorityUpdateFrame& priority_update);
// Process received HTTP/3 GOAWAY frame. This method should only be called on
// the client side.
virtual void OnHttp3GoAway(QuicStreamId stream_id);
+ // Send GOAWAY if the peer is blocked on the implementation max.
+ bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override;
+
// Write the GOAWAY |frame| on control stream.
void SendHttp3GoAway();
@@ -171,7 +236,15 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
const QuicHeadersStream* headers_stream() const { return headers_stream_; }
- bool server_push_enabled() const { return server_push_enabled_; }
+ // Returns whether server push is enabled.
+ // For a Google QUIC client this always returns false.
+ // For a Google QUIC server this is set by incoming SETTINGS_ENABLE_PUSH.
+ // For an IETF QUIC client this returns true if SetMaxPushId() has ever been
+ // called.
+ // For an IETF QUIC server this returns true if EnableServerPush() has been
+ // called and the server has received at least one MAX_PUSH_ID frame from the
+ // client.
+ bool server_push_enabled() const;
// Called when a setting is parsed from an incoming SETTINGS frame.
void OnSetting(uint64_t id, uint64_t value);
@@ -231,9 +304,36 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
// those streams are not initialized yet.
void OnCanCreateNewOutgoingStream(bool unidirectional) override;
- void SetMaxAllowedPushId(QuicStreamId max_allowed_push_id);
-
- QuicStreamId max_allowed_push_id() { return max_allowed_push_id_; }
+ // Sets |max_push_id_| and sends a MAX_PUSH_ID frame.
+ // This method must only be called if protocol is IETF QUIC and perspective is
+ // client. |max_push_id| must be greater than or equal to current
+ // |max_push_id_|.
+ void SetMaxPushId(QuicStreamId max_push_id);
+
+ // Sets |max_push_id_|.
+ // This method must only be called if protocol is IETF QUIC and perspective is
+ // server. It must only be called if a MAX_PUSH_ID frame is received.
+ // Returns whether |max_push_id| is greater than or equal to current
+ // |max_push_id_|.
+ bool OnMaxPushIdFrame(QuicStreamId max_push_id);
+
+ // Enables server push.
+ // Must only be called when using IETF QUIC, for which server push is disabled
+ // by default. Server push defaults to enabled and cannot be disabled for
+ // Google QUIC.
+ // Must only be called for a server. A client can effectively disable push by
+ // never calling SetMaxPushId().
+ void EnableServerPush();
+
+ // Returns true if push is enabled and a push with |push_id| can be created.
+ // For a server this means that EnableServerPush() has been called, at least
+ // one MAX_PUSH_ID frame has been received, and the largest received
+ // MAX_PUSH_ID value is greater than or equal to |push_id|.
+ // For a client this means that SetMaxPushId() has been called with
+ // |max_push_id| greater than or equal to |push_id|.
+ // Must only be called when using IETF QUIC.
+ // TODO(b/136295430): Use sequential PUSH IDs instead of stream IDs.
+ bool CanCreatePushStreamWithId(QuicStreamId push_id);
int32_t destruction_indicator() const { return destruction_indicator_; }
@@ -273,6 +373,8 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
(qpack_decoder_ && qpack_decoder_->dynamic_table_entry_referenced());
}
+ void OnStreamCreated(QuicSpdyStream* stream);
+
protected:
// Override CreateIncomingStream(), CreateOutgoingBidirectionalStream() and
// CreateOutgoingUnidirectionalStream() with QuicSpdyStream return type to
@@ -282,7 +384,7 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
virtual QuicSpdyStream* CreateOutgoingBidirectionalStream() = 0;
virtual QuicSpdyStream* CreateOutgoingUnidirectionalStream() = 0;
- QuicSpdyStream* GetSpdyDataStream(const QuicStreamId stream_id);
+ QuicSpdyStream* GetOrCreateSpdyDataStream(const QuicStreamId stream_id);
// If an incoming stream can be created, return true.
virtual bool ShouldCreateIncomingStream(QuicStreamId id) = 0;
@@ -312,10 +414,12 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
bool exclusive,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
- void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override;
- void SetDefaultEncryptionLevel(quic::EncryptionLevel level) override;
+ void OnNewEncryptionKeyAvailable(
+ EncryptionLevel level,
+ std::unique_ptr<QuicEncrypter> encrypter) override;
- bool supports_push_promise() { return supports_push_promise_; }
+ void SetDefaultEncryptionLevel(quic::EncryptionLevel level) override;
+ void OnOneRttKeysAvailable() override;
// Optional, enables instrumentation related to go/quic-hpack.
void SetHpackEncoderDebugVisitor(
@@ -363,7 +467,7 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
const spdy::SpdyStreamPrecedence& precedence);
void CloseConnectionOnDuplicateHttp3UnidirectionalStreams(
- QuicStringPiece type);
+ quiche::QuicheStringPiece type);
// Sends any data which should be sent at the start of a connection,
// including the initial SETTINGS frame, etc.
@@ -408,25 +512,35 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
// The maximum size of a header block that can be sent to the peer. This field
// is informed and set by the peer via SETTINGS frame.
- // TODO(renjietang): Honor this field when sending headers.
+ // TODO(b/148616439): Honor this field when sending headers.
size_t max_outbound_header_list_size_;
- // Set during handshake. If true, resources in x-associated-content and link
- // headers will be pushed.
- bool server_push_enabled_;
-
// Data about the stream whose headers are being processed.
QuicStreamId stream_id_;
QuicStreamId promised_stream_id_;
bool fin_;
size_t frame_len_;
- bool supports_push_promise_;
-
spdy::SpdyFramer spdy_framer_;
http2::Http2DecoderAdapter h2_deframer_;
std::unique_ptr<SpdyFramerVisitor> spdy_framer_visitor_;
- QuicStreamId max_allowed_push_id_;
+
+ // Used in Google QUIC only. Set every time SETTINGS_ENABLE_PUSH is received.
+ // Defaults to true.
+ bool server_push_enabled_;
+
+ // Used in IETF QUIC only. Defaults to false.
+ // Server push is enabled for a server by calling EnableServerPush().
+ // Server push is enabled for a client by calling SetMaxPushId().
+ bool ietf_server_push_enabled_;
+
+ // Used in IETF QUIC only. Unset until a MAX_PUSH_ID frame is received/sent.
+ // For a server, the push ID in the most recently received MAX_PUSH_ID frame.
+ // For a client before 1-RTT keys are available, the push ID to be sent in the
+ // initial MAX_PUSH_ID frame.
+ // For a client after 1-RTT keys are available, the push ID in the most
+ // recently sent MAX_PUSH_ID frame.
+ quiche::QuicheOptional<QuicStreamId> max_push_id_;
// An integer used for live check. The indicator is assigned a value in
// constructor. As long as it is not the assigned value, that would indicate
@@ -441,8 +555,14 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
// If the endpoint has sent HTTP/3 GOAWAY frame.
bool http3_goaway_sent_;
- // If the sendpoint has sent the initial HTTP/3 MAX_PUSH_ID frame.
+ // If SendMaxPushId() has been called from SendInitialData(). Note that a
+ // MAX_PUSH_ID frame is only sent if SetMaxPushId() had been called
+ // beforehand.
bool http3_max_push_id_sent_;
+
+ // Priority values received in PRIORITY_UPDATE frames for streams that are not
+ // open yet.
+ QuicUnorderedMap<QuicStreamId, int> buffered_stream_priorities_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session_test.cc
index b37246acd23..20078062e94 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session_test.cc
@@ -5,6 +5,7 @@
#include "net/third_party/quiche/src/quic/core/http/quic_spdy_session.h"
#include <cstdint>
+#include <limits>
#include <set>
#include <string>
#include <utility>
@@ -12,8 +13,10 @@
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h"
#include "net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_streams_blocked_frame.h"
#include "net/third_party/quiche/src/quic/core/http/http_constants.h"
#include "net/third_party/quiche/src/quic/core/http/http_encoder.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_header_table.h"
#include "net/third_party/quiche/src/quic/core/quic_config.h"
#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
@@ -21,15 +24,11 @@
#include "net/third_party/quiche/src/quic/core/quic_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_header_table_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
@@ -41,7 +40,11 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_stream_send_buffer_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
using spdy::kV3HighestPriority;
@@ -73,12 +76,15 @@ class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {
: QuicCryptoStream(session),
QuicCryptoHandshaker(this, session),
encryption_established_(false),
- handshake_confirmed_(false),
- params_(new QuicCryptoNegotiatedParameters) {}
+ one_rtt_keys_available_(false),
+ params_(new QuicCryptoNegotiatedParameters) {
+ // Simulate a negotiated cipher_suite with a fake value.
+ params_->cipher_suite = 1;
+ }
void OnHandshakeMessage(const CryptoHandshakeMessage& /*message*/) override {
encryption_established_ = true;
- handshake_confirmed_ = true;
+ one_rtt_keys_available_ = true;
QuicErrorCode error;
std::string error_details;
session()->config()->SetInitialStreamFlowControlWindowToSend(
@@ -99,22 +105,29 @@ class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {
session()->config()->ProcessPeerHello(msg, CLIENT, &error_details);
}
EXPECT_THAT(error, IsQuicNoError());
+ session()->OnNewEncryptionKeyAvailable(
+ ENCRYPTION_FORWARD_SECURE,
+ std::make_unique<NullEncrypter>(session()->perspective()));
session()->OnConfigNegotiated();
- if (session()->use_handshake_delegate()) {
- session()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
- session()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
+ if (session()->connection()->version().handshake_protocol ==
+ PROTOCOL_TLS1_3) {
+ session()->OnOneRttKeysAvailable();
} else {
- session()->connection()->SetDefaultEncryptionLevel(
- ENCRYPTION_FORWARD_SECURE);
- session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
+ session()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
}
+ session()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
}
// QuicCryptoStream implementation
bool encryption_established() const override {
return encryption_established_;
}
- bool handshake_confirmed() const override { return handshake_confirmed_; }
+ bool one_rtt_keys_available() const override {
+ return one_rtt_keys_available_;
+ }
+ HandshakeState GetHandshakeState() const override {
+ return one_rtt_keys_available() ? HANDSHAKE_COMPLETE : HANDSHAKE_START;
+ }
const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
const override {
return *params_;
@@ -123,6 +136,8 @@ class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {
return QuicCryptoHandshaker::crypto_message_parser();
}
void OnPacketDecrypted(EncryptionLevel /*level*/) override {}
+ void OnOneRttPacketAcknowledged() override {}
+ void OnHandshakeDoneReceived() override {}
MOCK_METHOD0(OnCanWrite, void());
@@ -134,7 +149,7 @@ class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {
using QuicCryptoStream::session;
bool encryption_established_;
- bool handshake_confirmed_;
+ bool one_rtt_keys_available_;
QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
};
@@ -146,19 +161,6 @@ class TestHeadersStream : public QuicHeadersStream {
MOCK_METHOD0(OnCanWrite, void());
};
-class MockHttp3DebugVisitor : public Http3DebugVisitor {
- public:
- MOCK_METHOD1(OnPeerControlStreamCreated, void(QuicStreamId));
-
- MOCK_METHOD1(OnPeerQpackEncoderStreamCreated, void(QuicStreamId));
-
- MOCK_METHOD1(OnPeerQpackDecoderStreamCreated, void(QuicStreamId));
-
- MOCK_METHOD1(OnSettingsFrameReceived, void(const SettingsFrame&));
-
- MOCK_METHOD1(OnSettingsFrameSent, void(const SettingsFrame&));
-};
-
class TestStream : public QuicSpdyStream {
public:
TestStream(QuicStreamId id, QuicSpdySession* session, StreamType type)
@@ -172,8 +174,8 @@ class TestStream : public QuicSpdyStream {
void OnBodyAvailable() override {}
MOCK_METHOD0(OnCanWrite, void());
- MOCK_METHOD3(RetransmitStreamData,
- bool(QuicStreamOffset, QuicByteCount, bool));
+ MOCK_METHOD4(RetransmitStreamData,
+ bool(QuicStreamOffset, QuicByteCount, bool, TransmissionType));
MOCK_CONST_METHOD0(HasPendingRetransmission, bool());
};
@@ -193,7 +195,7 @@ class TestSession : public QuicSpdySession {
std::make_unique<NullEncrypter>(connection->perspective()));
}
- ~TestSession() override { delete connection(); }
+ ~TestSession() override { DeleteConnection(); }
TestCryptoStream* GetMutableCryptoStream() override {
return &crypto_stream_;
@@ -261,19 +263,18 @@ class TestSession : public QuicSpdySession {
return QuicSpdySession::GetOrCreateStream(stream_id);
}
- QuicConsumedData WritevData(QuicStream* stream,
- QuicStreamId id,
- size_t write_length,
- QuicStreamOffset offset,
- StreamSendingState state) override {
+ QuicConsumedData WritevData(
+ QuicStreamId id,
+ size_t write_length,
+ QuicStreamOffset offset,
+ StreamSendingState state,
+ TransmissionType type,
+ quiche::QuicheOptional<EncryptionLevel> level) override {
bool fin = state != NO_FIN;
QuicConsumedData consumed(write_length, fin);
if (!writev_consumes_all_data_) {
consumed =
- QuicSession::WritevData(stream, id, write_length, offset, state);
- }
- if (fin && consumed.fin_consumed) {
- stream->set_fin_sent(true);
+ QuicSession::WritevData(id, write_length, offset, state, type, level);
}
QuicSessionPeer::GetWriteBlockedStreams(this)->UpdateBytesForStream(
id, consumed.bytes_consumed);
@@ -293,7 +294,8 @@ class TestSession : public QuicSpdySession {
}
MakeIOVector("not empty", &iov);
QuicStreamPeer::SendBuffer(stream).SaveStreamData(&iov, 1, 0, 9);
- QuicConsumedData consumed = WritevData(stream, stream->id(), 9, 0, FIN);
+ QuicConsumedData consumed =
+ WritevData(stream->id(), 9, 0, FIN, NOT_RETRANSMISSION, QuicheNullOpt);
QuicStreamPeer::SendBuffer(stream).OnStreamDataConsumed(
consumed.bytes_consumed);
return consumed;
@@ -301,7 +303,8 @@ class TestSession : public QuicSpdySession {
QuicConsumedData SendLargeFakeData(QuicStream* stream, int bytes) {
DCHECK(writev_consumes_all_data_);
- return WritevData(stream, stream->id(), bytes, 0, FIN);
+ return WritevData(stream->id(), bytes, 0, FIN, NOT_RETRANSMISSION,
+ QuicheNullOpt);
}
using QuicSession::closed_streams;
@@ -339,7 +342,7 @@ class QuicSpdySessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
session_.config()->SetInitialSessionFlowControlWindowToSend(
kInitialSessionFlowControlWindowForTest);
if (VersionUsesHttp3(transport_version())) {
- QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams(
+ QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(
session_.config(),
session_.num_expected_unidirectional_static_streams());
}
@@ -356,6 +359,8 @@ class QuicSpdySessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
.Times(testing::AnyNumber());
+ writer_ = static_cast<MockPacketWriter*>(
+ QuicConnectionPeer::GetWriter(session_.connection()));
}
void CheckClosedStreams() {
@@ -410,6 +415,15 @@ class QuicSpdySessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
return std::string(buffer.get(), header_length);
}
+ std::string SerializePriorityUpdateFrame(
+ const PriorityUpdateFrame& priority_update) {
+ std::unique_ptr<char[]> priority_buffer;
+ QuicByteCount priority_frame_length =
+ HttpEncoder::SerializePriorityUpdateFrame(priority_update,
+ &priority_buffer);
+ return std::string(priority_buffer.get(), priority_frame_length);
+ }
+
QuicStreamId StreamCountToId(QuicStreamCount stream_count,
Perspective perspective,
bool bidirectional) {
@@ -428,11 +442,30 @@ class QuicSpdySessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
return id;
}
+ void CompleteHandshake() {
+ if (VersionHasIetfQuicFrames(transport_version())) {
+ EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
+ }
+ // HANDSHAKE_DONE frame sent by the server.
+ if (connection_->version().HasHandshakeDone() &&
+ connection_->perspective() == Perspective::IS_SERVER) {
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillOnce(Invoke(&ClearControlFrame));
+ }
+
+ CryptoHandshakeMessage message;
+ session_.GetMutableCryptoStream()->OnHandshakeMessage(message);
+ testing::Mock::VerifyAndClearExpectations(writer_);
+ testing::Mock::VerifyAndClearExpectations(connection_);
+ }
+
MockQuicConnectionHelper helper_;
MockAlarmFactory alarm_factory_;
StrictMock<MockQuicConnection>* connection_;
TestSession session_;
std::set<QuicStreamId> closed_streams_;
+ MockPacketWriter* writer_;
};
class QuicSpdySessionTestServer : public QuicSpdySessionTestBase {
@@ -462,18 +495,10 @@ TEST_P(QuicSpdySessionTestServer, SelfAddress) {
EXPECT_TRUE(session_.self_address().IsInitialized());
}
-TEST_P(QuicSpdySessionTestServer, IsCryptoHandshakeConfirmed) {
- if (VersionUsesHttp3(transport_version())) {
- MockPacketWriter* writer = static_cast<MockPacketWriter*>(
- QuicConnectionPeer::GetWriter(session_.connection()));
- EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
- .Times(1)
- .WillRepeatedly(Return(WriteResult(WRITE_STATUS_OK, 0)));
- }
- EXPECT_FALSE(session_.IsCryptoHandshakeConfirmed());
- CryptoHandshakeMessage message;
- session_.GetMutableCryptoStream()->OnHandshakeMessage(message);
- EXPECT_TRUE(session_.IsCryptoHandshakeConfirmed());
+TEST_P(QuicSpdySessionTestServer, OneRttKeysAvailable) {
+ EXPECT_FALSE(session_.OneRttKeysAvailable());
+ CompleteHandshake();
+ EXPECT_TRUE(session_.OneRttKeysAvailable());
}
TEST_P(QuicSpdySessionTestServer, IsClosedStreamDefault) {
@@ -616,10 +641,9 @@ TEST_P(QuicSpdySessionTestServer, ManyAvailableStreams) {
TEST_P(QuicSpdySessionTestServer,
DebugDFatalIfMarkingClosedStreamWriteBlocked) {
- // EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
- if (GetParam() != AllSupportedVersions()[0]) {
- return;
- }
+ CompleteHandshake();
+ EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
+ .WillRepeatedly(Return(WriteResult(WRITE_STATUS_OK, 0)));
TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
QuicStreamId closed_stream_id = stream2->id();
@@ -627,8 +651,8 @@ TEST_P(QuicSpdySessionTestServer,
EXPECT_CALL(*connection_, SendControlFrame(_));
EXPECT_CALL(*connection_, OnStreamReset(closed_stream_id, _));
stream2->Reset(QUIC_BAD_APPLICATION_PAYLOAD);
- std::string msg =
- QuicStrCat("Marking unknown stream ", closed_stream_id, " blocked.");
+ std::string msg = quiche::QuicheStrCat("Marking unknown stream ",
+ closed_stream_id, " blocked.");
EXPECT_QUIC_BUG(session_.MarkConnectionLevelWriteBlocked(closed_stream_id),
msg);
}
@@ -662,6 +686,28 @@ TEST_P(QuicSpdySessionTestServer, OnCanWrite) {
EXPECT_TRUE(session_.WillingAndAbleToWrite());
}
+TEST_P(QuicSpdySessionTestServer, TooLargeStreamBlocked) {
+ // STREAMS_BLOCKED frame is IETF QUIC only.
+ if (!VersionUsesHttp3(transport_version())) {
+ return;
+ }
+
+ CompleteHandshake();
+ StrictMock<MockHttp3DebugVisitor> debug_visitor;
+ session_.set_debug_visitor(&debug_visitor);
+
+ // Simualte the situation where the incoming stream count is at its limit and
+ // the peer is blocked.
+ QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(
+ static_cast<QuicSession*>(&session_), QuicUtils::GetMaxStreamCount());
+ QuicStreamsBlockedFrame frame;
+ frame.stream_count = QuicUtils::GetMaxStreamCount();
+ EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
+ EXPECT_CALL(debug_visitor, OnGoAwayFrameSent(_));
+ session_.OnStreamsBlockedFrame(frame);
+}
+
TEST_P(QuicSpdySessionTestServer, TestBatchedWrites) {
session_.set_writev_consumes_all_data(true);
TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
@@ -729,21 +775,8 @@ TEST_P(QuicSpdySessionTestServer, TestBatchedWrites) {
}
TEST_P(QuicSpdySessionTestServer, OnCanWriteBundlesStreams) {
- if (VersionHasIetfQuicFrames(transport_version())) {
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .WillRepeatedly(Invoke(
- this, &QuicSpdySessionTestServer::ClearMaxStreamsControlFrame));
- }
-
// Encryption needs to be established before data can be sent.
- CryptoHandshakeMessage msg;
- MockPacketWriter* writer = static_cast<MockPacketWriter*>(
- QuicConnectionPeer::GetWriter(session_.connection()));
- EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
- .Times(testing::AnyNumber())
- .WillRepeatedly(Return(WriteResult(WRITE_STATUS_OK, 0)));
- session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
- testing::Mock::VerifyAndClearExpectations(writer);
+ CompleteHandshake();
// Drive congestion control manually.
MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
@@ -773,7 +806,7 @@ TEST_P(QuicSpdySessionTestServer, OnCanWriteBundlesStreams) {
// Expect that we only send one packet, the writes from different streams
// should be bundled together.
- EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
+ EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
EXPECT_CALL(*send_algorithm, OnPacketSent(_, _, _, _, _));
EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
@@ -835,10 +868,8 @@ TEST_P(QuicSpdySessionTestServer, OnCanWriteWriterBlocks) {
EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(true));
// Drive packet writer manually.
- MockPacketWriter* writer = static_cast<MockPacketWriter*>(
- QuicConnectionPeer::GetWriter(session_.connection()));
- EXPECT_CALL(*writer, IsWriteBlocked()).WillRepeatedly(Return(true));
- EXPECT_CALL(*writer, WritePacket(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*writer_, IsWriteBlocked()).WillRepeatedly(Return(true));
+ EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _)).Times(0);
TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
@@ -987,9 +1018,7 @@ TEST_P(QuicSpdySessionTestServer, SendGoAway) {
return;
}
connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
- MockPacketWriter* writer = static_cast<MockPacketWriter*>(
- QuicConnectionPeer::GetWriter(session_.connection()));
- EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
+ EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
EXPECT_CALL(*connection_, SendControlFrame(_))
@@ -1010,8 +1039,14 @@ TEST_P(QuicSpdySessionTestServer, SendHttp3GoAway) {
if (!VersionUsesHttp3(transport_version())) {
return;
}
- connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ CompleteHandshake();
+ StrictMock<MockHttp3DebugVisitor> debug_visitor;
+ session_.set_debug_visitor(&debug_visitor);
+
+ EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
+ EXPECT_CALL(debug_visitor, OnGoAwayFrameSent(_));
session_.SendHttp3GoAway();
EXPECT_TRUE(session_.http3_goaway_sent());
@@ -1067,35 +1102,35 @@ TEST_P(QuicSpdySessionTestServer, ServerReplyToConnecitivityProbe) {
}
TEST_P(QuicSpdySessionTestServer, IncreasedTimeoutAfterCryptoHandshake) {
- if (VersionUsesHttp3(transport_version())) {
- MockPacketWriter* writer = static_cast<MockPacketWriter*>(
- QuicConnectionPeer::GetWriter(session_.connection()));
- EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
- .Times(1)
- .WillRepeatedly(Return(WriteResult(WRITE_STATUS_OK, 0)));
- }
EXPECT_EQ(kInitialIdleTimeoutSecs + 3,
QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds());
- CryptoHandshakeMessage msg;
- session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
+ CompleteHandshake();
EXPECT_EQ(kMaximumIdleTimeoutSecs + 3,
QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds());
}
TEST_P(QuicSpdySessionTestServer, RstStreamBeforeHeadersDecompressed) {
+ CompleteHandshake();
// Send two bytes of payload.
QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
- QuicStringPiece("HT"));
+ quiche::QuicheStringPiece("HT"));
session_.OnStreamFrame(data1);
EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams());
- EXPECT_CALL(*connection_, SendControlFrame(_));
if (!VersionHasIetfQuicFrames(transport_version())) {
// For version99, OnStreamReset gets called because of the STOP_SENDING,
// below. EXPECT the call there.
EXPECT_CALL(*connection_,
OnStreamReset(GetNthClientInitiatedBidirectionalId(0), _));
}
+
+ // In HTTP/3, Qpack stream will send data on stream reset and cause packet to
+ // be flushed.
+ if (VersionUsesHttp3(transport_version())) {
+ EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
+ }
+ EXPECT_CALL(*connection_, SendControlFrame(_));
QuicRstStreamFrame rst1(kInvalidControlFrameId,
GetNthClientInitiatedBidirectionalId(0),
QUIC_ERROR_PROCESSING_STREAM, 0);
@@ -1129,14 +1164,14 @@ TEST_P(QuicSpdySessionTestServer, OnStreamFrameFinStaticStreamId) {
id = GetNthClientInitiatedUnidirectionalStreamId(transport_version(), 3);
char type[] = {kControlStream};
- QuicStreamFrame data1(id, false, 0, QuicStringPiece(type, 1));
+ QuicStreamFrame data1(id, false, 0, quiche::QuicheStringPiece(type, 1));
session_.OnStreamFrame(data1);
} else {
id = QuicUtils::GetHeadersStreamId(transport_version());
}
// Send two bytes of payload.
- QuicStreamFrame data1(id, true, 0, QuicStringPiece("HT"));
+ QuicStreamFrame data1(id, true, 0, quiche::QuicheStringPiece("HT"));
EXPECT_CALL(*connection_,
CloseConnection(
QUIC_INVALID_STREAM_ID, "Attempt to close a static stream",
@@ -1146,31 +1181,37 @@ TEST_P(QuicSpdySessionTestServer, OnStreamFrameFinStaticStreamId) {
TEST_P(QuicSpdySessionTestServer, OnRstStreamStaticStreamId) {
QuicStreamId id;
+ QuicErrorCode expected_error;
+ std::string error_message;
// Initialize HTTP/3 control stream.
if (VersionUsesHttp3(transport_version())) {
id = GetNthClientInitiatedUnidirectionalStreamId(transport_version(), 3);
char type[] = {kControlStream};
- QuicStreamFrame data1(id, false, 0, QuicStringPiece(type, 1));
+ QuicStreamFrame data1(id, false, 0, quiche::QuicheStringPiece(type, 1));
session_.OnStreamFrame(data1);
+ expected_error = QUIC_HTTP_CLOSED_CRITICAL_STREAM;
+ error_message = "RESET_STREAM received for receive control stream";
} else {
id = QuicUtils::GetHeadersStreamId(transport_version());
+ expected_error = QUIC_INVALID_STREAM_ID;
+ error_message = "Attempt to reset headers stream";
}
// Send two bytes of payload.
QuicRstStreamFrame rst1(kInvalidControlFrameId, id,
QUIC_ERROR_PROCESSING_STREAM, 0);
- EXPECT_CALL(*connection_,
- CloseConnection(
- QUIC_INVALID_STREAM_ID, "Attempt to reset a static stream",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(expected_error, error_message,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
session_.OnRstStream(rst1);
}
TEST_P(QuicSpdySessionTestServer, OnStreamFrameInvalidStreamId) {
// Send two bytes of payload.
QuicStreamFrame data1(QuicUtils::GetInvalidStreamId(transport_version()),
- true, 0, QuicStringPiece("HT"));
+ true, 0, quiche::QuicheStringPiece("HT"));
EXPECT_CALL(*connection_,
CloseConnection(
QUIC_INVALID_STREAM_ID, "Received data for an invalid stream",
@@ -1217,8 +1258,7 @@ TEST_P(QuicSpdySessionTestServer, HandshakeUnblocksFlowControlBlockedStream) {
// Now complete the crypto handshake, resulting in an increased flow control
// send window.
- CryptoHandshakeMessage msg;
- session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
+ CompleteHandshake();
EXPECT_TRUE(QuicSessionPeer::IsStreamWriteBlocked(&session_, stream2->id()));
// Stream is now unblocked.
EXPECT_FALSE(stream2->flow_controller()->IsBlocked());
@@ -1269,8 +1309,7 @@ TEST_P(QuicSpdySessionTestServer,
// Now complete the crypto handshake, resulting in an increased flow control
// send window.
- CryptoHandshakeMessage msg;
- session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
+ CompleteHandshake();
EXPECT_TRUE(QuicSessionPeer::IsStreamWriteBlocked(
&session_, QuicUtils::GetCryptoStreamId(transport_version())));
// Stream is now unblocked and will no longer have buffered data.
@@ -1320,8 +1359,8 @@ TEST_P(QuicSpdySessionTestServer,
while (!headers_stream->flow_controller()->IsBlocked() && stream_id < 2000) {
EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
- headers["header"] = QuicStrCat(random.RandUint64(), random.RandUint64(),
- random.RandUint64());
+ headers["header"] = quiche::QuicheStrCat(
+ random.RandUint64(), random.RandUint64(), random.RandUint64());
session_.WriteHeadersOnHeadersStream(stream_id, headers.Clone(), true,
spdy::SpdyStreamPrecedence(0),
nullptr);
@@ -1341,8 +1380,7 @@ TEST_P(QuicSpdySessionTestServer,
// Now complete the crypto handshake, resulting in an increased flow control
// send window.
- CryptoHandshakeMessage msg;
- session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
+ CompleteHandshake();
// Stream is now unblocked and will no longer have buffered data.
EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked());
@@ -1356,6 +1394,9 @@ TEST_P(QuicSpdySessionTestServer,
TEST_P(QuicSpdySessionTestServer,
ConnectionFlowControlAccountingRstOutOfOrder) {
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillRepeatedly(Invoke(&ClearControlFrame));
+ CompleteHandshake();
// Test that when we receive an out of order stream RST we correctly adjust
// our connection level flow control receive window.
// On close, the stream should mark as consumed all bytes between the highest
@@ -1365,13 +1406,14 @@ TEST_P(QuicSpdySessionTestServer,
const QuicStreamOffset kByteOffset =
1 + kInitialSessionFlowControlWindowForTest / 2;
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .Times(2)
- .WillRepeatedly(Invoke(&ClearControlFrame));
if (!VersionHasIetfQuicFrames(transport_version())) {
// For version99 the call to OnStreamReset happens as a result of receiving
// the STOP_SENDING, so set up the EXPECT there.
EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ } else {
+ EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
}
QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(),
QUIC_STREAM_CANCELLED, kByteOffset);
@@ -1388,6 +1430,7 @@ TEST_P(QuicSpdySessionTestServer,
// STOP_SENDING.
EXPECT_CALL(*connection_,
OnStreamReset(stream->id(), QUIC_STREAM_CANCELLED));
+ EXPECT_CALL(*connection_, SendControlFrame(_));
session_.OnStopSendingFrame(stop_sending);
}
@@ -1422,6 +1465,9 @@ TEST_P(QuicSpdySessionTestServer,
}
TEST_P(QuicSpdySessionTestServer, ConnectionFlowControlAccountingFinAfterRst) {
+ CompleteHandshake();
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillRepeatedly(Invoke(&ClearControlFrame));
// Test that when we RST the stream (and tear down stream state), and then
// receive a FIN from the peer, we correctly adjust our connection level flow
// control receive window.
@@ -1438,7 +1484,10 @@ TEST_P(QuicSpdySessionTestServer, ConnectionFlowControlAccountingFinAfterRst) {
// Reset our stream: this results in the stream being closed locally.
TestStream* stream = session_.CreateOutgoingBidirectionalStream();
- EXPECT_CALL(*connection_, SendControlFrame(_));
+ if (VersionUsesHttp3(transport_version())) {
+ EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
+ }
EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
stream->Reset(QUIC_STREAM_CANCELLED);
@@ -1447,7 +1496,8 @@ TEST_P(QuicSpdySessionTestServer, ConnectionFlowControlAccountingFinAfterRst) {
// account the total number of bytes sent by the peer.
const QuicStreamOffset kByteOffset = 5678;
std::string body = "hello";
- QuicStreamFrame frame(stream->id(), true, kByteOffset, QuicStringPiece(body));
+ QuicStreamFrame frame(stream->id(), true, kByteOffset,
+ quiche::QuicheStringPiece(body));
session_.OnStreamFrame(frame);
QuicStreamOffset total_stream_bytes_sent_by_peer =
@@ -1460,6 +1510,7 @@ TEST_P(QuicSpdySessionTestServer, ConnectionFlowControlAccountingFinAfterRst) {
}
TEST_P(QuicSpdySessionTestServer, ConnectionFlowControlAccountingRstAfterRst) {
+ CompleteHandshake();
// Test that when we RST the stream (and tear down stream state), and then
// receive a RST from the peer, we correctly adjust our connection level flow
// control receive window.
@@ -1476,6 +1527,10 @@ TEST_P(QuicSpdySessionTestServer, ConnectionFlowControlAccountingRstAfterRst) {
// Reset our stream: this results in the stream being closed locally.
TestStream* stream = session_.CreateOutgoingBidirectionalStream();
+ if (VersionUsesHttp3(transport_version())) {
+ EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
+ }
EXPECT_CALL(*connection_, SendControlFrame(_));
EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
stream->Reset(QUIC_STREAM_CANCELLED);
@@ -1531,8 +1586,7 @@ TEST_P(QuicSpdySessionTestServer, TooLowUnidirectionalStreamLimitHttp3) {
if (!VersionUsesHttp3(transport_version())) {
return;
}
- QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams(session_.config(),
- 2u);
+ QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(session_.config(), 2u);
EXPECT_CALL(
*connection_,
@@ -1552,6 +1606,7 @@ TEST_P(QuicSpdySessionTestServer, CustomFlowControlWindow) {
}
TEST_P(QuicSpdySessionTestServer, FlowControlWithInvalidFinalOffset) {
+ CompleteHandshake();
// Test that if we receive a stream RST with a highest byte offset that
// violates flow control, that we close the connection.
const uint64_t kLargeOffset = kInitialSessionFlowControlWindowForTest + 1;
@@ -1561,10 +1616,15 @@ TEST_P(QuicSpdySessionTestServer, FlowControlWithInvalidFinalOffset) {
// Check that stream frame + FIN results in connection close.
TestStream* stream = session_.CreateOutgoingBidirectionalStream();
+ if (VersionUsesHttp3(transport_version())) {
+ EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
+ }
EXPECT_CALL(*connection_, SendControlFrame(_));
EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
stream->Reset(QUIC_STREAM_CANCELLED);
- QuicStreamFrame frame(stream->id(), true, kLargeOffset, QuicStringPiece());
+ QuicStreamFrame frame(stream->id(), true, kLargeOffset,
+ quiche::QuicheStringPiece());
session_.OnStreamFrame(frame);
// Check that RST results in connection close.
@@ -1630,7 +1690,7 @@ TEST_P(QuicSpdySessionTestServer,
// FIN or a RST_STREAM from the client.
const QuicStreamId kNextId = QuicUtils::StreamIdDelta(transport_version());
for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId; i += kNextId) {
- QuicStreamFrame data1(i, false, 0, QuicStringPiece("HT"));
+ QuicStreamFrame data1(i, false, 0, quiche::QuicheStringPiece("HT"));
session_.OnStreamFrame(data1);
// EXPECT_EQ(1u, session_.GetNumOpenStreams());
if (!VersionHasIetfQuicFrames(transport_version())) {
@@ -1666,7 +1726,8 @@ TEST_P(QuicSpdySessionTestServer,
_));
}
// Create one more data streams to exceed limit of open stream.
- QuicStreamFrame data1(kFinalStreamId, false, 0, QuicStringPiece("HT"));
+ QuicStreamFrame data1(kFinalStreamId, false, 0,
+ quiche::QuicheStringPiece("HT"));
session_.OnStreamFrame(data1);
}
@@ -1701,7 +1762,7 @@ TEST_P(QuicSpdySessionTestServer, DrainingStreamsDoNotCountAsOpened) {
const QuicStreamId kFinalStreamId =
GetNthClientInitiatedBidirectionalId(kMaxStreams + 1);
for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId; i += IdDelta()) {
- QuicStreamFrame data1(i, true, 0, QuicStringPiece("HT"));
+ QuicStreamFrame data1(i, true, 0, quiche::QuicheStringPiece("HT"));
session_.OnStreamFrame(data1);
EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams());
session_.StreamDraining(i);
@@ -1787,9 +1848,11 @@ TEST_P(QuicSpdySessionTestClient, TooLargeHeadersMustNotCauseWriteAfterReset) {
if (VersionUsesHttp3(transport_version())) {
return;
}
-
+ CompleteHandshake();
TestStream* stream = session_.CreateOutgoingBidirectionalStream();
+ EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
// Write headers with FIN set to close write side of stream.
// Header block does not matter.
stream->WriteHeaders(SpdyHeaderBlock(), /* fin = */ true, nullptr);
@@ -1815,7 +1878,7 @@ TEST_P(QuicSpdySessionTestClient, RecordFinAfterReadSideClosed) {
QuicStreamPeer::CloseReadSide(stream);
// Receive a stream data frame with FIN.
- QuicStreamFrame frame(stream_id, true, 0, QuicStringPiece());
+ QuicStreamFrame frame(stream_id, true, 0, quiche::QuicheStringPiece());
session_.OnStreamFrame(frame);
EXPECT_TRUE(stream->fin_received());
@@ -1841,15 +1904,15 @@ TEST_P(QuicSpdySessionTestClient, WritePriority) {
// IETF QUIC currently doesn't support PRIORITY.
return;
}
+ CompleteHandshake();
+
TestHeadersStream* headers_stream;
QuicSpdySessionPeer::SetHeadersStream(&session_, nullptr);
headers_stream = new TestHeadersStream(&session_);
QuicSpdySessionPeer::SetHeadersStream(&session_, headers_stream);
// Make packet writer blocked so |headers_stream| will buffer its write data.
- MockPacketWriter* writer = static_cast<MockPacketWriter*>(
- QuicConnectionPeer::GetWriter(session_.connection()));
- EXPECT_CALL(*writer, IsWriteBlocked()).WillRepeatedly(Return(true));
+ EXPECT_CALL(*writer_, IsWriteBlocked()).WillRepeatedly(Return(true));
const QuicStreamId id = 4;
const QuicStreamId parent_stream_id = 9;
@@ -1869,8 +1932,8 @@ TEST_P(QuicSpdySessionTestClient, WritePriority) {
const QuicMemSlice& slice =
QuicStreamSendBufferPeer::CurrentWriteSlice(&send_buffer)->slice;
- EXPECT_EQ(QuicStringPiece(frame.data(), frame.size()),
- QuicStringPiece(slice.data(), slice.length()));
+ EXPECT_EQ(quiche::QuicheStringPiece(frame.data(), frame.size()),
+ quiche::QuicheStringPiece(slice.data(), slice.length()));
}
TEST_P(QuicSpdySessionTestClient, Http3ServerPush) {
@@ -1881,7 +1944,7 @@ TEST_P(QuicSpdySessionTestClient, Http3ServerPush) {
EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
// Push unidirectional stream is type 0x01.
- std::string frame_type1 = QuicTextUtils::HexDecode("01");
+ std::string frame_type1 = quiche::QuicheTextUtils::HexDecode("01");
QuicStreamId stream_id1 =
GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0);
session_.OnStreamFrame(QuicStreamFrame(stream_id1, /* fin = */ false,
@@ -1893,7 +1956,7 @@ TEST_P(QuicSpdySessionTestClient, Http3ServerPush) {
EXPECT_EQ(1u, session_.flow_controller()->bytes_consumed());
// The same stream type can be encoded differently.
- std::string frame_type2 = QuicTextUtils::HexDecode("80000001");
+ std::string frame_type2 = quiche::QuicheTextUtils::HexDecode("80000001");
QuicStreamId stream_id2 =
GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 1);
session_.OnStreamFrame(QuicStreamFrame(stream_id2, /* fin = */ false,
@@ -1913,9 +1976,9 @@ TEST_P(QuicSpdySessionTestClient, Http3ServerPushOutofOrderFrame) {
EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
// Push unidirectional stream is type 0x01.
- std::string frame_type = QuicTextUtils::HexDecode("01");
+ std::string frame_type = quiche::QuicheTextUtils::HexDecode("01");
// The first field of a push stream is the Push ID.
- std::string push_id = QuicTextUtils::HexDecode("4000");
+ std::string push_id = quiche::QuicheTextUtils::HexDecode("4000");
QuicStreamId stream_id =
GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0);
@@ -2095,11 +2158,14 @@ TEST_P(QuicSpdySessionTestServer, RetransmitFrames) {
frames.push_back(QuicFrame(frame3));
EXPECT_FALSE(session_.WillingAndAbleToWrite());
- EXPECT_CALL(*stream2, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
+ EXPECT_CALL(*stream2, RetransmitStreamData(_, _, _, _))
+ .WillOnce(Return(true));
EXPECT_CALL(*connection_, SendControlFrame(_))
.WillOnce(Invoke(&ClearControlFrame));
- EXPECT_CALL(*stream4, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
- EXPECT_CALL(*stream6, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
+ EXPECT_CALL(*stream4, RetransmitStreamData(_, _, _, _))
+ .WillOnce(Return(true));
+ EXPECT_CALL(*stream6, RetransmitStreamData(_, _, _, _))
+ .WillOnce(Return(true));
EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
session_.RetransmitFrames(frames, TLP_RETRANSMISSION);
}
@@ -2113,6 +2179,77 @@ TEST_P(QuicSpdySessionTestServer, OnPriorityFrame) {
stream->precedence());
}
+TEST_P(QuicSpdySessionTestServer, OnPriorityUpdateFrame) {
+ if (!VersionUsesHttp3(transport_version())) {
+ return;
+ }
+
+ StrictMock<MockHttp3DebugVisitor> debug_visitor;
+ session_.set_debug_visitor(&debug_visitor);
+
+ // Create control stream.
+ QuicStreamId receive_control_stream_id =
+ GetNthClientInitiatedUnidirectionalStreamId(transport_version(), 3);
+ char type[] = {kControlStream};
+ quiche::QuicheStringPiece stream_type(type, 1);
+ QuicStreamOffset offset = 0;
+ QuicStreamFrame data1(receive_control_stream_id, false, offset, stream_type);
+ offset += stream_type.length();
+ EXPECT_CALL(debug_visitor,
+ OnPeerControlStreamCreated(receive_control_stream_id));
+ session_.OnStreamFrame(data1);
+ EXPECT_EQ(receive_control_stream_id,
+ QuicSpdySessionPeer::GetReceiveControlStream(&session_)->id());
+
+ // Send SETTINGS frame.
+ std::string serialized_settings = EncodeSettings({});
+ QuicStreamFrame data2(receive_control_stream_id, false, offset,
+ serialized_settings);
+ offset += serialized_settings.length();
+ EXPECT_CALL(debug_visitor, OnSettingsFrameReceived(_));
+ session_.OnStreamFrame(data2);
+
+ // PRIORITY_UPDATE frame for first request stream.
+ const QuicStreamId stream_id1 = GetNthClientInitiatedBidirectionalId(0);
+ struct PriorityUpdateFrame priority_update1;
+ priority_update1.prioritized_element_type = REQUEST_STREAM;
+ priority_update1.prioritized_element_id = stream_id1;
+ priority_update1.priority_field_value = "u=2";
+ std::string serialized_priority_update1 =
+ SerializePriorityUpdateFrame(priority_update1);
+ QuicStreamFrame data3(receive_control_stream_id,
+ /* fin = */ false, offset, serialized_priority_update1);
+ offset += serialized_priority_update1.size();
+
+ // PRIORITY_UPDATE frame arrives after stream creation.
+ TestStream* stream1 = session_.CreateIncomingStream(stream_id1);
+ EXPECT_EQ(QuicStream::kDefaultUrgency,
+ stream1->precedence().spdy3_priority());
+ EXPECT_CALL(debug_visitor, OnPriorityUpdateFrameReceived(priority_update1));
+ session_.OnStreamFrame(data3);
+ EXPECT_EQ(2u, stream1->precedence().spdy3_priority());
+
+ // PRIORITY_UPDATE frame for second request stream.
+ const QuicStreamId stream_id2 = GetNthClientInitiatedBidirectionalId(1);
+ struct PriorityUpdateFrame priority_update2;
+ priority_update2.prioritized_element_type = REQUEST_STREAM;
+ priority_update2.prioritized_element_id = stream_id2;
+ priority_update2.priority_field_value = "u=2";
+ std::string serialized_priority_update2 =
+ SerializePriorityUpdateFrame(priority_update2);
+ QuicStreamFrame stream_frame3(receive_control_stream_id,
+ /* fin = */ false, offset,
+ serialized_priority_update2);
+
+ // PRIORITY_UPDATE frame arrives before stream creation,
+ // priority value is buffered.
+ EXPECT_CALL(debug_visitor, OnPriorityUpdateFrameReceived(priority_update2));
+ session_.OnStreamFrame(stream_frame3);
+ // Priority is applied upon stream construction.
+ TestStream* stream2 = session_.CreateIncomingStream(stream_id2);
+ EXPECT_EQ(2u, stream2->precedence().spdy3_priority());
+}
+
TEST_P(QuicSpdySessionTestServer, SimplePendingStreamType) {
if (!VersionUsesHttp3(transport_version())) {
return;
@@ -2120,7 +2257,7 @@ TEST_P(QuicSpdySessionTestServer, SimplePendingStreamType) {
char input[] = {0x04, // type
'a', 'b', 'c'}; // data
- QuicStringPiece payload(input, QUIC_ARRAYSIZE(input));
+ quiche::QuicheStringPiece payload(input, QUICHE_ARRAYSIZE(input));
// This is a server test with a client-initiated unidirectional stream.
QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
@@ -2131,7 +2268,17 @@ TEST_P(QuicSpdySessionTestServer, SimplePendingStreamType) {
// A STOP_SENDING frame is sent in response to the unknown stream type.
EXPECT_CALL(*connection_, SendControlFrame(_))
- .WillOnce(Invoke(&VerifyAndClearStopSendingFrame));
+ .WillOnce(Invoke([stream_id](const QuicFrame& frame) {
+ EXPECT_EQ(STOP_SENDING_FRAME, frame.type);
+
+ QuicStopSendingFrame* stop_sending = frame.stop_sending_frame;
+ EXPECT_EQ(stream_id, stop_sending->stream_id);
+ EXPECT_EQ(QuicHttp3ErrorCode::IETF_QUIC_HTTP3_STREAM_CREATION_ERROR,
+ static_cast<QuicHttp3ErrorCode>(
+ stop_sending->application_error_code));
+
+ return ClearControlFrame(frame);
+ }));
session_.OnStreamFrame(frame);
PendingStream* pending =
@@ -2156,7 +2303,7 @@ TEST_P(QuicSpdySessionTestServer, SimplePendingStreamTypeOutOfOrderDelivery) {
char input[] = {0x04, // type
'a', 'b', 'c'}; // data
- QuicStringPiece payload(input, QUIC_ARRAYSIZE(input));
+ quiche::QuicheStringPiece payload(input, QUICHE_ARRAYSIZE(input));
// This is a server test with a client-initiated unidirectional stream.
QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
@@ -2197,7 +2344,7 @@ TEST_P(QuicSpdySessionTestServer,
char input[] = {0x41, 0x00, // type (256)
'a', 'b', 'c'}; // data
- QuicStringPiece payload(input, QUIC_ARRAYSIZE(input));
+ quiche::QuicheStringPiece payload(input, QUICHE_ARRAYSIZE(input));
// This is a server test with a client-initiated unidirectional stream.
QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
@@ -2238,25 +2385,29 @@ TEST_P(QuicSpdySessionTestServer, ReceiveControlStream) {
if (!VersionUsesHttp3(transport_version())) {
return;
}
- MockHttp3DebugVisitor debug_visitor;
+
+ CompleteHandshake();
+ StrictMock<MockHttp3DebugVisitor> debug_visitor;
+ session_.set_debug_visitor(&debug_visitor);
+
// Use an arbitrary stream id.
QuicStreamId stream_id =
GetNthClientInitiatedUnidirectionalStreamId(transport_version(), 3);
char type[] = {kControlStream};
- QuicStreamFrame data1(stream_id, false, 0, QuicStringPiece(type, 1));
- EXPECT_CALL(debug_visitor, OnPeerControlStreamCreated(stream_id)).Times(0);
+ QuicStreamFrame data1(stream_id, false, 0,
+ quiche::QuicheStringPiece(type, 1));
+ EXPECT_CALL(debug_visitor, OnPeerControlStreamCreated(stream_id));
session_.OnStreamFrame(data1);
EXPECT_EQ(stream_id,
QuicSpdySessionPeer::GetReceiveControlStream(&session_)->id());
- session_.set_debug_visitor(&debug_visitor);
SettingsFrame settings;
settings.values[SETTINGS_QPACK_MAX_TABLE_CAPACITY] = 512;
settings.values[SETTINGS_MAX_HEADER_LIST_SIZE] = 5;
settings.values[SETTINGS_QPACK_BLOCKED_STREAMS] = 42;
std::string data = EncodeSettings(settings);
- QuicStreamFrame frame(stream_id, false, 1, QuicStringPiece(data));
+ QuicStreamFrame frame(stream_id, false, 1, quiche::QuicheStringPiece(data));
QpackEncoder* qpack_encoder = session_.qpack_encoder();
QpackHeaderTable* header_table =
@@ -2267,6 +2418,8 @@ TEST_P(QuicSpdySessionTestServer, ReceiveControlStream) {
EXPECT_NE(5u, session_.max_outbound_header_list_size());
EXPECT_NE(42u, QpackEncoderPeer::maximum_blocked_streams(qpack_encoder));
+ EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
EXPECT_CALL(debug_visitor, OnSettingsFrameReceived(settings));
session_.OnStreamFrame(frame);
@@ -2289,8 +2442,9 @@ TEST_P(QuicSpdySessionTestServer, ReceiveControlStreamOutOfOrderDelivery) {
settings.values[SETTINGS_MAX_HEADER_LIST_SIZE] = 5;
std::string data = EncodeSettings(settings);
- QuicStreamFrame data1(stream_id, false, 1, QuicStringPiece(data));
- QuicStreamFrame data2(stream_id, false, 0, QuicStringPiece(type, 1));
+ QuicStreamFrame data1(stream_id, false, 1, quiche::QuicheStringPiece(data));
+ QuicStreamFrame data2(stream_id, false, 0,
+ quiche::QuicheStringPiece(type, 1));
session_.OnStreamFrame(data1);
EXPECT_NE(5u, session_.max_outbound_header_list_size());
@@ -2310,14 +2464,15 @@ TEST_P(QuicSpdySessionTestServer, StreamClosedWhileHeaderDecodingBlocked) {
TestStream* stream = session_.CreateIncomingStream(stream_id);
// HEADERS frame referencing first dynamic table entry.
- std::string headers_payload = QuicTextUtils::HexDecode("020080");
+ std::string headers_payload = quiche::QuicheTextUtils::HexDecode("020080");
std::unique_ptr<char[]> headers_buffer;
QuicByteCount headers_frame_header_length =
HttpEncoder::SerializeHeadersFrameHeader(headers_payload.length(),
&headers_buffer);
- QuicStringPiece headers_frame_header(headers_buffer.get(),
- headers_frame_header_length);
- std::string headers = QuicStrCat(headers_frame_header, headers_payload);
+ quiche::QuicheStringPiece headers_frame_header(headers_buffer.get(),
+ headers_frame_header_length);
+ std::string headers =
+ quiche::QuicheStrCat(headers_frame_header, headers_payload);
stream->OnStreamFrame(QuicStreamFrame(stream_id, false, 0, headers));
// Decoding is blocked because dynamic table entry has not been received yet.
@@ -2344,14 +2499,15 @@ TEST_P(QuicSpdySessionTestServer, SessionDestroyedWhileHeaderDecodingBlocked) {
TestStream* stream = session_.CreateIncomingStream(stream_id);
// HEADERS frame referencing first dynamic table entry.
- std::string headers_payload = QuicTextUtils::HexDecode("020080");
+ std::string headers_payload = quiche::QuicheTextUtils::HexDecode("020080");
std::unique_ptr<char[]> headers_buffer;
QuicByteCount headers_frame_header_length =
HttpEncoder::SerializeHeadersFrameHeader(headers_payload.length(),
&headers_buffer);
- QuicStringPiece headers_frame_header(headers_buffer.get(),
- headers_frame_header_length);
- std::string headers = QuicStrCat(headers_frame_header, headers_payload);
+ quiche::QuicheStringPiece headers_frame_header(headers_buffer.get(),
+ headers_frame_header_length);
+ std::string headers =
+ quiche::QuicheStrCat(headers_frame_header, headers_payload);
stream->OnStreamFrame(QuicStreamFrame(stream_id, false, 0, headers));
// Decoding is blocked because dynamic table entry has not been received yet.
@@ -2376,7 +2532,7 @@ TEST_P(QuicSpdySessionTestClient, ResetAfterInvalidIncomingStreamType) {
// Payload consists of two bytes. The first byte is an unknown unidirectional
// stream type. The second one would be the type of a push stream, but it
// must not be interpreted as stream type.
- std::string payload = QuicTextUtils::HexDecode("3f01");
+ std::string payload = quiche::QuicheTextUtils::HexDecode("3f01");
QuicStreamFrame frame(stream_id, /* fin = */ false, /* offset = */ 0,
payload);
@@ -2422,7 +2578,7 @@ TEST_P(QuicSpdySessionTestClient, FinAfterInvalidIncomingStreamType) {
// Payload consists of two bytes. The first byte is an unknown unidirectional
// stream type. The second one would be the type of a push stream, but it
// must not be interpreted as stream type.
- std::string payload = QuicTextUtils::HexDecode("3f01");
+ std::string payload = quiche::QuicheTextUtils::HexDecode("3f01");
QuicStreamFrame frame(stream_id, /* fin = */ false, /* offset = */ 0,
payload);
@@ -2459,7 +2615,7 @@ TEST_P(QuicSpdySessionTestClient, ResetInMiddleOfStreamType) {
GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0);
// Payload is the first byte of a two byte varint encoding.
- std::string payload = QuicTextUtils::HexDecode("40");
+ std::string payload = quiche::QuicheTextUtils::HexDecode("40");
QuicStreamFrame frame(stream_id, /* fin = */ false, /* offset = */ 0,
payload);
@@ -2487,7 +2643,7 @@ TEST_P(QuicSpdySessionTestClient, FinInMiddleOfStreamType) {
GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0);
// Payload is the first byte of a two byte varint encoding with a FIN.
- std::string payload = QuicTextUtils::HexDecode("40");
+ std::string payload = quiche::QuicheTextUtils::HexDecode("40");
QuicStreamFrame frame(stream_id, /* fin = */ true, /* offset = */ 0, payload);
session_.OnStreamFrame(frame);
@@ -2499,22 +2655,22 @@ TEST_P(QuicSpdySessionTestClient, DuplicateHttp3UnidirectionalStreams) {
return;
}
- MockHttp3DebugVisitor debug_visitor;
+ StrictMock<MockHttp3DebugVisitor> debug_visitor;
session_.set_debug_visitor(&debug_visitor);
QuicStreamId id1 =
GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0);
char type1[] = {kControlStream};
- QuicStreamFrame data1(id1, false, 0, QuicStringPiece(type1, 1));
+ QuicStreamFrame data1(id1, false, 0, quiche::QuicheStringPiece(type1, 1));
EXPECT_CALL(debug_visitor, OnPeerControlStreamCreated(id1));
session_.OnStreamFrame(data1);
QuicStreamId id2 =
GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 1);
- QuicStreamFrame data2(id2, false, 0, QuicStringPiece(type1, 1));
+ QuicStreamFrame data2(id2, false, 0, quiche::QuicheStringPiece(type1, 1));
EXPECT_CALL(debug_visitor, OnPeerControlStreamCreated(id2)).Times(0);
EXPECT_CALL(*connection_,
- CloseConnection(QUIC_INVALID_STREAM_ID,
+ CloseConnection(QUIC_HTTP_DUPLICATE_UNIDIRECTIONAL_STREAM,
"Control stream is received twice.", _));
EXPECT_QUIC_PEER_BUG(
session_.OnStreamFrame(data2),
@@ -2524,16 +2680,16 @@ TEST_P(QuicSpdySessionTestClient, DuplicateHttp3UnidirectionalStreams) {
GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 2);
char type2[]{kQpackEncoderStream};
- QuicStreamFrame data3(id3, false, 0, QuicStringPiece(type2, 1));
+ QuicStreamFrame data3(id3, false, 0, quiche::QuicheStringPiece(type2, 1));
EXPECT_CALL(debug_visitor, OnPeerQpackEncoderStreamCreated(id3));
session_.OnStreamFrame(data3);
QuicStreamId id4 =
GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 3);
- QuicStreamFrame data4(id4, false, 0, QuicStringPiece(type2, 1));
+ QuicStreamFrame data4(id4, false, 0, quiche::QuicheStringPiece(type2, 1));
EXPECT_CALL(debug_visitor, OnPeerQpackEncoderStreamCreated(id4)).Times(0);
EXPECT_CALL(*connection_,
- CloseConnection(QUIC_INVALID_STREAM_ID,
+ CloseConnection(QUIC_HTTP_DUPLICATE_UNIDIRECTIONAL_STREAM,
"QPACK encoder stream is received twice.", _));
EXPECT_QUIC_PEER_BUG(
session_.OnStreamFrame(data4),
@@ -2543,16 +2699,16 @@ TEST_P(QuicSpdySessionTestClient, DuplicateHttp3UnidirectionalStreams) {
GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 4);
char type3[]{kQpackDecoderStream};
- QuicStreamFrame data5(id5, false, 0, QuicStringPiece(type3, 1));
+ QuicStreamFrame data5(id5, false, 0, quiche::QuicheStringPiece(type3, 1));
EXPECT_CALL(debug_visitor, OnPeerQpackDecoderStreamCreated(id5));
session_.OnStreamFrame(data5);
QuicStreamId id6 =
GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 5);
- QuicStreamFrame data6(id6, false, 0, QuicStringPiece(type3, 1));
+ QuicStreamFrame data6(id6, false, 0, quiche::QuicheStringPiece(type3, 1));
EXPECT_CALL(debug_visitor, OnPeerQpackDecoderStreamCreated(id6)).Times(0);
EXPECT_CALL(*connection_,
- CloseConnection(QUIC_INVALID_STREAM_ID,
+ CloseConnection(QUIC_HTTP_DUPLICATE_UNIDIRECTIONAL_STREAM,
"QPACK decoder stream is received twice.", _));
EXPECT_QUIC_PEER_BUG(
session_.OnStreamFrame(data6),
@@ -2564,7 +2720,7 @@ TEST_P(QuicSpdySessionTestClient, EncoderStreamError) {
return;
}
- std::string data = QuicTextUtils::HexDecode(
+ std::string data = quiche::QuicheTextUtils::HexDecode(
"02" // Encoder stream.
"00"); // Duplicate entry 0, but no entries exist.
@@ -2585,7 +2741,7 @@ TEST_P(QuicSpdySessionTestClient, DecoderStreamError) {
return;
}
- std::string data = QuicTextUtils::HexDecode(
+ std::string data = quiche::QuicheTextUtils::HexDecode(
"03" // Decoder stream.
"00"); // Insert Count Increment with forbidden increment value of zero.
@@ -2615,6 +2771,285 @@ TEST_P(QuicSpdySessionTestClient, InvalidHttp3GoAway) {
session_.OnHttp3GoAway(stream_id);
}
+// Test that receipt of CANCEL_PUSH frame does not result in closing the
+// connection.
+// TODO(b/151841240): Handle CANCEL_PUSH frames instead of ignoring them.
+TEST_P(QuicSpdySessionTestClient, IgnoreCancelPush) {
+ if (!VersionUsesHttp3(transport_version())) {
+ return;
+ }
+
+ StrictMock<MockHttp3DebugVisitor> debug_visitor;
+ session_.set_debug_visitor(&debug_visitor);
+
+ // Create control stream.
+ QuicStreamId receive_control_stream_id =
+ GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 3);
+ char type[] = {kControlStream};
+ quiche::QuicheStringPiece stream_type(type, 1);
+ QuicStreamOffset offset = 0;
+ QuicStreamFrame data1(receive_control_stream_id, /* fin = */ false, offset,
+ stream_type);
+ offset += stream_type.length();
+ EXPECT_CALL(debug_visitor,
+ OnPeerControlStreamCreated(receive_control_stream_id));
+ session_.OnStreamFrame(data1);
+ EXPECT_EQ(receive_control_stream_id,
+ QuicSpdySessionPeer::GetReceiveControlStream(&session_)->id());
+
+ // First frame has to be SETTINGS.
+ std::string serialized_settings = EncodeSettings({});
+ QuicStreamFrame data2(receive_control_stream_id, /* fin = */ false, offset,
+ serialized_settings);
+ offset += serialized_settings.length();
+ EXPECT_CALL(debug_visitor, OnSettingsFrameReceived(_));
+ session_.OnStreamFrame(data2);
+
+ CancelPushFrame cancel_push{/* push_id = */ 0};
+ std::unique_ptr<char[]> buffer;
+ auto frame_length =
+ HttpEncoder::SerializeCancelPushFrame(cancel_push, &buffer);
+ QuicStreamFrame data3(receive_control_stream_id, /* fin = */ false, offset,
+ quiche::QuicheStringPiece(buffer.get(), frame_length));
+ EXPECT_CALL(debug_visitor, OnCancelPushFrameReceived(_));
+ session_.OnStreamFrame(data3);
+}
+
+TEST_P(QuicSpdySessionTestServer, ServerPushEnabledDefaultValue) {
+ if (VersionUsesHttp3(transport_version())) {
+ EXPECT_FALSE(session_.server_push_enabled());
+ } else {
+ EXPECT_TRUE(session_.server_push_enabled());
+ }
+}
+
+TEST_P(QuicSpdySessionTestServer, OnSetting) {
+ CompleteHandshake();
+ if (VersionUsesHttp3(transport_version())) {
+ EXPECT_EQ(std::numeric_limits<size_t>::max(),
+ session_.max_outbound_header_list_size());
+ session_.OnSetting(SETTINGS_MAX_HEADER_LIST_SIZE, 5);
+ EXPECT_EQ(5u, session_.max_outbound_header_list_size());
+
+ EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
+ .WillRepeatedly(Return(WriteResult(WRITE_STATUS_OK, 0)));
+ QpackEncoder* qpack_encoder = session_.qpack_encoder();
+ EXPECT_EQ(0u, QpackEncoderPeer::maximum_blocked_streams(qpack_encoder));
+ session_.OnSetting(SETTINGS_QPACK_BLOCKED_STREAMS, 12);
+ EXPECT_EQ(12u, QpackEncoderPeer::maximum_blocked_streams(qpack_encoder));
+
+ QpackHeaderTable* header_table =
+ QpackEncoderPeer::header_table(qpack_encoder);
+ EXPECT_EQ(0u, header_table->maximum_dynamic_table_capacity());
+ session_.OnSetting(SETTINGS_QPACK_MAX_TABLE_CAPACITY, 37);
+ EXPECT_EQ(37u, header_table->maximum_dynamic_table_capacity());
+
+ return;
+ }
+
+ EXPECT_EQ(std::numeric_limits<size_t>::max(),
+ session_.max_outbound_header_list_size());
+ session_.OnSetting(SETTINGS_MAX_HEADER_LIST_SIZE, 5);
+ EXPECT_EQ(5u, session_.max_outbound_header_list_size());
+
+ EXPECT_TRUE(session_.server_push_enabled());
+ session_.OnSetting(spdy::SETTINGS_ENABLE_PUSH, 0);
+ EXPECT_FALSE(session_.server_push_enabled());
+
+ spdy::HpackEncoder* hpack_encoder =
+ QuicSpdySessionPeer::GetSpdyFramer(&session_)->GetHpackEncoder();
+ EXPECT_EQ(4096u, hpack_encoder->CurrentHeaderTableSizeSetting());
+ session_.OnSetting(spdy::SETTINGS_HEADER_TABLE_SIZE, 59);
+ EXPECT_EQ(59u, hpack_encoder->CurrentHeaderTableSizeSetting());
+}
+
+TEST_P(QuicSpdySessionTestServer, FineGrainedHpackErrorCodes) {
+ if (VersionUsesHttp3(transport_version())) {
+ // HPACK is not used in HTTP/3.
+ return;
+ }
+
+ QuicFlagSaver flag_saver;
+ SetQuicReloadableFlag(spdy_enable_granular_decompress_errors, true);
+
+ QuicStreamId request_stream_id = 5;
+ session_.CreateIncomingStream(request_stream_id);
+
+ // Index 126 does not exist (static table has 61 entries and dynamic table is
+ // empty).
+ std::string headers_frame = quiche::QuicheTextUtils::HexDecode(
+ "000006" // length
+ "01" // type
+ "24" // flags: PRIORITY | END_HEADERS
+ "00000005" // stream_id
+ "00000000" // stream dependency
+ "10" // weight
+ "fe"); // payload: reference to index 126.
+ QuicStreamId headers_stream_id =
+ QuicUtils::GetHeadersStreamId(transport_version());
+ QuicStreamFrame data(headers_stream_id, false, 0, headers_frame);
+
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_HPACK_INVALID_INDEX,
+ "SPDY framing error: HPACK_INVALID_INDEX",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
+ session_.OnStreamFrame(data);
+}
+
+TEST_P(QuicSpdySessionTestServer, PeerClosesCriticalReceiveStream) {
+ if (!VersionUsesHttp3(transport_version())) {
+ return;
+ }
+
+ struct {
+ char type;
+ const char* error_details;
+ } kTestData[] = {
+ {kControlStream, "RESET_STREAM received for receive control stream"},
+ {kQpackEncoderStream, "RESET_STREAM received for QPACK receive stream"},
+ {kQpackDecoderStream, "RESET_STREAM received for QPACK receive stream"},
+ };
+ for (size_t i = 0; i < QUICHE_ARRAYSIZE(kTestData); ++i) {
+ QuicStreamId stream_id =
+ GetNthClientInitiatedUnidirectionalStreamId(transport_version(), i + 1);
+ const QuicByteCount data_length = 1;
+ QuicStreamFrame data(
+ stream_id, false, 0,
+ quiche::QuicheStringPiece(&kTestData[i].type, data_length));
+ session_.OnStreamFrame(data);
+
+ EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_CLOSED_CRITICAL_STREAM,
+ kTestData[i].error_details, _));
+
+ QuicRstStreamFrame rst(kInvalidControlFrameId, stream_id,
+ QUIC_STREAM_CANCELLED, data_length);
+ session_.OnRstStream(rst);
+ }
+}
+
+TEST_P(QuicSpdySessionTestServer, PeerClosesCriticalSendStream) {
+ if (!VersionUsesHttp3(transport_version())) {
+ return;
+ }
+
+ QuicSendControlStream* control_stream =
+ QuicSpdySessionPeer::GetSendControlStream(&session_);
+ ASSERT_TRUE(control_stream);
+
+ QuicStopSendingFrame stop_sending_control_stream(
+ kInvalidControlFrameId, control_stream->id(),
+ static_cast<QuicApplicationErrorCode>(QUIC_STREAM_CANCELLED));
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_HTTP_CLOSED_CRITICAL_STREAM,
+ "STOP_SENDING received for send control stream", _));
+ session_.OnStopSendingFrame(stop_sending_control_stream);
+
+ QpackSendStream* decoder_stream =
+ QuicSpdySessionPeer::GetQpackDecoderSendStream(&session_);
+ ASSERT_TRUE(decoder_stream);
+
+ QuicStopSendingFrame stop_sending_decoder_stream(
+ kInvalidControlFrameId, decoder_stream->id(),
+ static_cast<QuicApplicationErrorCode>(QUIC_STREAM_CANCELLED));
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_HTTP_CLOSED_CRITICAL_STREAM,
+ "STOP_SENDING received for QPACK send stream", _));
+ session_.OnStopSendingFrame(stop_sending_decoder_stream);
+
+ QpackSendStream* encoder_stream =
+ QuicSpdySessionPeer::GetQpackEncoderSendStream(&session_);
+ ASSERT_TRUE(encoder_stream);
+
+ QuicStopSendingFrame stop_sending_encoder_stream(
+ kInvalidControlFrameId, encoder_stream->id(),
+ static_cast<QuicApplicationErrorCode>(QUIC_STREAM_CANCELLED));
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_HTTP_CLOSED_CRITICAL_STREAM,
+ "STOP_SENDING received for QPACK send stream", _));
+ session_.OnStopSendingFrame(stop_sending_encoder_stream);
+}
+
+// Test that receipt of CANCEL_PUSH frame does not result in closing the
+// connection.
+// TODO(b/151841240): Handle CANCEL_PUSH frames instead of ignoring them.
+TEST_P(QuicSpdySessionTestServer, IgnoreCancelPush) {
+ if (!VersionUsesHttp3(transport_version())) {
+ return;
+ }
+
+ StrictMock<MockHttp3DebugVisitor> debug_visitor;
+ session_.set_debug_visitor(&debug_visitor);
+
+ // Create control stream.
+ QuicStreamId receive_control_stream_id =
+ GetNthClientInitiatedUnidirectionalStreamId(transport_version(), 3);
+ char type[] = {kControlStream};
+ quiche::QuicheStringPiece stream_type(type, 1);
+ QuicStreamOffset offset = 0;
+ QuicStreamFrame data1(receive_control_stream_id, /* fin = */ false, offset,
+ stream_type);
+ offset += stream_type.length();
+ EXPECT_CALL(debug_visitor,
+ OnPeerControlStreamCreated(receive_control_stream_id));
+ session_.OnStreamFrame(data1);
+ EXPECT_EQ(receive_control_stream_id,
+ QuicSpdySessionPeer::GetReceiveControlStream(&session_)->id());
+
+ // First frame has to be SETTINGS.
+ std::string serialized_settings = EncodeSettings({});
+ QuicStreamFrame data2(receive_control_stream_id, /* fin = */ false, offset,
+ serialized_settings);
+ offset += serialized_settings.length();
+ EXPECT_CALL(debug_visitor, OnSettingsFrameReceived(_));
+ session_.OnStreamFrame(data2);
+
+ CancelPushFrame cancel_push{/* push_id = */ 0};
+ std::unique_ptr<char[]> buffer;
+ auto frame_length =
+ HttpEncoder::SerializeCancelPushFrame(cancel_push, &buffer);
+ QuicStreamFrame data3(receive_control_stream_id, /* fin = */ false, offset,
+ quiche::QuicheStringPiece(buffer.get(), frame_length));
+ EXPECT_CALL(debug_visitor, OnCancelPushFrameReceived(_));
+ session_.OnStreamFrame(data3);
+}
+
+TEST_P(QuicSpdySessionTestClient, SendInitialMaxPushIdIfSet) {
+ if (!VersionUsesHttp3(transport_version())) {
+ return;
+ }
+
+ StrictMock<MockHttp3DebugVisitor> debug_visitor;
+ session_.set_debug_visitor(&debug_visitor);
+
+ const QuicStreamId max_push_id = 5;
+ session_.SetMaxPushId(max_push_id);
+
+ InSequence s;
+ EXPECT_CALL(debug_visitor, OnSettingsFrameSent(_));
+ const MaxPushIdFrame max_push_id_frame{max_push_id};
+ EXPECT_CALL(debug_visitor, OnMaxPushIdFrameSent(max_push_id_frame));
+
+ CompleteHandshake();
+}
+
+TEST_P(QuicSpdySessionTestClient, DoNotSendInitialMaxPushIdIfNotSet) {
+ if (!VersionUsesHttp3(transport_version())) {
+ return;
+ }
+
+ StrictMock<MockHttp3DebugVisitor> debug_visitor;
+ session_.set_debug_visitor(&debug_visitor);
+
+ InSequence s;
+ EXPECT_CALL(debug_visitor, OnSettingsFrameSent(_));
+
+ CompleteHandshake();
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.cc
index f7a13f62254..c376d010c8f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.cc
@@ -17,14 +17,14 @@
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice_storage.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
using spdy::SpdyHeaderBlock;
@@ -40,20 +40,8 @@ class QuicSpdyStream::HttpDecoderVisitor : public HttpDecoder::Visitor {
HttpDecoderVisitor(const HttpDecoderVisitor&) = delete;
HttpDecoderVisitor& operator=(const HttpDecoderVisitor&) = delete;
- void OnError(HttpDecoder* /*decoder*/) override {
- stream_->session()->connection()->CloseConnection(
- QUIC_HTTP_DECODER_ERROR, "Http decoder internal error",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- }
-
- bool OnPriorityFrameStart(QuicByteCount /*header_length*/) override {
- CloseConnectionOnWrongFrame("Priority");
- return false;
- }
-
- bool OnPriorityFrame(const PriorityFrame& /*frame*/) override {
- CloseConnectionOnWrongFrame("Priority");
- return false;
+ void OnError(HttpDecoder* decoder) override {
+ stream_->OnUnrecoverableError(decoder->error(), decoder->error_detail());
}
bool OnCancelPushFrame(const CancelPushFrame& /*frame*/) override {
@@ -81,32 +69,28 @@ class QuicSpdyStream::HttpDecoderVisitor : public HttpDecoder::Visitor {
return false;
}
- bool OnDuplicatePushFrame(const DuplicatePushFrame& /*frame*/) override {
- // TODO(b/137554973): Consume frame.
- CloseConnectionOnWrongFrame("Duplicate Push");
- return false;
- }
-
- bool OnDataFrameStart(QuicByteCount header_length) override {
- return stream_->OnDataFrameStart(header_length);
+ bool OnDataFrameStart(QuicByteCount header_length,
+ QuicByteCount payload_length) override {
+ return stream_->OnDataFrameStart(header_length, payload_length);
}
- bool OnDataFramePayload(QuicStringPiece payload) override {
+ bool OnDataFramePayload(quiche::QuicheStringPiece payload) override {
DCHECK(!payload.empty());
return stream_->OnDataFramePayload(payload);
}
bool OnDataFrameEnd() override { return stream_->OnDataFrameEnd(); }
- bool OnHeadersFrameStart(QuicByteCount header_length) override {
+ bool OnHeadersFrameStart(QuicByteCount header_length,
+ QuicByteCount payload_length) override {
if (!VersionUsesHttp3(stream_->transport_version())) {
CloseConnectionOnWrongFrame("Headers");
return false;
}
- return stream_->OnHeadersFrameStart(header_length);
+ return stream_->OnHeadersFrameStart(header_length, payload_length);
}
- bool OnHeadersFramePayload(QuicStringPiece payload) override {
+ bool OnHeadersFramePayload(quiche::QuicheStringPiece payload) override {
DCHECK(!payload.empty());
if (!VersionUsesHttp3(stream_->transport_version())) {
CloseConnectionOnWrongFrame("Headers");
@@ -132,15 +116,17 @@ class QuicSpdyStream::HttpDecoderVisitor : public HttpDecoder::Visitor {
}
bool OnPushPromiseFramePushId(PushId push_id,
- QuicByteCount push_id_length) override {
+ QuicByteCount push_id_length,
+ QuicByteCount header_block_length) override {
if (!VersionUsesHttp3(stream_->transport_version())) {
CloseConnectionOnWrongFrame("Push Promise");
return false;
}
- return stream_->OnPushPromiseFramePushId(push_id, push_id_length);
+ return stream_->OnPushPromiseFramePushId(push_id, push_id_length,
+ header_block_length);
}
- bool OnPushPromiseFramePayload(QuicStringPiece payload) override {
+ bool OnPushPromiseFramePayload(quiche::QuicheStringPiece payload) override {
DCHECK(!payload.empty());
if (!VersionUsesHttp3(stream_->transport_version())) {
CloseConnectionOnWrongFrame("Push Promise");
@@ -157,23 +143,34 @@ class QuicSpdyStream::HttpDecoderVisitor : public HttpDecoder::Visitor {
return stream_->OnPushPromiseFrameEnd();
}
+ bool OnPriorityUpdateFrameStart(QuicByteCount /*header_length*/) override {
+ CloseConnectionOnWrongFrame("Priority update");
+ return false;
+ }
+
+ bool OnPriorityUpdateFrame(const PriorityUpdateFrame& /*frame*/) override {
+ CloseConnectionOnWrongFrame("Priority update");
+ return false;
+ }
+
bool OnUnknownFrameStart(uint64_t frame_type,
- QuicByteCount header_length) override {
- return stream_->OnUnknownFrameStart(frame_type, header_length);
+ QuicByteCount header_length,
+ QuicByteCount payload_length) override {
+ return stream_->OnUnknownFrameStart(frame_type, header_length,
+ payload_length);
}
- bool OnUnknownFramePayload(QuicStringPiece payload) override {
+ bool OnUnknownFramePayload(quiche::QuicheStringPiece payload) override {
return stream_->OnUnknownFramePayload(payload);
}
bool OnUnknownFrameEnd() override { return stream_->OnUnknownFrameEnd(); }
private:
- void CloseConnectionOnWrongFrame(QuicStringPiece frame_type) {
- stream_->session()->connection()->CloseConnection(
- QUIC_HTTP_DECODER_ERROR,
- QuicStrCat(frame_type, " frame received on data stream"),
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ void CloseConnectionOnWrongFrame(quiche::QuicheStringPiece frame_type) {
+ stream_->OnUnrecoverableError(
+ QUIC_HTTP_FRAME_UNEXPECTED_ON_SPDY_STREAM,
+ quiche::QuicheStrCat(frame_type, " frame received on data stream"));
}
QuicSpdyStream* stream_;
@@ -198,12 +195,12 @@ QuicSpdyStream::QuicSpdyStream(QuicStreamId id,
trailers_payload_length_(0),
trailers_decompressed_(false),
trailers_consumed_(false),
- priority_sent_(false),
http_decoder_visitor_(std::make_unique<HttpDecoderVisitor>(this)),
decoder_(http_decoder_visitor_.get()),
sequencer_offset_(0),
is_decoder_processing_input_(false),
- ack_listener_(nullptr) {
+ ack_listener_(nullptr),
+ last_sent_urgency_(kDefaultUrgency) {
DCHECK_EQ(session()->connection(), spdy_session->connection());
DCHECK_EQ(transport_version(), spdy_session->transport_version());
DCHECK(!QuicUtils::IsCryptoStreamId(transport_version(), id));
@@ -217,6 +214,8 @@ QuicSpdyStream::QuicSpdyStream(QuicStreamId id,
if (VersionUsesHttp3(transport_version())) {
sequencer()->set_level_triggered(true);
}
+
+ spdy_session_->OnStreamCreated(this);
}
QuicSpdyStream::QuicSpdyStream(PendingStream* pending,
@@ -233,12 +232,12 @@ QuicSpdyStream::QuicSpdyStream(PendingStream* pending,
trailers_payload_length_(0),
trailers_decompressed_(false),
trailers_consumed_(false),
- priority_sent_(false),
http_decoder_visitor_(std::make_unique<HttpDecoderVisitor>(this)),
decoder_(http_decoder_visitor_.get()),
sequencer_offset_(sequencer()->NumBytesConsumed()),
is_decoder_processing_input_(false),
- ack_listener_(nullptr) {
+ ack_listener_(nullptr),
+ last_sent_urgency_(kDefaultUrgency) {
DCHECK_EQ(session()->connection(), spdy_session->connection());
DCHECK_EQ(transport_version(), spdy_session->transport_version());
DCHECK(!QuicUtils::IsCryptoStreamId(transport_version(), id()));
@@ -251,6 +250,8 @@ QuicSpdyStream::QuicSpdyStream(PendingStream* pending,
if (VersionUsesHttp3(transport_version())) {
sequencer()->set_level_triggered(true);
}
+
+ spdy_session_->OnStreamCreated(this);
}
QuicSpdyStream::~QuicSpdyStream() {}
@@ -264,7 +265,7 @@ size_t QuicSpdyStream::WriteHeaders(
if (VersionUsesHttp3(transport_version()) && type() == WRITE_UNIDIRECTIONAL &&
send_buffer().stream_offset() == 0) {
char data[sizeof(kServerPushStream)];
- QuicDataWriter writer(QUIC_ARRAYSIZE(data), data);
+ QuicDataWriter writer(QUICHE_ARRAYSIZE(data), data);
writer.WriteVarInt62(kServerPushStream);
// Similar to frame headers, stream type byte shouldn't be exposed to upper
@@ -273,9 +274,10 @@ size_t QuicSpdyStream::WriteHeaders(
QUIC_LOG(INFO) << ENDPOINT << "Stream " << id()
<< " is writing type as server push";
- WriteOrBufferData(QuicStringPiece(writer.data(), writer.length()), false,
- nullptr);
+ WriteOrBufferData(quiche::QuicheStringPiece(writer.data(), writer.length()),
+ false, nullptr);
}
+
size_t bytes_written =
WriteHeadersImpl(std::move(header_block), fin, std::move(ack_listener));
if (!VersionUsesHttp3(transport_version()) && fin) {
@@ -289,13 +291,18 @@ size_t QuicSpdyStream::WriteHeaders(
return bytes_written;
}
-void QuicSpdyStream::WriteOrBufferBody(QuicStringPiece data, bool fin) {
+void QuicSpdyStream::WriteOrBufferBody(quiche::QuicheStringPiece data,
+ bool fin) {
if (!VersionUsesHttp3(transport_version()) || data.length() == 0) {
WriteOrBufferData(data, fin, nullptr);
return;
}
QuicConnection::ScopedPacketFlusher flusher(spdy_session_->connection());
+ if (spdy_session_->debug_visitor()) {
+ spdy_session_->debug_visitor()->OnDataFrameSent(id(), data.length());
+ }
+
// Write frame header.
std::unique_ptr<char[]> buffer;
QuicByteCount header_length =
@@ -306,8 +313,8 @@ void QuicSpdyStream::WriteOrBufferBody(QuicStringPiece data, bool fin) {
QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
<< " is writing DATA frame header of length "
<< header_length;
- WriteOrBufferData(QuicStringPiece(buffer.get(), header_length), false,
- nullptr);
+ WriteOrBufferData(quiche::QuicheStringPiece(buffer.get(), header_length),
+ false, nullptr);
// Write body.
QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
@@ -331,8 +338,9 @@ size_t QuicSpdyStream::WriteTrailers(
stream_bytes_written() + BufferedDataBytes();
QUIC_DLOG(INFO) << ENDPOINT << "Inserting trailer: ("
<< kFinalOffsetHeaderKey << ", " << final_offset << ")";
- trailer_block.insert(std::make_pair(
- kFinalOffsetHeaderKey, QuicTextUtils::Uint64ToString(final_offset)));
+ trailer_block.insert(
+ std::make_pair(kFinalOffsetHeaderKey,
+ quiche::QuicheTextUtils::Uint64ToString(final_offset)));
}
// Write the trailing headers with a FIN, and close stream for writing:
@@ -373,8 +381,8 @@ void QuicSpdyStream::WritePushPromise(const PushPromiseFrame& frame) {
<< " is writing Push Promise frame header of length "
<< push_promise_frame_length << " , with promised id "
<< frame.push_id;
- WriteOrBufferData(QuicStringPiece(push_promise_frame_with_id.get(),
- push_promise_frame_length),
+ WriteOrBufferData(quiche::QuicheStringPiece(push_promise_frame_with_id.get(),
+ push_promise_frame_length),
/* fin = */ false, /* ack_listener = */ nullptr);
// Write response headers.
@@ -408,6 +416,11 @@ QuicConsumedData QuicSpdyStream::WriteBodySlices(QuicMemSliceSpan slices,
return {0, false};
}
+ if (spdy_session_->debug_visitor()) {
+ spdy_session_->debug_visitor()->OnDataFrameSent(id(),
+ slices.total_length());
+ }
+
QuicConnection::ScopedPacketFlusher flusher(spdy_session_->connection());
// Write frame header.
@@ -538,9 +551,9 @@ void QuicSpdyStream::OnStreamHeaderList(bool fin,
}
}
-void QuicSpdyStream::OnHeadersDecoded(QuicHeaderList headers) {
- header_list_size_limit_exceeded_ =
- qpack_decoded_headers_accumulator_->header_list_size_limit_exceeded();
+void QuicSpdyStream::OnHeadersDecoded(QuicHeaderList headers,
+ bool header_list_size_limit_exceeded) {
+ header_list_size_limit_exceeded_ = header_list_size_limit_exceeded;
qpack_decoded_headers_accumulator_.reset();
QuicSpdySession::LogHeaderCompressionRatioHistogram(
@@ -548,13 +561,23 @@ void QuicSpdyStream::OnHeadersDecoded(QuicHeaderList headers) {
/* is_sent = */ false, headers.compressed_header_bytes(),
headers.uncompressed_header_bytes());
- if (spdy_session_->promised_stream_id() ==
- QuicUtils::GetInvalidStreamId(session()->transport_version())) {
+ const QuicStreamId promised_stream_id = spdy_session()->promised_stream_id();
+ Http3DebugVisitor* const debug_visitor = spdy_session()->debug_visitor();
+ if (promised_stream_id ==
+ QuicUtils::GetInvalidStreamId(transport_version())) {
+ if (debug_visitor) {
+ debug_visitor->OnHeadersDecoded(id(), headers);
+ }
+
const QuicByteCount frame_length = headers_decompressed_
? trailers_payload_length_
: headers_payload_length_;
OnStreamHeaderList(/* fin = */ false, frame_length, headers);
} else {
+ if (debug_visitor) {
+ debug_visitor->OnPushPromiseDecoded(id(), promised_stream_id, headers);
+ }
+
spdy_session_->OnHeaderList(headers);
}
@@ -565,14 +588,35 @@ void QuicSpdyStream::OnHeadersDecoded(QuicHeaderList headers) {
}
}
-void QuicSpdyStream::OnHeaderDecodingError(QuicStringPiece error_message) {
+void QuicSpdyStream::OnHeaderDecodingError(
+ quiche::QuicheStringPiece error_message) {
qpack_decoded_headers_accumulator_.reset();
- std::string connection_close_error_message = QuicStrCat(
+ std::string connection_close_error_message = quiche::QuicheStrCat(
"Error decoding ", headers_decompressed_ ? "trailers" : "headers",
" on stream ", id(), ": ", error_message);
- CloseConnectionWithDetails(QUIC_QPACK_DECOMPRESSION_FAILED,
- connection_close_error_message);
+ OnUnrecoverableError(QUIC_QPACK_DECOMPRESSION_FAILED,
+ connection_close_error_message);
+}
+
+void QuicSpdyStream::MaybeSendPriorityUpdateFrame() {
+ if (!VersionUsesHttp3(transport_version()) ||
+ session()->perspective() != Perspective::IS_CLIENT) {
+ return;
+ }
+
+ // Value between 0 and 7, inclusive. Lower value means higher priority.
+ int urgency = precedence().spdy3_priority();
+ if (last_sent_urgency_ == urgency) {
+ return;
+ }
+ last_sent_urgency_ = urgency;
+
+ PriorityUpdateFrame priority_update;
+ priority_update.prioritized_element_type = REQUEST_STREAM;
+ priority_update.prioritized_element_id = id();
+ priority_update.priority_field_value = quiche::QuicheStrCat("u=", urgency);
+ spdy_session_->WriteHttp3PriorityUpdate(priority_update);
}
void QuicSpdyStream::OnHeadersTooLarge() {
@@ -580,9 +624,9 @@ void QuicSpdyStream::OnHeadersTooLarge() {
// TODO(b/124216424): Reset stream with H3_REQUEST_CANCELLED (if client)
// or with H3_REQUEST_REJECTED (if server).
std::string error_message =
- QuicStrCat("Too large headers received on stream ", id());
- CloseConnectionWithDetails(QUIC_HEADERS_STREAM_DATA_DECOMPRESS_FAILURE,
- error_message);
+ quiche::QuicheStrCat("Too large headers received on stream ", id());
+ OnUnrecoverableError(QUIC_HEADERS_STREAM_DATA_DECOMPRESS_FAILURE,
+ error_message);
} else {
Reset(QUIC_HEADERS_TOO_LARGE);
}
@@ -601,14 +645,14 @@ void QuicSpdyStream::OnInitialHeadersComplete(
OnStreamFrame(
QuicStreamFrame(id(), /* fin = */ true,
flow_controller()->highest_received_byte_offset(),
- QuicStringPiece()));
+ quiche::QuicheStringPiece()));
}
return;
}
if (fin && !rst_sent()) {
- OnStreamFrame(
- QuicStreamFrame(id(), fin, /* offset = */ 0, QuicStringPiece()));
+ OnStreamFrame(QuicStreamFrame(id(), fin, /* offset = */ 0,
+ quiche::QuicheStringPiece()));
}
if (FinishedReadingHeaders()) {
sequencer()->SetUnblocked();
@@ -621,9 +665,8 @@ void QuicSpdyStream::OnPromiseHeaderList(
const QuicHeaderList& /*header_list */) {
// To be overridden in QuicSpdyClientStream. Not supported on
// server side.
- session()->connection()->CloseConnection(
- QUIC_INVALID_HEADERS_STREAM_DATA, "Promise headers received by server",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ stream_delegate()->OnStreamError(QUIC_INVALID_HEADERS_STREAM_DATA,
+ "Promise headers received by server");
}
void QuicSpdyStream::OnTrailingHeadersComplete(
@@ -635,18 +678,16 @@ void QuicSpdyStream::OnTrailingHeadersComplete(
if (!VersionUsesHttp3(transport_version()) && fin_received()) {
QUIC_DLOG(INFO) << ENDPOINT
<< "Received Trailers after FIN, on stream: " << id();
- session()->connection()->CloseConnection(
- QUIC_INVALID_HEADERS_STREAM_DATA, "Trailers after fin",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ stream_delegate()->OnStreamError(QUIC_INVALID_HEADERS_STREAM_DATA,
+ "Trailers after fin");
return;
}
if (!VersionUsesHttp3(transport_version()) && !fin) {
QUIC_DLOG(INFO) << ENDPOINT
<< "Trailers must have FIN set, on stream: " << id();
- session()->connection()->CloseConnection(
- QUIC_INVALID_HEADERS_STREAM_DATA, "Fin missing from trailers",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ stream_delegate()->OnStreamError(QUIC_INVALID_HEADERS_STREAM_DATA,
+ "Fin missing from trailers");
return;
}
@@ -657,9 +698,8 @@ void QuicSpdyStream::OnTrailingHeadersComplete(
&received_trailers_)) {
QUIC_DLOG(ERROR) << ENDPOINT << "Trailers for stream " << id()
<< " are malformed.";
- session()->connection()->CloseConnection(
- QUIC_INVALID_HEADERS_STREAM_DATA, "Trailers are malformed",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ stream_delegate()->OnStreamError(QUIC_INVALID_HEADERS_STREAM_DATA,
+ "Trailers are malformed");
return;
}
trailers_decompressed_ = true;
@@ -668,7 +708,8 @@ void QuicSpdyStream::OnTrailingHeadersComplete(
VersionUsesHttp3(transport_version())
? flow_controller()->highest_received_byte_offset()
: final_byte_offset;
- OnStreamFrame(QuicStreamFrame(id(), fin, offset, QuicStringPiece()));
+ OnStreamFrame(
+ QuicStreamFrame(id(), fin, offset, quiche::QuicheStringPiece()));
}
}
@@ -680,7 +721,10 @@ void QuicSpdyStream::OnPriorityFrame(
void QuicSpdyStream::OnStreamReset(const QuicRstStreamFrame& frame) {
if (frame.error_code != QUIC_STREAM_NO_ERROR) {
- // TODO(b/145684124) Call QpackDecoder::OnStreamReset().
+ if (VersionUsesHttp3(transport_version()) && !fin_received() &&
+ spdy_session_->qpack_decoder()) {
+ spdy_session_->qpack_decoder()->OnStreamReset(id());
+ }
QuicStream::OnStreamReset(frame);
return;
@@ -695,7 +739,10 @@ void QuicSpdyStream::OnStreamReset(const QuicRstStreamFrame& frame) {
}
void QuicSpdyStream::Reset(QuicRstStreamErrorCode error) {
- // TODO(b/145684124) Call QpackDecoder::OnStreamReset().
+ if (VersionUsesHttp3(transport_version()) && !fin_received() &&
+ spdy_session_->qpack_decoder()) {
+ spdy_session_->qpack_decoder()->OnStreamReset(id());
+ }
QuicStream::Reset(error);
}
@@ -788,7 +835,7 @@ bool QuicSpdyStream::ParseHeaderStatusCode(const SpdyHeaderBlock& header,
if (it == header.end()) {
return false;
}
- const QuicStringPiece status(it->second);
+ const quiche::QuicheStringPiece status(it->second);
if (status.size() != 3) {
return false;
}
@@ -800,7 +847,7 @@ bool QuicSpdyStream::ParseHeaderStatusCode(const SpdyHeaderBlock& header,
if (!isdigit(status[1]) || !isdigit(status[2])) {
return false;
}
- return QuicTextUtils::StringToInt(status, status_code);
+ return quiche::QuicheTextUtils::StringToInt(status, status_code);
}
bool QuicSpdyStream::FinishedReadingTrailers() const {
@@ -819,13 +866,18 @@ void QuicSpdyStream::ClearSession() {
spdy_session_ = nullptr;
}
-bool QuicSpdyStream::OnDataFrameStart(QuicByteCount header_length) {
+bool QuicSpdyStream::OnDataFrameStart(QuicByteCount header_length,
+ QuicByteCount payload_length) {
DCHECK(VersionUsesHttp3(transport_version()));
+
+ if (spdy_session_->debug_visitor()) {
+ spdy_session_->debug_visitor()->OnDataFrameReceived(id(), payload_length);
+ }
+
if (!headers_decompressed_ || trailers_decompressed_) {
- // TODO(b/124216424): Change error code to HTTP_UNEXPECTED_FRAME.
- session()->connection()->CloseConnection(
- QUIC_INVALID_HEADERS_STREAM_DATA, "Unexpected DATA frame received.",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ stream_delegate()->OnStreamError(
+ QUIC_HTTP_INVALID_FRAME_SEQUENCE_ON_SPDY_STREAM,
+ "Unexpected DATA frame received.");
return false;
}
@@ -834,7 +886,7 @@ bool QuicSpdyStream::OnDataFrameStart(QuicByteCount header_length) {
return true;
}
-bool QuicSpdyStream::OnDataFramePayload(QuicStringPiece payload) {
+bool QuicSpdyStream::OnDataFramePayload(quiche::QuicheStringPiece payload) {
DCHECK(VersionUsesHttp3(transport_version()));
body_manager_.OnBody(payload);
@@ -844,6 +896,7 @@ bool QuicSpdyStream::OnDataFramePayload(QuicStringPiece payload) {
bool QuicSpdyStream::OnDataFrameEnd() {
DCHECK(VersionUsesHttp3(transport_version()));
+
QUIC_DVLOG(1) << ENDPOINT
<< "Reaches the end of a data frame. Total bytes received are "
<< body_manager_.total_body_bytes_received();
@@ -854,9 +907,11 @@ bool QuicSpdyStream::OnStreamFrameAcked(QuicStreamOffset offset,
QuicByteCount data_length,
bool fin_acked,
QuicTime::Delta ack_delay_time,
+ QuicTime receive_timestamp,
QuicByteCount* newly_acked_length) {
const bool new_data_acked = QuicStream::OnStreamFrameAcked(
- offset, data_length, fin_acked, ack_delay_time, newly_acked_length);
+ offset, data_length, fin_acked, ack_delay_time, receive_timestamp,
+ newly_acked_length);
const QuicByteCount newly_acked_header_length =
GetNumFrameHeadersInInterval(offset, data_length);
@@ -897,16 +952,20 @@ QuicByteCount QuicSpdyStream::GetNumFrameHeadersInInterval(
return header_acked_length;
}
-bool QuicSpdyStream::OnHeadersFrameStart(QuicByteCount header_length) {
+bool QuicSpdyStream::OnHeadersFrameStart(QuicByteCount header_length,
+ QuicByteCount payload_length) {
DCHECK(VersionUsesHttp3(transport_version()));
DCHECK(!qpack_decoded_headers_accumulator_);
+ if (spdy_session_->debug_visitor()) {
+ spdy_session_->debug_visitor()->OnHeadersFrameReceived(id(),
+ payload_length);
+ }
+
if (trailers_decompressed_) {
- // TODO(b/124216424): Change error code to HTTP_UNEXPECTED_FRAME.
- session()->connection()->CloseConnection(
- QUIC_INVALID_HEADERS_STREAM_DATA,
- "HEADERS frame received after trailing HEADERS.",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ stream_delegate()->OnStreamError(
+ QUIC_HTTP_INVALID_FRAME_SEQUENCE_ON_SPDY_STREAM,
+ "HEADERS frame received after trailing HEADERS.");
return false;
}
@@ -920,10 +979,13 @@ bool QuicSpdyStream::OnHeadersFrameStart(QuicByteCount header_length) {
return true;
}
-bool QuicSpdyStream::OnHeadersFramePayload(QuicStringPiece payload) {
+bool QuicSpdyStream::OnHeadersFramePayload(quiche::QuicheStringPiece payload) {
DCHECK(VersionUsesHttp3(transport_version()));
DCHECK(qpack_decoded_headers_accumulator_);
+ // TODO(b/152518220): Save |payload_length| argument of OnHeadersFrameStart()
+ // instead of accumulating payload length in |headers_payload_length_| or
+ // |trailers_payload_length_|.
if (headers_decompressed_) {
trailers_payload_length_ += payload.length();
} else {
@@ -966,11 +1028,18 @@ bool QuicSpdyStream::OnPushPromiseFrameStart(QuicByteCount header_length) {
return true;
}
-bool QuicSpdyStream::OnPushPromiseFramePushId(PushId push_id,
- QuicByteCount push_id_length) {
+bool QuicSpdyStream::OnPushPromiseFramePushId(
+ PushId push_id,
+ QuicByteCount push_id_length,
+ QuicByteCount header_block_length) {
DCHECK(VersionUsesHttp3(transport_version()));
DCHECK(!qpack_decoded_headers_accumulator_);
+ if (spdy_session_->debug_visitor()) {
+ spdy_session_->debug_visitor()->OnPushPromiseFrameReceived(
+ id(), push_id, header_block_length);
+ }
+
// TODO(renjietang): Check max push id and handle errors.
spdy_session_->OnPushPromise(id(), push_id);
sequencer()->MarkConsumed(body_manager_.OnNonBody(push_id_length));
@@ -983,7 +1052,8 @@ bool QuicSpdyStream::OnPushPromiseFramePushId(PushId push_id,
return true;
}
-bool QuicSpdyStream::OnPushPromiseFramePayload(QuicStringPiece payload) {
+bool QuicSpdyStream::OnPushPromiseFramePayload(
+ quiche::QuicheStringPiece payload) {
spdy_session_->OnCompressedFrameSize(payload.length());
return OnHeadersFramePayload(payload);
}
@@ -995,7 +1065,13 @@ bool QuicSpdyStream::OnPushPromiseFrameEnd() {
}
bool QuicSpdyStream::OnUnknownFrameStart(uint64_t frame_type,
- QuicByteCount header_length) {
+ QuicByteCount header_length,
+ QuicByteCount payload_length) {
+ if (spdy_session_->debug_visitor()) {
+ spdy_session_->debug_visitor()->OnUnknownFrameReceived(id(), frame_type,
+ payload_length);
+ }
+
// Ignore unknown frames, but consume frame header.
QUIC_DVLOG(1) << ENDPOINT << "Discarding " << header_length
<< " byte long frame header of frame of unknown type "
@@ -1004,7 +1080,7 @@ bool QuicSpdyStream::OnUnknownFrameStart(uint64_t frame_type,
return true;
}
-bool QuicSpdyStream::OnUnknownFramePayload(QuicStringPiece payload) {
+bool QuicSpdyStream::OnUnknownFramePayload(quiche::QuicheStringPiece payload) {
// Ignore unknown frames, but consume frame payload.
QUIC_DVLOG(1) << ENDPOINT << "Discarding " << payload.size()
<< " bytes of payload of frame of unknown type.";
@@ -1026,20 +1102,16 @@ size_t QuicSpdyStream::WriteHeadersImpl(
std::move(ack_listener));
}
- if (GetQuicFlag(FLAGS_quic_allow_http3_priority) &&
- session()->perspective() == Perspective::IS_CLIENT && !priority_sent_) {
- PriorityFrame frame;
- PopulatePriorityFrame(&frame);
- spdy_session_->WriteH3Priority(frame);
- priority_sent_ = true;
- }
-
// Encode header list.
QuicByteCount encoder_stream_sent_byte_count;
std::string encoded_headers =
spdy_session_->qpack_encoder()->EncodeHeaderList(
id(), header_block, &encoder_stream_sent_byte_count);
+ if (spdy_session_->debug_visitor()) {
+ spdy_session_->debug_visitor()->OnHeadersFrameSent(id(), header_block);
+ }
+
// Write HEADERS frame.
std::unique_ptr<char[]> headers_frame_header;
const size_t headers_frame_header_length =
@@ -1052,9 +1124,9 @@ size_t QuicSpdyStream::WriteHeadersImpl(
QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
<< " is writing HEADERS frame header of length "
<< headers_frame_header_length;
- WriteOrBufferData(
- QuicStringPiece(headers_frame_header.get(), headers_frame_header_length),
- /* fin = */ false, /* ack_listener = */ nullptr);
+ WriteOrBufferData(quiche::QuicheStringPiece(headers_frame_header.get(),
+ headers_frame_header_length),
+ /* fin = */ false, /* ack_listener = */ nullptr);
QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
<< " is writing HEADERS frame payload of length "
@@ -1070,12 +1142,5 @@ size_t QuicSpdyStream::WriteHeadersImpl(
return encoded_headers.size() + encoder_stream_sent_byte_count;
}
-void QuicSpdyStream::PopulatePriorityFrame(PriorityFrame* frame) {
- frame->weight = precedence().spdy3_priority();
- frame->dependency_type = ROOT_OF_TREE;
- frame->prioritized_type = REQUEST_STREAM;
- frame->prioritized_element_id = id();
-}
-
#undef ENDPOINT // undef for jumbo builds
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h
index 8610dbb1f2d..abf3ef4b78e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h
@@ -26,6 +26,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
namespace quic {
@@ -121,7 +122,7 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
// Sends |data| to the peer, or buffers if it can't be sent immediately.
- void WriteOrBufferBody(QuicStringPiece data, bool fin);
+ void WriteOrBufferBody(quiche::QuicheStringPiece data, bool fin);
// Writes the trailers contained in |trailer_block| on the dedicated headers
// stream or on this stream, depending on VersionUsesHttp3(). Trailers will
@@ -139,6 +140,7 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream
QuicByteCount data_length,
bool fin_acked,
QuicTime::Delta ack_delay_time,
+ QuicTime receive_timestamp,
QuicByteCount* newly_acked_length) override;
// Override to report bytes retransmitted via ack_listener_.
@@ -214,8 +216,15 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream
bool IsClosed() { return sequencer()->IsClosed(); }
// QpackDecodedHeadersAccumulator::Visitor implementation.
- void OnHeadersDecoded(QuicHeaderList headers) override;
- void OnHeaderDecodingError(QuicStringPiece error_message) override;
+ void OnHeadersDecoded(QuicHeaderList headers,
+ bool header_list_size_limit_exceeded) override;
+ void OnHeaderDecodingError(quiche::QuicheStringPiece error_message) override;
+
+ QuicSpdySession* spdy_session() const { return spdy_session_; }
+
+ // Send PRIORITY_UPDATE frame and update |last_sent_urgency_| if
+ // |last_sent_urgency_| is different from current priority.
+ void MaybeSendPriorityUpdateFrame() override;
protected:
// Called when the received headers are too large. By default this will
@@ -233,7 +242,6 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream
bool fin,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
- QuicSpdySession* spdy_session() const { return spdy_session_; }
Visitor* visitor() { return visitor_; }
void set_headers_decompressed(bool val) { headers_decompressed_ = val; }
@@ -243,9 +251,6 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream
ack_listener_ = std::move(ack_listener);
}
- // Fills in |frame| with appropriate fields.
- virtual void PopulatePriorityFrame(PriorityFrame* frame);
-
private:
friend class test::QuicSpdyStreamPeer;
friend class test::QuicStreamPeer;
@@ -253,18 +258,24 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream
class HttpDecoderVisitor;
// Called by HttpDecoderVisitor.
- bool OnDataFrameStart(QuicByteCount header_length);
- bool OnDataFramePayload(QuicStringPiece payload);
+ bool OnDataFrameStart(QuicByteCount header_length,
+ QuicByteCount payload_length);
+ bool OnDataFramePayload(quiche::QuicheStringPiece payload);
bool OnDataFrameEnd();
- bool OnHeadersFrameStart(QuicByteCount header_length);
- bool OnHeadersFramePayload(QuicStringPiece payload);
+ bool OnHeadersFrameStart(QuicByteCount header_length,
+ QuicByteCount payload_length);
+ bool OnHeadersFramePayload(quiche::QuicheStringPiece payload);
bool OnHeadersFrameEnd();
bool OnPushPromiseFrameStart(QuicByteCount header_length);
- bool OnPushPromiseFramePushId(PushId push_id, QuicByteCount push_id_length);
- bool OnPushPromiseFramePayload(QuicStringPiece payload);
+ bool OnPushPromiseFramePushId(PushId push_id,
+ QuicByteCount push_id_length,
+ QuicByteCount header_block_length);
+ bool OnPushPromiseFramePayload(quiche::QuicheStringPiece payload);
bool OnPushPromiseFrameEnd();
- bool OnUnknownFrameStart(uint64_t frame_type, QuicByteCount header_length);
- bool OnUnknownFramePayload(QuicStringPiece payload);
+ bool OnUnknownFrameStart(uint64_t frame_type,
+ QuicByteCount header_length,
+ QuicByteCount payload_length);
+ bool OnUnknownFramePayload(quiche::QuicheStringPiece payload);
bool OnUnknownFrameEnd();
// Given the interval marked by [|offset|, |offset| + |data_length|), return
@@ -299,9 +310,6 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream
// True if the trailers have been consumed.
bool trailers_consumed_;
- // True if the stream has already sent an priority frame.
- bool priority_sent_;
-
// The parsed trailers received from the peer.
spdy::SpdyHeaderBlock received_trailers_;
@@ -333,6 +341,10 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream
// Offset of unacked frame headers.
QuicIntervalSet<QuicStreamOffset> unacked_frame_headers_offsets_;
+
+ // Urgency value sent in the last PRIORITY_UPDATE frame, or default urgency
+ // defined by the spec if no PRIORITY_UPDATE frame has been sent.
+ int last_sent_urgency_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager.cc
index 798f55142ca..1e36aa70af9 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -27,7 +28,7 @@ size_t QuicSpdyStreamBodyManager::OnNonBody(QuicByteCount length) {
return 0;
}
-void QuicSpdyStreamBodyManager::OnBody(QuicStringPiece body) {
+void QuicSpdyStreamBodyManager::OnBody(quiche::QuicheStringPiece body) {
DCHECK(!body.empty());
fragments_.push_back({body, 0});
@@ -45,7 +46,7 @@ size_t QuicSpdyStreamBodyManager::OnBodyConsumed(size_t num_bytes) {
}
Fragment& fragment = fragments_.front();
- const QuicStringPiece body = fragment.body;
+ const quiche::QuicheStringPiece body = fragment.body;
if (body.length() > remaining_bytes) {
// Consume leading |remaining_bytes| bytes of body.
@@ -77,7 +78,7 @@ int QuicSpdyStreamBodyManager::PeekBody(iovec* iov, size_t iov_len) const {
size_t iov_filled = 0;
while (iov_filled < fragments_.size() && iov_filled < iov_len) {
- QuicStringPiece body = fragments_[iov_filled].body;
+ quiche::QuicheStringPiece body = fragments_[iov_filled].body;
iov[iov_filled].iov_base = const_cast<char*>(body.data());
iov[iov_filled].iov_len = body.size();
iov_filled++;
@@ -101,7 +102,7 @@ size_t QuicSpdyStreamBodyManager::ReadBody(const struct iovec* iov,
while (!fragments_.empty()) {
Fragment& fragment = fragments_.front();
- const QuicStringPiece body = fragment.body;
+ const quiche::QuicheStringPiece body = fragment.body;
const size_t bytes_to_copy =
std::min<size_t>(body.length(), dest_remaining);
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager.h
index 1942c261188..a5afecaa5e7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager.h
@@ -5,13 +5,13 @@
#ifndef QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_STREAM_BODY_MANAGER_H_
#define QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_STREAM_BODY_MANAGER_H_
+#include "net/third_party/quiche/src/quic/core/quic_circular_deque.h"
#include "net/third_party/quiche/src/quic/core/quic_constants.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_iovec.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_macros.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -43,7 +43,7 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStreamBodyManager {
// Called when body is received. |body| is added to |fragments_|. The data
// pointed to by |body| must be kept alive until an OnBodyConsumed() or
// ReadBody() call consumes it. |body| must not be empty.
- void OnBody(QuicStringPiece body);
+ void OnBody(quiche::QuicheStringPiece body);
// Internally marks |num_bytes| of body consumed. |num_bytes| might be zero.
// Returns the number of bytes that the caller should mark consumed with the
@@ -79,12 +79,12 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStreamBodyManager {
// consumed as soon as all of the body fragment is read.
struct QUIC_EXPORT_PRIVATE Fragment {
// |body| must not be empty.
- QuicStringPiece body;
+ quiche::QuicheStringPiece body;
// Might be zero.
QuicByteCount trailing_non_body_byte_count;
};
// Queue of body fragments and trailing non-body byte counts.
- QuicDeque<Fragment> fragments_;
+ QuicCircularDeque<Fragment> fragments_;
// Total body bytes received.
QuicByteCount total_body_bytes_received_;
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager_test.cc
index 10b19f1d668..0cdc65af3b1 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager_test.cc
@@ -8,10 +8,11 @@
#include <numeric>
#include <string>
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -74,7 +75,7 @@ TEST_F(QuicSpdyStreamBodyManagerTest, OnBodyConsumed) {
};
for (size_t test_case_index = 0;
- test_case_index < QUIC_ARRAYSIZE(kOnBodyConsumedTestData);
+ test_case_index < QUICHE_ARRAYSIZE(kOnBodyConsumedTestData);
++test_case_index) {
const std::vector<QuicByteCount>& frame_header_lengths =
kOnBodyConsumedTestData[test_case_index].frame_header_lengths;
@@ -126,7 +127,8 @@ TEST_F(QuicSpdyStreamBodyManagerTest, PeekBody) {
};
for (size_t test_case_index = 0;
- test_case_index < QUIC_ARRAYSIZE(kPeekBodyTestData); ++test_case_index) {
+ test_case_index < QUICHE_ARRAYSIZE(kPeekBodyTestData);
+ ++test_case_index) {
const std::vector<QuicByteCount>& frame_header_lengths =
kPeekBodyTestData[test_case_index].frame_header_lengths;
const std::vector<const char*>& frame_payloads =
@@ -152,7 +154,7 @@ TEST_F(QuicSpdyStreamBodyManagerTest, PeekBody) {
static_cast<size_t>(body_manager.PeekBody(&iovecs[0], iov_len)));
for (size_t iovec_index = 0; iovec_index < iovs_filled; ++iovec_index) {
EXPECT_EQ(frame_payloads[iovec_index],
- QuicStringPiece(
+ quiche::QuicheStringPiece(
static_cast<const char*>(iovecs[iovec_index].iov_base),
iovecs[iovec_index].iov_len));
}
@@ -219,7 +221,8 @@ TEST_F(QuicSpdyStreamBodyManagerTest, ReadBody) {
};
for (size_t test_case_index = 0;
- test_case_index < QUIC_ARRAYSIZE(kReadBodyTestData); ++test_case_index) {
+ test_case_index < QUICHE_ARRAYSIZE(kReadBodyTestData);
+ ++test_case_index) {
const std::vector<QuicByteCount>& frame_header_lengths =
kReadBodyTestData[test_case_index].frame_header_lengths;
const std::vector<const char*>& frame_payloads =
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_test.cc
index 62ef3b5015a..fab6d86a415 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_test.cc
@@ -4,10 +4,12 @@
#include "net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h"
+#include <cstring>
#include <memory>
#include <string>
#include <utility>
+#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h"
#include "net/third_party/quiche/src/quic/core/http/http_encoder.h"
#include "net/third_party/quiche/src/quic/core/http/spdy_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
@@ -15,21 +17,22 @@
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_flow_controller_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_session_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_stream_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
using spdy::kV3HighestPriority;
using spdy::kV3LowestPriority;
@@ -52,6 +55,89 @@ namespace {
const bool kShouldProcessData = true;
const char kDataFramePayload[] = "some data";
+class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {
+ public:
+ explicit TestCryptoStream(QuicSession* session)
+ : QuicCryptoStream(session),
+ QuicCryptoHandshaker(this, session),
+ encryption_established_(false),
+ one_rtt_keys_available_(false),
+ params_(new QuicCryptoNegotiatedParameters) {
+ // Simulate a negotiated cipher_suite with a fake value.
+ params_->cipher_suite = 1;
+ }
+
+ void OnHandshakeMessage(const CryptoHandshakeMessage& /*message*/) override {
+ encryption_established_ = true;
+ one_rtt_keys_available_ = true;
+ QuicErrorCode error;
+ std::string error_details;
+ session()->config()->SetInitialStreamFlowControlWindowToSend(
+ kInitialStreamFlowControlWindowForTest);
+ session()->config()->SetInitialSessionFlowControlWindowToSend(
+ kInitialSessionFlowControlWindowForTest);
+ if (session()->connection()->version().handshake_protocol ==
+ PROTOCOL_TLS1_3) {
+ TransportParameters transport_parameters;
+ EXPECT_TRUE(
+ session()->config()->FillTransportParameters(&transport_parameters));
+ error = session()->config()->ProcessTransportParameters(
+ transport_parameters, CLIENT, &error_details);
+ } else {
+ CryptoHandshakeMessage msg;
+ session()->config()->ToHandshakeMessage(&msg, transport_version());
+ error =
+ session()->config()->ProcessPeerHello(msg, CLIENT, &error_details);
+ }
+ EXPECT_THAT(error, IsQuicNoError());
+ session()->OnNewEncryptionKeyAvailable(
+ ENCRYPTION_FORWARD_SECURE,
+ std::make_unique<NullEncrypter>(session()->perspective()));
+ session()->OnConfigNegotiated();
+ if (session()->connection()->version().handshake_protocol ==
+ PROTOCOL_TLS1_3) {
+ session()->OnOneRttKeysAvailable();
+ } else {
+ session()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ }
+ session()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
+ }
+
+ // QuicCryptoStream implementation
+ bool encryption_established() const override {
+ return encryption_established_;
+ }
+ bool one_rtt_keys_available() const override {
+ return one_rtt_keys_available_;
+ }
+ HandshakeState GetHandshakeState() const override {
+ return one_rtt_keys_available() ? HANDSHAKE_COMPLETE : HANDSHAKE_START;
+ }
+ const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
+ const override {
+ return *params_;
+ }
+ CryptoMessageParser* crypto_message_parser() override {
+ return QuicCryptoHandshaker::crypto_message_parser();
+ }
+ void OnPacketDecrypted(EncryptionLevel /*level*/) override {}
+ void OnOneRttPacketAcknowledged() override {}
+ void OnHandshakeDoneReceived() override {}
+
+ MOCK_METHOD0(OnCanWrite, void());
+
+ bool HasPendingCryptoRetransmission() const override { return false; }
+
+ MOCK_CONST_METHOD0(HasPendingRetransmission, bool());
+
+ private:
+ using QuicCryptoStream::session;
+
+ bool encryption_established_;
+ bool one_rtt_keys_available_;
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
+};
+
class TestStream : public QuicSpdyStream {
public:
TestStream(QuicStreamId id,
@@ -72,7 +158,7 @@ class TestStream : public QuicSpdyStream {
char buffer[2048];
struct iovec vec;
vec.iov_base = buffer;
- vec.iov_len = QUIC_ARRAYSIZE(buffer);
+ vec.iov_len = QUICHE_ARRAYSIZE(buffer);
size_t bytes_read = Readv(&vec, 1);
data_ += std::string(buffer, bytes_read);
}
@@ -107,6 +193,24 @@ class TestStream : public QuicSpdyStream {
std::string data_;
};
+class TestSession : public MockQuicSpdySession {
+ public:
+ explicit TestSession(QuicConnection* connection)
+ : MockQuicSpdySession(connection, /*create_mock_crypto_stream=*/false),
+ crypto_stream_(this) {}
+
+ TestCryptoStream* GetMutableCryptoStream() override {
+ return &crypto_stream_;
+ }
+
+ const TestCryptoStream* GetCryptoStream() const override {
+ return &crypto_stream_;
+ }
+
+ private:
+ StrictMock<TestCryptoStream> crypto_stream_;
+};
+
class TestMockUpdateStreamSession : public MockQuicSpdySession {
public:
explicit TestMockUpdateStreamSession(QuicConnection* connection)
@@ -168,7 +272,8 @@ class QuicSpdyStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
// Return QPACK-encoded header block without using the dynamic table.
std::string EncodeQpackHeaders(
- std::vector<std::pair<QuicStringPiece, QuicStringPiece>> headers) {
+ std::vector<std::pair<quiche::QuicheStringPiece,
+ quiche::QuicheStringPiece>> headers) {
SpdyHeaderBlock header_block;
for (const auto& header_field : headers) {
header_block.AppendValueOrAddHeader(header_field.first,
@@ -199,10 +304,11 @@ class QuicSpdyStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
Perspective perspective) {
connection_ = new StrictMock<MockQuicConnection>(
&helper_, &alarm_factory_, perspective, SupportedVersions(GetParam()));
- session_ = std::make_unique<StrictMock<MockQuicSpdySession>>(connection_);
+ session_ = std::make_unique<StrictMock<TestSession>>(connection_);
session_->Initialize();
- ON_CALL(*session_, WritevData(_, _, _, _, _))
- .WillByDefault(Invoke(MockQuicSession::ConsumeData));
+ ON_CALL(*session_, WritevData(_, _, _, _, _, _))
+ .WillByDefault(
+ Invoke(session_.get(), &MockQuicSpdySession::ConsumeData));
stream_ =
new StrictMock<TestStream>(GetNthClientInitiatedBidirectionalId(0),
@@ -220,43 +326,37 @@ class QuicSpdyStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
session_->config(), kMinimumFlowControlSendWindow);
QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesOutgoingBidirectional(
session_->config(), kMinimumFlowControlSendWindow);
- QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams(
- session_->config(), 10);
+ QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(session_->config(), 10);
session_->OnConfigNegotiated();
- EXPECT_CALL(*connection_, OnCanWrite());
if (UsesHttp3()) {
- // In this case, TestStream::WriteHeadersImpl() does not prevent writes.
- // Six writes include priority for headers, headers frame header, headers
- // frame, priority of trailers, trailing headers frame header, and
- // trailers.
+ // The control stream will write the stream type, a greased frame, and
+ // SETTINGS frame.
+ int num_control_stream_writes = 3;
auto send_control_stream =
QuicSpdySessionPeer::GetSendControlStream(session_.get());
- // The control stream will write 3 times, including stream type, settings
- // frame and max push id, priority for headers.
- int num_control_stream_writes = 2;
- if (session_->perspective() == Perspective::IS_CLIENT) {
- // The control stream also writes the max push id frame.
- num_control_stream_writes++;
- }
- EXPECT_CALL(*session_, WritevData(send_control_stream,
- send_control_stream->id(), _, _, _))
+ EXPECT_CALL(*session_,
+ WritevData(send_control_stream->id(), _, _, _, _, _))
.Times(num_control_stream_writes);
auto qpack_decoder_stream =
QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
- EXPECT_CALL(*session_, WritevData(qpack_decoder_stream,
- qpack_decoder_stream->id(), 1, 0, _));
+ EXPECT_CALL(*session_,
+ WritevData(qpack_decoder_stream->id(), 1, 0, _, _, _));
auto qpack_encoder_stream =
QuicSpdySessionPeer::GetQpackEncoderSendStream(session_.get());
- EXPECT_CALL(*session_, WritevData(qpack_encoder_stream,
- qpack_encoder_stream->id(), 1, 0, _));
+ EXPECT_CALL(*session_,
+ WritevData(qpack_encoder_stream->id(), 1, 0, _, _, _));
}
- if (session_->use_handshake_delegate()) {
- static_cast<QuicSession*>(session_.get())
- ->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
- } else {
- static_cast<QuicSession*>(session_.get())
- ->OnCryptoHandshakeEvent(QuicSession::ENCRYPTION_ESTABLISHED);
+ TestCryptoStream* crypto_stream = session_->GetMutableCryptoStream();
+ EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
+ .Times(testing::AnyNumber());
+
+ if (connection_->version().HasHandshakeDone() &&
+ session_->perspective() == Perspective::IS_SERVER) {
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillOnce(Invoke(&ClearControlFrame));
}
+ CryptoHandshakeMessage message;
+ session_->GetMutableCryptoStream()->OnHandshakeMessage(message);
}
QuicHeaderList ProcessHeaders(bool fin, const SpdyHeaderBlock& headers) {
@@ -277,7 +377,8 @@ class QuicSpdyStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
// Construct HEADERS frame with QPACK-encoded |headers| without using the
// dynamic table.
std::string HeadersFrame(
- std::vector<std::pair<QuicStringPiece, QuicStringPiece>> headers) {
+ std::vector<std::pair<quiche::QuicheStringPiece,
+ quiche::QuicheStringPiece>> headers) {
return HeadersFrame(EncodeQpackHeaders(headers));
}
@@ -288,26 +389,27 @@ class QuicSpdyStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
}
// Construct HEADERS frame with given payload.
- std::string HeadersFrame(QuicStringPiece payload) {
+ std::string HeadersFrame(quiche::QuicheStringPiece payload) {
std::unique_ptr<char[]> headers_buffer;
QuicByteCount headers_frame_header_length =
HttpEncoder::SerializeHeadersFrameHeader(payload.length(),
&headers_buffer);
- QuicStringPiece headers_frame_header(headers_buffer.get(),
- headers_frame_header_length);
- return QuicStrCat(headers_frame_header, payload);
+ quiche::QuicheStringPiece headers_frame_header(headers_buffer.get(),
+ headers_frame_header_length);
+ return quiche::QuicheStrCat(headers_frame_header, payload);
}
- std::string DataFrame(QuicStringPiece payload) {
+ std::string DataFrame(quiche::QuicheStringPiece payload) {
std::unique_ptr<char[]> data_buffer;
QuicByteCount data_frame_header_length =
HttpEncoder::SerializeDataFrameHeader(payload.length(), &data_buffer);
- QuicStringPiece data_frame_header(data_buffer.get(),
- data_frame_header_length);
- return QuicStrCat(data_frame_header, payload);
+ quiche::QuicheStringPiece data_frame_header(data_buffer.get(),
+ data_frame_header_length);
+ return quiche::QuicheStrCat(data_frame_header, payload);
}
- std::string UnknownFrame(uint64_t frame_type, QuicStringPiece payload) {
+ std::string UnknownFrame(uint64_t frame_type,
+ quiche::QuicheStringPiece payload) {
std::string frame;
const size_t length = QuicDataWriter::GetVarInt62Len(frame_type) +
QuicDataWriter::GetVarInt62Len(payload.size()) +
@@ -328,7 +430,7 @@ class QuicSpdyStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
MockQuicConnectionHelper helper_;
MockAlarmFactory alarm_factory_;
MockQuicConnection* connection_;
- std::unique_ptr<MockQuicSpdySession> session_;
+ std::unique_ptr<TestSession> session_;
// Owned by the |session_|.
TestStream* stream_;
@@ -480,8 +582,8 @@ TEST_P(QuicSpdyStreamTest, ProcessWrongFramesOnSpdyStream) {
return;
}
- testing::InSequence s;
Initialize(kShouldProcessData);
+ testing::InSequence s;
connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
GoAwayFrame goaway;
goaway.stream_id = 0x1;
@@ -495,9 +597,10 @@ TEST_P(QuicSpdyStreamTest, ProcessWrongFramesOnSpdyStream) {
EXPECT_EQ(headers, stream_->header_list());
stream_->ConsumeHeaderList();
QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
- QuicStringPiece(data));
+ quiche::QuicheStringPiece(data));
- EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_DECODER_ERROR, _, _))
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_HTTP_FRAME_UNEXPECTED_ON_SPDY_STREAM, _, _))
.WillOnce(
(Invoke([this](QuicErrorCode error, const std::string& error_details,
ConnectionCloseBehavior connection_close_behavior) {
@@ -516,6 +619,39 @@ TEST_P(QuicSpdyStreamTest, ProcessWrongFramesOnSpdyStream) {
stream_->OnStreamFrame(frame);
}
+TEST_P(QuicSpdyStreamTest, Http3FrameError) {
+ if (!UsesHttp3()) {
+ return;
+ }
+
+ Initialize(kShouldProcessData);
+
+ // PUSH_PROMISE frame with empty payload is considered invalid.
+ std::string invalid_http3_frame = quiche::QuicheTextUtils::HexDecode("0500");
+ QuicStreamFrame stream_frame(stream_->id(), /* fin = */ false,
+ /* offset = */ 0, invalid_http3_frame);
+
+ EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_FRAME_ERROR, _, _));
+ stream_->OnStreamFrame(stream_frame);
+}
+
+TEST_P(QuicSpdyStreamTest, UnexpectedHttp3Frame) {
+ if (!UsesHttp3()) {
+ return;
+ }
+
+ Initialize(kShouldProcessData);
+
+ // SETTINGS frame with empty payload.
+ std::string settings = quiche::QuicheTextUtils::HexDecode("0400");
+ QuicStreamFrame stream_frame(stream_->id(), /* fin = */ false,
+ /* offset = */ 0, settings);
+
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_HTTP_FRAME_UNEXPECTED_ON_SPDY_STREAM, _, _));
+ stream_->OnStreamFrame(stream_frame);
+}
+
TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBody) {
Initialize(kShouldProcessData);
@@ -527,7 +663,7 @@ TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBody) {
EXPECT_EQ(headers, stream_->header_list());
stream_->ConsumeHeaderList();
QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
- QuicStringPiece(data));
+ quiche::QuicheStringPiece(data));
stream_->OnStreamFrame(frame);
EXPECT_EQ(QuicHeaderList(), stream_->header_list());
EXPECT_EQ(body, stream_->data());
@@ -544,10 +680,10 @@ TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyFragments) {
stream_->ConsumeHeaderList();
for (size_t offset = 0; offset < data.size(); offset += fragment_size) {
size_t remaining_data = data.size() - offset;
- QuicStringPiece fragment(data.data() + offset,
- std::min(fragment_size, remaining_data));
+ quiche::QuicheStringPiece fragment(
+ data.data() + offset, std::min(fragment_size, remaining_data));
QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false,
- offset, QuicStringPiece(fragment));
+ offset, quiche::QuicheStringPiece(fragment));
stream_->OnStreamFrame(frame);
}
ASSERT_EQ(body, stream_->data()) << "fragment_size: " << fragment_size;
@@ -564,15 +700,15 @@ TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyFragmentsSplit) {
ASSERT_EQ(headers, stream_->header_list());
stream_->ConsumeHeaderList();
- QuicStringPiece fragment1(data.data(), split_point);
+ quiche::QuicheStringPiece fragment1(data.data(), split_point);
QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
- QuicStringPiece(fragment1));
+ quiche::QuicheStringPiece(fragment1));
stream_->OnStreamFrame(frame1);
- QuicStringPiece fragment2(data.data() + split_point,
- data.size() - split_point);
+ quiche::QuicheStringPiece fragment2(data.data() + split_point,
+ data.size() - split_point);
QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(0), false,
- split_point, QuicStringPiece(fragment2));
+ split_point, quiche::QuicheStringPiece(fragment2));
stream_->OnStreamFrame(frame2);
ASSERT_EQ(body, stream_->data()) << "split_point: " << split_point;
@@ -587,15 +723,15 @@ TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyReadv) {
ProcessHeaders(false, headers_);
QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
- QuicStringPiece(data));
+ quiche::QuicheStringPiece(data));
stream_->OnStreamFrame(frame);
stream_->ConsumeHeaderList();
char buffer[2048];
- ASSERT_LT(data.length(), QUIC_ARRAYSIZE(buffer));
+ ASSERT_LT(data.length(), QUICHE_ARRAYSIZE(buffer));
struct iovec vec;
vec.iov_base = buffer;
- vec.iov_len = QUIC_ARRAYSIZE(buffer);
+ vec.iov_len = QUICHE_ARRAYSIZE(buffer);
size_t bytes_read = stream_->Readv(&vec, 1);
QuicStreamPeer::CloseReadSide(stream_);
@@ -610,16 +746,16 @@ TEST_P(QuicSpdyStreamTest, ProcessHeadersAndLargeBodySmallReadv) {
ProcessHeaders(false, headers_);
QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
- QuicStringPiece(data));
+ quiche::QuicheStringPiece(data));
stream_->OnStreamFrame(frame);
stream_->ConsumeHeaderList();
char buffer[2048];
char buffer2[2048];
struct iovec vec[2];
vec[0].iov_base = buffer;
- vec[0].iov_len = QUIC_ARRAYSIZE(buffer);
+ vec[0].iov_len = QUICHE_ARRAYSIZE(buffer);
vec[1].iov_base = buffer2;
- vec[1].iov_len = QUIC_ARRAYSIZE(buffer2);
+ vec[1].iov_len = QUICHE_ARRAYSIZE(buffer2);
size_t bytes_read = stream_->Readv(vec, 2);
EXPECT_EQ(2048u * 2, bytes_read);
EXPECT_EQ(body.substr(0, 2048), std::string(buffer, 2048));
@@ -634,7 +770,7 @@ TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyMarkConsumed) {
ProcessHeaders(false, headers_);
QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
- QuicStringPiece(data));
+ quiche::QuicheStringPiece(data));
stream_->OnStreamFrame(frame);
stream_->ConsumeHeaderList();
@@ -657,9 +793,9 @@ TEST_P(QuicSpdyStreamTest, ProcessHeadersAndConsumeMultipleBody) {
ProcessHeaders(false, headers_);
QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
- QuicStringPiece(data1));
+ quiche::QuicheStringPiece(data1));
QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(0), false,
- data1.length(), QuicStringPiece(data2));
+ data1.length(), quiche::QuicheStringPiece(data2));
stream_->OnStreamFrame(frame1);
stream_->OnStreamFrame(frame2);
stream_->ConsumeHeaderList();
@@ -677,14 +813,14 @@ TEST_P(QuicSpdyStreamTest, ProcessHeadersAndBodyIncrementalReadv) {
ProcessHeaders(false, headers_);
QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
- QuicStringPiece(data));
+ quiche::QuicheStringPiece(data));
stream_->OnStreamFrame(frame);
stream_->ConsumeHeaderList();
char buffer[1];
struct iovec vec;
vec.iov_base = buffer;
- vec.iov_len = QUIC_ARRAYSIZE(buffer);
+ vec.iov_len = QUICHE_ARRAYSIZE(buffer);
for (size_t i = 0; i < body.length(); ++i) {
size_t bytes_read = stream_->Readv(&vec, 1);
@@ -701,7 +837,7 @@ TEST_P(QuicSpdyStreamTest, ProcessHeadersUsingReadvWithMultipleIovecs) {
ProcessHeaders(false, headers_);
QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
- QuicStringPiece(data));
+ quiche::QuicheStringPiece(data));
stream_->OnStreamFrame(frame);
stream_->ConsumeHeaderList();
@@ -709,9 +845,9 @@ TEST_P(QuicSpdyStreamTest, ProcessHeadersUsingReadvWithMultipleIovecs) {
char buffer2[1];
struct iovec vec[2];
vec[0].iov_base = buffer1;
- vec[0].iov_len = QUIC_ARRAYSIZE(buffer1);
+ vec[0].iov_len = QUICHE_ARRAYSIZE(buffer1);
vec[1].iov_base = buffer2;
- vec[1].iov_len = QUIC_ARRAYSIZE(buffer2);
+ vec[1].iov_len = QUICHE_ARRAYSIZE(buffer2);
for (size_t i = 0; i < body.length(); i += 2) {
size_t bytes_read = stream_->Readv(vec, 2);
@@ -724,8 +860,8 @@ TEST_P(QuicSpdyStreamTest, ProcessHeadersUsingReadvWithMultipleIovecs) {
// Tests that we send a BLOCKED frame to the peer when we attempt to write, but
// are flow control blocked.
TEST_P(QuicSpdyStreamTest, StreamFlowControlBlocked) {
- testing::InSequence seq;
Initialize(kShouldProcessData);
+ testing::InSequence seq;
// Set a small flow control limit.
const uint64_t kWindow = 36;
@@ -740,9 +876,9 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlBlocked) {
const uint64_t kHeaderLength = UsesHttp3() ? 2 : 0;
if (UsesHttp3()) {
- EXPECT_CALL(*session_, WritevData(_, _, kHeaderLength, _, NO_FIN));
+ EXPECT_CALL(*session_, WritevData(_, kHeaderLength, _, NO_FIN, _, _));
}
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
.WillOnce(Return(QuicConsumedData(kWindow - kHeaderLength, true)));
EXPECT_CALL(*connection_, SendControlFrame(_));
stream_->WriteOrBufferBody(body, false);
@@ -792,7 +928,7 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlNoWindowUpdateIfNotConsumed) {
ProcessHeaders(false, headers_);
QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
- QuicStringPiece(data));
+ quiche::QuicheStringPiece(data));
stream_->OnStreamFrame(frame1);
EXPECT_EQ(
kWindow - (kWindow / 3) - header_length,
@@ -802,7 +938,8 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlNoWindowUpdateIfNotConsumed) {
// half full. This should all be buffered, decreasing the receive window but
// not sending WINDOW_UPDATE.
QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(0), false,
- kWindow / 3 + header_length, QuicStringPiece(data));
+ kWindow / 3 + header_length,
+ quiche::QuicheStringPiece(data));
stream_->OnStreamFrame(frame2);
EXPECT_EQ(
kWindow - (2 * kWindow / 3) - 2 * header_length,
@@ -843,7 +980,7 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlWindowUpdate) {
stream_->ConsumeHeaderList();
QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
- QuicStringPiece(data));
+ quiche::QuicheStringPiece(data));
stream_->OnStreamFrame(frame1);
EXPECT_EQ(
kWindow - (kWindow / 3) - header_length,
@@ -854,7 +991,8 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlWindowUpdate) {
// offset and send a WINDOW_UPDATE. The result will be again an available
// window of kWindow bytes.
QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(0), false,
- kWindow / 3 + header_length, QuicStringPiece(data));
+ kWindow / 3 + header_length,
+ quiche::QuicheStringPiece(data));
EXPECT_CALL(*connection_, SendControlFrame(_));
stream_->OnStreamFrame(frame2);
EXPECT_EQ(kWindow, QuicFlowControllerPeer::ReceiveWindowSize(
@@ -918,10 +1056,10 @@ TEST_P(QuicSpdyStreamTest, ConnectionFlowControlWindowUpdate) {
}
QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
- QuicStringPiece(data));
+ quiche::QuicheStringPiece(data));
stream_->OnStreamFrame(frame1);
QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(1), false, 0,
- QuicStringPiece(data));
+ quiche::QuicheStringPiece(data));
stream2_->OnStreamFrame(frame2);
// Now receive a further single byte on one stream - again this does not
@@ -929,7 +1067,8 @@ TEST_P(QuicSpdyStreamTest, ConnectionFlowControlWindowUpdate) {
// is over half full and thus a connection WINDOW_UPDATE is sent.
EXPECT_CALL(*connection_, SendControlFrame(_));
QuicStreamFrame frame3(GetNthClientInitiatedBidirectionalId(0), false,
- body.length() + header_length, QuicStringPiece(data2));
+ body.length() + header_length,
+ quiche::QuicheStringPiece(data2));
stream_->OnStreamFrame(frame3);
}
@@ -951,7 +1090,7 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlViolation) {
std::string body(kWindow + 1, 'a');
std::string data = UsesHttp3() ? DataFrame(body) : body;
QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
- QuicStringPiece(data));
+ quiche::QuicheStringPiece(data));
EXPECT_CALL(*connection_,
CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _));
stream_->OnStreamFrame(frame);
@@ -991,7 +1130,7 @@ TEST_P(QuicSpdyStreamTest, ConnectionFlowControlViolation) {
EXPECT_LT(data.size(), kStreamWindow);
QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
- QuicStringPiece(data));
+ quiche::QuicheStringPiece(data));
EXPECT_CALL(*connection_,
CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _));
@@ -1015,7 +1154,7 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlFinNotBlocked) {
EXPECT_CALL(*connection_,
SendBlocked(GetNthClientInitiatedBidirectionalId(0)))
.Times(0);
- EXPECT_CALL(*session_, WritevData(_, _, 0, _, FIN));
+ EXPECT_CALL(*session_, WritevData(_, 0, _, FIN, _, _));
stream_->WriteOrBufferBody(body, fin);
}
@@ -1091,7 +1230,7 @@ TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithOffset) {
trailers_block["key2"] = "value2";
trailers_block["key3"] = "value3";
trailers_block[kFinalOffsetHeaderKey] =
- QuicTextUtils::Uint64ToString(data.size());
+ quiche::QuicheTextUtils::Uint64ToString(data.size());
QuicHeaderList trailers = ProcessHeaders(true, trailers_block);
@@ -1256,8 +1395,9 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersSendsAFin) {
if (UsesHttp3()) {
// In this case, TestStream::WriteHeadersImpl() does not prevent writes.
- EXPECT_CALL(*session_, WritevData(stream_, stream_->id(), _, _, _))
- .Times(AtLeast(1));
+ // Four writes on the request stream: HEADERS frame header and payload both
+ // for headers and trailers.
+ EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _)).Times(4);
}
// Write the initial headers, without a FIN.
@@ -1272,38 +1412,89 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersSendsAFin) {
EXPECT_TRUE(stream_->fin_sent());
}
-TEST_P(QuicSpdyStreamTest, ClientWritesPriority) {
- SetQuicFlag(FLAGS_quic_allow_http3_priority, true);
- SetQuicReloadableFlag(quic_send_max_push_id_with_settings, true);
- InitializeWithPerspective(kShouldProcessData, Perspective::IS_CLIENT);
-
- if (UsesHttp3()) {
- // In this case, TestStream::WriteHeadersImpl() does not prevent writes.
- // Six writes include priority for headers, headers frame header, headers
- // frame, priority of trailers, trailing headers frame header, and trailers.
- EXPECT_CALL(*session_, WritevData(stream_, stream_->id(), _, _, _))
- .Times(4);
- auto send_control_stream =
- QuicSpdySessionPeer::GetSendControlStream(session_.get());
- // The control stream will write priority for headers as well as
- // the settings/max_push_id.
- EXPECT_CALL(*session_, WritevData(send_control_stream,
- send_control_stream->id(), _, _, _))
- .Times(1);
+TEST_P(QuicSpdyStreamTest, DoNotSendPriorityUpdateWithDefaultUrgency) {
+ if (!UsesHttp3()) {
+ return;
}
+ InitializeWithPerspective(kShouldProcessData, Perspective::IS_CLIENT);
+ StrictMock<MockHttp3DebugVisitor> debug_visitor;
+ session_->set_debug_visitor(&debug_visitor);
+
+ // Four writes on the request stream: HEADERS frame header and payload both
+ // for headers and trailers.
+ EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _)).Times(4);
+
+ // No PRIORITY_UPDATE frames on the control stream,
+ // because the stream has default priority.
+ auto send_control_stream =
+ QuicSpdySessionPeer::GetSendControlStream(session_.get());
+ EXPECT_CALL(*session_, WritevData(send_control_stream->id(), _, _, _, _, _))
+ .Times(0);
+
// Write the initial headers, without a FIN.
EXPECT_CALL(*stream_, WriteHeadersMock(false));
+ EXPECT_CALL(debug_visitor, OnHeadersFrameSent(stream_->id(), _));
stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr);
// Writing trailers implicitly sends a FIN.
SpdyHeaderBlock trailers;
trailers["trailer key"] = "trailer value";
EXPECT_CALL(*stream_, WriteHeadersMock(true));
+ EXPECT_CALL(debug_visitor, OnHeadersFrameSent(stream_->id(), _));
stream_->WriteTrailers(std::move(trailers), nullptr);
EXPECT_TRUE(stream_->fin_sent());
}
+TEST_P(QuicSpdyStreamTest, ChangePriority) {
+ if (!UsesHttp3()) {
+ return;
+ }
+
+ InitializeWithPerspective(kShouldProcessData, Perspective::IS_CLIENT);
+ StrictMock<MockHttp3DebugVisitor> debug_visitor;
+ session_->set_debug_visitor(&debug_visitor);
+
+ // Two writes on the request stream: HEADERS frame header and payload.
+ EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _)).Times(2);
+ EXPECT_CALL(*stream_, WriteHeadersMock(false));
+ EXPECT_CALL(debug_visitor, OnHeadersFrameSent(stream_->id(), _));
+ stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr);
+
+ // PRIORITY_UPDATE frame on the control stream.
+ auto send_control_stream =
+ QuicSpdySessionPeer::GetSendControlStream(session_.get());
+ EXPECT_CALL(*session_, WritevData(send_control_stream->id(), _, _, _, _, _));
+ PriorityUpdateFrame priority_update;
+ priority_update.prioritized_element_id = 0;
+ priority_update.priority_field_value = "u=0";
+ EXPECT_CALL(debug_visitor, OnPriorityUpdateFrameSent(priority_update));
+ stream_->SetPriority(spdy::SpdyStreamPrecedence(kV3HighestPriority));
+}
+
+TEST_P(QuicSpdyStreamTest, ChangePriorityBeforeWritingHeaders) {
+ if (!UsesHttp3()) {
+ return;
+ }
+
+ InitializeWithPerspective(kShouldProcessData, Perspective::IS_CLIENT);
+
+ // PRIORITY_UPDATE frame sent on the control stream as soon as SetPriority()
+ // is called, before HEADERS frame is sent.
+ auto send_control_stream =
+ QuicSpdySessionPeer::GetSendControlStream(session_.get());
+ EXPECT_CALL(*session_, WritevData(send_control_stream->id(), _, _, _, _, _));
+
+ stream_->SetPriority(spdy::SpdyStreamPrecedence(kV3HighestPriority));
+ testing::Mock::VerifyAndClearExpectations(session_.get());
+
+ // Two writes on the request stream: HEADERS frame header and payload.
+ // PRIORITY_UPDATE frame is not sent this time, because one is already sent.
+ EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _)).Times(2);
+ EXPECT_CALL(*stream_, WriteHeadersMock(true));
+ stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/true, nullptr);
+}
+
// Test that when writing trailers, the trailers that are actually sent to the
// peer contain the final offset field indicating last byte of data.
TEST_P(QuicSpdyStreamTest, WritingTrailersFinalOffset) {
@@ -1311,8 +1502,8 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersFinalOffset) {
if (UsesHttp3()) {
// In this case, TestStream::WriteHeadersImpl() does not prevent writes.
- EXPECT_CALL(*session_, WritevData(stream_, stream_->id(), _, _, _))
- .Times(AtLeast(1));
+ // HEADERS frame header and payload on the request stream.
+ EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _)).Times(2);
}
// Write the initial headers.
@@ -1320,7 +1511,7 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersFinalOffset) {
stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr);
// Write non-zero body data to force a non-zero final offset.
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1));
std::string body(1024, 'x'); // 1 kB
QuicByteCount header_length = 0;
if (UsesHttp3()) {
@@ -1340,7 +1531,7 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersFinalOffset) {
// on the headers stream.
if (!UsesHttp3()) {
expected_trailers[kFinalOffsetHeaderKey] =
- QuicTextUtils::Uint64ToString(body.length() + header_length);
+ quiche::QuicheTextUtils::Uint64ToString(body.length() + header_length);
}
EXPECT_CALL(*stream_, WriteHeadersMock(true));
@@ -1355,7 +1546,7 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersClosesWriteSide) {
// Expect data being written on the stream. In addition to that, headers are
// also written on the stream in case of IETF QUIC.
- EXPECT_CALL(*session_, WritevData(stream_, stream_->id(), _, _, _))
+ EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _))
.Times(AtLeast(1));
// Write the initial headers.
@@ -1394,9 +1585,9 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersWithQueuedBytes) {
// Write non-zero body data, but only consume partially, ensuring queueing.
const int kBodySize = 1 * 1024; // 1 kB
if (UsesHttp3()) {
- EXPECT_CALL(*session_, WritevData(_, _, 3, _, NO_FIN));
+ EXPECT_CALL(*session_, WritevData(_, 3, _, NO_FIN, _, _));
}
- EXPECT_CALL(*session_, WritevData(_, _, kBodySize, _, NO_FIN))
+ EXPECT_CALL(*session_, WritevData(_, kBodySize, _, NO_FIN, _, _))
.WillOnce(Return(QuicConsumedData(kBodySize - 1, false)));
stream_->WriteOrBufferBody(std::string(kBodySize, 'x'), false);
EXPECT_EQ(1u, stream_->BufferedDataBytes());
@@ -1409,18 +1600,16 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersWithQueuedBytes) {
EXPECT_FALSE(stream_->write_side_closed());
// Writing the queued bytes will close the write side of the stream.
- EXPECT_CALL(*session_, WritevData(_, _, 1, _, NO_FIN));
+ EXPECT_CALL(*session_, WritevData(_, 1, _, NO_FIN, _, _));
stream_->OnCanWrite();
EXPECT_TRUE(stream_->write_side_closed());
}
// Test that it is not possible to write Trailers after a FIN has been sent.
TEST_P(QuicSpdyStreamTest, WritingTrailersAfterFIN) {
- // EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
// In IETF QUIC, there is no such thing as FIN flag on HTTP/3 frames like the
- // HEADERS frame. That is version 99, which is element 0 of the array, so
- // pick another element.
- if (GetParam() != AllSupportedVersions()[1]) {
+ // HEADERS frame.
+ if (UsesHttp3()) {
return;
}
@@ -1449,7 +1638,7 @@ TEST_P(QuicSpdyStreamTest, HeaderStreamNotiferCorrespondingSpdyStream) {
const char kBody2[] = "Test2";
Initialize(kShouldProcessData);
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1));
testing::InSequence s;
QuicReferenceCountedPointer<MockAckListener> ack_listener1(
new MockAckListener());
@@ -1495,7 +1684,7 @@ TEST_P(QuicSpdyStreamTest, HeaderStreamNotiferCorrespondingSpdyStream) {
TEST_P(QuicSpdyStreamTest, StreamBecomesZombieWithWriteThatCloses) {
Initialize(kShouldProcessData);
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1));
QuicStreamPeer::CloseReadSide(stream_);
// This write causes stream to be closed.
stream_->WriteOrBufferBody("Test1", true);
@@ -1513,13 +1702,13 @@ TEST_P(QuicSpdyStreamTest, OnPriorityFrame) {
}
TEST_P(QuicSpdyStreamTest, OnPriorityFrameAfterSendingData) {
- testing::InSequence seq;
Initialize(kShouldProcessData);
+ testing::InSequence seq;
if (UsesHttp3()) {
- EXPECT_CALL(*session_, WritevData(_, _, 2, _, NO_FIN));
+ EXPECT_CALL(*session_, WritevData(_, 2, _, NO_FIN, _, _));
}
- EXPECT_CALL(*session_, WritevData(_, _, 4, _, FIN));
+ EXPECT_CALL(*session_, WritevData(_, 4, _, FIN, _, _));
stream_->WriteOrBufferBody("data", true);
stream_->OnPriorityFrame(spdy::SpdyStreamPrecedence(kV3HighestPriority));
EXPECT_EQ(spdy::SpdyStreamPrecedence(kV3HighestPriority),
@@ -1556,7 +1745,7 @@ TEST_P(QuicSpdyStreamTest, StreamWaitsForAcks) {
QuicReferenceCountedPointer<MockAckListener> mock_ack_listener(
new StrictMock<MockAckListener>);
stream_->set_ack_listener(mock_ack_listener);
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1));
// Stream is not waiting for acks initially.
EXPECT_FALSE(stream_->IsWaitingForAcks());
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
@@ -1568,6 +1757,7 @@ TEST_P(QuicSpdyStreamTest, StreamWaitsForAcks) {
EXPECT_CALL(*mock_ack_listener, OnPacketAcked(9, _));
QuicByteCount newly_acked_length = 0;
EXPECT_TRUE(stream_->OnStreamFrameAcked(0, 9, false, QuicTime::Delta::Zero(),
+ QuicTime::Zero(),
&newly_acked_length));
// Stream is not waiting for acks as all sent data is acked.
EXPECT_FALSE(stream_->IsWaitingForAcks());
@@ -1589,6 +1779,7 @@ TEST_P(QuicSpdyStreamTest, StreamWaitsForAcks) {
// kData2 is acked.
EXPECT_CALL(*mock_ack_listener, OnPacketAcked(9, _));
EXPECT_TRUE(stream_->OnStreamFrameAcked(9, 9, false, QuicTime::Delta::Zero(),
+ QuicTime::Zero(),
&newly_acked_length));
// Stream is waiting for acks as FIN is not acked.
EXPECT_TRUE(stream_->IsWaitingForAcks());
@@ -1597,6 +1788,7 @@ TEST_P(QuicSpdyStreamTest, StreamWaitsForAcks) {
// FIN is acked.
EXPECT_CALL(*mock_ack_listener, OnPacketAcked(0, _));
EXPECT_TRUE(stream_->OnStreamFrameAcked(18, 0, true, QuicTime::Delta::Zero(),
+ QuicTime::Zero(),
&newly_acked_length));
EXPECT_FALSE(stream_->IsWaitingForAcks());
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
@@ -1607,7 +1799,7 @@ TEST_P(QuicSpdyStreamTest, StreamDataGetAckedMultipleTimes) {
QuicReferenceCountedPointer<MockAckListener> mock_ack_listener(
new StrictMock<MockAckListener>);
stream_->set_ack_listener(mock_ack_listener);
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1));
// Send [0, 27) and fin.
stream_->WriteOrBufferData("FooAndBar", false, nullptr);
stream_->WriteOrBufferData("FooAndBar", false, nullptr);
@@ -1618,16 +1810,19 @@ TEST_P(QuicSpdyStreamTest, StreamDataGetAckedMultipleTimes) {
QuicByteCount newly_acked_length = 0;
EXPECT_CALL(*mock_ack_listener, OnPacketAcked(9, _));
EXPECT_TRUE(stream_->OnStreamFrameAcked(0, 9, false, QuicTime::Delta::Zero(),
+ QuicTime::Zero(),
&newly_acked_length));
EXPECT_EQ(2u, QuicStreamPeer::SendBuffer(stream_).size());
// Verify [9, 22) 13 bytes are acked.
EXPECT_CALL(*mock_ack_listener, OnPacketAcked(13, _));
EXPECT_TRUE(stream_->OnStreamFrameAcked(5, 17, false, QuicTime::Delta::Zero(),
+ QuicTime::Zero(),
&newly_acked_length));
EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
// Verify [22, 26) 4 bytes are acked.
EXPECT_CALL(*mock_ack_listener, OnPacketAcked(4, _));
EXPECT_TRUE(stream_->OnStreamFrameAcked(18, 8, false, QuicTime::Delta::Zero(),
+ QuicTime::Zero(),
&newly_acked_length));
EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
EXPECT_TRUE(stream_->IsWaitingForAcks());
@@ -1636,6 +1831,7 @@ TEST_P(QuicSpdyStreamTest, StreamDataGetAckedMultipleTimes) {
// Verify [26, 27) 1 byte is acked.
EXPECT_CALL(*mock_ack_listener, OnPacketAcked(1, _));
EXPECT_TRUE(stream_->OnStreamFrameAcked(26, 1, false, QuicTime::Delta::Zero(),
+ QuicTime::Zero(),
&newly_acked_length));
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
EXPECT_TRUE(stream_->IsWaitingForAcks());
@@ -1643,6 +1839,7 @@ TEST_P(QuicSpdyStreamTest, StreamDataGetAckedMultipleTimes) {
// Ack Fin. Verify OnPacketAcked is called.
EXPECT_CALL(*mock_ack_listener, OnPacketAcked(0, _));
EXPECT_TRUE(stream_->OnStreamFrameAcked(27, 0, true, QuicTime::Delta::Zero(),
+ QuicTime::Zero(),
&newly_acked_length));
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
EXPECT_FALSE(stream_->IsWaitingForAcks());
@@ -1650,8 +1847,9 @@ TEST_P(QuicSpdyStreamTest, StreamDataGetAckedMultipleTimes) {
// Ack [10, 27) and fin.
// No new data is acked, verify OnPacketAcked is not called.
EXPECT_CALL(*mock_ack_listener, OnPacketAcked(_, _)).Times(0);
- EXPECT_FALSE(stream_->OnStreamFrameAcked(
- 10, 17, true, QuicTime::Delta::Zero(), &newly_acked_length));
+ EXPECT_FALSE(
+ stream_->OnStreamFrameAcked(10, 17, true, QuicTime::Delta::Zero(),
+ QuicTime::Zero(), &newly_acked_length));
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
EXPECT_FALSE(stream_->IsWaitingForAcks());
}
@@ -1669,7 +1867,7 @@ TEST_P(QuicSpdyStreamTest, HeadersAckNotReportedWriteOrBufferBody) {
std::string body = "Test1";
std::string body2(100, 'x');
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1));
stream_->WriteOrBufferBody(body, false);
stream_->WriteOrBufferBody(body2, true);
@@ -1722,7 +1920,7 @@ TEST_P(QuicSpdyStreamTest, HeadersAckNotReportedWriteBodySlices) {
helper_.GetStreamSendBufferAllocator(), 1024);
QuicMemSliceStorage storage2(&body2_iov, 1,
helper_.GetStreamSendBufferAllocator(), 1024);
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1));
stream_->WriteBodySlices(storage.ToSpan(), false);
stream_->WriteBodySlices(storage2.ToSpan(), true);
@@ -1752,7 +1950,7 @@ TEST_P(QuicSpdyStreamTest, HeaderBytesNotReportedOnRetransmission) {
std::string body1 = "Test1";
std::string body2(100, 'x');
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1));
stream_->WriteOrBufferBody(body1, false);
stream_->WriteOrBufferBody(body2, true);
@@ -1783,7 +1981,8 @@ TEST_P(QuicSpdyStreamTest, HeadersFrameOnRequestStream) {
std::string trailers =
HeadersFrame({std::make_pair("custom-key", "custom-value")});
- std::string stream_frame_payload = QuicStrCat(headers, data, trailers);
+ std::string stream_frame_payload =
+ quiche::QuicheStrCat(headers, data, trailers);
QuicStreamFrame frame(stream_->id(), false, 0, stream_frame_payload);
stream_->OnStreamFrame(frame);
@@ -1817,7 +2016,8 @@ TEST_P(QuicSpdyStreamTest, ProcessBodyAfterTrailers) {
std::string trailers = HeadersFrame(trailers_block);
// Feed all three HTTP/3 frames in a single stream frame.
- std::string stream_frame_payload = QuicStrCat(headers, data, trailers);
+ std::string stream_frame_payload =
+ quiche::QuicheStrCat(headers, data, trailers);
QuicStreamFrame frame(stream_->id(), false, 0, stream_frame_payload);
stream_->OnStreamFrame(frame);
@@ -1833,9 +2033,9 @@ TEST_P(QuicSpdyStreamTest, ProcessBodyAfterTrailers) {
char buffer[2048];
struct iovec vec;
vec.iov_base = buffer;
- vec.iov_len = QUIC_ARRAYSIZE(buffer);
+ vec.iov_len = QUICHE_ARRAYSIZE(buffer);
size_t bytes_read = stream_->Readv(&vec, 1);
- EXPECT_EQ(kDataFramePayload, QuicStringPiece(buffer, bytes_read));
+ EXPECT_EQ(kDataFramePayload, quiche::QuicheStringPiece(buffer, bytes_read));
EXPECT_FALSE(stream_->HasBytesToRead());
}
@@ -1848,17 +2048,16 @@ TEST_P(QuicSpdyStreamTest, MalformedHeadersStopHttpDecoder) {
return;
}
- testing::InSequence s;
-
Initialize(kShouldProcessData);
+ testing::InSequence s;
connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
// Random bad headers.
std::string headers =
- HeadersFrame(QuicTextUtils::HexDecode("00002a94e7036261"));
+ HeadersFrame(quiche::QuicheTextUtils::HexDecode("00002a94e7036261"));
std::string data = DataFrame(kDataFramePayload);
- std::string stream_frame_payload = QuicStrCat(headers, data);
+ std::string stream_frame_payload = quiche::QuicheStrCat(headers, data);
QuicStreamFrame frame(stream_->id(), false, 0, stream_frame_payload);
EXPECT_CALL(
@@ -1921,7 +2120,8 @@ TEST_P(QuicSpdyStreamTest, DoNotMarkConsumedAfterQpackDecodingError) {
// Invalid headers: Required Insert Count is zero, but the header block
// contains a dynamic table reference.
- std::string headers = HeadersFrame(QuicTextUtils::HexDecode("000080"));
+ std::string headers =
+ HeadersFrame(quiche::QuicheTextUtils::HexDecode("000080"));
QuicStreamFrame frame(stream_->id(), false, 0, headers);
stream_->OnStreamFrame(frame);
}
@@ -1931,21 +2131,26 @@ TEST_P(QuicSpdyStreamTest, ImmediateHeaderDecodingWithDynamicTableEntries) {
return;
}
- testing::InSequence s;
Initialize(kShouldProcessData);
+ testing::InSequence s;
session_->qpack_decoder()->OnSetDynamicTableCapacity(1024);
+ StrictMock<MockHttp3DebugVisitor> debug_visitor;
+ session_->set_debug_visitor(&debug_visitor);
auto decoder_send_stream =
QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
- // The stream byte will be written in the first byte.
- EXPECT_CALL(*session_, WritevData(decoder_send_stream,
- decoder_send_stream->id(), _, _, _));
// Deliver dynamic table entry to decoder.
session_->qpack_decoder()->OnInsertWithoutNameReference("foo", "bar");
// HEADERS frame referencing first dynamic table entry.
- std::string headers = HeadersFrame(QuicTextUtils::HexDecode("020080"));
+ std::string encoded_headers = quiche::QuicheTextUtils::HexDecode("020080");
+ std::string headers = HeadersFrame(encoded_headers);
+ EXPECT_CALL(debug_visitor,
+ OnHeadersFrameReceived(stream_->id(), encoded_headers.length()));
+ // Decoder stream type and header acknowledgement.
+ EXPECT_CALL(*session_, WritevData(decoder_send_stream->id(), _, _, _, _, _));
+ EXPECT_CALL(debug_visitor, OnHeadersDecoded(stream_->id(), _));
stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, 0, headers));
// Headers can be decoded immediately.
@@ -1957,17 +2162,23 @@ TEST_P(QuicSpdyStreamTest, ImmediateHeaderDecodingWithDynamicTableEntries) {
// DATA frame.
std::string data = DataFrame(kDataFramePayload);
+ EXPECT_CALL(debug_visitor,
+ OnDataFrameReceived(stream_->id(), strlen(kDataFramePayload)));
stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, /* offset = */
headers.length(), data));
EXPECT_EQ(kDataFramePayload, stream_->data());
- EXPECT_CALL(*session_, WritevData(decoder_send_stream,
- decoder_send_stream->id(), _, _, _));
// Deliver second dynamic table entry to decoder.
session_->qpack_decoder()->OnInsertWithoutNameReference("trailing", "foobar");
// Trailing HEADERS frame referencing second dynamic table entry.
- std::string trailers = HeadersFrame(QuicTextUtils::HexDecode("030080"));
+ std::string encoded_trailers = quiche::QuicheTextUtils::HexDecode("030080");
+ std::string trailers = HeadersFrame(encoded_trailers);
+ EXPECT_CALL(debug_visitor,
+ OnHeadersFrameReceived(stream_->id(), encoded_trailers.length()));
+ // Header acknowledgement.
+ EXPECT_CALL(*session_, WritevData(decoder_send_stream->id(), _, _, _, _, _));
+ EXPECT_CALL(debug_visitor, OnHeadersDecoded(stream_->id(), _));
stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), true, /* offset = */
headers.length() + data.length(),
trailers));
@@ -1986,12 +2197,17 @@ TEST_P(QuicSpdyStreamTest, BlockedHeaderDecoding) {
return;
}
- testing::InSequence s;
Initialize(kShouldProcessData);
+ testing::InSequence s;
session_->qpack_decoder()->OnSetDynamicTableCapacity(1024);
+ StrictMock<MockHttp3DebugVisitor> debug_visitor;
+ session_->set_debug_visitor(&debug_visitor);
// HEADERS frame referencing first dynamic table entry.
- std::string headers = HeadersFrame(QuicTextUtils::HexDecode("020080"));
+ std::string encoded_headers = quiche::QuicheTextUtils::HexDecode("020080");
+ std::string headers = HeadersFrame(encoded_headers);
+ EXPECT_CALL(debug_visitor,
+ OnHeadersFrameReceived(stream_->id(), encoded_headers.length()));
stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, 0, headers));
// Decoding is blocked because dynamic table entry has not been received yet.
@@ -2000,9 +2216,9 @@ TEST_P(QuicSpdyStreamTest, BlockedHeaderDecoding) {
auto decoder_send_stream =
QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
- // The stream byte will be written in the first byte.
- EXPECT_CALL(*session_, WritevData(decoder_send_stream,
- decoder_send_stream->id(), _, _, _));
+ // Decoder stream type and header acknowledgement.
+ EXPECT_CALL(*session_, WritevData(decoder_send_stream->id(), _, _, _, _, _));
+ EXPECT_CALL(debug_visitor, OnHeadersDecoded(stream_->id(), _));
// Deliver dynamic table entry to decoder.
session_->qpack_decoder()->OnInsertWithoutNameReference("foo", "bar");
EXPECT_TRUE(stream_->headers_decompressed());
@@ -2013,12 +2229,17 @@ TEST_P(QuicSpdyStreamTest, BlockedHeaderDecoding) {
// DATA frame.
std::string data = DataFrame(kDataFramePayload);
+ EXPECT_CALL(debug_visitor,
+ OnDataFrameReceived(stream_->id(), strlen(kDataFramePayload)));
stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, /* offset = */
headers.length(), data));
EXPECT_EQ(kDataFramePayload, stream_->data());
// Trailing HEADERS frame referencing second dynamic table entry.
- std::string trailers = HeadersFrame(QuicTextUtils::HexDecode("030080"));
+ std::string encoded_trailers = quiche::QuicheTextUtils::HexDecode("030080");
+ std::string trailers = HeadersFrame(encoded_trailers);
+ EXPECT_CALL(debug_visitor,
+ OnHeadersFrameReceived(stream_->id(), encoded_trailers.length()));
stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), true, /* offset = */
headers.length() + data.length(),
trailers));
@@ -2026,8 +2247,8 @@ TEST_P(QuicSpdyStreamTest, BlockedHeaderDecoding) {
// Decoding is blocked because dynamic table entry has not been received yet.
EXPECT_FALSE(stream_->trailers_decompressed());
- EXPECT_CALL(*session_, WritevData(decoder_send_stream,
- decoder_send_stream->id(), _, _, _));
+ EXPECT_CALL(*session_, WritevData(decoder_send_stream->id(), _, _, _, _, _));
+ EXPECT_CALL(debug_visitor, OnHeadersDecoded(stream_->id(), _));
// Deliver second dynamic table entry to decoder.
session_->qpack_decoder()->OnInsertWithoutNameReference("trailing", "foobar");
EXPECT_TRUE(stream_->trailers_decompressed());
@@ -2048,7 +2269,8 @@ TEST_P(QuicSpdyStreamTest, AsyncErrorDecodingHeaders) {
// HEADERS frame only referencing entry with absolute index 0 but with
// Required Insert Count = 2, which is incorrect.
- std::string headers = HeadersFrame(QuicTextUtils::HexDecode("030081"));
+ std::string headers =
+ HeadersFrame(quiche::QuicheTextUtils::HexDecode("030081"));
stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, 0, headers));
// Even though entire header block is received and every referenced entry is
@@ -2080,7 +2302,8 @@ TEST_P(QuicSpdyStreamTest, BlockedHeaderDecodingUnblockedWithBufferedError) {
session_->qpack_decoder()->OnSetDynamicTableCapacity(1024);
// Relative index 2 is invalid because it is larger than or equal to the Base.
- std::string headers = HeadersFrame(QuicTextUtils::HexDecode("020082"));
+ std::string headers =
+ HeadersFrame(quiche::QuicheTextUtils::HexDecode("020082"));
stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, 0, headers));
// Decoding is blocked.
@@ -2103,12 +2326,13 @@ TEST_P(QuicSpdyStreamTest, AsyncErrorDecodingTrailers) {
return;
}
- testing::InSequence s;
Initialize(kShouldProcessData);
+ testing::InSequence s;
session_->qpack_decoder()->OnSetDynamicTableCapacity(1024);
// HEADERS frame referencing first dynamic table entry.
- std::string headers = HeadersFrame(QuicTextUtils::HexDecode("020080"));
+ std::string headers =
+ HeadersFrame(quiche::QuicheTextUtils::HexDecode("020080"));
stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, 0, headers));
// Decoding is blocked because dynamic table entry has not been received yet.
@@ -2118,8 +2342,7 @@ TEST_P(QuicSpdyStreamTest, AsyncErrorDecodingTrailers) {
QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
// The stream byte will be written in the first byte.
- EXPECT_CALL(*session_, WritevData(decoder_send_stream,
- decoder_send_stream->id(), _, _, _));
+ EXPECT_CALL(*session_, WritevData(decoder_send_stream->id(), _, _, _, _, _));
// Deliver dynamic table entry to decoder.
session_->qpack_decoder()->OnInsertWithoutNameReference("foo", "bar");
EXPECT_TRUE(stream_->headers_decompressed());
@@ -2136,7 +2359,8 @@ TEST_P(QuicSpdyStreamTest, AsyncErrorDecodingTrailers) {
// Trailing HEADERS frame only referencing entry with absolute index 0 but
// with Required Insert Count = 2, which is incorrect.
- std::string trailers = HeadersFrame(QuicTextUtils::HexDecode("030081"));
+ std::string trailers =
+ HeadersFrame(quiche::QuicheTextUtils::HexDecode("030081"));
stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), true, /* offset = */
headers.length() + data.length(),
trailers));
@@ -2165,7 +2389,7 @@ class QuicSpdyStreamIncrementalConsumptionTest : public QuicSpdyStreamTest {
// Create QuicStreamFrame with |payload|
// and pass it to stream_->OnStreamFrame().
- void OnStreamFrame(QuicStringPiece payload) {
+ void OnStreamFrame(quiche::QuicheStringPiece payload) {
QuicStreamFrame frame(stream_->id(), /* fin = */ false, offset_, payload);
stream_->OnStreamFrame(frame);
offset_ += payload.size();
@@ -2201,8 +2425,7 @@ class QuicSpdyStreamIncrementalConsumptionTest : public QuicSpdyStreamTest {
INSTANTIATE_TEST_SUITE_P(Tests,
QuicSpdyStreamIncrementalConsumptionTest,
- ::testing::Values(ParsedQuicVersion{PROTOCOL_TLS1_3,
- QUIC_VERSION_99}),
+ ::testing::ValuesIn(AllSupportedVersions()),
::testing::PrintToStringParamName());
// Test that stream bytes are consumed (by calling
@@ -2218,11 +2441,12 @@ TEST_P(QuicSpdyStreamIncrementalConsumptionTest, OnlyKnownFrames) {
// All HEADERS frame bytes are consumed even if the frame is not received
// completely.
- OnStreamFrame(QuicStringPiece(headers).substr(0, headers.size() - 1));
+ OnStreamFrame(
+ quiche::QuicheStringPiece(headers).substr(0, headers.size() - 1));
EXPECT_EQ(headers.size() - 1, NewlyConsumedBytes());
// The rest of the HEADERS frame is also consumed immediately.
- OnStreamFrame(QuicStringPiece(headers).substr(headers.size() - 1));
+ OnStreamFrame(quiche::QuicheStringPiece(headers).substr(headers.size() - 1));
EXPECT_EQ(1u, NewlyConsumedBytes());
// Verify headers.
@@ -2230,7 +2454,7 @@ TEST_P(QuicSpdyStreamIncrementalConsumptionTest, OnlyKnownFrames) {
stream_->ConsumeHeaderList();
// DATA frame.
- QuicStringPiece data_payload(kDataFramePayload);
+ quiche::QuicheStringPiece data_payload(kDataFramePayload);
std::string data_frame = DataFrame(data_payload);
QuicByteCount data_frame_header_length =
data_frame.size() - data_payload.size();
@@ -2249,7 +2473,8 @@ TEST_P(QuicSpdyStreamIncrementalConsumptionTest, OnlyKnownFrames) {
HeadersFrame({std::make_pair("custom-key", "custom-value")});
// No bytes are consumed, because last byte of DATA payload is still buffered.
- OnStreamFrame(QuicStringPiece(trailers).substr(0, trailers.size() - 1));
+ OnStreamFrame(
+ quiche::QuicheStringPiece(trailers).substr(0, trailers.size() - 1));
EXPECT_EQ(0u, NewlyConsumedBytes());
// Reading last byte of DATA payload triggers consumption of all data received
@@ -2258,7 +2483,8 @@ TEST_P(QuicSpdyStreamIncrementalConsumptionTest, OnlyKnownFrames) {
EXPECT_EQ(1 + trailers.size() - 1, NewlyConsumedBytes());
// Last byte of trailers is immediately consumed.
- OnStreamFrame(QuicStringPiece(trailers).substr(trailers.size() - 1));
+ OnStreamFrame(
+ quiche::QuicheStringPiece(trailers).substr(trailers.size() - 1));
EXPECT_EQ(1u, NewlyConsumedBytes());
// Verify trailers.
@@ -2266,6 +2492,22 @@ TEST_P(QuicSpdyStreamIncrementalConsumptionTest, OnlyKnownFrames) {
ElementsAre(Pair("custom-key", "custom-value")));
}
+TEST_P(QuicSpdyStreamIncrementalConsumptionTest, ReceiveUnknownFrame) {
+ if (!UsesHttp3()) {
+ return;
+ }
+
+ Initialize(kShouldProcessData);
+ StrictMock<MockHttp3DebugVisitor> debug_visitor;
+ session_->set_debug_visitor(&debug_visitor);
+
+ EXPECT_CALL(debug_visitor,
+ OnUnknownFrameReceived(stream_->id(), /* frame_type = */ 0x21,
+ /* payload_length = */ 3));
+ std::string unknown_frame = UnknownFrame(0x21, "foo");
+ OnStreamFrame(unknown_frame);
+}
+
TEST_P(QuicSpdyStreamIncrementalConsumptionTest, UnknownFramesInterleaved) {
if (!UsesHttp3()) {
return;
@@ -2282,11 +2524,12 @@ TEST_P(QuicSpdyStreamIncrementalConsumptionTest, UnknownFramesInterleaved) {
// All HEADERS frame bytes are consumed even if the frame is not received
// completely.
- OnStreamFrame(QuicStringPiece(headers).substr(0, headers.size() - 1));
+ OnStreamFrame(
+ quiche::QuicheStringPiece(headers).substr(0, headers.size() - 1));
EXPECT_EQ(headers.size() - 1, NewlyConsumedBytes());
// The rest of the HEADERS frame is also consumed immediately.
- OnStreamFrame(QuicStringPiece(headers).substr(headers.size() - 1));
+ OnStreamFrame(quiche::QuicheStringPiece(headers).substr(headers.size() - 1));
EXPECT_EQ(1u, NewlyConsumedBytes());
// Verify headers.
@@ -2300,7 +2543,7 @@ TEST_P(QuicSpdyStreamIncrementalConsumptionTest, UnknownFramesInterleaved) {
EXPECT_EQ(unknown_frame2.size(), NewlyConsumedBytes());
// DATA frame.
- QuicStringPiece data_payload(kDataFramePayload);
+ quiche::QuicheStringPiece data_payload(kDataFramePayload);
std::string data_frame = DataFrame(data_payload);
QuicByteCount data_frame_header_length =
data_frame.size() - data_payload.size();
@@ -2325,7 +2568,8 @@ TEST_P(QuicSpdyStreamIncrementalConsumptionTest, UnknownFramesInterleaved) {
HeadersFrame({std::make_pair("custom-key", "custom-value")});
// No bytes are consumed, because last byte of DATA payload is still buffered.
- OnStreamFrame(QuicStringPiece(trailers).substr(0, trailers.size() - 1));
+ OnStreamFrame(
+ quiche::QuicheStringPiece(trailers).substr(0, trailers.size() - 1));
EXPECT_EQ(0u, NewlyConsumedBytes());
// Reading last byte of DATA payload triggers consumption of all data received
@@ -2335,7 +2579,8 @@ TEST_P(QuicSpdyStreamIncrementalConsumptionTest, UnknownFramesInterleaved) {
NewlyConsumedBytes());
// Last byte of trailers is immediately consumed.
- OnStreamFrame(QuicStringPiece(trailers).substr(trailers.size() - 1));
+ OnStreamFrame(
+ quiche::QuicheStringPiece(trailers).substr(trailers.size() - 1));
EXPECT_EQ(1u, NewlyConsumedBytes());
// Verify trailers.
@@ -2354,10 +2599,16 @@ TEST_P(QuicSpdyStreamTest, PushPromiseOnDataStream) {
return;
}
- std::string headers = EncodeQpackHeaders({{"foo", "bar"}});
+ StrictMock<MockHttp3DebugVisitor> debug_visitor;
+ session_->set_debug_visitor(&debug_visitor);
+
+ SpdyHeaderBlock pushed_headers;
+ pushed_headers["foo"] = "bar";
+ std::string headers = EncodeQpackHeaders(pushed_headers);
+ const QuicStreamId push_id = 1;
PushPromiseFrame push_promise;
- push_promise.push_id = 0x01;
+ push_promise.push_id = push_id;
push_promise.headers = headers;
std::unique_ptr<char[]> buffer;
uint64_t length = HttpEncoder::SerializePushPromiseFrameWithOnlyPushId(
@@ -2365,6 +2616,11 @@ TEST_P(QuicSpdyStreamTest, PushPromiseOnDataStream) {
std::string data = std::string(buffer.get(), length) + headers;
QuicStreamFrame frame(stream_->id(), false, 0, data);
+ EXPECT_CALL(debug_visitor, OnPushPromiseFrameReceived(stream_->id(), push_id,
+ headers.length()));
+ EXPECT_CALL(debug_visitor,
+ OnPushPromiseDecoded(stream_->id(), push_id,
+ AsHeaderList(pushed_headers)));
EXPECT_CALL(*session_,
OnPromiseHeaderList(stream_->id(), push_promise.push_id,
headers.length(), _));
@@ -2381,10 +2637,9 @@ TEST_P(QuicSpdyStreamTest, DataBeforeHeaders) {
// Closing the connection is mocked out in tests. Instead, simply stop
// reading data at the stream level to prevent QuicSpdyStream from blowing up.
- // TODO(b/124216424): Change error code to HTTP_UNEXPECTED_FRAME.
EXPECT_CALL(
*connection_,
- CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
+ CloseConnection(QUIC_HTTP_INVALID_FRAME_SEQUENCE_ON_SPDY_STREAM,
"Unexpected DATA frame received.",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET))
.WillOnce(InvokeWithoutArgs([this]() { stream_->StopReading(); }));
@@ -2431,10 +2686,9 @@ TEST_P(QuicSpdyStreamTest, TrailersAfterTrailers) {
// Closing the connection is mocked out in tests. Instead, simply stop
// reading data at the stream level to prevent QuicSpdyStream from blowing up.
- // TODO(b/124216424): Change error code to HTTP_UNEXPECTED_FRAME.
EXPECT_CALL(
*connection_,
- CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
+ CloseConnection(QUIC_HTTP_INVALID_FRAME_SEQUENCE_ON_SPDY_STREAM,
"HEADERS frame received after trailing HEADERS.",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET))
.WillOnce(InvokeWithoutArgs([this]() { stream_->StopReading(); }));
@@ -2482,10 +2736,9 @@ TEST_P(QuicSpdyStreamTest, DataAfterTrailers) {
// Closing the connection is mocked out in tests. Instead, simply stop
// reading data at the stream level to prevent QuicSpdyStream from blowing up.
- // TODO(b/124216424): Change error code to HTTP_UNEXPECTED_FRAME.
EXPECT_CALL(
*connection_,
- CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
+ CloseConnection(QUIC_HTTP_INVALID_FRAME_SEQUENCE_ON_SPDY_STREAM,
"Unexpected DATA frame received.",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET))
.WillOnce(InvokeWithoutArgs([this]() { stream_->StopReading(); }));
@@ -2505,7 +2758,7 @@ TEST_P(QuicSpdyStreamTest, StopProcessingIfConnectionClosed) {
Initialize(kShouldProcessData);
// SETTINGS frame with empty payload.
- std::string settings = QuicTextUtils::HexDecode("0400");
+ std::string settings = quiche::QuicheTextUtils::HexDecode("0400");
// HEADERS frame.
// Since it arrives after a SETTINGS frame, it should never be read.
@@ -2513,11 +2766,12 @@ TEST_P(QuicSpdyStreamTest, StopProcessingIfConnectionClosed) {
// Combine the two frames to make sure they are processed in a single
// QuicSpdyStream::OnDataAvailable() call.
- std::string frames = QuicStrCat(settings, headers);
+ std::string frames = quiche::QuicheStrCat(settings, headers);
EXPECT_EQ(0u, stream_->sequencer()->NumBytesConsumed());
- EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_DECODER_ERROR, _, _))
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_HTTP_FRAME_UNEXPECTED_ON_SPDY_STREAM, _, _))
.WillOnce(
Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _));
@@ -2531,8 +2785,7 @@ TEST_P(QuicSpdyStreamTest, StopProcessingIfConnectionClosed) {
// Stream Cancellation instruction is sent on QPACK decoder stream
// when stream is reset.
-// TODO(b/145684124) Re-enable.
-TEST_P(QuicSpdyStreamTest, DISABLED_StreamCancellationWhenStreamReset) {
+TEST_P(QuicSpdyStreamTest, StreamCancellationWhenStreamReset) {
if (!UsesHttp3()) {
return;
}
@@ -2541,8 +2794,7 @@ TEST_P(QuicSpdyStreamTest, DISABLED_StreamCancellationWhenStreamReset) {
auto qpack_decoder_stream =
QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
- EXPECT_CALL(*session_, WritevData(qpack_decoder_stream,
- qpack_decoder_stream->id(), 1, 1, _));
+ EXPECT_CALL(*session_, WritevData(qpack_decoder_stream->id(), 1, 1, _, _, _));
EXPECT_CALL(*session_,
SendRstStream(stream_->id(), QUIC_STREAM_CANCELLED, 0));
@@ -2551,8 +2803,7 @@ TEST_P(QuicSpdyStreamTest, DISABLED_StreamCancellationWhenStreamReset) {
// Stream Cancellation instruction is sent on QPACK decoder stream
// when RESET_STREAM frame is received.
-// TODO(b/145684124) Re-enable.
-TEST_P(QuicSpdyStreamTest, DISABLED_StreamCancellationOnResetReceived) {
+TEST_P(QuicSpdyStreamTest, StreamCancellationOnResetReceived) {
if (!UsesHttp3()) {
return;
}
@@ -2561,8 +2812,7 @@ TEST_P(QuicSpdyStreamTest, DISABLED_StreamCancellationOnResetReceived) {
auto qpack_decoder_stream =
QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
- EXPECT_CALL(*session_, WritevData(qpack_decoder_stream,
- qpack_decoder_stream->id(), 1, 1, _));
+ EXPECT_CALL(*session_, WritevData(qpack_decoder_stream->id(), 1, 1, _, _, _));
stream_->OnStreamReset(QuicRstStreamFrame(
kInvalidControlFrameId, stream_->id(), QUIC_STREAM_CANCELLED, 0));
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/spdy_server_push_utils.cc b/chromium/net/third_party/quiche/src/quic/core/http/spdy_server_push_utils.cc
index 02c963ce20a..4ba328943ff 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/spdy_server_push_utils.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/spdy_server_push_utils.cc
@@ -5,6 +5,7 @@
#include "net/third_party/quiche/src/quic/core/http/spdy_server_push_utils.h"
#include "url/gurl.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
using spdy::SpdyHeaderBlock;
@@ -39,7 +40,7 @@ std::string SpdyServerPushUtils::GetPromisedUrlFromHeaders(
if (it == headers.end() || it->second.empty()) {
return std::string();
}
- QuicStringPiece scheme = it->second;
+ quiche::QuicheStringPiece scheme = it->second;
// RFC 7540, Section 8.2: The server MUST include a value in the
// ":authority" pseudo-header field for which the server is authoritative
@@ -48,7 +49,7 @@ std::string SpdyServerPushUtils::GetPromisedUrlFromHeaders(
if (it == headers.end() || it->second.empty()) {
return std::string();
}
- QuicStringPiece authority = it->second;
+ quiche::QuicheStringPiece authority = it->second;
// RFC 7540, Section 8.1.2.3 requires that the ":path" pseudo-header MUST
// NOT be empty for "http" or "https" URIs;
@@ -59,7 +60,7 @@ std::string SpdyServerPushUtils::GetPromisedUrlFromHeaders(
if (it == headers.end()) {
return std::string();
}
- QuicStringPiece path = it->second;
+ quiche::QuicheStringPiece path = it->second;
return GetPushPromiseUrl(scheme, authority, path);
}
@@ -79,9 +80,10 @@ bool SpdyServerPushUtils::PromisedUrlIsValid(const SpdyHeaderBlock& headers) {
}
// static
-std::string SpdyServerPushUtils::GetPushPromiseUrl(QuicStringPiece scheme,
- QuicStringPiece authority,
- QuicStringPiece path) {
+std::string SpdyServerPushUtils::GetPushPromiseUrl(
+ quiche::QuicheStringPiece scheme,
+ quiche::QuicheStringPiece authority,
+ quiche::QuicheStringPiece path) {
// RFC 7540, Section 8.1.2.3: The ":path" pseudo-header field includes the
// path and query parts of the target URI (the "path-absolute" production
// and optionally a '?' character followed by the "query" production (see
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/spdy_server_push_utils.h b/chromium/net/third_party/quiche/src/quic/core/http/spdy_server_push_utils.h
index 3d11b65a0d1..16e1ac6db64 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/spdy_server_push_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/spdy_server_push_utils.h
@@ -6,7 +6,7 @@
#define QUICHE_QUIC_CORE_HTTP_SPDY_SERVER_PUSH_UTILS_H_
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "net/third_party/quiche/src/spdy/core/spdy_header_block.h"
namespace quic {
@@ -33,9 +33,9 @@ class QUIC_EXPORT_PRIVATE SpdyServerPushUtils {
// Returns a canonical, valid URL for a PUSH_PROMISE with the specified
// ":scheme", ":authority", and ":path" header fields, or an empty
// string if the resulting URL is not valid or supported.
- static std::string GetPushPromiseUrl(QuicStringPiece scheme,
- QuicStringPiece authority,
- QuicStringPiece path);
+ static std::string GetPushPromiseUrl(quiche::QuicheStringPiece scheme,
+ quiche::QuicheStringPiece authority,
+ quiche::QuicheStringPiece path);
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/spdy_server_push_utils_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/spdy_server_push_utils_test.cc
index 0f6ec8a6287..ed7895e3b0a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/spdy_server_push_utils_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/spdy_server_push_utils_test.cc
@@ -7,10 +7,8 @@
#include <memory>
#include <string>
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
using spdy::SpdyHeaderBlock;
@@ -159,11 +157,11 @@ TEST_F(PushPromiseUrlTest, GetPushPromiseUrl) {
{"[::ffff:192.168", 0},
{"]/", 0},
{"//", 0}};
- for (size_t i = 0; i < QUIC_ARRAYSIZE(input_headers); ++i) {
+ for (size_t i = 0; i < QUICHE_ARRAYSIZE(input_headers); ++i) {
bool should_accept = (input_headers[i].second & SCHEME);
- for (size_t j = 0; j < QUIC_ARRAYSIZE(input_headers); ++j) {
+ for (size_t j = 0; j < QUICHE_ARRAYSIZE(input_headers); ++j) {
bool should_accept_2 = should_accept && (input_headers[j].second & AUTH);
- for (size_t k = 0; k < QUIC_ARRAYSIZE(input_headers); ++k) {
+ for (size_t k = 0; k < QUICHE_ARRAYSIZE(input_headers); ++k) {
// |should_accept_3| indicates whether or not GetPushPromiseUrl() is
// expected to accept this input combination.
bool should_accept_3 =
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.cc b/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.cc
index 56d3b198991..98d22cb9a24 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.cc
@@ -12,9 +12,9 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
using spdy::SpdyHeaderBlock;
@@ -29,12 +29,12 @@ bool SpdyUtils::ExtractContentLengthFromHeaders(int64_t* content_length,
return false;
} else {
// Check whether multiple values are consistent.
- QuicStringPiece content_length_header = it->second;
- std::vector<QuicStringPiece> values =
- QuicTextUtils::Split(content_length_header, '\0');
- for (const QuicStringPiece& value : values) {
+ quiche::QuicheStringPiece content_length_header = it->second;
+ std::vector<quiche::QuicheStringPiece> values =
+ quiche::QuicheTextUtils::Split(content_length_header, '\0');
+ for (const quiche::QuicheStringPiece& value : values) {
uint64_t new_value;
- if (!QuicTextUtils::StringToUint64(value, &new_value)) {
+ if (!quiche::QuicheTextUtils::StringToUint64(value, &new_value)) {
QUIC_DLOG(ERROR)
<< "Content length was either unparseable or negative.";
return false;
@@ -65,7 +65,7 @@ bool SpdyUtils::CopyAndValidateHeaders(const QuicHeaderList& header_list,
return false;
}
- if (QuicTextUtils::ContainsUpperCase(name)) {
+ if (quiche::QuicheTextUtils::ContainsUpperCase(name)) {
QUIC_DLOG(ERROR) << "Malformed header: Header name " << name
<< " contains upper-case characters.";
return false;
@@ -95,7 +95,7 @@ bool SpdyUtils::CopyAndValidateTrailers(const QuicHeaderList& header_list,
// response body bytes expected.
if (expect_final_byte_offset && !found_final_byte_offset &&
name == kFinalOffsetHeaderKey &&
- QuicTextUtils::StringToSizeT(p.second, final_byte_offset)) {
+ quiche::QuicheTextUtils::StringToSizeT(p.second, final_byte_offset)) {
found_final_byte_offset = true;
continue;
}
@@ -107,7 +107,7 @@ bool SpdyUtils::CopyAndValidateTrailers(const QuicHeaderList& header_list,
return false;
}
- if (QuicTextUtils::ContainsUpperCase(name)) {
+ if (quiche::QuicheTextUtils::ContainsUpperCase(name)) {
QUIC_DLOG(ERROR) << "Malformed header: Header name " << name
<< " contains upper-case characters.";
return false;
@@ -162,7 +162,7 @@ std::string SpdyUtils::H3SettingsToString(
RETURN_STRING_LITERAL(SETTINGS_MAX_HEADER_LIST_SIZE);
RETURN_STRING_LITERAL(SETTINGS_QPACK_BLOCKED_STREAMS);
}
- return QuicStrCat("UNSUPPORTED_SETTINGS_TYPE(", identifier, ")");
+ return quiche::QuicheStrCat("UNSUPPORTED_SETTINGS_TYPE(", identifier, ")");
}
#undef RETURN_STRING_LITERAL // undef for jumbo builds
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils_test.cc
index 2ebf0cff680..55d4706359a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils_test.cc
@@ -6,10 +6,10 @@
#include <string>
#include "net/third_party/quiche/src/quic/core/http/spdy_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
using spdy::SpdyHeaderBlock;
using testing::Pair;
@@ -66,13 +66,14 @@ TEST_F(CopyAndValidateHeaders, NormalUsage) {
SpdyHeaderBlock block;
ASSERT_TRUE(
SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block));
- EXPECT_THAT(block,
- UnorderedElementsAre(
- Pair("cookie", " part 1; part 2 ; part3; fin!"),
- Pair("passed-through", QuicStringPiece("foo\0baz", 7)),
- Pair("joined", QuicStringPiece("value 1\0value 2", 15)),
- Pair("empty", ""),
- Pair("empty-joined", QuicStringPiece("\0foo\0\0", 6))));
+ EXPECT_THAT(
+ block,
+ UnorderedElementsAre(
+ Pair("cookie", " part 1; part 2 ; part3; fin!"),
+ Pair("passed-through", quiche::QuicheStringPiece("foo\0baz", 7)),
+ Pair("joined", quiche::QuicheStringPiece("value 1\0value 2", 15)),
+ Pair("empty", ""),
+ Pair("empty-joined", quiche::QuicheStringPiece("\0foo\0\0", 6))));
EXPECT_EQ(-1, content_length);
}
@@ -103,10 +104,11 @@ TEST_F(CopyAndValidateHeaders, MultipleContentLengths) {
SpdyHeaderBlock block;
ASSERT_TRUE(
SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block));
- EXPECT_THAT(block, UnorderedElementsAre(
- Pair("foo", "foovalue"), Pair("bar", "barvalue"),
- Pair("content-length", QuicStringPiece("9\09", 3)),
- Pair("baz", "")));
+ EXPECT_THAT(block,
+ UnorderedElementsAre(
+ Pair("foo", "foovalue"), Pair("bar", "barvalue"),
+ Pair("content-length", quiche::QuicheStringPiece("9\09", 3)),
+ Pair("baz", "")));
EXPECT_EQ(9, content_length);
}
@@ -133,7 +135,8 @@ TEST_F(CopyAndValidateHeaders, LargeContentLength) {
SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block));
EXPECT_THAT(block, UnorderedElementsAre(
Pair("foo", "foovalue"), Pair("bar", "barvalue"),
- Pair("content-length", QuicStringPiece("9000000000")),
+ Pair("content-length",
+ quiche::QuicheStringPiece("9000000000")),
Pair("baz", "")));
EXPECT_EQ(9000000000, content_length);
}
@@ -148,10 +151,11 @@ TEST_F(CopyAndValidateHeaders, MultipleValues) {
SpdyHeaderBlock block;
ASSERT_TRUE(
SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block));
- EXPECT_THAT(block, UnorderedElementsAre(
- Pair("foo", QuicStringPiece("foovalue\0boo", 12)),
- Pair("bar", "barvalue"),
- Pair("baz", QuicStringPiece("\0buzz", 5))));
+ EXPECT_THAT(block,
+ UnorderedElementsAre(
+ Pair("foo", quiche::QuicheStringPiece("foovalue\0boo", 12)),
+ Pair("bar", "barvalue"),
+ Pair("baz", quiche::QuicheStringPiece("\0buzz", 5))));
EXPECT_EQ(-1, content_length);
}
@@ -163,9 +167,9 @@ TEST_F(CopyAndValidateHeaders, MoreThanTwoValues) {
SpdyHeaderBlock block;
ASSERT_TRUE(
SpdyUtils::CopyAndValidateHeaders(*headers, &content_length, &block));
- EXPECT_THAT(
- block, UnorderedElementsAre(Pair(
- "set-cookie", QuicStringPiece("value1\0value2\0value3", 20))));
+ EXPECT_THAT(block, UnorderedElementsAre(Pair(
+ "set-cookie", quiche::QuicheStringPiece(
+ "value1\0value2\0value3", 20))));
EXPECT_EQ(-1, content_length);
}
@@ -307,7 +311,7 @@ TEST_F(CopyAndValidateTrailers, DuplicateTrailers) {
block,
UnorderedElementsAre(
Pair("key",
- QuicStringPiece(
+ quiche::QuicheStringPiece(
"value0\0value1\0\0\0value2\0\0non_contiguous_duplicate",
48)),
Pair("other_key", "value")));
diff --git a/chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.cc b/chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.cc
index 157e3751434..6e8f13a10d6 100644
--- a/chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.cc
@@ -4,47 +4,34 @@
#include "net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.h"
#include "net/third_party/quiche/src/quic/core/quic_session.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
namespace quic {
-#define ENDPOINT \
- (session_->perspective() == Perspective::IS_SERVER ? "Server: " : "Client: ")
-
LegacyQuicStreamIdManager::LegacyQuicStreamIdManager(
- QuicSession* session,
+ Perspective perspective,
+ QuicTransportVersion transport_version,
size_t max_open_outgoing_streams,
size_t max_open_incoming_streams)
- : session_(session),
+ : perspective_(perspective),
+ transport_version_(transport_version),
max_open_outgoing_streams_(max_open_outgoing_streams),
max_open_incoming_streams_(max_open_incoming_streams),
next_outgoing_stream_id_(
- QuicUtils::GetFirstBidirectionalStreamId(session->transport_version(),
- session->perspective())),
+ QuicUtils::GetFirstBidirectionalStreamId(transport_version_,
+ perspective_)),
largest_peer_created_stream_id_(
- session->perspective() == Perspective::IS_SERVER
- ? (QuicVersionUsesCryptoFrames(session->transport_version())
- ? QuicUtils::GetInvalidStreamId(
- session->transport_version())
- : QuicUtils::GetCryptoStreamId(
- session->transport_version()))
- : QuicUtils::GetInvalidStreamId(session->transport_version())) {}
-
-LegacyQuicStreamIdManager::~LegacyQuicStreamIdManager() {
- QUIC_LOG_IF(WARNING,
- session_->num_locally_closed_incoming_streams_highest_offset() >
- max_open_incoming_streams_)
- << "Surprisingly high number of locally closed peer initiated streams"
- "still waiting for final byte offset: "
- << session_->num_locally_closed_incoming_streams_highest_offset();
- QUIC_LOG_IF(WARNING,
- session_->GetNumLocallyClosedOutgoingStreamsHighestOffset() >
- max_open_outgoing_streams_)
- << "Surprisingly high number of locally closed self initiated streams"
- "still waiting for final byte offset: "
- << session_->GetNumLocallyClosedOutgoingStreamsHighestOffset();
-}
+ perspective_ == Perspective::IS_SERVER
+ ? (QuicVersionUsesCryptoFrames(transport_version_)
+ ? QuicUtils::GetInvalidStreamId(transport_version_)
+ : QuicUtils::GetCryptoStreamId(transport_version_))
+ : QuicUtils::GetInvalidStreamId(transport_version_)) {}
+
+LegacyQuicStreamIdManager::~LegacyQuicStreamIdManager() {}
bool LegacyQuicStreamIdManager::CanOpenNextOutgoingStream(
size_t current_num_open_outgoing_streams) const {
@@ -69,7 +56,7 @@ bool LegacyQuicStreamIdManager::MaybeIncreaseLargestPeerStreamId(
available_streams_.erase(stream_id);
if (largest_peer_created_stream_id_ !=
- QuicUtils::GetInvalidStreamId(session_->transport_version()) &&
+ QuicUtils::GetInvalidStreamId(transport_version_) &&
stream_id <= largest_peer_created_stream_id_) {
return true;
}
@@ -80,31 +67,26 @@ bool LegacyQuicStreamIdManager::MaybeIncreaseLargestPeerStreamId(
size_t additional_available_streams =
(stream_id - largest_peer_created_stream_id_) / 2 - 1;
if (largest_peer_created_stream_id_ ==
- QuicUtils::GetInvalidStreamId(session_->transport_version())) {
+ QuicUtils::GetInvalidStreamId(transport_version_)) {
additional_available_streams = (stream_id + 1) / 2 - 1;
}
size_t new_num_available_streams =
GetNumAvailableStreams() + additional_available_streams;
if (new_num_available_streams > MaxAvailableStreams()) {
- QUIC_DLOG(INFO) << ENDPOINT
+ QUIC_DLOG(INFO) << perspective_
<< "Failed to create a new incoming stream with id:"
<< stream_id << ". There are already "
<< GetNumAvailableStreams()
<< " streams available, which would become "
<< new_num_available_streams << ", which exceeds the limit "
<< MaxAvailableStreams() << ".";
- session_->connection()->CloseConnection(
- QUIC_TOO_MANY_AVAILABLE_STREAMS,
- QuicStrCat(new_num_available_streams, " above ", MaxAvailableStreams()),
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return false;
}
QuicStreamId first_available_stream = largest_peer_created_stream_id_ + 2;
if (largest_peer_created_stream_id_ ==
- QuicUtils::GetInvalidStreamId(session_->transport_version())) {
+ QuicUtils::GetInvalidStreamId(transport_version_)) {
first_available_stream = QuicUtils::GetFirstBidirectionalStreamId(
- session_->transport_version(),
- QuicUtils::InvertPerspective(session_->perspective()));
+ transport_version_, QuicUtils::InvertPerspective(perspective_));
}
for (QuicStreamId id = first_available_stream; id < stream_id; id += 2) {
available_streams_.insert(id);
@@ -128,7 +110,7 @@ bool LegacyQuicStreamIdManager::IsAvailableStream(QuicStreamId id) const {
}
// For peer created streams, we also need to consider available streams.
return largest_peer_created_stream_id_ ==
- QuicUtils::GetInvalidStreamId(session_->transport_version()) ||
+ QuicUtils::GetInvalidStreamId(transport_version_) ||
id > largest_peer_created_stream_id_ ||
QuicContainsKey(available_streams_, id);
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.h b/chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.h
index 78d45453c79..1a94905e41a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.h
+++ b/chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.h
@@ -5,6 +5,8 @@
#define QUICHE_QUIC_CORE_LEGACY_QUIC_STREAM_ID_MANAGER_H_
#include "net/third_party/quiche/src/quic/core/quic_stream_id_manager.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
namespace quic {
@@ -19,7 +21,8 @@ class QuicSession;
// next outgoing stream ID) and 2) can a new incoming stream be opened.
class QUIC_EXPORT_PRIVATE LegacyQuicStreamIdManager {
public:
- LegacyQuicStreamIdManager(QuicSession* session,
+ LegacyQuicStreamIdManager(Perspective perspective,
+ QuicTransportVersion transport_version,
size_t max_open_outgoing_streams,
size_t max_open_incoming_streams);
@@ -32,6 +35,8 @@ class QUIC_EXPORT_PRIVATE LegacyQuicStreamIdManager {
// Returns true if a new incoming stream can be opened.
bool CanOpenIncomingStream(size_t current_num_open_incoming_streams) const;
+ // Returns false when increasing the largest created stream id to |id| would
+ // violate the limit, so the connection should be closed.
bool MaybeIncreaseLargestPeerStreamId(const QuicStreamId id);
// Returns true if |id| is still available.
@@ -75,13 +80,13 @@ class QUIC_EXPORT_PRIVATE LegacyQuicStreamIdManager {
return largest_peer_created_stream_id_;
}
+ size_t GetNumAvailableStreams() const;
+
private:
friend class test::QuicSessionPeer;
- size_t GetNumAvailableStreams() const;
-
- // Not owned.
- QuicSession* session_;
+ const Perspective perspective_;
+ const QuicTransportVersion transport_version_;
// The maximum number of outgoing streams this connection can open.
size_t max_open_outgoing_streams_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager_test.cc b/chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager_test.cc
index 75e381db92a..bd37ffe338e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager_test.cc
@@ -6,10 +6,13 @@
#include <utility>
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_session_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
namespace quic {
namespace test {
@@ -18,166 +21,153 @@ namespace {
using testing::_;
using testing::StrictMock;
-class LegacyQuicStreamIdManagerTest : public QuicTest {
- protected:
- void Initialize(Perspective perspective) {
- SetQuicReloadableFlag(quic_enable_version_99, false);
- connection_ = new MockQuicConnection(
- &helper_, &alarm_factory_, perspective,
- ParsedVersionOfIndex(CurrentSupportedVersions(), 0));
- session_ = std::make_unique<StrictMock<MockQuicSession>>(connection_);
- manager_ = QuicSessionPeer::GetStreamIdManager(session_.get());
- session_->Initialize();
- }
+struct TestParams {
+ TestParams(ParsedQuicVersion version, Perspective perspective)
+ : version(version), perspective(perspective) {}
- QuicStreamId GetNthClientInitiatedId(int n) {
- return QuicUtils::GetFirstBidirectionalStreamId(
- connection_->transport_version(), Perspective::IS_CLIENT) +
- 2 * n;
- }
+ ParsedQuicVersion version;
+ Perspective perspective;
+};
- QuicStreamId GetNthServerInitiatedId(int n) { return 2 + 2 * n; }
+// Used by ::testing::PrintToStringParamName().
+std::string PrintToString(const TestParams& p) {
+ return quiche::QuicheStrCat(
+ ParsedQuicVersionToString(p.version),
+ (p.perspective == Perspective::IS_CLIENT ? "Client" : "Server"));
+}
- MockQuicConnectionHelper helper_;
- MockAlarmFactory alarm_factory_;
- MockQuicConnection* connection_;
- std::unique_ptr<StrictMock<MockQuicSession>> session_;
- LegacyQuicStreamIdManager* manager_;
-};
+std::vector<TestParams> GetTestParams() {
+ std::vector<TestParams> params;
+ for (ParsedQuicVersion version : AllSupportedVersions()) {
+ for (auto perspective : {Perspective::IS_CLIENT, Perspective::IS_SERVER}) {
+ // LegacyQuicStreamIdManager is only used when IETF QUIC frames are not
+ // presented.
+ if (!VersionHasIetfQuicFrames(version.transport_version)) {
+ params.push_back(TestParams(version, perspective));
+ }
+ }
+ }
+ return params;
+}
+
+class LegacyQuicStreamIdManagerTest : public QuicTestWithParam<TestParams> {
+ public:
+ LegacyQuicStreamIdManagerTest()
+ : manager_(GetParam().perspective,
+ GetParam().version.transport_version,
+ kDefaultMaxStreamsPerConnection,
+ kDefaultMaxStreamsPerConnection) {}
-class LegacyQuicStreamIdManagerTestServer
- : public LegacyQuicStreamIdManagerTest {
protected:
- LegacyQuicStreamIdManagerTestServer() { Initialize(Perspective::IS_SERVER); }
+ QuicStreamId GetNthPeerInitiatedId(int n) {
+ if (GetParam().perspective == Perspective::IS_SERVER) {
+ return QuicUtils::GetFirstBidirectionalStreamId(
+ GetParam().version.transport_version, Perspective::IS_CLIENT) +
+ 2 * n;
+ } else {
+ return 2 + 2 * n;
+ }
+ }
+
+ LegacyQuicStreamIdManager manager_;
};
-TEST_F(LegacyQuicStreamIdManagerTestServer, CanOpenNextOutgoingStream) {
- EXPECT_TRUE(manager_->CanOpenNextOutgoingStream(
- manager_->max_open_outgoing_streams() - 1));
- EXPECT_FALSE(manager_->CanOpenNextOutgoingStream(
- manager_->max_open_outgoing_streams()));
+INSTANTIATE_TEST_SUITE_P(Tests,
+ LegacyQuicStreamIdManagerTest,
+ ::testing::ValuesIn(GetTestParams()),
+ ::testing::PrintToStringParamName());
+
+TEST_P(LegacyQuicStreamIdManagerTest, CanOpenNextOutgoingStream) {
+ EXPECT_TRUE(manager_.CanOpenNextOutgoingStream(
+ manager_.max_open_outgoing_streams() - 1));
+ EXPECT_FALSE(
+ manager_.CanOpenNextOutgoingStream(manager_.max_open_outgoing_streams()));
}
-TEST_F(LegacyQuicStreamIdManagerTestServer, CanOpenIncomingStream) {
- EXPECT_TRUE(manager_->CanOpenIncomingStream(
- manager_->max_open_incoming_streams() - 1));
+TEST_P(LegacyQuicStreamIdManagerTest, CanOpenIncomingStream) {
+ EXPECT_TRUE(
+ manager_.CanOpenIncomingStream(manager_.max_open_incoming_streams() - 1));
EXPECT_FALSE(
- manager_->CanOpenIncomingStream(manager_->max_open_incoming_streams()));
+ manager_.CanOpenIncomingStream(manager_.max_open_incoming_streams()));
}
-TEST_F(LegacyQuicStreamIdManagerTestServer, AvailableStreams) {
+TEST_P(LegacyQuicStreamIdManagerTest, AvailableStreams) {
ASSERT_TRUE(
- manager_->MaybeIncreaseLargestPeerStreamId(GetNthClientInitiatedId(3)));
- EXPECT_TRUE(manager_->IsAvailableStream(GetNthClientInitiatedId(1)));
- EXPECT_TRUE(manager_->IsAvailableStream(GetNthClientInitiatedId(2)));
+ manager_.MaybeIncreaseLargestPeerStreamId(GetNthPeerInitiatedId(3)));
+ EXPECT_TRUE(manager_.IsAvailableStream(GetNthPeerInitiatedId(1)));
+ EXPECT_TRUE(manager_.IsAvailableStream(GetNthPeerInitiatedId(2)));
ASSERT_TRUE(
- manager_->MaybeIncreaseLargestPeerStreamId(GetNthClientInitiatedId(2)));
+ manager_.MaybeIncreaseLargestPeerStreamId(GetNthPeerInitiatedId(2)));
ASSERT_TRUE(
- manager_->MaybeIncreaseLargestPeerStreamId(GetNthClientInitiatedId(1)));
+ manager_.MaybeIncreaseLargestPeerStreamId(GetNthPeerInitiatedId(1)));
}
-TEST_F(LegacyQuicStreamIdManagerTestServer, MaxAvailableStreams) {
+TEST_P(LegacyQuicStreamIdManagerTest, MaxAvailableStreams) {
// Test that the server closes the connection if a client makes too many data
// streams available. The server accepts slightly more than the negotiated
// stream limit to deal with rare cases where a client FIN/RST is lost.
const size_t kMaxStreamsForTest = 10;
- session_->OnConfigNegotiated();
- const size_t kAvailableStreamLimit = manager_->MaxAvailableStreams();
+ const size_t kAvailableStreamLimit = manager_.MaxAvailableStreams();
EXPECT_EQ(
- manager_->max_open_incoming_streams() * kMaxAvailableStreamsMultiplier,
- manager_->MaxAvailableStreams());
+ manager_.max_open_incoming_streams() * kMaxAvailableStreamsMultiplier,
+ manager_.MaxAvailableStreams());
// The protocol specification requires that there can be at least 10 times
// as many available streams as the connection's maximum open streams.
EXPECT_LE(10 * kMaxStreamsForTest, kAvailableStreamLimit);
EXPECT_TRUE(
- manager_->MaybeIncreaseLargestPeerStreamId(GetNthClientInitiatedId(0)));
+ manager_.MaybeIncreaseLargestPeerStreamId(GetNthPeerInitiatedId(0)));
// Establish available streams up to the server's limit.
const int kLimitingStreamId =
- GetNthClientInitiatedId(kAvailableStreamLimit + 1);
+ GetNthPeerInitiatedId(kAvailableStreamLimit + 1);
// This exceeds the stream limit. In versions other than 99
// this is allowed. Version 99 hews to the IETF spec and does
// not allow it.
- EXPECT_TRUE(manager_->MaybeIncreaseLargestPeerStreamId(kLimitingStreamId));
- // A further available stream will result in connection close.
- EXPECT_CALL(*connection_,
- CloseConnection(QUIC_TOO_MANY_AVAILABLE_STREAMS, _, _));
+ EXPECT_TRUE(manager_.MaybeIncreaseLargestPeerStreamId(kLimitingStreamId));
// This forces stream kLimitingStreamId + 2 to become available, which
// violates the quota.
EXPECT_FALSE(
- manager_->MaybeIncreaseLargestPeerStreamId(kLimitingStreamId + 2 * 2));
+ manager_.MaybeIncreaseLargestPeerStreamId(kLimitingStreamId + 2 * 2));
}
-TEST_F(LegacyQuicStreamIdManagerTestServer, MaximumAvailableOpenedStreams) {
- QuicStreamId stream_id = GetNthClientInitiatedId(0);
- EXPECT_TRUE(manager_->MaybeIncreaseLargestPeerStreamId(stream_id));
+TEST_P(LegacyQuicStreamIdManagerTest, MaximumAvailableOpenedStreams) {
+ QuicStreamId stream_id = GetNthPeerInitiatedId(0);
+ EXPECT_TRUE(manager_.MaybeIncreaseLargestPeerStreamId(stream_id));
- EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
- EXPECT_TRUE(manager_->MaybeIncreaseLargestPeerStreamId(
- stream_id + 2 * (manager_->max_open_incoming_streams() - 1)));
+ EXPECT_TRUE(manager_.MaybeIncreaseLargestPeerStreamId(
+ stream_id + 2 * (manager_.max_open_incoming_streams() - 1)));
}
-TEST_F(LegacyQuicStreamIdManagerTestServer, TooManyAvailableStreams) {
- QuicStreamId stream_id = GetNthClientInitiatedId(0);
- EXPECT_TRUE(manager_->MaybeIncreaseLargestPeerStreamId(stream_id));
+TEST_P(LegacyQuicStreamIdManagerTest, TooManyAvailableStreams) {
+ QuicStreamId stream_id = GetNthPeerInitiatedId(0);
+ EXPECT_TRUE(manager_.MaybeIncreaseLargestPeerStreamId(stream_id));
// A stream ID which is too large to create.
QuicStreamId stream_id2 =
- GetNthClientInitiatedId(2 * manager_->MaxAvailableStreams() + 4);
- EXPECT_CALL(*connection_,
- CloseConnection(QUIC_TOO_MANY_AVAILABLE_STREAMS, _, _));
- EXPECT_FALSE(manager_->MaybeIncreaseLargestPeerStreamId(stream_id2));
+ GetNthPeerInitiatedId(2 * manager_.MaxAvailableStreams() + 4);
+ EXPECT_FALSE(manager_.MaybeIncreaseLargestPeerStreamId(stream_id2));
}
-TEST_F(LegacyQuicStreamIdManagerTestServer, ManyAvailableStreams) {
+TEST_P(LegacyQuicStreamIdManagerTest, ManyAvailableStreams) {
// When max_open_streams_ is 200, should be able to create 200 streams
// out-of-order, that is, creating the one with the largest stream ID first.
- manager_->set_max_open_incoming_streams(200);
- QuicStreamId stream_id = GetNthClientInitiatedId(0);
- EXPECT_TRUE(manager_->MaybeIncreaseLargestPeerStreamId(stream_id));
- EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
+ manager_.set_max_open_incoming_streams(200);
+ QuicStreamId stream_id = GetNthPeerInitiatedId(0);
+ EXPECT_TRUE(manager_.MaybeIncreaseLargestPeerStreamId(stream_id));
// Create the largest stream ID of a threatened total of 200 streams.
// GetNth... starts at 0, so for 200 streams, get the 199th.
EXPECT_TRUE(
- manager_->MaybeIncreaseLargestPeerStreamId(GetNthClientInitiatedId(199)));
+ manager_.MaybeIncreaseLargestPeerStreamId(GetNthPeerInitiatedId(199)));
}
-TEST_F(LegacyQuicStreamIdManagerTestServer,
+TEST_P(LegacyQuicStreamIdManagerTest,
TestMaxIncomingAndOutgoingStreamsAllowed) {
- // Tests that on server side, the value of max_open_incoming/outgoing
- // streams are setup correctly during negotiation. The value for outgoing
- // stream is limited to negotiated value and for incoming stream it is set to
- // be larger than that.
- session_->OnConfigNegotiated();
- // The max number of open outgoing streams is less than that of incoming
- // streams, and it should be same as negotiated value.
- EXPECT_LT(manager_->max_open_outgoing_streams(),
- manager_->max_open_incoming_streams());
- EXPECT_EQ(manager_->max_open_outgoing_streams(),
+ EXPECT_EQ(manager_.max_open_incoming_streams(),
kDefaultMaxStreamsPerConnection);
- EXPECT_GT(manager_->max_open_incoming_streams(),
- kDefaultMaxStreamsPerConnection);
-}
-
-class LegacyQuicStreamIdManagerTestClient
- : public LegacyQuicStreamIdManagerTest {
- protected:
- LegacyQuicStreamIdManagerTestClient() { Initialize(Perspective::IS_CLIENT); }
-};
-
-TEST_F(LegacyQuicStreamIdManagerTestClient,
- TestMaxIncomingAndOutgoingStreamsAllowed) {
- // Tests that on client side, the value of max_open_incoming/outgoing
- // streams are setup correctly during negotiation. When flag is true, the
- // value for outgoing stream is limited to negotiated value and for incoming
- // stream it is set to be larger than that.
- session_->OnConfigNegotiated();
- EXPECT_LT(manager_->max_open_outgoing_streams(),
- manager_->max_open_incoming_streams());
- EXPECT_EQ(manager_->max_open_outgoing_streams(),
+ EXPECT_EQ(manager_.max_open_outgoing_streams(),
kDefaultMaxStreamsPerConnection);
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/packet_number_indexed_queue.h b/chromium/net/third_party/quiche/src/quic/core/packet_number_indexed_queue.h
index 470a58c1f11..a0870228141 100644
--- a/chromium/net/third_party/quiche/src/quic/core/packet_number_indexed_queue.h
+++ b/chromium/net/third_party/quiche/src/quic/core/packet_number_indexed_queue.h
@@ -5,11 +5,11 @@
#ifndef QUICHE_QUIC_CORE_PACKET_NUMBER_INDEXED_QUEUE_H_
#define QUICHE_QUIC_CORE_PACKET_NUMBER_INDEXED_QUEUE_H_
+#include "net/third_party/quiche/src/quic/core/quic_circular_deque.h"
#include "net/third_party/quiche/src/quic/core/quic_constants.h"
#include "net/third_party/quiche/src/quic/core/quic_packet_number.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
namespace quic {
@@ -34,6 +34,8 @@ namespace quic {
// just two entries will cause it to consume all of the memory available.
// Because of that, it is not a general-purpose container and should not be used
// as one.
+// TODO(wub): Update the comments when deprecating
+// --quic_bw_sampler_remove_packets_once_per_congestion_event.
template <typename T>
class QUIC_NO_EXPORT PacketNumberIndexedQueue {
public:
@@ -60,6 +62,11 @@ class QUIC_NO_EXPORT PacketNumberIndexedQueue {
template <typename Function>
bool Remove(QuicPacketNumber packet_number, Function f);
+ // Remove up to, but not including |packet_number|.
+ // Unused slots in the front are also removed, which means when the function
+ // returns, |first_packet()| can be larger than |packet_number|.
+ void RemoveUpTo(QuicPacketNumber packet_number);
+
bool IsEmpty() const { return number_of_present_entries_ == 0; }
// Returns the number of entries in the queue.
@@ -87,6 +94,9 @@ class QUIC_NO_EXPORT PacketNumberIndexedQueue {
private:
// Wrapper around T used to mark whether the entry is actually in the map.
struct QUIC_NO_EXPORT EntryWrapper : T {
+ // NOTE(wub): When quic_bw_sampler_remove_packets_once_per_congestion_event
+ // is enabled, |present| is false if and only if this is a placeholder entry
+ // for holes in the parent's |entries|.
bool present;
EntryWrapper() : present(false) {}
@@ -105,7 +115,10 @@ class QUIC_NO_EXPORT PacketNumberIndexedQueue {
return const_cast<EntryWrapper*>(const_this->GetEntryWrapper(offset));
}
- QuicDeque<EntryWrapper> entries_;
+ QuicCircularDeque<EntryWrapper> entries_;
+ // NOTE(wub): When --quic_bw_sampler_remove_packets_once_per_congestion_event
+ // is enabled, |number_of_present_entries_| only represents number of holes,
+ // which does not include number of acked or lost packets.
size_t number_of_present_entries_;
QuicPacketNumber first_packet_;
};
@@ -189,6 +202,19 @@ bool PacketNumberIndexedQueue<T>::Remove(QuicPacketNumber packet_number,
}
template <typename T>
+void PacketNumberIndexedQueue<T>::RemoveUpTo(QuicPacketNumber packet_number) {
+ while (!entries_.empty() && first_packet_.IsInitialized() &&
+ first_packet_ < packet_number) {
+ if (entries_.front().present) {
+ number_of_present_entries_--;
+ }
+ entries_.pop_front();
+ first_packet_++;
+ }
+ Cleanup();
+}
+
+template <typename T>
void PacketNumberIndexedQueue<T>::Cleanup() {
while (!entries_.empty() && !entries_.front().present) {
entries_.pop_front();
diff --git a/chromium/net/third_party/quiche/src/quic/core/packet_number_indexed_queue_test.cc b/chromium/net/third_party/quiche/src/quic/core/packet_number_indexed_queue_test.cc
index c2931336bc0..5f6b09cdd74 100644
--- a/chromium/net/third_party/quiche/src/quic/core/packet_number_indexed_queue_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/packet_number_indexed_queue_test.cc
@@ -8,6 +8,7 @@
#include <map>
#include <string>
+#include "net/third_party/quiche/src/quic/core/quic_packet_number.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
namespace quic {
@@ -167,6 +168,31 @@ TEST_F(PacketNumberIndexedQueueTest, FailToRemoveElementsTwice) {
ASSERT_FALSE(queue_.Remove(QuicPacketNumber(1001)));
}
+TEST_F(PacketNumberIndexedQueueTest, RemoveUpTo) {
+ queue_.Emplace(QuicPacketNumber(1001), "one");
+ queue_.Emplace(QuicPacketNumber(2001), "two");
+ EXPECT_EQ(QuicPacketNumber(1001u), queue_.first_packet());
+ EXPECT_EQ(2u, queue_.number_of_present_entries());
+
+ queue_.RemoveUpTo(QuicPacketNumber(1001));
+ EXPECT_EQ(QuicPacketNumber(1001u), queue_.first_packet());
+ EXPECT_EQ(2u, queue_.number_of_present_entries());
+
+ // Remove up to 1100, since [1100, 2001) are !present, they should be cleaned
+ // up from the front.
+ queue_.RemoveUpTo(QuicPacketNumber(1100));
+ EXPECT_EQ(QuicPacketNumber(2001u), queue_.first_packet());
+ EXPECT_EQ(1u, queue_.number_of_present_entries());
+
+ queue_.RemoveUpTo(QuicPacketNumber(2001));
+ EXPECT_EQ(QuicPacketNumber(2001u), queue_.first_packet());
+ EXPECT_EQ(1u, queue_.number_of_present_entries());
+
+ queue_.RemoveUpTo(QuicPacketNumber(2002));
+ EXPECT_FALSE(queue_.first_packet().IsInitialized());
+ EXPECT_EQ(0u, queue_.number_of_present_entries());
+}
+
TEST_F(PacketNumberIndexedQueueTest, ConstGetter) {
queue_.Emplace(QuicPacketNumber(1001), "one");
const auto& const_queue = queue_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_blocking_manager.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_blocking_manager.h
index 6d2df9cfcf8..f1659a64fc9 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_blocking_manager.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_blocking_manager.h
@@ -74,8 +74,8 @@ class QUIC_EXPORT_PRIVATE QpackBlockingManager {
// A stream typically has only one header block, except for the rare cases of
// 1xx responses, trailers, or push promises. Even if there are multiple
// header blocks sent on a single stream, they might not be blocked at the
- // same time. Use std::list instead of QuicDeque because it has lower memory
- // footprint when holding few elements.
+ // same time. Use std::list instead of QuicCircularDeque because it has lower
+ // memory footprint when holding few elements.
using HeaderBlocksForStream = std::list<IndexSet>;
using HeaderBlocks = QuicUnorderedMap<QuicStreamId, HeaderBlocksForStream>;
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.cc
index e16aa5a2de7..7aa0f1125d2 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.cc
@@ -5,6 +5,7 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -31,8 +32,9 @@ QpackDecodedHeadersAccumulator::QpackDecodedHeadersAccumulator(
quic_header_list_.OnHeaderBlockStart();
}
-void QpackDecodedHeadersAccumulator::OnHeaderDecoded(QuicStringPiece name,
- QuicStringPiece value) {
+void QpackDecodedHeadersAccumulator::OnHeaderDecoded(
+ quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value) {
DCHECK(!error_detected_);
uncompressed_header_bytes_without_overhead_ += name.size() + value.size();
@@ -62,11 +64,12 @@ void QpackDecodedHeadersAccumulator::OnDecodingCompleted() {
uncompressed_header_bytes_without_overhead_, compressed_header_bytes_);
// Might destroy |this|.
- visitor_->OnHeadersDecoded(std::move(quic_header_list_));
+ visitor_->OnHeadersDecoded(std::move(quic_header_list_),
+ header_list_size_limit_exceeded_);
}
void QpackDecodedHeadersAccumulator::OnDecodingErrorDetected(
- QuicStringPiece error_message) {
+ quiche::QuicheStringPiece error_message) {
DCHECK(!error_detected_);
DCHECK(!headers_decoded_);
@@ -75,7 +78,7 @@ void QpackDecodedHeadersAccumulator::OnDecodingErrorDetected(
visitor_->OnHeaderDecodingError(error_message);
}
-void QpackDecodedHeadersAccumulator::Decode(QuicStringPiece data) {
+void QpackDecodedHeadersAccumulator::Decode(quiche::QuicheStringPiece data) {
DCHECK(!error_detected_);
compressed_header_bytes_ += data.size();
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.h
index 0a2db6a348d..334fcbda543 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.h
@@ -12,7 +12,7 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -34,16 +34,19 @@ class QUIC_EXPORT_PRIVATE QpackDecodedHeadersAccumulator
public:
virtual ~Visitor() = default;
- // Called when headers are successfully decoded. If header list size
- // exceeds the limit specified via |max_header_list_size| in
- // QpackDecodedHeadersAccumulator constructor, then |headers| will be empty,
- // but will still have the correct compressed and uncompressed size
- // information. However, header_list_size_limit_exceeded() is recommended
- // instead of headers.empty() to check whether header size exceeds limit.
- virtual void OnHeadersDecoded(QuicHeaderList headers) = 0;
+ // Called when headers are successfully decoded. If the uncompressed header
+ // list size including an overhead for each header field exceeds the limit
+ // specified via |max_header_list_size| in QpackDecodedHeadersAccumulator
+ // constructor, then |header_list_size_limit_exceeded| will be true, and
+ // |headers| will be empty but will still have the correct compressed and
+ // uncompressed size
+ // information.
+ virtual void OnHeadersDecoded(QuicHeaderList headers,
+ bool header_list_size_limit_exceeded) = 0;
// Called when an error has occurred.
- virtual void OnHeaderDecodingError(QuicStringPiece error_message) = 0;
+ virtual void OnHeaderDecodingError(
+ quiche::QuicheStringPiece error_message) = 0;
};
QpackDecodedHeadersAccumulator(QuicStreamId id,
@@ -54,27 +57,22 @@ class QUIC_EXPORT_PRIVATE QpackDecodedHeadersAccumulator
// QpackProgressiveDecoder::HeadersHandlerInterface implementation.
// These methods should only be called by |decoder_|.
- void OnHeaderDecoded(QuicStringPiece name, QuicStringPiece value) override;
+ void OnHeaderDecoded(quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value) override;
void OnDecodingCompleted() override;
- void OnDecodingErrorDetected(QuicStringPiece error_message) override;
+ void OnDecodingErrorDetected(
+ quiche::QuicheStringPiece error_message) override;
// Decode payload data.
// Must not be called if an error has been detected.
// Must not be called after EndHeaderBlock().
- void Decode(QuicStringPiece data);
+ void Decode(quiche::QuicheStringPiece data);
// Signal end of HEADERS frame.
// Must not be called if an error has been detected.
// Must not be called more that once.
void EndHeaderBlock();
- // Returns true if the uncompressed size of the header list, including an
- // overhead for each header field, exceeds |max_header_list_size| passed in
- // the constructor.
- bool header_list_size_limit_exceeded() const {
- return header_list_size_limit_exceeded_;
- }
-
private:
std::unique_ptr<QpackProgressiveDecoder> decoder_;
Visitor* visitor_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator_test.cc
index 6616517330f..c98f8543ffa 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator_test.cc
@@ -8,9 +8,10 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_decoder_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
using ::testing::_;
using ::testing::ElementsAre;
@@ -41,8 +42,11 @@ const char* const kHeaderAcknowledgement = "\x81";
class MockVisitor : public QpackDecodedHeadersAccumulator::Visitor {
public:
~MockVisitor() override = default;
- MOCK_METHOD1(OnHeadersDecoded, void(QuicHeaderList headers));
- MOCK_METHOD1(OnHeaderDecodingError, void(QuicStringPiece error_message));
+ MOCK_METHOD2(OnHeadersDecoded,
+ void(QuicHeaderList headers,
+ bool header_list_size_limit_exceeded));
+ MOCK_METHOD1(OnHeaderDecodingError,
+ void(quiche::QuicheStringPiece error_message));
};
} // anonymous namespace
@@ -77,7 +81,7 @@ TEST_F(QpackDecodedHeadersAccumulatorTest, EmptyPayload) {
// HEADERS frame payload must have a complete Header Block Prefix.
TEST_F(QpackDecodedHeadersAccumulatorTest, TruncatedHeaderBlockPrefix) {
- accumulator_.Decode(QuicTextUtils::HexDecode("00"));
+ accumulator_.Decode(quiche::QuicheTextUtils::HexDecode("00"));
EXPECT_CALL(visitor_,
OnHeaderDecodingError(Eq("Incomplete header data prefix.")));
@@ -85,13 +89,13 @@ TEST_F(QpackDecodedHeadersAccumulatorTest, TruncatedHeaderBlockPrefix) {
}
TEST_F(QpackDecodedHeadersAccumulatorTest, EmptyHeaderList) {
- std::string encoded_data(QuicTextUtils::HexDecode("0000"));
+ std::string encoded_data(quiche::QuicheTextUtils::HexDecode("0000"));
accumulator_.Decode(encoded_data);
QuicHeaderList header_list;
- EXPECT_CALL(visitor_, OnHeadersDecoded(_)).WillOnce(SaveArg<0>(&header_list));
+ EXPECT_CALL(visitor_, OnHeadersDecoded(_, false))
+ .WillOnce(SaveArg<0>(&header_list));
accumulator_.EndHeaderBlock();
- EXPECT_FALSE(accumulator_.header_list_size_limit_exceeded());
EXPECT_EQ(0u, header_list.uncompressed_header_bytes());
EXPECT_EQ(encoded_data.size(), header_list.compressed_header_bytes());
@@ -101,7 +105,7 @@ TEST_F(QpackDecodedHeadersAccumulatorTest, EmptyHeaderList) {
// This payload is the prefix of a valid payload, but EndHeaderBlock() is called
// before it can be completely decoded.
TEST_F(QpackDecodedHeadersAccumulatorTest, TruncatedPayload) {
- accumulator_.Decode(QuicTextUtils::HexDecode("00002366"));
+ accumulator_.Decode(quiche::QuicheTextUtils::HexDecode("00002366"));
EXPECT_CALL(visitor_, OnHeaderDecodingError(Eq("Incomplete header block.")));
accumulator_.EndHeaderBlock();
@@ -111,17 +115,18 @@ TEST_F(QpackDecodedHeadersAccumulatorTest, TruncatedPayload) {
TEST_F(QpackDecodedHeadersAccumulatorTest, InvalidPayload) {
EXPECT_CALL(visitor_,
OnHeaderDecodingError(Eq("Static table entry not found.")));
- accumulator_.Decode(QuicTextUtils::HexDecode("0000ff23ff24"));
+ accumulator_.Decode(quiche::QuicheTextUtils::HexDecode("0000ff23ff24"));
}
TEST_F(QpackDecodedHeadersAccumulatorTest, Success) {
- std::string encoded_data(QuicTextUtils::HexDecode("000023666f6f03626172"));
+ std::string encoded_data(
+ quiche::QuicheTextUtils::HexDecode("000023666f6f03626172"));
accumulator_.Decode(encoded_data);
QuicHeaderList header_list;
- EXPECT_CALL(visitor_, OnHeadersDecoded(_)).WillOnce(SaveArg<0>(&header_list));
+ EXPECT_CALL(visitor_, OnHeadersDecoded(_, false))
+ .WillOnce(SaveArg<0>(&header_list));
accumulator_.EndHeaderBlock();
- EXPECT_FALSE(accumulator_.header_list_size_limit_exceeded());
EXPECT_THAT(header_list, ElementsAre(Pair("foo", "bar")));
EXPECT_EQ(strlen("foo") + strlen("bar"),
@@ -133,7 +138,7 @@ TEST_F(QpackDecodedHeadersAccumulatorTest, Success) {
// otherwise decoding could fail with "incomplete header block" error.
TEST_F(QpackDecodedHeadersAccumulatorTest, ExceedLimitThenSplitInstruction) {
// Total length of header list exceeds kMaxHeaderListSize.
- accumulator_.Decode(QuicTextUtils::HexDecode(
+ accumulator_.Decode(quiche::QuicheTextUtils::HexDecode(
"0000" // header block prefix
"26666f6f626172" // header key: "foobar"
"7d61616161616161616161616161616161616161" // header value: 'a' 125 times
@@ -141,19 +146,18 @@ TEST_F(QpackDecodedHeadersAccumulatorTest, ExceedLimitThenSplitInstruction) {
"616161616161616161616161616161616161616161616161616161616161616161616161"
"61616161616161616161616161616161616161616161616161616161616161616161"
"ff")); // first byte of a two-byte long Indexed Header Field instruction
- accumulator_.Decode(QuicTextUtils::HexDecode(
+ accumulator_.Decode(quiche::QuicheTextUtils::HexDecode(
"0f" // second byte of a two-byte long Indexed Header Field instruction
));
- EXPECT_CALL(visitor_, OnHeadersDecoded(_));
+ EXPECT_CALL(visitor_, OnHeadersDecoded(_, true));
accumulator_.EndHeaderBlock();
- EXPECT_TRUE(accumulator_.header_list_size_limit_exceeded());
}
// Test that header list limit enforcement works with blocked encoding.
TEST_F(QpackDecodedHeadersAccumulatorTest, ExceedLimitBlocked) {
// Total length of header list exceeds kMaxHeaderListSize.
- accumulator_.Decode(QuicTextUtils::HexDecode(
+ accumulator_.Decode(quiche::QuicheTextUtils::HexDecode(
"0200" // header block prefix
"80" // reference to dynamic table entry not yet received
"26666f6f626172" // header key: "foobar"
@@ -169,14 +173,13 @@ TEST_F(QpackDecodedHeadersAccumulatorTest, ExceedLimitBlocked) {
EXPECT_CALL(decoder_stream_sender_delegate_,
WriteStreamData(Eq(kHeaderAcknowledgement)));
- EXPECT_CALL(visitor_, OnHeadersDecoded(_));
+ EXPECT_CALL(visitor_, OnHeadersDecoded(_, true));
qpack_decoder_.OnInsertWithoutNameReference("foo", "bar");
- EXPECT_TRUE(accumulator_.header_list_size_limit_exceeded());
}
TEST_F(QpackDecodedHeadersAccumulatorTest, BlockedDecoding) {
// Reference to dynamic table entry not yet received.
- std::string encoded_data(QuicTextUtils::HexDecode("020080"));
+ std::string encoded_data(quiche::QuicheTextUtils::HexDecode("020080"));
accumulator_.Decode(encoded_data);
accumulator_.EndHeaderBlock();
@@ -187,10 +190,10 @@ TEST_F(QpackDecodedHeadersAccumulatorTest, BlockedDecoding) {
WriteStreamData(Eq(kHeaderAcknowledgement)));
QuicHeaderList header_list;
- EXPECT_CALL(visitor_, OnHeadersDecoded(_)).WillOnce(SaveArg<0>(&header_list));
+ EXPECT_CALL(visitor_, OnHeadersDecoded(_, false))
+ .WillOnce(SaveArg<0>(&header_list));
qpack_decoder_.OnInsertWithoutNameReference("foo", "bar");
- EXPECT_FALSE(accumulator_.header_list_size_limit_exceeded());
EXPECT_THAT(header_list, ElementsAre(Pair("foo", "bar")));
EXPECT_EQ(strlen("foo") + strlen("bar"),
header_list.uncompressed_header_bytes());
@@ -200,7 +203,7 @@ TEST_F(QpackDecodedHeadersAccumulatorTest, BlockedDecoding) {
TEST_F(QpackDecodedHeadersAccumulatorTest,
BlockedDecodingUnblockedBeforeEndOfHeaderBlock) {
// Reference to dynamic table entry not yet received.
- accumulator_.Decode(QuicTextUtils::HexDecode("020080"));
+ accumulator_.Decode(quiche::QuicheTextUtils::HexDecode("020080"));
// Set dynamic table capacity.
qpack_decoder_.OnSetDynamicTableCapacity(kMaxDynamicTableCapacity);
@@ -210,12 +213,12 @@ TEST_F(QpackDecodedHeadersAccumulatorTest,
// Rest of header block: same entry again.
EXPECT_CALL(decoder_stream_sender_delegate_,
WriteStreamData(Eq(kHeaderAcknowledgement)));
- accumulator_.Decode(QuicTextUtils::HexDecode("80"));
+ accumulator_.Decode(quiche::QuicheTextUtils::HexDecode("80"));
QuicHeaderList header_list;
- EXPECT_CALL(visitor_, OnHeadersDecoded(_)).WillOnce(SaveArg<0>(&header_list));
+ EXPECT_CALL(visitor_, OnHeadersDecoded(_, false))
+ .WillOnce(SaveArg<0>(&header_list));
accumulator_.EndHeaderBlock();
- EXPECT_FALSE(accumulator_.header_list_size_limit_exceeded());
EXPECT_THAT(header_list, ElementsAre(Pair("foo", "bar"), Pair("foo", "bar")));
}
@@ -225,12 +228,12 @@ TEST_F(QpackDecodedHeadersAccumulatorTest,
BlockedDecodingUnblockedAndErrorBeforeEndOfHeaderBlock) {
// Required Insert Count higher than number of entries causes decoding to be
// blocked.
- accumulator_.Decode(QuicTextUtils::HexDecode("0200"));
+ accumulator_.Decode(quiche::QuicheTextUtils::HexDecode("0200"));
// Indexed Header Field instruction addressing dynamic table entry with
// relative index 0, absolute index 0.
- accumulator_.Decode(QuicTextUtils::HexDecode("80"));
+ accumulator_.Decode(quiche::QuicheTextUtils::HexDecode("80"));
// Relative index larger than or equal to Base is invalid.
- accumulator_.Decode(QuicTextUtils::HexDecode("81"));
+ accumulator_.Decode(quiche::QuicheTextUtils::HexDecode("81"));
// Set dynamic table capacity.
qpack_decoder_.OnSetDynamicTableCapacity(kMaxDynamicTableCapacity);
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder.cc
index 3ae6bce6e6b..17790defd5f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder.cc
@@ -8,6 +8,7 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_index_conversions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -69,7 +70,7 @@ void QpackDecoder::OnDecodingCompleted(QuicStreamId stream_id,
void QpackDecoder::OnInsertWithNameReference(bool is_static,
uint64_t name_index,
- QuicStringPiece value) {
+ quiche::QuicheStringPiece value) {
if (is_static) {
auto entry = header_table_.LookupEntry(/* is_static = */ true, name_index);
if (!entry) {
@@ -108,8 +109,9 @@ void QpackDecoder::OnInsertWithNameReference(bool is_static,
}
}
-void QpackDecoder::OnInsertWithoutNameReference(QuicStringPiece name,
- QuicStringPiece value) {
+void QpackDecoder::OnInsertWithoutNameReference(
+ quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value) {
const QpackEntry* entry = header_table_.InsertEntry(name, value);
if (!entry) {
encoder_stream_error_delegate_->OnEncoderStreamError(
@@ -147,7 +149,7 @@ void QpackDecoder::OnSetDynamicTableCapacity(uint64_t capacity) {
}
}
-void QpackDecoder::OnErrorDetected(QuicStringPiece error_message) {
+void QpackDecoder::OnErrorDetected(quiche::QuicheStringPiece error_message) {
encoder_stream_error_delegate_->OnEncoderStreamError(error_message);
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h
index 4ac1e449bc6..e09b14bef91 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h
@@ -15,7 +15,7 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -34,7 +34,8 @@ class QUIC_EXPORT_PRIVATE QpackDecoder
public:
virtual ~EncoderStreamErrorDelegate() {}
- virtual void OnEncoderStreamError(QuicStringPiece error_message) = 0;
+ virtual void OnEncoderStreamError(
+ quiche::QuicheStringPiece error_message) = 0;
};
QpackDecoder(uint64_t maximum_dynamic_table_capacity,
@@ -79,12 +80,12 @@ class QUIC_EXPORT_PRIVATE QpackDecoder
// QpackEncoderStreamReceiver::Delegate implementation
void OnInsertWithNameReference(bool is_static,
uint64_t name_index,
- QuicStringPiece value) override;
- void OnInsertWithoutNameReference(QuicStringPiece name,
- QuicStringPiece value) override;
+ quiche::QuicheStringPiece value) override;
+ void OnInsertWithoutNameReference(quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value) override;
void OnDuplicate(uint64_t index) override;
void OnSetDynamicTableCapacity(uint64_t capacity) override;
- void OnErrorDetected(QuicStringPiece error_message) override;
+ void OnErrorDetected(quiche::QuicheStringPiece error_message) override;
// delegate must be set if dynamic table capacity is not zero.
void set_qpack_stream_sender_delegate(QpackStreamSenderDelegate* delegate) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver.cc
index 2ba89d48a82..5d6cf837621 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver.cc
@@ -7,6 +7,7 @@
#include "net/third_party/quiche/src/http2/decoder/decode_buffer.h"
#include "net/third_party/quiche/src/http2/decoder/decode_status.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -17,7 +18,7 @@ QpackDecoderStreamReceiver::QpackDecoderStreamReceiver(Delegate* delegate)
DCHECK(delegate_);
}
-void QpackDecoderStreamReceiver::Decode(QuicStringPiece data) {
+void QpackDecoderStreamReceiver::Decode(quiche::QuicheStringPiece data) {
if (data.empty() || error_detected_) {
return;
}
@@ -42,7 +43,8 @@ bool QpackDecoderStreamReceiver::OnInstructionDecoded(
return true;
}
-void QpackDecoderStreamReceiver::OnError(QuicStringPiece error_message) {
+void QpackDecoderStreamReceiver::OnError(
+ quiche::QuicheStringPiece error_message) {
DCHECK(!error_detected_);
error_detected_ = true;
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver.h
index 396c6df8779..19f51f0d3b4 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver.h
@@ -11,7 +11,7 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_stream_receiver.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -34,7 +34,7 @@ class QUIC_EXPORT_PRIVATE QpackDecoderStreamReceiver
// 5.3.3 Stream Cancellation
virtual void OnStreamCancellation(QuicStreamId stream_id) = 0;
// Decoding error
- virtual void OnErrorDetected(QuicStringPiece error_message) = 0;
+ virtual void OnErrorDetected(quiche::QuicheStringPiece error_message) = 0;
};
explicit QpackDecoderStreamReceiver(Delegate* delegate);
@@ -47,11 +47,11 @@ class QUIC_EXPORT_PRIVATE QpackDecoderStreamReceiver
// Decode data and call appropriate Delegate method after each decoded
// instruction. Once an error occurs, Delegate::OnErrorDetected() is called,
// and all further data is ignored.
- void Decode(QuicStringPiece data) override;
+ void Decode(quiche::QuicheStringPiece data) override;
// QpackInstructionDecoder::Delegate implementation.
bool OnInstructionDecoded(const QpackInstruction* instruction) override;
- void OnError(QuicStringPiece error_message) override;
+ void OnError(quiche::QuicheStringPiece error_message) override;
private:
QpackInstructionDecoder instruction_decoder_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver_test.cc
index 29a00d15a79..44a2286a244 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver_test.cc
@@ -5,7 +5,8 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
using testing::Eq;
using testing::StrictMock;
@@ -21,7 +22,7 @@ class MockDelegate : public QpackDecoderStreamReceiver::Delegate {
MOCK_METHOD1(OnInsertCountIncrement, void(uint64_t increment));
MOCK_METHOD1(OnHeaderAcknowledgement, void(QuicStreamId stream_id));
MOCK_METHOD1(OnStreamCancellation, void(QuicStreamId stream_id));
- MOCK_METHOD1(OnErrorDetected, void(QuicStringPiece error_message));
+ MOCK_METHOD1(OnErrorDetected, void(quiche::QuicheStringPiece error_message));
};
class QpackDecoderStreamReceiverTest : public QuicTest {
@@ -35,53 +36,53 @@ class QpackDecoderStreamReceiverTest : public QuicTest {
TEST_F(QpackDecoderStreamReceiverTest, InsertCountIncrement) {
EXPECT_CALL(delegate_, OnInsertCountIncrement(0));
- stream_.Decode(QuicTextUtils::HexDecode("00"));
+ stream_.Decode(quiche::QuicheTextUtils::HexDecode("00"));
EXPECT_CALL(delegate_, OnInsertCountIncrement(10));
- stream_.Decode(QuicTextUtils::HexDecode("0a"));
+ stream_.Decode(quiche::QuicheTextUtils::HexDecode("0a"));
EXPECT_CALL(delegate_, OnInsertCountIncrement(63));
- stream_.Decode(QuicTextUtils::HexDecode("3f00"));
+ stream_.Decode(quiche::QuicheTextUtils::HexDecode("3f00"));
EXPECT_CALL(delegate_, OnInsertCountIncrement(200));
- stream_.Decode(QuicTextUtils::HexDecode("3f8901"));
+ stream_.Decode(quiche::QuicheTextUtils::HexDecode("3f8901"));
EXPECT_CALL(delegate_, OnErrorDetected(Eq("Encoded integer too large.")));
- stream_.Decode(QuicTextUtils::HexDecode("3fffffffffffffffffffff"));
+ stream_.Decode(quiche::QuicheTextUtils::HexDecode("3fffffffffffffffffffff"));
}
TEST_F(QpackDecoderStreamReceiverTest, HeaderAcknowledgement) {
EXPECT_CALL(delegate_, OnHeaderAcknowledgement(0));
- stream_.Decode(QuicTextUtils::HexDecode("80"));
+ stream_.Decode(quiche::QuicheTextUtils::HexDecode("80"));
EXPECT_CALL(delegate_, OnHeaderAcknowledgement(37));
- stream_.Decode(QuicTextUtils::HexDecode("a5"));
+ stream_.Decode(quiche::QuicheTextUtils::HexDecode("a5"));
EXPECT_CALL(delegate_, OnHeaderAcknowledgement(127));
- stream_.Decode(QuicTextUtils::HexDecode("ff00"));
+ stream_.Decode(quiche::QuicheTextUtils::HexDecode("ff00"));
EXPECT_CALL(delegate_, OnHeaderAcknowledgement(503));
- stream_.Decode(QuicTextUtils::HexDecode("fff802"));
+ stream_.Decode(quiche::QuicheTextUtils::HexDecode("fff802"));
EXPECT_CALL(delegate_, OnErrorDetected(Eq("Encoded integer too large.")));
- stream_.Decode(QuicTextUtils::HexDecode("ffffffffffffffffffffff"));
+ stream_.Decode(quiche::QuicheTextUtils::HexDecode("ffffffffffffffffffffff"));
}
TEST_F(QpackDecoderStreamReceiverTest, StreamCancellation) {
EXPECT_CALL(delegate_, OnStreamCancellation(0));
- stream_.Decode(QuicTextUtils::HexDecode("40"));
+ stream_.Decode(quiche::QuicheTextUtils::HexDecode("40"));
EXPECT_CALL(delegate_, OnStreamCancellation(19));
- stream_.Decode(QuicTextUtils::HexDecode("53"));
+ stream_.Decode(quiche::QuicheTextUtils::HexDecode("53"));
EXPECT_CALL(delegate_, OnStreamCancellation(63));
- stream_.Decode(QuicTextUtils::HexDecode("7f00"));
+ stream_.Decode(quiche::QuicheTextUtils::HexDecode("7f00"));
EXPECT_CALL(delegate_, OnStreamCancellation(110));
- stream_.Decode(QuicTextUtils::HexDecode("7f2f"));
+ stream_.Decode(quiche::QuicheTextUtils::HexDecode("7f2f"));
EXPECT_CALL(delegate_, OnErrorDetected(Eq("Encoded integer too large.")));
- stream_.Decode(QuicTextUtils::HexDecode("7fffffffffffffffffffff"));
+ stream_.Decode(quiche::QuicheTextUtils::HexDecode("7fffffffffffffffffffff"));
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.cc
index 72a446b420a..34f4de8d2af 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.cc
@@ -10,6 +10,7 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.h
index d9033b04dee..eee95c131cb 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.h
@@ -11,7 +11,6 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_stream_sender_delegate.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender_test.cc
index e3dc12497e3..1d18fa92e59 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender_test.cc
@@ -5,8 +5,8 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
using ::testing::Eq;
using ::testing::StrictMock;
@@ -27,57 +27,67 @@ class QpackDecoderStreamSenderTest : public QuicTest {
};
TEST_F(QpackDecoderStreamSenderTest, InsertCountIncrement) {
- EXPECT_CALL(delegate_, WriteStreamData(Eq(QuicTextUtils::HexDecode("00"))));
+ EXPECT_CALL(delegate_,
+ WriteStreamData(Eq(quiche::QuicheTextUtils::HexDecode("00"))));
stream_.SendInsertCountIncrement(0);
stream_.Flush();
- EXPECT_CALL(delegate_, WriteStreamData(Eq(QuicTextUtils::HexDecode("0a"))));
+ EXPECT_CALL(delegate_,
+ WriteStreamData(Eq(quiche::QuicheTextUtils::HexDecode("0a"))));
stream_.SendInsertCountIncrement(10);
stream_.Flush();
- EXPECT_CALL(delegate_, WriteStreamData(Eq(QuicTextUtils::HexDecode("3f00"))));
+ EXPECT_CALL(delegate_,
+ WriteStreamData(Eq(quiche::QuicheTextUtils::HexDecode("3f00"))));
stream_.SendInsertCountIncrement(63);
stream_.Flush();
- EXPECT_CALL(delegate_,
- WriteStreamData(Eq(QuicTextUtils::HexDecode("3f8901"))));
+ EXPECT_CALL(delegate_, WriteStreamData(
+ Eq(quiche::QuicheTextUtils::HexDecode("3f8901"))));
stream_.SendInsertCountIncrement(200);
stream_.Flush();
}
TEST_F(QpackDecoderStreamSenderTest, HeaderAcknowledgement) {
- EXPECT_CALL(delegate_, WriteStreamData(Eq(QuicTextUtils::HexDecode("80"))));
+ EXPECT_CALL(delegate_,
+ WriteStreamData(Eq(quiche::QuicheTextUtils::HexDecode("80"))));
stream_.SendHeaderAcknowledgement(0);
stream_.Flush();
- EXPECT_CALL(delegate_, WriteStreamData(Eq(QuicTextUtils::HexDecode("a5"))));
+ EXPECT_CALL(delegate_,
+ WriteStreamData(Eq(quiche::QuicheTextUtils::HexDecode("a5"))));
stream_.SendHeaderAcknowledgement(37);
stream_.Flush();
- EXPECT_CALL(delegate_, WriteStreamData(Eq(QuicTextUtils::HexDecode("ff00"))));
+ EXPECT_CALL(delegate_,
+ WriteStreamData(Eq(quiche::QuicheTextUtils::HexDecode("ff00"))));
stream_.SendHeaderAcknowledgement(127);
stream_.Flush();
- EXPECT_CALL(delegate_,
- WriteStreamData(Eq(QuicTextUtils::HexDecode("fff802"))));
+ EXPECT_CALL(delegate_, WriteStreamData(
+ Eq(quiche::QuicheTextUtils::HexDecode("fff802"))));
stream_.SendHeaderAcknowledgement(503);
stream_.Flush();
}
TEST_F(QpackDecoderStreamSenderTest, StreamCancellation) {
- EXPECT_CALL(delegate_, WriteStreamData(Eq(QuicTextUtils::HexDecode("40"))));
+ EXPECT_CALL(delegate_,
+ WriteStreamData(Eq(quiche::QuicheTextUtils::HexDecode("40"))));
stream_.SendStreamCancellation(0);
stream_.Flush();
- EXPECT_CALL(delegate_, WriteStreamData(Eq(QuicTextUtils::HexDecode("53"))));
+ EXPECT_CALL(delegate_,
+ WriteStreamData(Eq(quiche::QuicheTextUtils::HexDecode("53"))));
stream_.SendStreamCancellation(19);
stream_.Flush();
- EXPECT_CALL(delegate_, WriteStreamData(Eq(QuicTextUtils::HexDecode("7f00"))));
+ EXPECT_CALL(delegate_,
+ WriteStreamData(Eq(quiche::QuicheTextUtils::HexDecode("7f00"))));
stream_.SendStreamCancellation(63);
stream_.Flush();
- EXPECT_CALL(delegate_, WriteStreamData(Eq(QuicTextUtils::HexDecode("7f2f"))));
+ EXPECT_CALL(delegate_,
+ WriteStreamData(Eq(quiche::QuicheTextUtils::HexDecode("7f2f"))));
stream_.SendStreamCancellation(110);
stream_.Flush();
}
@@ -87,15 +97,16 @@ TEST_F(QpackDecoderStreamSenderTest, Coalesce) {
stream_.SendHeaderAcknowledgement(37);
stream_.SendStreamCancellation(0);
- EXPECT_CALL(delegate_,
- WriteStreamData(Eq(QuicTextUtils::HexDecode("0aa540"))));
+ EXPECT_CALL(delegate_, WriteStreamData(
+ Eq(quiche::QuicheTextUtils::HexDecode("0aa540"))));
stream_.Flush();
stream_.SendInsertCountIncrement(63);
stream_.SendStreamCancellation(110);
- EXPECT_CALL(delegate_,
- WriteStreamData(Eq(QuicTextUtils::HexDecode("3f007f2f"))));
+ EXPECT_CALL(
+ delegate_,
+ WriteStreamData(Eq(quiche::QuicheTextUtils::HexDecode("3f007f2f"))));
stream_.Flush();
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test.cc
index 1fc5802d83c..8b546b0ed9f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test.cc
@@ -8,9 +8,10 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_decoder_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
#include "net/third_party/quiche/src/spdy/core/spdy_header_block.h"
using ::testing::_;
@@ -48,12 +49,13 @@ class QpackDecoderTest : public QuicTestWithParam<FragmentMode> {
// Destroy QpackProgressiveDecoder on error to test that it does not crash.
// See https://crbug.com/1025209.
ON_CALL(handler_, OnDecodingErrorDetected(_))
- .WillByDefault(Invoke([this](QuicStringPiece /* error_message */) {
- progressive_decoder_.reset();
- }));
+ .WillByDefault(
+ Invoke([this](quiche::QuicheStringPiece /* error_message */) {
+ progressive_decoder_.reset();
+ }));
}
- void DecodeEncoderStreamData(QuicStringPiece data) {
+ void DecodeEncoderStreamData(quiche::QuicheStringPiece data) {
qpack_decoder_.encoder_stream_receiver()->Decode(data);
}
@@ -69,7 +71,7 @@ class QpackDecoderTest : public QuicTestWithParam<FragmentMode> {
// Pass header block data to QpackProgressiveDecoder::Decode()
// in fragments dictated by |fragment_mode_|.
- void DecodeData(QuicStringPiece data) {
+ void DecodeData(quiche::QuicheStringPiece data) {
auto fragment_size_generator =
FragmentModeToFragmentSizeGenerator(fragment_mode_);
while (progressive_decoder_ && !data.empty()) {
@@ -89,7 +91,7 @@ class QpackDecoderTest : public QuicTestWithParam<FragmentMode> {
}
// Decode an entire header block.
- void DecodeHeaderBlock(QuicStringPiece data) {
+ void DecodeHeaderBlock(quiche::QuicheStringPiece data) {
StartDecoding();
DecodeData(data);
EndDecoding();
@@ -115,7 +117,7 @@ TEST_P(QpackDecoderTest, NoPrefix) {
OnDecodingErrorDetected(Eq("Incomplete header data prefix.")));
// Header Data Prefix is at least two bytes long.
- DecodeHeaderBlock(QuicTextUtils::HexDecode("00"));
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode("00"));
}
// Regression test for https://1025209: QpackProgressiveDecoder must not crash
@@ -127,50 +129,52 @@ TEST_P(QpackDecoderTest, InvalidPrefix) {
OnDecodingErrorDetected(Eq("Encoded integer too large.")));
// Encoded Required Insert Count in Header Data Prefix is too large.
- DecodeData(QuicTextUtils::HexDecode("ffffffffffffffffffffffffffff"));
+ DecodeData(
+ quiche::QuicheTextUtils::HexDecode("ffffffffffffffffffffffffffff"));
}
TEST_P(QpackDecoderTest, EmptyHeaderBlock) {
EXPECT_CALL(handler_, OnDecodingCompleted());
- DecodeHeaderBlock(QuicTextUtils::HexDecode("0000"));
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode("0000"));
}
TEST_P(QpackDecoderTest, LiteralEntryEmptyName) {
EXPECT_CALL(handler_, OnHeaderDecoded(Eq(""), Eq("foo")));
EXPECT_CALL(handler_, OnDecodingCompleted());
- DecodeHeaderBlock(QuicTextUtils::HexDecode("00002003666f6f"));
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode("00002003666f6f"));
}
TEST_P(QpackDecoderTest, LiteralEntryEmptyValue) {
EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("")));
EXPECT_CALL(handler_, OnDecodingCompleted());
- DecodeHeaderBlock(QuicTextUtils::HexDecode("000023666f6f00"));
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode("000023666f6f00"));
}
TEST_P(QpackDecoderTest, LiteralEntryEmptyNameAndValue) {
EXPECT_CALL(handler_, OnHeaderDecoded(Eq(""), Eq("")));
EXPECT_CALL(handler_, OnDecodingCompleted());
- DecodeHeaderBlock(QuicTextUtils::HexDecode("00002000"));
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode("00002000"));
}
TEST_P(QpackDecoderTest, SimpleLiteralEntry) {
EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
EXPECT_CALL(handler_, OnDecodingCompleted());
- DecodeHeaderBlock(QuicTextUtils::HexDecode("000023666f6f03626172"));
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode("000023666f6f03626172"));
}
TEST_P(QpackDecoderTest, MultipleLiteralEntries) {
EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
std::string str(127, 'a');
- EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foobaar"), QuicStringPiece(str)));
+ EXPECT_CALL(handler_,
+ OnHeaderDecoded(Eq("foobaar"), quiche::QuicheStringPiece(str)));
EXPECT_CALL(handler_, OnDecodingCompleted());
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0000" // prefix
"23666f6f03626172" // foo: bar
"2700666f6f62616172" // 7 octet long header name, the smallest number
@@ -188,7 +192,8 @@ TEST_P(QpackDecoderTest, NameLenTooLargeForVarintDecoder) {
EXPECT_CALL(handler_,
OnDecodingErrorDetected(Eq("Encoded integer too large.")));
- DecodeHeaderBlock(QuicTextUtils::HexDecode("000027ffffffffffffffffffff"));
+ DecodeHeaderBlock(
+ quiche::QuicheTextUtils::HexDecode("000027ffffffffffffffffffff"));
}
// Name Length value can be decoded by varint decoder but exceeds 1 MB limit.
@@ -196,7 +201,7 @@ TEST_P(QpackDecoderTest, NameLenExceedsLimit) {
EXPECT_CALL(handler_,
OnDecodingErrorDetected(Eq("String literal too long.")));
- DecodeHeaderBlock(QuicTextUtils::HexDecode("000027ffff7f"));
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode("000027ffff7f"));
}
// Value Length value is too large for varint decoder to decode.
@@ -205,7 +210,7 @@ TEST_P(QpackDecoderTest, ValueLenTooLargeForVarintDecoder) {
OnDecodingErrorDetected(Eq("Encoded integer too large.")));
DecodeHeaderBlock(
- QuicTextUtils::HexDecode("000023666f6f7fffffffffffffffffffff"));
+ quiche::QuicheTextUtils::HexDecode("000023666f6f7fffffffffffffffffffff"));
}
// Value Length value can be decoded by varint decoder but exceeds 1 MB limit.
@@ -213,22 +218,22 @@ TEST_P(QpackDecoderTest, ValueLenExceedsLimit) {
EXPECT_CALL(handler_,
OnDecodingErrorDetected(Eq("String literal too long.")));
- DecodeHeaderBlock(QuicTextUtils::HexDecode("000023666f6f7fffff7f"));
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode("000023666f6f7fffff7f"));
}
TEST_P(QpackDecoderTest, IncompleteHeaderBlock) {
EXPECT_CALL(handler_,
OnDecodingErrorDetected(Eq("Incomplete header block.")));
- DecodeHeaderBlock(QuicTextUtils::HexDecode("00002366"));
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode("00002366"));
}
TEST_P(QpackDecoderTest, HuffmanSimple) {
EXPECT_CALL(handler_, OnHeaderDecoded(Eq("custom-key"), Eq("custom-value")));
EXPECT_CALL(handler_, OnDecodingCompleted());
- DecodeHeaderBlock(
- QuicTextUtils::HexDecode("00002f0125a849e95ba97d7f8925a849e95bb8e8b4bf"));
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
+ "00002f0125a849e95ba97d7f8925a849e95bb8e8b4bf"));
}
TEST_P(QpackDecoderTest, AlternatingHuffmanNonHuffman) {
@@ -236,7 +241,7 @@ TEST_P(QpackDecoderTest, AlternatingHuffmanNonHuffman) {
.Times(4);
EXPECT_CALL(handler_, OnDecodingCompleted());
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0000" // Prefix.
"2f0125a849e95ba97d7f" // Huffman-encoded name.
"8925a849e95bb8e8b4bf" // Huffman-encoded value.
@@ -249,44 +254,44 @@ TEST_P(QpackDecoderTest, AlternatingHuffmanNonHuffman) {
}
TEST_P(QpackDecoderTest, HuffmanNameDoesNotHaveEOSPrefix) {
- EXPECT_CALL(handler_, OnDecodingErrorDetected(QuicStringPiece(
+ EXPECT_CALL(handler_, OnDecodingErrorDetected(quiche::QuicheStringPiece(
"Error in Huffman-encoded string.")));
// 'y' ends in 0b0 on the most significant bit of the last byte.
// The remaining 7 bits must be a prefix of EOS, which is all 1s.
- DecodeHeaderBlock(
- QuicTextUtils::HexDecode("00002f0125a849e95ba97d7e8925a849e95bb8e8b4bf"));
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
+ "00002f0125a849e95ba97d7e8925a849e95bb8e8b4bf"));
}
TEST_P(QpackDecoderTest, HuffmanValueDoesNotHaveEOSPrefix) {
- EXPECT_CALL(handler_, OnDecodingErrorDetected(QuicStringPiece(
+ EXPECT_CALL(handler_, OnDecodingErrorDetected(quiche::QuicheStringPiece(
"Error in Huffman-encoded string.")));
// 'e' ends in 0b101, taking up the 3 most significant bits of the last byte.
// The remaining 5 bits must be a prefix of EOS, which is all 1s.
- DecodeHeaderBlock(
- QuicTextUtils::HexDecode("00002f0125a849e95ba97d7f8925a849e95bb8e8b4be"));
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
+ "00002f0125a849e95ba97d7f8925a849e95bb8e8b4be"));
}
TEST_P(QpackDecoderTest, HuffmanNameEOSPrefixTooLong) {
- EXPECT_CALL(handler_, OnDecodingErrorDetected(QuicStringPiece(
+ EXPECT_CALL(handler_, OnDecodingErrorDetected(quiche::QuicheStringPiece(
"Error in Huffman-encoded string.")));
// The trailing EOS prefix must be at most 7 bits long. Appending one octet
// with value 0xff is invalid, even though 0b111111111111111 (15 bits) is a
// prefix of EOS.
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"00002f0225a849e95ba97d7fff8925a849e95bb8e8b4bf"));
}
TEST_P(QpackDecoderTest, HuffmanValueEOSPrefixTooLong) {
- EXPECT_CALL(handler_, OnDecodingErrorDetected(QuicStringPiece(
+ EXPECT_CALL(handler_, OnDecodingErrorDetected(quiche::QuicheStringPiece(
"Error in Huffman-encoded string.")));
// The trailing EOS prefix must be at most 7 bits long. Appending one octet
// with value 0xff is invalid, even though 0b1111111111111 (13 bits) is a
// prefix of EOS.
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"00002f0125a849e95ba97d7f8a25a849e95bb8e8b4bfff"));
}
@@ -308,7 +313,7 @@ TEST_P(QpackDecoderTest, StaticTable) {
EXPECT_CALL(handler_, OnDecodingCompleted());
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0000d1dfccd45f108621e9aec2a11f5c8294e75f000554524143455f1000"));
}
@@ -321,11 +326,11 @@ TEST_P(QpackDecoderTest, TooHighStaticTableIndex) {
EXPECT_CALL(handler_,
OnDecodingErrorDetected(Eq("Static table entry not found.")));
- DecodeHeaderBlock(QuicTextUtils::HexDecode("0000ff23ff24"));
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode("0000ff23ff24"));
}
TEST_P(QpackDecoderTest, DynamicTable) {
- DecodeEncoderStreamData(QuicTextUtils::HexDecode(
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode(
"3fe107" // Set dynamic table capacity to 1024.
"6294e703626172" // Add literal entry with name "foo" and value "bar".
"80035a5a5a" // Add entry with name of dynamic table entry index 0
@@ -354,7 +359,7 @@ TEST_P(QpackDecoderTest, DynamicTable) {
.InSequence(s);
EXPECT_CALL(handler_, OnDecodingCompleted()).InSequence(s);
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0500" // Required Insert Count 4 and Delta Base 0.
// Base is 4 + 0 = 4.
"83" // Dynamic table entry with relative index 3, absolute index 0.
@@ -375,7 +380,7 @@ TEST_P(QpackDecoderTest, DynamicTable) {
.InSequence(s);
EXPECT_CALL(handler_, OnDecodingCompleted()).InSequence(s);
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0502" // Required Insert Count 4 and Delta Base 2.
// Base is 4 + 2 = 6.
"85" // Dynamic table entry with relative index 5, absolute index 0.
@@ -396,7 +401,7 @@ TEST_P(QpackDecoderTest, DynamicTable) {
.InSequence(s);
EXPECT_CALL(handler_, OnDecodingCompleted()).InSequence(s);
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0582" // Required Insert Count 4 and Delta Base 2 with sign bit set.
// Base is 4 - 2 - 1 = 1.
"80" // Dynamic table entry with relative index 0, absolute index 0.
@@ -409,28 +414,28 @@ TEST_P(QpackDecoderTest, DynamicTable) {
TEST_P(QpackDecoderTest, DecreasingDynamicTableCapacityEvictsEntries) {
// Set dynamic table capacity to 1024.
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fe107"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("3fe107"));
// Add literal entry with name "foo" and value "bar".
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("6294e703626172"));
EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
EXPECT_CALL(handler_, OnDecodingCompleted());
EXPECT_CALL(decoder_stream_sender_delegate_,
WriteStreamData(Eq(kHeaderAcknowledgement)));
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0200" // Required Insert Count 1 and Delta Base 0.
// Base is 1 + 0 = 1.
"80")); // Dynamic table entry with relative index 0, absolute index 0.
// Change dynamic table capacity to 32 bytes, smaller than the entry.
// This must cause the entry to be evicted.
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("3f01"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("3f01"));
EXPECT_CALL(handler_, OnDecodingErrorDetected(
Eq("Dynamic table entry already evicted.")));
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0200" // Required Insert Count 1 and Delta Base 0.
// Base is 1 + 0 = 1.
"80")); // Dynamic table entry with relative index 0, absolute index 0.
@@ -441,9 +446,9 @@ TEST_P(QpackDecoderTest, EncoderStreamErrorEntryTooLarge) {
OnEncoderStreamError(Eq("Error inserting literal entry.")));
// Set dynamic table capacity to 34.
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("3f03"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("3f03"));
// Add literal entry with name "foo" and value "bar", size is 32 + 3 + 3 = 38.
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("6294e703626172"));
}
TEST_P(QpackDecoderTest, EncoderStreamErrorInvalidStaticTableEntry) {
@@ -451,14 +456,14 @@ TEST_P(QpackDecoderTest, EncoderStreamErrorInvalidStaticTableEntry) {
OnEncoderStreamError(Eq("Invalid static table entry.")));
// Address invalid static table entry index 99.
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("ff2400"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("ff2400"));
}
TEST_P(QpackDecoderTest, EncoderStreamErrorInvalidDynamicTableEntry) {
EXPECT_CALL(encoder_stream_error_delegate_,
OnEncoderStreamError(Eq("Invalid relative index.")));
- DecodeEncoderStreamData(QuicTextUtils::HexDecode(
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode(
"3fe107" // Set dynamic table capacity to 1024.
"6294e703626172" // Add literal entry with name "foo" and value "bar".
"8100")); // Address dynamic table entry with relative index 1. Such
@@ -470,7 +475,7 @@ TEST_P(QpackDecoderTest, EncoderStreamErrorDuplicateInvalidEntry) {
EXPECT_CALL(encoder_stream_error_delegate_,
OnEncoderStreamError(Eq("Invalid relative index.")));
- DecodeEncoderStreamData(QuicTextUtils::HexDecode(
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode(
"3fe107" // Set dynamic table capacity to 1024.
"6294e703626172" // Add literal entry with name "foo" and value "bar".
"01")); // Duplicate dynamic table entry with relative index 1. Such
@@ -482,18 +487,19 @@ TEST_P(QpackDecoderTest, EncoderStreamErrorTooLargeInteger) {
EXPECT_CALL(encoder_stream_error_delegate_,
OnEncoderStreamError(Eq("Encoded integer too large.")));
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fffffffffffffffffffff"));
+ DecodeEncoderStreamData(
+ quiche::QuicheTextUtils::HexDecode("3fffffffffffffffffffff"));
}
TEST_P(QpackDecoderTest, InvalidDynamicEntryWhenBaseIsZero) {
EXPECT_CALL(handler_, OnDecodingErrorDetected(Eq("Invalid relative index.")));
// Set dynamic table capacity to 1024.
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fe107"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("3fe107"));
// Add literal entry with name "foo" and value "bar".
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("6294e703626172"));
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0280" // Required Insert Count is 1. Base 1 - 1 - 0 = 0 is explicitly
// permitted by the spec.
"80")); // However, addressing entry with relative index 0 would point to
@@ -505,18 +511,18 @@ TEST_P(QpackDecoderTest, InvalidNegativeBase) {
// Required Insert Count 1, Delta Base 1 with sign bit set, Base would
// be 1 - 1 - 1 = -1, but it is not allowed to be negative.
- DecodeHeaderBlock(QuicTextUtils::HexDecode("0281"));
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode("0281"));
}
TEST_P(QpackDecoderTest, InvalidDynamicEntryByRelativeIndex) {
// Set dynamic table capacity to 1024.
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fe107"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("3fe107"));
// Add literal entry with name "foo" and value "bar".
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("6294e703626172"));
EXPECT_CALL(handler_, OnDecodingErrorDetected(Eq("Invalid relative index.")));
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0200" // Required Insert Count 1 and Delta Base 0.
// Base is 1 + 0 = 1.
"81")); // Indexed Header Field instruction addressing relative index 1.
@@ -524,7 +530,7 @@ TEST_P(QpackDecoderTest, InvalidDynamicEntryByRelativeIndex) {
EXPECT_CALL(handler_, OnDecodingErrorDetected(Eq("Invalid relative index.")));
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0200" // Required Insert Count 1 and Delta Base 0.
// Base is 1 + 0 = 1.
"4100")); // Literal Header Field with Name Reference instruction
@@ -534,18 +540,18 @@ TEST_P(QpackDecoderTest, InvalidDynamicEntryByRelativeIndex) {
TEST_P(QpackDecoderTest, EvictedDynamicTableEntry) {
// Update dynamic table capacity to 128.
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("3f61"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("3f61"));
// Add literal entry with name "foo" and value "bar", size 32 + 3 + 3 = 38.
// This fits in the table three times.
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("6294e703626172"));
// Duplicate entry four times. This evicts the first two instances.
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("00000000"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("00000000"));
EXPECT_CALL(handler_, OnDecodingErrorDetected(
Eq("Dynamic table entry already evicted.")));
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0500" // Required Insert Count 4 and Delta Base 0.
// Base is 4 + 0 = 4.
"82")); // Indexed Header Field instruction addressing relative index 2.
@@ -554,7 +560,7 @@ TEST_P(QpackDecoderTest, EvictedDynamicTableEntry) {
EXPECT_CALL(handler_, OnDecodingErrorDetected(
Eq("Dynamic table entry already evicted.")));
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0500" // Required Insert Count 4 and Delta Base 0.
// Base is 4 + 0 = 4.
"4200")); // Literal Header Field with Name Reference instruction
@@ -564,7 +570,7 @@ TEST_P(QpackDecoderTest, EvictedDynamicTableEntry) {
EXPECT_CALL(handler_, OnDecodingErrorDetected(
Eq("Dynamic table entry already evicted.")));
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0380" // Required Insert Count 2 and Delta Base 0 with sign bit set.
// Base is 2 - 0 - 1 = 1
"10")); // Indexed Header Field instruction addressing dynamic table
@@ -574,7 +580,7 @@ TEST_P(QpackDecoderTest, EvictedDynamicTableEntry) {
EXPECT_CALL(handler_, OnDecodingErrorDetected(
Eq("Dynamic table entry already evicted.")));
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0380" // Required Insert Count 2 and Delta Base 0 with sign bit set.
// Base is 2 - 0 - 1 = 1
"0000")); // Literal Header Field With Name Reference instruction
@@ -588,12 +594,12 @@ TEST_P(QpackDecoderTest, TableCapacityMustNotExceedMaximum) {
OnEncoderStreamError(Eq("Error updating dynamic table capacity.")));
// Try to update dynamic table capacity to 2048, which exceeds the maximum.
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fe10f"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("3fe10f"));
}
TEST_P(QpackDecoderTest, SetDynamicTableCapacity) {
// Update dynamic table capacity to 128, which does not exceed the maximum.
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("3f61"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("3f61"));
}
TEST_P(QpackDecoderTest, InvalidEncodedRequiredInsertCount) {
@@ -603,7 +609,7 @@ TEST_P(QpackDecoderTest, InvalidEncodedRequiredInsertCount) {
// A value of 1 cannot be encoded as 65 even though it has the same remainder.
EXPECT_CALL(handler_, OnDecodingErrorDetected(
Eq("Error decoding Required Insert Count.")));
- DecodeHeaderBlock(QuicTextUtils::HexDecode("4100"));
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode("4100"));
}
// Regression test for https://crbug.com/970218: Decoder must stop processing
@@ -612,7 +618,7 @@ TEST_P(QpackDecoderTest, DataAfterInvalidEncodedRequiredInsertCount) {
EXPECT_CALL(handler_, OnDecodingErrorDetected(
Eq("Error decoding Required Insert Count.")));
// Header Block Prefix followed by some extra data.
- DecodeHeaderBlock(QuicTextUtils::HexDecode("410000"));
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode("410000"));
}
TEST_P(QpackDecoderTest, WrappedRequiredInsertCount) {
@@ -620,12 +626,12 @@ TEST_P(QpackDecoderTest, WrappedRequiredInsertCount) {
// MaxEntries is 1024 / 32 = 32.
// Set dynamic table capacity to 1024.
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fe107"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("3fe107"));
// Add literal entry with name "foo" and a 600 byte long value. This will fit
// in the dynamic table once but not twice.
DecodeEncoderStreamData(
- QuicTextUtils::HexDecode("6294e7" // Name "foo".
- "7fd903")); // Value length 600.
+ quiche::QuicheTextUtils::HexDecode("6294e7" // Name "foo".
+ "7fd903")); // Value length 600.
std::string header_value(600, 'Z');
DecodeEncoderStreamData(header_value);
@@ -640,7 +646,7 @@ TEST_P(QpackDecoderTest, WrappedRequiredInsertCount) {
WriteStreamData(Eq(kHeaderAcknowledgement)));
// Send header block with Required Insert Count = 201.
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0a00" // Encoded Required Insert Count 10, Required Insert Count 201,
// Delta Base 0, Base 201.
"80")); // Emit dynamic table entry with relative index 0.
@@ -648,31 +654,31 @@ TEST_P(QpackDecoderTest, WrappedRequiredInsertCount) {
TEST_P(QpackDecoderTest, NonZeroRequiredInsertCountButNoDynamicEntries) {
// Set dynamic table capacity to 1024.
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fe107"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("3fe107"));
// Add literal entry with name "foo" and value "bar".
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("6294e703626172"));
EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("GET")));
EXPECT_CALL(handler_,
OnDecodingErrorDetected(Eq("Required Insert Count too large.")));
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0200" // Required Insert Count is 1.
"d1")); // But the only instruction references the static table.
}
TEST_P(QpackDecoderTest, AddressEntryNotAllowedByRequiredInsertCount) {
// Set dynamic table capacity to 1024.
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fe107"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("3fe107"));
// Add literal entry with name "foo" and value "bar".
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("6294e703626172"));
EXPECT_CALL(
handler_,
OnDecodingErrorDetected(
Eq("Absolute Index must be smaller than Required Insert Count.")));
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0201" // Required Insert Count 1 and Delta Base 1.
// Base is 1 + 1 = 2.
"80")); // Indexed Header Field instruction addressing dynamic table
@@ -684,7 +690,7 @@ TEST_P(QpackDecoderTest, AddressEntryNotAllowedByRequiredInsertCount) {
OnDecodingErrorDetected(
Eq("Absolute Index must be smaller than Required Insert Count.")));
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0201" // Required Insert Count 1 and Delta Base 1.
// Base is 1 + 1 = 2.
"4000")); // Literal Header Field with Name Reference instruction
@@ -697,7 +703,7 @@ TEST_P(QpackDecoderTest, AddressEntryNotAllowedByRequiredInsertCount) {
OnDecodingErrorDetected(
Eq("Absolute Index must be smaller than Required Insert Count.")));
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0200" // Required Insert Count 1 and Delta Base 0.
// Base is 1 + 0 = 1.
"10")); // Indexed Header Field with Post-Base Index instruction
@@ -710,7 +716,7 @@ TEST_P(QpackDecoderTest, AddressEntryNotAllowedByRequiredInsertCount) {
OnDecodingErrorDetected(
Eq("Absolute Index must be smaller than Required Insert Count.")));
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0200" // Required Insert Count 1 and Delta Base 0.
// Base is 1 + 0 = 1.
"0000")); // Literal Header Field with Post-Base Name Reference
@@ -721,19 +727,19 @@ TEST_P(QpackDecoderTest, AddressEntryNotAllowedByRequiredInsertCount) {
TEST_P(QpackDecoderTest, PromisedRequiredInsertCountLargerThanActual) {
// Set dynamic table capacity to 1024.
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fe107"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("3fe107"));
// Add literal entry with name "foo" and value "bar".
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("6294e703626172"));
// Duplicate entry twice so that decoding of header blocks with Required
// Insert Count not exceeding 3 is not blocked.
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("00"));
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("00"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("00"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("00"));
EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
EXPECT_CALL(handler_,
OnDecodingErrorDetected(Eq("Required Insert Count too large.")));
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0300" // Required Insert Count 2 and Delta Base 0.
// Base is 2 + 0 = 2.
"81")); // Indexed Header Field instruction addressing dynamic table
@@ -745,7 +751,7 @@ TEST_P(QpackDecoderTest, PromisedRequiredInsertCountLargerThanActual) {
EXPECT_CALL(handler_,
OnDecodingErrorDetected(Eq("Required Insert Count too large.")));
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0300" // Required Insert Count 2 and Delta Base 0.
// Base is 2 + 0 = 2.
"4100")); // Literal Header Field with Name Reference instruction
@@ -757,7 +763,7 @@ TEST_P(QpackDecoderTest, PromisedRequiredInsertCountLargerThanActual) {
EXPECT_CALL(handler_,
OnDecodingErrorDetected(Eq("Required Insert Count too large.")));
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0481" // Required Insert Count 3 and Delta Base 1 with sign bit set.
// Base is 3 - 1 - 1 = 1.
"10")); // Indexed Header Field with Post-Base Index instruction
@@ -769,7 +775,7 @@ TEST_P(QpackDecoderTest, PromisedRequiredInsertCountLargerThanActual) {
EXPECT_CALL(handler_,
OnDecodingErrorDetected(Eq("Required Insert Count too large.")));
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0481" // Required Insert Count 3 and Delta Base 1 with sign bit set.
// Base is 3 - 1 - 1 = 1.
"0000")); // Literal Header Field with Post-Base Name Reference
@@ -779,7 +785,7 @@ TEST_P(QpackDecoderTest, PromisedRequiredInsertCountLargerThanActual) {
}
TEST_P(QpackDecoderTest, BlockedDecoding) {
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0200" // Required Insert Count 1 and Delta Base 0.
// Base is 1 + 0 = 1.
"80")); // Indexed Header Field instruction addressing dynamic table
@@ -791,14 +797,14 @@ TEST_P(QpackDecoderTest, BlockedDecoding) {
WriteStreamData(Eq(kHeaderAcknowledgement)));
// Set dynamic table capacity to 1024.
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fe107"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("3fe107"));
// Add literal entry with name "foo" and value "bar".
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("6294e703626172"));
}
TEST_P(QpackDecoderTest, BlockedDecodingUnblockedBeforeEndOfHeaderBlock) {
StartDecoding();
- DecodeData(QuicTextUtils::HexDecode(
+ DecodeData(quiche::QuicheTextUtils::HexDecode(
"0200" // Required Insert Count 1 and Delta Base 0.
// Base is 1 + 0 = 1.
"80" // Indexed Header Field instruction addressing dynamic table
@@ -806,7 +812,7 @@ TEST_P(QpackDecoderTest, BlockedDecodingUnblockedBeforeEndOfHeaderBlock) {
"d1")); // Static table entry with index 17.
// Set dynamic table capacity to 1024.
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fe107"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("3fe107"));
// Add literal entry with name "foo" and value "bar". Decoding is now
// unblocked because dynamic table Insert Count reached the Required Insert
@@ -814,14 +820,14 @@ TEST_P(QpackDecoderTest, BlockedDecodingUnblockedBeforeEndOfHeaderBlock) {
// the already consumed part of the header block.
EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("GET")));
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("6294e703626172"));
Mock::VerifyAndClearExpectations(&handler_);
// Rest of header block is processed by QpackProgressiveDecoder
// in the unblocked state.
EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":scheme"), Eq("https")));
- DecodeData(QuicTextUtils::HexDecode(
+ DecodeData(quiche::QuicheTextUtils::HexDecode(
"80" // Indexed Header Field instruction addressing dynamic table
// entry with relative index 0, absolute index 0.
"d7")); // Static table entry with index 23.
@@ -837,7 +843,7 @@ TEST_P(QpackDecoderTest, BlockedDecodingUnblockedBeforeEndOfHeaderBlock) {
TEST_P(QpackDecoderTest,
BlockedDecodingUnblockedAndErrorBeforeEndOfHeaderBlock) {
StartDecoding();
- DecodeData(QuicTextUtils::HexDecode(
+ DecodeData(quiche::QuicheTextUtils::HexDecode(
"0200" // Required Insert Count 1 and Delta Base 0.
// Base is 1 + 0 = 1.
"80" // Indexed Header Field instruction addressing dynamic table
@@ -845,7 +851,7 @@ TEST_P(QpackDecoderTest,
"81")); // Relative index 1 is equal to Base, therefore invalid.
// Set dynamic table capacity to 1024.
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fe107"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("3fe107"));
// Add literal entry with name "foo" and value "bar". Decoding is now
// unblocked because dynamic table Insert Count reached the Required Insert
@@ -853,7 +859,7 @@ TEST_P(QpackDecoderTest,
// the already consumed part of the header block.
EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
EXPECT_CALL(handler_, OnDecodingErrorDetected(Eq("Invalid relative index.")));
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("6294e703626172"));
}
// Make sure that Required Insert Count is compared to Insert Count,
@@ -861,19 +867,19 @@ TEST_P(QpackDecoderTest,
TEST_P(QpackDecoderTest, BlockedDecodingAndEvictedEntries) {
// Update dynamic table capacity to 128.
// At most three non-empty entries fit in the dynamic table.
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("3f61"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("3f61"));
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0700" // Required Insert Count 6 and Delta Base 0.
// Base is 6 + 0 = 6.
"80")); // Indexed Header Field instruction addressing dynamic table
// entry with relative index 0, absolute index 5.
// Add literal entry with name "foo" and value "bar".
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("6294e703626172"));
// Duplicate entry four times. This evicts the first two instances.
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("00000000"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("00000000"));
EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("baz")));
EXPECT_CALL(handler_, OnDecodingCompleted());
@@ -882,13 +888,13 @@ TEST_P(QpackDecoderTest, BlockedDecodingAndEvictedEntries) {
// Add literal entry with name "foo" and value "bar".
// Insert Count is now 6, reaching Required Insert Count of the header block.
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e70362617a"));
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode("6294e70362617a"));
}
TEST_P(QpackDecoderTest, TooManyBlockedStreams) {
// Required Insert Count 1 and Delta Base 0.
// Without any dynamic table entries received, decoding is blocked.
- std::string data = QuicTextUtils::HexDecode("0200");
+ std::string data = quiche::QuicheTextUtils::HexDecode("0200");
auto progressive_decoder1 = CreateProgressiveDecoder(/* stream_id = */ 1);
progressive_decoder1->Decode(data);
@@ -901,7 +907,7 @@ TEST_P(QpackDecoderTest, TooManyBlockedStreams) {
}
TEST_P(QpackDecoderTest, InsertCountIncrement) {
- DecodeEncoderStreamData(QuicTextUtils::HexDecode(
+ DecodeEncoderStreamData(quiche::QuicheTextUtils::HexDecode(
"3fe107" // Set dynamic table capacity to 1024.
"6294e703626172" // Add literal entry with name "foo" and value "bar".
"00")); // Duplicate entry.
@@ -913,11 +919,11 @@ TEST_P(QpackDecoderTest, InsertCountIncrement) {
// Known Insert Count to one. Decoder should send an Insert Count Increment
// instruction with increment of one to update Known Insert Count to two.
EXPECT_CALL(decoder_stream_sender_delegate_,
- WriteStreamData(Eq(QuicTextUtils::HexDecode(
+ WriteStreamData(Eq(quiche::QuicheTextUtils::HexDecode(
"81" // Header Acknowledgement on stream 1
"01")))); // Insert Count Increment with increment of one
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
+ DecodeHeaderBlock(quiche::QuicheTextUtils::HexDecode(
"0200" // Required Insert Count 1 and Delta Base 0.
// Base is 1 + 0 = 1.
"80")); // Dynamic table entry with relative index 0, absolute index 0.
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder.cc
index 59e172ec75a..2b30e982ea7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder.cc
@@ -12,7 +12,8 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_required_insert_count.h"
#include "net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -57,7 +58,7 @@ QpackInstructionWithValues
QpackEncoder::EncodeLiteralHeaderFieldWithNameReference(
bool is_static,
uint64_t index,
- QuicStringPiece value,
+ quiche::QuicheStringPiece value,
QpackBlockingManager::IndexSet* referred_indices) {
// Add |index| to |*referred_indices| only if entry is in the dynamic table.
if (!is_static) {
@@ -69,8 +70,8 @@ QpackEncoder::EncodeLiteralHeaderFieldWithNameReference(
// static
QpackInstructionWithValues QpackEncoder::EncodeLiteralHeaderField(
- QuicStringPiece name,
- QuicStringPiece value) {
+ quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value) {
return QpackInstructionWithValues::LiteralHeaderField(name, value);
}
@@ -104,8 +105,8 @@ QpackEncoder::Instructions QpackEncoder::FirstPassEncode(
for (const auto& header : ValueSplittingHeaderList(&header_list)) {
// These strings are owned by |header_list|.
- QuicStringPiece name = header.first;
- QuicStringPiece value = header.second;
+ quiche::QuicheStringPiece name = header.first;
+ quiche::QuicheStringPiece value = header.second;
bool is_static;
uint64_t index;
@@ -397,7 +398,7 @@ void QpackEncoder::OnInsertCountIncrement(uint64_t increment) {
if (blocking_manager_.known_received_count() >
header_table_.inserted_entry_count()) {
- decoder_stream_error_delegate_->OnDecoderStreamError(QuicStrCat(
+ decoder_stream_error_delegate_->OnDecoderStreamError(quiche::QuicheStrCat(
"Increment value ", increment, " raises known received count to ",
blocking_manager_.known_received_count(),
" exceeding inserted entry count ",
@@ -408,8 +409,8 @@ void QpackEncoder::OnInsertCountIncrement(uint64_t increment) {
void QpackEncoder::OnHeaderAcknowledgement(QuicStreamId stream_id) {
if (!blocking_manager_.OnHeaderAcknowledgement(stream_id)) {
decoder_stream_error_delegate_->OnDecoderStreamError(
- QuicStrCat("Header Acknowledgement received for stream ", stream_id,
- " with no outstanding header blocks."));
+ quiche::QuicheStrCat("Header Acknowledgement received for stream ",
+ stream_id, " with no outstanding header blocks."));
}
}
@@ -417,7 +418,7 @@ void QpackEncoder::OnStreamCancellation(QuicStreamId stream_id) {
blocking_manager_.OnStreamCancellation(stream_id);
}
-void QpackEncoder::OnErrorDetected(QuicStringPiece error_message) {
+void QpackEncoder::OnErrorDetected(quiche::QuicheStringPiece error_message) {
decoder_stream_error_delegate_->OnDecoderStreamError(error_message);
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder.h
index e635e3bf04b..0f1d14ca539 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder.h
@@ -18,7 +18,7 @@
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_exported_stats.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace spdy {
@@ -45,7 +45,8 @@ class QUIC_EXPORT_PRIVATE QpackEncoder
public:
virtual ~DecoderStreamErrorDelegate() {}
- virtual void OnDecoderStreamError(QuicStringPiece error_message) = 0;
+ virtual void OnDecoderStreamError(
+ quiche::QuicheStringPiece error_message) = 0;
};
QpackEncoder(DecoderStreamErrorDelegate* decoder_stream_error_delegate);
@@ -77,7 +78,7 @@ class QUIC_EXPORT_PRIVATE QpackEncoder
void OnInsertCountIncrement(uint64_t increment) override;
void OnHeaderAcknowledgement(QuicStreamId stream_id) override;
void OnStreamCancellation(QuicStreamId stream_id) override;
- void OnErrorDetected(QuicStringPiece error_message) override;
+ void OnErrorDetected(quiche::QuicheStringPiece error_message) override;
// delegate must be set if dynamic table capacity is not zero.
void set_qpack_stream_sender_delegate(QpackStreamSenderDelegate* delegate) {
@@ -110,13 +111,13 @@ class QUIC_EXPORT_PRIVATE QpackEncoder
static QpackInstructionWithValues EncodeLiteralHeaderFieldWithNameReference(
bool is_static,
uint64_t index,
- QuicStringPiece value,
+ quiche::QuicheStringPiece value,
QpackBlockingManager::IndexSet* referred_indices);
// Generate literal header field instruction.
static QpackInstructionWithValues EncodeLiteralHeaderField(
- QuicStringPiece name,
- QuicStringPiece value);
+ quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value);
// Performs first pass of two-pass encoding: represent each header field in
// |*header_list| as a reference to an existing entry, the name of an existing
@@ -127,8 +128,8 @@ class QUIC_EXPORT_PRIVATE QpackEncoder
// sets |*encoder_stream_sent_byte_count| to the number of bytes sent on the
// encoder stream to insert dynamic table entries. Returns list of header
// field representations, with all dynamic table entries referred to with
- // absolute indices. Returned Instructions object may have QuicStringPieces
- // pointing to strings owned by |*header_list|.
+ // absolute indices. Returned Instructions object may have
+ // quiche::QuicheStringPieces pointing to strings owned by |*header_list|.
Instructions FirstPassEncode(QuicStreamId stream_id,
const spdy::SpdyHeaderBlock& header_list,
QpackBlockingManager::IndexSet* referred_indices,
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver.cc
index c46cc3c0f41..56ee23241db 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver.cc
@@ -7,6 +7,7 @@
#include "net/third_party/quiche/src/http2/decoder/decode_buffer.h"
#include "net/third_party/quiche/src/http2/decoder/decode_status.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -17,7 +18,7 @@ QpackEncoderStreamReceiver::QpackEncoderStreamReceiver(Delegate* delegate)
DCHECK(delegate_);
}
-void QpackEncoderStreamReceiver::Decode(QuicStringPiece data) {
+void QpackEncoderStreamReceiver::Decode(quiche::QuicheStringPiece data) {
if (data.empty() || error_detected_) {
return;
}
@@ -50,7 +51,8 @@ bool QpackEncoderStreamReceiver::OnInstructionDecoded(
return true;
}
-void QpackEncoderStreamReceiver::OnError(QuicStringPiece error_message) {
+void QpackEncoderStreamReceiver::OnError(
+ quiche::QuicheStringPiece error_message) {
DCHECK(!error_detected_);
error_detected_ = true;
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver.h
index b393b546b60..80622e5460d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver.h
@@ -11,7 +11,7 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_stream_receiver.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -29,16 +29,17 @@ class QUIC_EXPORT_PRIVATE QpackEncoderStreamReceiver
// 5.2.1. Insert With Name Reference
virtual void OnInsertWithNameReference(bool is_static,
uint64_t name_index,
- QuicStringPiece value) = 0;
+ quiche::QuicheStringPiece value) = 0;
// 5.2.2. Insert Without Name Reference
- virtual void OnInsertWithoutNameReference(QuicStringPiece name,
- QuicStringPiece value) = 0;
+ virtual void OnInsertWithoutNameReference(
+ quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value) = 0;
// 5.2.3. Duplicate
virtual void OnDuplicate(uint64_t index) = 0;
// 5.2.4. Set Dynamic Table Capacity
virtual void OnSetDynamicTableCapacity(uint64_t capacity) = 0;
// Decoding error
- virtual void OnErrorDetected(QuicStringPiece error_message) = 0;
+ virtual void OnErrorDetected(quiche::QuicheStringPiece error_message) = 0;
};
explicit QpackEncoderStreamReceiver(Delegate* delegate);
@@ -52,11 +53,11 @@ class QUIC_EXPORT_PRIVATE QpackEncoderStreamReceiver
// Decode data and call appropriate Delegate method after each decoded
// instruction. Once an error occurs, Delegate::OnErrorDetected() is called,
// and all further data is ignored.
- void Decode(QuicStringPiece data) override;
+ void Decode(quiche::QuicheStringPiece data) override;
// QpackInstructionDecoder::Delegate implementation.
bool OnInstructionDecoded(const QpackInstruction* instruction) override;
- void OnError(QuicStringPiece error_message) override;
+ void OnError(quiche::QuicheStringPiece error_message) override;
private:
QpackInstructionDecoder instruction_decoder_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver_test.cc
index f0123902979..b5edd5f1472 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver_test.cc
@@ -5,7 +5,8 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
using testing::Eq;
using testing::StrictMock;
@@ -21,12 +22,13 @@ class MockDelegate : public QpackEncoderStreamReceiver::Delegate {
MOCK_METHOD3(OnInsertWithNameReference,
void(bool is_static,
uint64_t name_index,
- QuicStringPiece value));
+ quiche::QuicheStringPiece value));
MOCK_METHOD2(OnInsertWithoutNameReference,
- void(QuicStringPiece name, QuicStringPiece value));
+ void(quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value));
MOCK_METHOD1(OnDuplicate, void(uint64_t index));
MOCK_METHOD1(OnSetDynamicTableCapacity, void(uint64_t capacity));
- MOCK_METHOD1(OnErrorDetected, void(QuicStringPiece error_message));
+ MOCK_METHOD1(OnErrorDetected, void(quiche::QuicheStringPiece error_message));
};
class QpackEncoderStreamReceiverTest : public QuicTest {
@@ -34,7 +36,7 @@ class QpackEncoderStreamReceiverTest : public QuicTest {
QpackEncoderStreamReceiverTest() : stream_(&delegate_) {}
~QpackEncoderStreamReceiverTest() override = default;
- void Decode(QuicStringPiece data) { stream_.Decode(data); }
+ void Decode(quiche::QuicheStringPiece data) { stream_.Decode(data); }
StrictMock<MockDelegate>* delegate() { return &delegate_; }
private:
@@ -54,7 +56,7 @@ TEST_F(QpackEncoderStreamReceiverTest, InsertWithNameReference) {
EXPECT_CALL(*delegate(),
OnInsertWithNameReference(false, 42, Eq(std::string(127, 'Z'))));
- Decode(QuicTextUtils::HexDecode(
+ Decode(quiche::QuicheTextUtils::HexDecode(
"c500"
"c28294e7"
"bf4a03626172"
@@ -67,13 +69,13 @@ TEST_F(QpackEncoderStreamReceiverTest, InsertWithNameReference) {
TEST_F(QpackEncoderStreamReceiverTest, InsertWithNameReferenceIndexTooLarge) {
EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large.")));
- Decode(QuicTextUtils::HexDecode("bfffffffffffffffffffffff"));
+ Decode(quiche::QuicheTextUtils::HexDecode("bfffffffffffffffffffffff"));
}
TEST_F(QpackEncoderStreamReceiverTest, InsertWithNameReferenceValueTooLong) {
EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large.")));
- Decode(QuicTextUtils::HexDecode("c57fffffffffffffffffffff"));
+ Decode(quiche::QuicheTextUtils::HexDecode("c57fffffffffffffffffffff"));
}
TEST_F(QpackEncoderStreamReceiverTest, InsertWithoutNameReference) {
@@ -89,7 +91,7 @@ TEST_F(QpackEncoderStreamReceiverTest, InsertWithoutNameReference) {
OnInsertWithoutNameReference(Eq(std::string(31, 'Z')),
Eq(std::string(127, 'Z'))));
- Decode(QuicTextUtils::HexDecode(
+ Decode(quiche::QuicheTextUtils::HexDecode(
"4000"
"4362617203626172"
"6294e78294e7"
@@ -105,7 +107,7 @@ TEST_F(QpackEncoderStreamReceiverTest,
InsertWithoutNameReferenceNameTooLongForVarintDecoder) {
EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large.")));
- Decode(QuicTextUtils::HexDecode("5fffffffffffffffffffff"));
+ Decode(quiche::QuicheTextUtils::HexDecode("5fffffffffffffffffffff"));
}
// Name Length value can be decoded by varint decoder but exceeds 1 MB limit.
@@ -113,7 +115,7 @@ TEST_F(QpackEncoderStreamReceiverTest,
InsertWithoutNameReferenceNameExceedsLimit) {
EXPECT_CALL(*delegate(), OnErrorDetected(Eq("String literal too long.")));
- Decode(QuicTextUtils::HexDecode("5fffff7f"));
+ Decode(quiche::QuicheTextUtils::HexDecode("5fffff7f"));
}
// Value Length value is too large for varint decoder to decode.
@@ -121,7 +123,7 @@ TEST_F(QpackEncoderStreamReceiverTest,
InsertWithoutNameReferenceValueTooLongForVarintDecoder) {
EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large.")));
- Decode(QuicTextUtils::HexDecode("436261727fffffffffffffffffffff"));
+ Decode(quiche::QuicheTextUtils::HexDecode("436261727fffffffffffffffffffff"));
}
// Value Length value can be decoded by varint decoder but exceeds 1 MB limit.
@@ -129,7 +131,7 @@ TEST_F(QpackEncoderStreamReceiverTest,
InsertWithoutNameReferenceValueExceedsLimit) {
EXPECT_CALL(*delegate(), OnErrorDetected(Eq("String literal too long.")));
- Decode(QuicTextUtils::HexDecode("436261727fffff7f"));
+ Decode(quiche::QuicheTextUtils::HexDecode("436261727fffff7f"));
}
TEST_F(QpackEncoderStreamReceiverTest, Duplicate) {
@@ -138,13 +140,13 @@ TEST_F(QpackEncoderStreamReceiverTest, Duplicate) {
// Large index requires two extension bytes.
EXPECT_CALL(*delegate(), OnDuplicate(500));
- Decode(QuicTextUtils::HexDecode("111fd503"));
+ Decode(quiche::QuicheTextUtils::HexDecode("111fd503"));
}
TEST_F(QpackEncoderStreamReceiverTest, DuplicateIndexTooLarge) {
EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large.")));
- Decode(QuicTextUtils::HexDecode("1fffffffffffffffffffff"));
+ Decode(quiche::QuicheTextUtils::HexDecode("1fffffffffffffffffffff"));
}
TEST_F(QpackEncoderStreamReceiverTest, SetDynamicTableCapacity) {
@@ -153,13 +155,13 @@ TEST_F(QpackEncoderStreamReceiverTest, SetDynamicTableCapacity) {
// Large capacity requires two extension bytes.
EXPECT_CALL(*delegate(), OnSetDynamicTableCapacity(500));
- Decode(QuicTextUtils::HexDecode("313fd503"));
+ Decode(quiche::QuicheTextUtils::HexDecode("313fd503"));
}
TEST_F(QpackEncoderStreamReceiverTest, SetDynamicTableCapacityTooLarge) {
EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large.")));
- Decode(QuicTextUtils::HexDecode("3fffffffffffffffffffff"));
+ Decode(quiche::QuicheTextUtils::HexDecode("3fffffffffffffffffffff"));
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.cc
index 5182864ce6d..19311b6aeb9 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.cc
@@ -10,6 +10,7 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -18,7 +19,7 @@ QpackEncoderStreamSender::QpackEncoderStreamSender() : delegate_(nullptr) {}
void QpackEncoderStreamSender::SendInsertWithNameReference(
bool is_static,
uint64_t name_index,
- QuicStringPiece value) {
+ quiche::QuicheStringPiece value) {
instruction_encoder_.Encode(
QpackInstructionWithValues::InsertWithNameReference(is_static, name_index,
value),
@@ -26,8 +27,8 @@ void QpackEncoderStreamSender::SendInsertWithNameReference(
}
void QpackEncoderStreamSender::SendInsertWithoutNameReference(
- QuicStringPiece name,
- QuicStringPiece value) {
+ quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value) {
instruction_encoder_.Encode(
QpackInstructionWithValues::InsertWithoutNameReference(name, value),
&buffer_);
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.h
index de9e8f14839..5701db54ffe 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.h
@@ -11,7 +11,7 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_stream_sender_delegate.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -29,10 +29,10 @@ class QUIC_EXPORT_PRIVATE QpackEncoderStreamSender {
// 5.2.1. Insert With Name Reference
void SendInsertWithNameReference(bool is_static,
uint64_t name_index,
- QuicStringPiece value);
+ quiche::QuicheStringPiece value);
// 5.2.2. Insert Without Name Reference
- void SendInsertWithoutNameReference(QuicStringPiece name,
- QuicStringPiece value);
+ void SendInsertWithoutNameReference(quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value);
// 5.2.3. Duplicate
void SendDuplicate(uint64_t index);
// 5.2.4. Set Dynamic Table Capacity
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender_test.cc
index 0a42df220cb..b3fd5f9de6a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender_test.cc
@@ -5,8 +5,8 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
using ::testing::Eq;
using ::testing::StrictMock;
@@ -28,26 +28,27 @@ class QpackEncoderStreamSenderTest : public QuicTest {
TEST_F(QpackEncoderStreamSenderTest, InsertWithNameReference) {
// Static, index fits in prefix, empty value.
- std::string expected_encoded_data = QuicTextUtils::HexDecode("c500");
+ std::string expected_encoded_data =
+ quiche::QuicheTextUtils::HexDecode("c500");
EXPECT_CALL(delegate_, WriteStreamData(Eq(expected_encoded_data)));
stream_.SendInsertWithNameReference(true, 5, "");
EXPECT_EQ(expected_encoded_data.size(), stream_.Flush());
// Static, index fits in prefix, Huffman encoded value.
- expected_encoded_data = QuicTextUtils::HexDecode("c28294e7");
+ expected_encoded_data = quiche::QuicheTextUtils::HexDecode("c28294e7");
EXPECT_CALL(delegate_, WriteStreamData(Eq(expected_encoded_data)));
stream_.SendInsertWithNameReference(true, 2, "foo");
EXPECT_EQ(expected_encoded_data.size(), stream_.Flush());
// Not static, index does not fit in prefix, not Huffman encoded value.
- expected_encoded_data = QuicTextUtils::HexDecode("bf4a03626172");
+ expected_encoded_data = quiche::QuicheTextUtils::HexDecode("bf4a03626172");
EXPECT_CALL(delegate_, WriteStreamData(Eq(expected_encoded_data)));
stream_.SendInsertWithNameReference(false, 137, "bar");
EXPECT_EQ(expected_encoded_data.size(), stream_.Flush());
// Value length does not fit in prefix.
// 'Z' would be Huffman encoded to 8 bits, so no Huffman encoding is used.
- expected_encoded_data = QuicTextUtils::HexDecode(
+ expected_encoded_data = quiche::QuicheTextUtils::HexDecode(
"aa7f005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
"5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
"5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
@@ -59,26 +60,28 @@ TEST_F(QpackEncoderStreamSenderTest, InsertWithNameReference) {
TEST_F(QpackEncoderStreamSenderTest, InsertWithoutNameReference) {
// Empty name and value.
- std::string expected_encoded_data = QuicTextUtils::HexDecode("4000");
+ std::string expected_encoded_data =
+ quiche::QuicheTextUtils::HexDecode("4000");
EXPECT_CALL(delegate_, WriteStreamData(Eq(expected_encoded_data)));
stream_.SendInsertWithoutNameReference("", "");
EXPECT_EQ(expected_encoded_data.size(), stream_.Flush());
// Huffman encoded short strings.
- expected_encoded_data = QuicTextUtils::HexDecode("6294e78294e7");
+ expected_encoded_data = quiche::QuicheTextUtils::HexDecode("6294e78294e7");
EXPECT_CALL(delegate_, WriteStreamData(Eq(expected_encoded_data)));
stream_.SendInsertWithoutNameReference("foo", "foo");
EXPECT_EQ(expected_encoded_data.size(), stream_.Flush());
// Not Huffman encoded short strings.
- expected_encoded_data = QuicTextUtils::HexDecode("4362617203626172");
+ expected_encoded_data =
+ quiche::QuicheTextUtils::HexDecode("4362617203626172");
EXPECT_CALL(delegate_, WriteStreamData(Eq(expected_encoded_data)));
stream_.SendInsertWithoutNameReference("bar", "bar");
EXPECT_EQ(expected_encoded_data.size(), stream_.Flush());
// Not Huffman encoded long strings; length does not fit on prefix.
// 'Z' would be Huffman encoded to 8 bits, so no Huffman encoding is used.
- expected_encoded_data = QuicTextUtils::HexDecode(
+ expected_encoded_data = quiche::QuicheTextUtils::HexDecode(
"5f005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a7f"
"005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
"5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
@@ -92,13 +95,13 @@ TEST_F(QpackEncoderStreamSenderTest, InsertWithoutNameReference) {
TEST_F(QpackEncoderStreamSenderTest, Duplicate) {
// Small index fits in prefix.
- std::string expected_encoded_data = QuicTextUtils::HexDecode("11");
+ std::string expected_encoded_data = quiche::QuicheTextUtils::HexDecode("11");
EXPECT_CALL(delegate_, WriteStreamData(Eq(expected_encoded_data)));
stream_.SendDuplicate(17);
EXPECT_EQ(expected_encoded_data.size(), stream_.Flush());
// Large index requires two extension bytes.
- expected_encoded_data = QuicTextUtils::HexDecode("1fd503");
+ expected_encoded_data = quiche::QuicheTextUtils::HexDecode("1fd503");
EXPECT_CALL(delegate_, WriteStreamData(Eq(expected_encoded_data)));
stream_.SendDuplicate(500);
EXPECT_EQ(expected_encoded_data.size(), stream_.Flush());
@@ -106,13 +109,13 @@ TEST_F(QpackEncoderStreamSenderTest, Duplicate) {
TEST_F(QpackEncoderStreamSenderTest, SetDynamicTableCapacity) {
// Small capacity fits in prefix.
- std::string expected_encoded_data = QuicTextUtils::HexDecode("31");
+ std::string expected_encoded_data = quiche::QuicheTextUtils::HexDecode("31");
EXPECT_CALL(delegate_, WriteStreamData(Eq(expected_encoded_data)));
stream_.SendSetDynamicTableCapacity(17);
EXPECT_EQ(expected_encoded_data.size(), stream_.Flush());
// Large capacity requires two extension bytes.
- expected_encoded_data = QuicTextUtils::HexDecode("3fd503");
+ expected_encoded_data = quiche::QuicheTextUtils::HexDecode("3fd503");
EXPECT_CALL(delegate_, WriteStreamData(Eq(expected_encoded_data)));
stream_.SendSetDynamicTableCapacity(500);
EXPECT_EQ(expected_encoded_data.size(), stream_.Flush());
@@ -132,7 +135,7 @@ TEST_F(QpackEncoderStreamSenderTest, Coalesce) {
// Duplicate entry.
stream_.SendDuplicate(17);
- std::string expected_encoded_data = QuicTextUtils::HexDecode(
+ std::string expected_encoded_data = quiche::QuicheTextUtils::HexDecode(
"c500" // Insert entry with static name reference.
"c28294e7" // Insert entry with static name reference.
"6294e78294e7" // Insert literal entry.
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test.cc
index 6b92e4bfc95..212257cedb6 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test.cc
@@ -8,11 +8,12 @@
#include <string>
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_header_table_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
using ::testing::_;
using ::testing::Eq;
@@ -48,7 +49,7 @@ TEST_F(QpackEncoderTest, Empty) {
spdy::SpdyHeaderBlock header_list;
std::string output = Encode(header_list);
- EXPECT_EQ(QuicTextUtils::HexDecode("0000"), output);
+ EXPECT_EQ(quiche::QuicheTextUtils::HexDecode("0000"), output);
}
TEST_F(QpackEncoderTest, EmptyName) {
@@ -56,7 +57,7 @@ TEST_F(QpackEncoderTest, EmptyName) {
header_list[""] = "foo";
std::string output = Encode(header_list);
- EXPECT_EQ(QuicTextUtils::HexDecode("0000208294e7"), output);
+ EXPECT_EQ(quiche::QuicheTextUtils::HexDecode("0000208294e7"), output);
}
TEST_F(QpackEncoderTest, EmptyValue) {
@@ -64,7 +65,7 @@ TEST_F(QpackEncoderTest, EmptyValue) {
header_list["foo"] = "";
std::string output = Encode(header_list);
- EXPECT_EQ(QuicTextUtils::HexDecode("00002a94e700"), output);
+ EXPECT_EQ(quiche::QuicheTextUtils::HexDecode("00002a94e700"), output);
}
TEST_F(QpackEncoderTest, EmptyNameAndValue) {
@@ -72,7 +73,7 @@ TEST_F(QpackEncoderTest, EmptyNameAndValue) {
header_list[""] = "";
std::string output = Encode(header_list);
- EXPECT_EQ(QuicTextUtils::HexDecode("00002000"), output);
+ EXPECT_EQ(quiche::QuicheTextUtils::HexDecode("00002000"), output);
}
TEST_F(QpackEncoderTest, Simple) {
@@ -80,7 +81,7 @@ TEST_F(QpackEncoderTest, Simple) {
header_list["foo"] = "bar";
std::string output = Encode(header_list);
- EXPECT_EQ(QuicTextUtils::HexDecode("00002a94e703626172"), output);
+ EXPECT_EQ(quiche::QuicheTextUtils::HexDecode("00002a94e703626172"), output);
}
TEST_F(QpackEncoderTest, Multiple) {
@@ -91,7 +92,7 @@ TEST_F(QpackEncoderTest, Multiple) {
std::string output = Encode(header_list);
EXPECT_EQ(
- QuicTextUtils::HexDecode(
+ quiche::QuicheTextUtils::HexDecode(
"0000" // prefix
"2a94e703626172" // foo: bar
"27005a5a5a5a5a5a5a" // 7 octet long header name, the smallest number
@@ -113,7 +114,7 @@ TEST_F(QpackEncoderTest, StaticTable) {
header_list["location"] = "";
std::string output = Encode(header_list);
- EXPECT_EQ(QuicTextUtils::HexDecode("0000d1dfcc"), output);
+ EXPECT_EQ(quiche::QuicheTextUtils::HexDecode("0000d1dfcc"), output);
}
{
spdy::SpdyHeaderBlock header_list;
@@ -122,8 +123,9 @@ TEST_F(QpackEncoderTest, StaticTable) {
header_list["location"] = "foo";
std::string output = Encode(header_list);
- EXPECT_EQ(QuicTextUtils::HexDecode("0000d45f108621e9aec2a11f5c8294e7"),
- output);
+ EXPECT_EQ(
+ quiche::QuicheTextUtils::HexDecode("0000d45f108621e9aec2a11f5c8294e7"),
+ output);
}
{
spdy::SpdyHeaderBlock header_list;
@@ -131,7 +133,8 @@ TEST_F(QpackEncoderTest, StaticTable) {
header_list["accept-encoding"] = "";
std::string output = Encode(header_list);
- EXPECT_EQ(QuicTextUtils::HexDecode("00005f000554524143455f1000"), output);
+ EXPECT_EQ(quiche::QuicheTextUtils::HexDecode("00005f000554524143455f1000"),
+ output);
}
}
@@ -142,19 +145,19 @@ TEST_F(QpackEncoderTest, DecoderStreamError) {
QpackEncoder encoder(&decoder_stream_error_delegate_);
encoder.set_qpack_stream_sender_delegate(&encoder_stream_sender_delegate_);
encoder.decoder_stream_receiver()->Decode(
- QuicTextUtils::HexDecode("ffffffffffffffffffffff"));
+ quiche::QuicheTextUtils::HexDecode("ffffffffffffffffffffff"));
}
TEST_F(QpackEncoderTest, SplitAlongNullCharacter) {
spdy::SpdyHeaderBlock header_list;
- header_list["foo"] = QuicStringPiece("bar\0bar\0baz", 11);
+ header_list["foo"] = quiche::QuicheStringPiece("bar\0bar\0baz", 11);
std::string output = Encode(header_list);
- EXPECT_EQ(QuicTextUtils::HexDecode("0000" // prefix
- "2a94e703626172" // foo: bar
- "2a94e703626172" // foo: bar
- "2a94e70362617a" // foo: baz
- ),
+ EXPECT_EQ(quiche::QuicheTextUtils::HexDecode("0000" // prefix
+ "2a94e703626172" // foo: bar
+ "2a94e703626172" // foo: bar
+ "2a94e70362617a" // foo: baz
+ ),
output);
}
@@ -212,8 +215,9 @@ TEST_F(QpackEncoderTest, DynamicTable) {
encoder_.SetMaximumDynamicTableCapacity(4096);
// Set Dynamic Table Capacity instruction.
- EXPECT_CALL(encoder_stream_sender_delegate_,
- WriteStreamData(Eq(QuicTextUtils::HexDecode("3fe11f"))));
+ EXPECT_CALL(
+ encoder_stream_sender_delegate_,
+ WriteStreamData(Eq(quiche::QuicheTextUtils::HexDecode("3fe11f"))));
encoder_.SetDynamicTableCapacity(4096);
spdy::SpdyHeaderBlock header_list;
@@ -223,7 +227,7 @@ TEST_F(QpackEncoderTest, DynamicTable) {
header_list["cookie"] = "baz"; // name matches static entry
// Insert three entries into the dynamic table.
- std::string insert_entries = QuicTextUtils::HexDecode(
+ std::string insert_entries = quiche::QuicheTextUtils::HexDecode(
"62" // insert without name reference
"94e7" // Huffman-encoded name "foo"
"03626172" // value "bar"
@@ -234,7 +238,7 @@ TEST_F(QpackEncoderTest, DynamicTable) {
EXPECT_CALL(encoder_stream_sender_delegate_,
WriteStreamData(Eq(insert_entries)));
- EXPECT_EQ(QuicTextUtils::HexDecode(
+ EXPECT_EQ(quiche::QuicheTextUtils::HexDecode(
"0400" // prefix
"828180"), // dynamic entries with relative index 0, 1, and 2
Encode(header_list));
@@ -249,7 +253,7 @@ TEST_F(QpackEncoderTest, SmallDynamicTable) {
// Set Dynamic Table Capacity instruction.
EXPECT_CALL(encoder_stream_sender_delegate_,
- WriteStreamData(Eq(QuicTextUtils::HexDecode("3f07"))));
+ WriteStreamData(Eq(quiche::QuicheTextUtils::HexDecode("3f07"))));
encoder_.SetDynamicTableCapacity(QpackEntry::Size("foo", "bar"));
spdy::SpdyHeaderBlock header_list;
@@ -260,21 +264,22 @@ TEST_F(QpackEncoderTest, SmallDynamicTable) {
header_list["bar"] = "baz"; // no match
// Insert one entry into the dynamic table.
- std::string insert_entry = QuicTextUtils::HexDecode(
+ std::string insert_entry = quiche::QuicheTextUtils::HexDecode(
"62" // insert without name reference
"94e7" // Huffman-encoded name "foo"
"03626172"); // value "bar"
EXPECT_CALL(encoder_stream_sender_delegate_,
WriteStreamData(Eq(insert_entry)));
- EXPECT_EQ(QuicTextUtils::HexDecode("0200" // prefix
- "80" // dynamic entry 0
- "40" // reference to dynamic entry 0 name
- "0362617a" // with literal value "baz"
- "55" // reference to static entry 5 name
- "0362617a" // with literal value "baz"
- "23626172" // literal name "bar"
- "0362617a"), // with literal value "baz"
+ EXPECT_EQ(quiche::QuicheTextUtils::HexDecode(
+ "0200" // prefix
+ "80" // dynamic entry 0
+ "40" // reference to dynamic entry 0 name
+ "0362617a" // with literal value "baz"
+ "55" // reference to static entry 5 name
+ "0362617a" // with literal value "baz"
+ "23626172" // literal name "bar"
+ "0362617a"), // with literal value "baz"
Encode(header_list));
EXPECT_EQ(insert_entry.size(), encoder_stream_sent_byte_count_);
@@ -285,23 +290,24 @@ TEST_F(QpackEncoderTest, BlockedStream) {
encoder_.SetMaximumDynamicTableCapacity(4096);
// Set Dynamic Table Capacity instruction.
- EXPECT_CALL(encoder_stream_sender_delegate_,
- WriteStreamData(Eq(QuicTextUtils::HexDecode("3fe11f"))));
+ EXPECT_CALL(
+ encoder_stream_sender_delegate_,
+ WriteStreamData(Eq(quiche::QuicheTextUtils::HexDecode("3fe11f"))));
encoder_.SetDynamicTableCapacity(4096);
spdy::SpdyHeaderBlock header_list1;
header_list1["foo"] = "bar";
// Insert one entry into the dynamic table.
- std::string insert_entry1 = QuicTextUtils::HexDecode(
+ std::string insert_entry1 = quiche::QuicheTextUtils::HexDecode(
"62" // insert without name reference
"94e7" // Huffman-encoded name "foo"
"03626172"); // value "bar"
EXPECT_CALL(encoder_stream_sender_delegate_,
WriteStreamData(Eq(insert_entry1)));
- EXPECT_EQ(QuicTextUtils::HexDecode("0200" // prefix
- "80"), // dynamic entry 0
+ EXPECT_EQ(quiche::QuicheTextUtils::HexDecode("0200" // prefix
+ "80"), // dynamic entry 0
encoder_.EncodeHeaderList(/* stream_id = */ 1, header_list1,
&encoder_stream_sent_byte_count_));
EXPECT_EQ(insert_entry1.size(), encoder_stream_sent_byte_count_);
@@ -314,15 +320,16 @@ TEST_F(QpackEncoderTest, BlockedStream) {
header_list2["cookie"] = "baz"; // name matches static entry
header_list2["bar"] = "baz"; // no match
- EXPECT_EQ(QuicTextUtils::HexDecode("0000" // prefix
- "2a94e7" // literal name "foo"
- "03626172" // with literal value "bar"
- "2a94e7" // literal name "foo"
- "0362617a" // with literal value "baz"
- "55" // name of static entry 5
- "0362617a" // with literal value "baz"
- "23626172" // literal name "bar"
- "0362617a"), // with literal value "baz"
+ EXPECT_EQ(quiche::QuicheTextUtils::HexDecode(
+ "0000" // prefix
+ "2a94e7" // literal name "foo"
+ "03626172" // with literal value "bar"
+ "2a94e7" // literal name "foo"
+ "0362617a" // with literal value "baz"
+ "55" // name of static entry 5
+ "0362617a" // with literal value "baz"
+ "23626172" // literal name "bar"
+ "0362617a"), // with literal value "baz"
encoder_.EncodeHeaderList(/* stream_id = */ 2, header_list2,
&encoder_stream_sent_byte_count_));
EXPECT_EQ(0u, encoder_stream_sent_byte_count_);
@@ -332,7 +339,7 @@ TEST_F(QpackEncoderTest, BlockedStream) {
encoder_.OnInsertCountIncrement(1);
// Insert three entries into the dynamic table.
- std::string insert_entries = QuicTextUtils::HexDecode(
+ std::string insert_entries = quiche::QuicheTextUtils::HexDecode(
"80" // insert with name reference, dynamic index 0
"0362617a" // value "baz"
"c5" // insert with name reference, static index 5
@@ -343,22 +350,23 @@ TEST_F(QpackEncoderTest, BlockedStream) {
EXPECT_CALL(encoder_stream_sender_delegate_,
WriteStreamData(Eq(insert_entries)));
- EXPECT_EQ(QuicTextUtils::HexDecode("0500" // prefix
- "83828180"), // dynamic entries
+ EXPECT_EQ(quiche::QuicheTextUtils::HexDecode("0500" // prefix
+ "83828180"), // dynamic entries
encoder_.EncodeHeaderList(/* stream_id = */ 3, header_list2,
&encoder_stream_sent_byte_count_));
EXPECT_EQ(insert_entries.size(), encoder_stream_sent_byte_count_);
// Stream 3 is blocked. Stream 4 is not allowed to block, but it can
// reference already acknowledged dynamic entry 0.
- EXPECT_EQ(QuicTextUtils::HexDecode("0200" // prefix
- "80" // dynamic entry 0
- "2a94e7" // literal name "foo"
- "0362617a" // with literal value "baz"
- "2c21cfd4c5" // literal name "cookie"
- "0362617a" // with literal value "baz"
- "23626172" // literal name "bar"
- "0362617a"), // with literal value "baz"
+ EXPECT_EQ(quiche::QuicheTextUtils::HexDecode(
+ "0200" // prefix
+ "80" // dynamic entry 0
+ "2a94e7" // literal name "foo"
+ "0362617a" // with literal value "baz"
+ "2c21cfd4c5" // literal name "cookie"
+ "0362617a" // with literal value "baz"
+ "23626172" // literal name "bar"
+ "0362617a"), // with literal value "baz"
encoder_.EncodeHeaderList(/* stream_id = */ 4, header_list2,
&encoder_stream_sent_byte_count_));
EXPECT_EQ(0u, encoder_stream_sent_byte_count_);
@@ -369,10 +377,11 @@ TEST_F(QpackEncoderTest, BlockedStream) {
// Stream 5 is not allowed to block, but it can reference already acknowledged
// dynamic entries 0, 1, and 2.
- EXPECT_EQ(QuicTextUtils::HexDecode("0400" // prefix
- "828180" // dynamic entries
- "23626172" // literal name "bar"
- "0362617a"), // with literal value "baz"
+ EXPECT_EQ(quiche::QuicheTextUtils::HexDecode(
+ "0400" // prefix
+ "828180" // dynamic entries
+ "23626172" // literal name "bar"
+ "0362617a"), // with literal value "baz"
encoder_.EncodeHeaderList(/* stream_id = */ 5, header_list2,
&encoder_stream_sent_byte_count_));
EXPECT_EQ(0u, encoder_stream_sent_byte_count_);
@@ -381,8 +390,8 @@ TEST_F(QpackEncoderTest, BlockedStream) {
// Stream 3 is not blocked any longer.
encoder_.OnHeaderAcknowledgement(3);
- EXPECT_EQ(QuicTextUtils::HexDecode("0500" // prefix
- "83828180"), // dynamic entries
+ EXPECT_EQ(quiche::QuicheTextUtils::HexDecode("0500" // prefix
+ "83828180"), // dynamic entries
encoder_.EncodeHeaderList(/* stream_id = */ 6, header_list2,
&encoder_stream_sent_byte_count_));
EXPECT_EQ(0u, encoder_stream_sent_byte_count_);
@@ -419,10 +428,10 @@ TEST_F(QpackEncoderTest, Draining) {
// Insert ten entries into the dynamic table.
EXPECT_CALL(encoder_stream_sender_delegate_, WriteStreamData(_));
- EXPECT_EQ(
- QuicTextUtils::HexDecode("0b00" // prefix
- "89888786858483828180"), // dynamic entries
- Encode(header_list1));
+ EXPECT_EQ(quiche::QuicheTextUtils::HexDecode(
+ "0b00" // prefix
+ "89888786858483828180"), // dynamic entries
+ Encode(header_list1));
// Entry is identical to oldest one, which is draining. It will be
// duplicated and referenced.
@@ -431,10 +440,11 @@ TEST_F(QpackEncoderTest, Draining) {
// Duplicate oldest entry.
EXPECT_CALL(encoder_stream_sender_delegate_,
- WriteStreamData(Eq(QuicTextUtils::HexDecode("09"))));
+ WriteStreamData(Eq(quiche::QuicheTextUtils::HexDecode("09"))));
- EXPECT_EQ(QuicTextUtils::HexDecode("0c00" // prefix
- "80"), // most recent dynamic table entry
+ EXPECT_EQ(quiche::QuicheTextUtils::HexDecode(
+ "0c00" // prefix
+ "80"), // most recent dynamic table entry
Encode(header_list2));
spdy::SpdyHeaderBlock header_list3;
@@ -445,12 +455,13 @@ TEST_F(QpackEncoderTest, Draining) {
// no room to insert new entry, it will be encoded with string literals.
header_list3.AppendValueOrAddHeader("two", "bar");
- EXPECT_EQ(QuicTextUtils::HexDecode("0000" // prefix
- "2374776f" // literal name "two"
- "8294e7" // literal value "foo"
- "2374776f" // literal name "two"
- "03626172"), // literal value "bar"
- Encode(header_list3));
+ EXPECT_EQ(
+ quiche::QuicheTextUtils::HexDecode("0000" // prefix
+ "2374776f" // literal name "two"
+ "8294e7" // literal value "foo"
+ "2374776f" // literal name "two"
+ "03626172"), // literal value "bar"
+ Encode(header_list3));
}
TEST_F(QpackEncoderTest, DynamicTableCapacityLessThanMaximum) {
@@ -458,7 +469,7 @@ TEST_F(QpackEncoderTest, DynamicTableCapacityLessThanMaximum) {
// Set Dynamic Table Capacity instruction.
EXPECT_CALL(encoder_stream_sender_delegate_,
- WriteStreamData(Eq(QuicTextUtils::HexDecode("3e"))));
+ WriteStreamData(Eq(quiche::QuicheTextUtils::HexDecode("3e"))));
encoder_.SetDynamicTableCapacity(30);
QpackHeaderTable* header_table = QpackEncoderPeer::header_table(&encoder_);
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table.cc
index 4cafa196815..472db893540 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table.cc
@@ -6,6 +6,7 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_static_table.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -50,8 +51,8 @@ const QpackEntry* QpackHeaderTable::LookupEntry(bool is_static,
}
QpackHeaderTable::MatchType QpackHeaderTable::FindHeaderField(
- QuicStringPiece name,
- QuicStringPiece value,
+ quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value,
bool* is_static,
uint64_t* index) const {
QpackEntry query(name, value);
@@ -95,8 +96,9 @@ QpackHeaderTable::MatchType QpackHeaderTable::FindHeaderField(
return MatchType::kNoMatch;
}
-const QpackEntry* QpackHeaderTable::InsertEntry(QuicStringPiece name,
- QuicStringPiece value) {
+const QpackEntry* QpackHeaderTable::InsertEntry(
+ quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value) {
const uint64_t entry_size = QpackEntry::Size(name, value);
if (entry_size > dynamic_table_capacity_) {
return nullptr;
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table.h
index dd5ca3ba3e5..e3fb97504b3 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table.h
@@ -11,7 +11,7 @@
#include <vector>
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_entry.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.h"
@@ -70,15 +70,16 @@ class QUIC_EXPORT_PRIVATE QpackHeaderTable {
// Returns the absolute index of an entry with matching name and value if such
// exists, otherwise one with matching name is such exists. |index| is zero
// based for both the static and the dynamic table.
- MatchType FindHeaderField(QuicStringPiece name,
- QuicStringPiece value,
+ MatchType FindHeaderField(quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value,
bool* is_static,
uint64_t* index) const;
// Insert (name, value) into the dynamic table. May evict entries. Returns a
// pointer to the inserted owned entry on success. Returns nullptr if entry
// is larger than the capacity of the dynamic table.
- const QpackEntry* InsertEntry(QuicStringPiece name, QuicStringPiece value);
+ const QpackEntry* InsertEntry(quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value);
// Returns the size of the largest entry that could be inserted into the
// dynamic table without evicting entry |index|. |index| might be larger than
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table_test.cc
index 5638aff0033..5cf392023af 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table_test.cc
@@ -7,8 +7,9 @@
#include <utility>
#include "net/third_party/quiche/src/quic/core/qpack/qpack_static_table.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_entry.h"
using ::testing::Mock;
@@ -39,8 +40,8 @@ class QpackHeaderTableTest : public QuicTest {
void ExpectEntryAtIndex(bool is_static,
uint64_t index,
- QuicStringPiece expected_name,
- QuicStringPiece expected_value) const {
+ quiche::QuicheStringPiece expected_name,
+ quiche::QuicheStringPiece expected_value) const {
const auto* entry = table_.LookupEntry(is_static, index);
ASSERT_TRUE(entry);
EXPECT_EQ(expected_name, entry->name());
@@ -51,8 +52,8 @@ class QpackHeaderTableTest : public QuicTest {
EXPECT_FALSE(table_.LookupEntry(is_static, index));
}
- void ExpectMatch(QuicStringPiece name,
- QuicStringPiece value,
+ void ExpectMatch(quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value,
QpackHeaderTable::MatchType expected_match_type,
bool expected_is_static,
uint64_t expected_index) const {
@@ -69,7 +70,8 @@ class QpackHeaderTableTest : public QuicTest {
EXPECT_EQ(expected_index, index) << name << ": " << value;
}
- void ExpectNoMatch(QuicStringPiece name, QuicStringPiece value) const {
+ void ExpectNoMatch(quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value) const {
bool is_static = false;
uint64_t index = 0;
@@ -80,11 +82,13 @@ class QpackHeaderTableTest : public QuicTest {
<< name << ": " << value;
}
- void InsertEntry(QuicStringPiece name, QuicStringPiece value) {
+ void InsertEntry(quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value) {
EXPECT_TRUE(table_.InsertEntry(name, value));
}
- void ExpectToFailInsertingEntry(QuicStringPiece name, QuicStringPiece value) {
+ void ExpectToFailInsertingEntry(quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value) {
EXPECT_FALSE(table_.InsertEntry(name, value));
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.cc
index fede8e307df..1f85d7f1fa7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.cc
@@ -9,6 +9,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -32,7 +33,7 @@ QpackInstructionDecoder::QpackInstructionDecoder(const QpackLanguage* language,
error_detected_(false),
state_(State::kStartInstruction) {}
-bool QpackInstructionDecoder::Decode(QuicStringPiece data) {
+bool QpackInstructionDecoder::Decode(quiche::QuicheStringPiece data) {
DCHECK(!data.empty());
DCHECK(!error_detected_);
@@ -76,8 +77,8 @@ bool QpackInstructionDecoder::Decode(QuicStringPiece data) {
DCHECK_LE(bytes_consumed, data.size());
- data = QuicStringPiece(data.data() + bytes_consumed,
- data.size() - bytes_consumed);
+ data = quiche::QuicheStringPiece(data.data() + bytes_consumed,
+ data.size() - bytes_consumed);
// Stop processing if no more data but next state would require it.
if (data.empty() && (state_ != State::kStartField) &&
@@ -93,7 +94,8 @@ bool QpackInstructionDecoder::AtInstructionBoundary() const {
return state_ == State::kStartInstruction;
}
-bool QpackInstructionDecoder::DoStartInstruction(QuicStringPiece data) {
+bool QpackInstructionDecoder::DoStartInstruction(
+ quiche::QuicheStringPiece data) {
DCHECK(!data.empty());
instruction_ = LookupOpcode(data[0]);
@@ -131,7 +133,7 @@ bool QpackInstructionDecoder::DoStartField() {
}
}
-bool QpackInstructionDecoder::DoReadBit(QuicStringPiece data) {
+bool QpackInstructionDecoder::DoReadBit(quiche::QuicheStringPiece data) {
DCHECK(!data.empty());
switch (field_->type) {
@@ -161,7 +163,7 @@ bool QpackInstructionDecoder::DoReadBit(QuicStringPiece data) {
}
}
-bool QpackInstructionDecoder::DoVarintStart(QuicStringPiece data,
+bool QpackInstructionDecoder::DoVarintStart(quiche::QuicheStringPiece data,
size_t* bytes_consumed) {
DCHECK(!data.empty());
DCHECK(field_->type == QpackInstructionFieldType::kVarint ||
@@ -190,7 +192,7 @@ bool QpackInstructionDecoder::DoVarintStart(QuicStringPiece data,
}
}
-bool QpackInstructionDecoder::DoVarintResume(QuicStringPiece data,
+bool QpackInstructionDecoder::DoVarintResume(quiche::QuicheStringPiece data,
size_t* bytes_consumed) {
DCHECK(!data.empty());
DCHECK(field_->type == QpackInstructionFieldType::kVarint ||
@@ -263,7 +265,7 @@ bool QpackInstructionDecoder::DoVarintDone() {
return true;
}
-bool QpackInstructionDecoder::DoReadString(QuicStringPiece data,
+bool QpackInstructionDecoder::DoReadString(quiche::QuicheStringPiece data,
size_t* bytes_consumed) {
DCHECK(!data.empty());
DCHECK(field_->type == QpackInstructionFieldType::kName ||
@@ -321,7 +323,7 @@ const QpackInstruction* QpackInstructionDecoder::LookupOpcode(
return nullptr;
}
-void QpackInstructionDecoder::OnError(QuicStringPiece error_message) {
+void QpackInstructionDecoder::OnError(quiche::QuicheStringPiece error_message) {
DCHECK(!error_detected_);
error_detected_ = true;
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.h
index 4c217731a92..08eb665749b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.h
@@ -13,7 +13,7 @@
#include "net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -42,7 +42,7 @@ class QUIC_EXPORT_PRIVATE QpackInstructionDecoder {
// No more data is processed afterwards.
// Implementations are allowed to destroy the QpackInstructionDecoder
// instance synchronously.
- virtual void OnError(QuicStringPiece error_message) = 0;
+ virtual void OnError(quiche::QuicheStringPiece error_message) = 0;
};
// Both |*language| and |*delegate| must outlive this object.
@@ -54,7 +54,7 @@ class QUIC_EXPORT_PRIVATE QpackInstructionDecoder {
// Provide a data fragment to decode. Must not be called after an error has
// occurred. Must not be called with empty |data|. Return true on success,
// false on error (in which case Delegate::OnError() is called synchronously).
- bool Decode(QuicStringPiece data);
+ bool Decode(quiche::QuicheStringPiece data);
// Returns true if no decoding has taken place yet or if the last instruction
// has been entirely parsed.
@@ -94,13 +94,13 @@ class QUIC_EXPORT_PRIVATE QpackInstructionDecoder {
// data and set |*bytes_consumed| to the number of octets processed. Some
// take input data but do not consume any bytes. Some do not take any
// arguments because they only change internal state.
- bool DoStartInstruction(QuicStringPiece data);
+ bool DoStartInstruction(quiche::QuicheStringPiece data);
bool DoStartField();
- bool DoReadBit(QuicStringPiece data);
- bool DoVarintStart(QuicStringPiece data, size_t* bytes_consumed);
- bool DoVarintResume(QuicStringPiece data, size_t* bytes_consumed);
+ bool DoReadBit(quiche::QuicheStringPiece data);
+ bool DoVarintStart(quiche::QuicheStringPiece data, size_t* bytes_consumed);
+ bool DoVarintResume(quiche::QuicheStringPiece data, size_t* bytes_consumed);
bool DoVarintDone();
- bool DoReadString(QuicStringPiece data, size_t* bytes_consumed);
+ bool DoReadString(quiche::QuicheStringPiece data, size_t* bytes_consumed);
bool DoReadStringDone();
// Identify instruction based on opcode encoded in |byte|.
@@ -108,7 +108,7 @@ class QUIC_EXPORT_PRIVATE QpackInstructionDecoder {
const QpackInstruction* LookupOpcode(uint8_t byte) const;
// Stops decoding and calls Delegate::OnError().
- void OnError(QuicStringPiece error_message);
+ void OnError(quiche::QuicheStringPiece error_message);
// Describes the language used for decoding.
const QpackLanguage* const language_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder_test.cc
index c066827d295..99cda08dd28 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder_test.cc
@@ -9,8 +9,9 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
using ::testing::_;
using ::testing::Eq;
@@ -61,7 +62,7 @@ class MockDelegate : public QpackInstructionDecoder::Delegate {
~MockDelegate() override = default;
MOCK_METHOD1(OnInstructionDecoded, bool(const QpackInstruction* instruction));
- MOCK_METHOD1(OnError, void(QuicStringPiece error_message));
+ MOCK_METHOD1(OnError, void(quiche::QuicheStringPiece error_message));
};
class QpackInstructionDecoderTest : public QuicTestWithParam<FragmentMode> {
@@ -76,8 +77,10 @@ class QpackInstructionDecoderTest : public QuicTestWithParam<FragmentMode> {
// Destroy QpackInstructionDecoder on error to test that it does not crash.
// See https://crbug.com/1025209.
ON_CALL(delegate_, OnError(_))
- .WillByDefault(Invoke(
- [this](QuicStringPiece /* error_message */) { decoder_.reset(); }));
+ .WillByDefault(
+ Invoke([this](quiche::QuicheStringPiece /* error_message */) {
+ decoder_.reset();
+ }));
}
// Decode one full instruction with fragment sizes dictated by
@@ -86,7 +89,7 @@ class QpackInstructionDecoderTest : public QuicTestWithParam<FragmentMode> {
// verifies that AtInstructionBoundary() returns true before and after the
// instruction, and returns false while decoding is in progress.
// Assumes that delegate methods destroy |decoder_| if they return false.
- void DecodeInstruction(QuicStringPiece data) {
+ void DecodeInstruction(quiche::QuicheStringPiece data) {
EXPECT_TRUE(decoder_->AtInstructionBoundary());
FragmentSizeGenerator fragment_size_generator =
@@ -123,14 +126,14 @@ INSTANTIATE_TEST_SUITE_P(All,
TEST_P(QpackInstructionDecoderTest, SBitAndVarint2) {
EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction1()));
- DecodeInstruction(QuicTextUtils::HexDecode("7f01ff65"));
+ DecodeInstruction(quiche::QuicheTextUtils::HexDecode("7f01ff65"));
EXPECT_TRUE(decoder_->s_bit());
EXPECT_EQ(64u, decoder_->varint());
EXPECT_EQ(356u, decoder_->varint2());
EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction1()));
- DecodeInstruction(QuicTextUtils::HexDecode("05c8"));
+ DecodeInstruction(quiche::QuicheTextUtils::HexDecode("05c8"));
EXPECT_FALSE(decoder_->s_bit());
EXPECT_EQ(5u, decoder_->varint());
@@ -139,19 +142,19 @@ TEST_P(QpackInstructionDecoderTest, SBitAndVarint2) {
TEST_P(QpackInstructionDecoderTest, NameAndValue) {
EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction2()));
- DecodeInstruction(QuicTextUtils::HexDecode("83666f6f03626172"));
+ DecodeInstruction(quiche::QuicheTextUtils::HexDecode("83666f6f03626172"));
EXPECT_EQ("foo", decoder_->name());
EXPECT_EQ("bar", decoder_->value());
EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction2()));
- DecodeInstruction(QuicTextUtils::HexDecode("8000"));
+ DecodeInstruction(quiche::QuicheTextUtils::HexDecode("8000"));
EXPECT_EQ("", decoder_->name());
EXPECT_EQ("", decoder_->value());
EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction2()));
- DecodeInstruction(QuicTextUtils::HexDecode("c294e7838c767f"));
+ DecodeInstruction(quiche::QuicheTextUtils::HexDecode("c294e7838c767f"));
EXPECT_EQ("foo", decoder_->name());
EXPECT_EQ("bar", decoder_->value());
@@ -159,12 +162,13 @@ TEST_P(QpackInstructionDecoderTest, NameAndValue) {
TEST_P(QpackInstructionDecoderTest, InvalidHuffmanEncoding) {
EXPECT_CALL(delegate_, OnError(Eq("Error in Huffman-encoded string.")));
- DecodeInstruction(QuicTextUtils::HexDecode("c1ff"));
+ DecodeInstruction(quiche::QuicheTextUtils::HexDecode("c1ff"));
}
TEST_P(QpackInstructionDecoderTest, InvalidVarintEncoding) {
EXPECT_CALL(delegate_, OnError(Eq("Encoded integer too large.")));
- DecodeInstruction(QuicTextUtils::HexDecode("ffffffffffffffffffffff"));
+ DecodeInstruction(
+ quiche::QuicheTextUtils::HexDecode("ffffffffffffffffffffff"));
}
TEST_P(QpackInstructionDecoderTest, DelegateSignalsError) {
@@ -186,8 +190,8 @@ TEST_P(QpackInstructionDecoderTest, DelegateSignalsError) {
return false;
}));
- EXPECT_FALSE(
- decoder_->Decode(QuicTextUtils::HexDecode("01000200030004000500")));
+ EXPECT_FALSE(decoder_->Decode(
+ quiche::QuicheTextUtils::HexDecode("01000200030004000500")));
}
// QpackInstructionDecoder must not crash if it is destroyed from a
@@ -200,7 +204,7 @@ TEST_P(QpackInstructionDecoderTest, DelegateSignalsErrorAndDestroysDecoder) {
decoder_.reset();
return false;
}));
- DecodeInstruction(QuicTextUtils::HexDecode("0100"));
+ DecodeInstruction(quiche::QuicheTextUtils::HexDecode("0100"));
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder.cc
index a87489d9e67..41e2d763455 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder.cc
@@ -10,6 +10,7 @@
#include "net/third_party/quiche/src/http2/hpack/varint/hpack_varint_encoder.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -127,8 +128,8 @@ void QpackInstructionEncoder::DoVarintEncode(uint64_t varint,
state_ = State::kWriteString;
}
-void QpackInstructionEncoder::DoStartString(QuicStringPiece name,
- QuicStringPiece value) {
+void QpackInstructionEncoder::DoStartString(quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value) {
DCHECK(field_->type == QpackInstructionFieldType::kName ||
field_->type == QpackInstructionFieldType::kValue);
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder.h
index 04b2888172e..2a955f88db4 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder.h
@@ -10,7 +10,7 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -52,7 +52,8 @@ class QUIC_EXPORT_PRIVATE QpackInstructionEncoder {
void DoStartField();
void DoSBit(bool s_bit);
void DoVarintEncode(uint64_t varint, uint64_t varint2, std::string* output);
- void DoStartString(QuicStringPiece name, QuicStringPiece value);
+ void DoStartString(quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value);
void DoWriteString(std::string* output);
@@ -63,7 +64,7 @@ class QUIC_EXPORT_PRIVATE QpackInstructionEncoder {
// If Huffman encoding is used, points to a substring of
// |huffman_encoded_string_|.
// Otherwise points to a substring of |name_| or |value_|.
- QuicStringPiece string_to_write_;
+ quiche::QuicheStringPiece string_to_write_;
// Storage for a single byte that contains multiple fields, that is, multiple
// states are writing it.
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder_test.cc
index 79dfe2af379..6f3337c1a61 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder_test.cc
@@ -6,7 +6,8 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
namespace test {
@@ -36,12 +37,12 @@ class QpackInstructionWithValuesPeer {
}
static void set_name(QpackInstructionWithValues* instruction_with_values,
- QuicStringPiece name) {
+ quiche::QuicheStringPiece name) {
instruction_with_values->name_ = name;
}
static void set_value(QpackInstructionWithValues* instruction_with_values,
- QuicStringPiece value) {
+ quiche::QuicheStringPiece value) {
instruction_with_values->value_ = value;
}
};
@@ -61,9 +62,12 @@ class QpackInstructionEncoderTest : public QuicTest {
// Compare substring appended to |output_| since last EncodedSegmentMatches()
// call against hex-encoded argument.
- bool EncodedSegmentMatches(QuicStringPiece hex_encoded_expected_substring) {
- auto recently_encoded = QuicStringPiece(output_).substr(verified_position_);
- auto expected = QuicTextUtils::HexDecode(hex_encoded_expected_substring);
+ bool EncodedSegmentMatches(
+ quiche::QuicheStringPiece hex_encoded_expected_substring) {
+ auto recently_encoded =
+ quiche::QuicheStringPiece(output_).substr(verified_position_);
+ auto expected =
+ quiche::QuicheTextUtils::HexDecode(hex_encoded_expected_substring);
verified_position_ = output_.size();
return recently_encoded == expected;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instructions.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instructions.cc
index a6a7529bf09..1e5d1124c57 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instructions.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instructions.cc
@@ -7,6 +7,7 @@
#include <limits>
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -203,7 +204,7 @@ const QpackLanguage* QpackRequestStreamLanguage() {
QpackInstructionWithValues QpackInstructionWithValues::InsertWithNameReference(
bool is_static,
uint64_t name_index,
- QuicStringPiece value) {
+ quiche::QuicheStringPiece value) {
QpackInstructionWithValues instruction_with_values;
instruction_with_values.instruction_ = InsertWithNameReferenceInstruction();
instruction_with_values.s_bit_ = is_static;
@@ -215,8 +216,9 @@ QpackInstructionWithValues QpackInstructionWithValues::InsertWithNameReference(
// static
QpackInstructionWithValues
-QpackInstructionWithValues::InsertWithoutNameReference(QuicStringPiece name,
- QuicStringPiece value) {
+QpackInstructionWithValues::InsertWithoutNameReference(
+ quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value) {
QpackInstructionWithValues instruction_with_values;
instruction_with_values.instruction_ =
InsertWithoutNameReferenceInstruction();
@@ -305,7 +307,7 @@ QpackInstructionWithValues
QpackInstructionWithValues::LiteralHeaderFieldNameReference(
bool is_static,
uint64_t index,
- QuicStringPiece value) {
+ quiche::QuicheStringPiece value) {
QpackInstructionWithValues instruction_with_values;
instruction_with_values.instruction_ =
QpackLiteralHeaderFieldNameReferenceInstruction();
@@ -318,8 +320,8 @@ QpackInstructionWithValues::LiteralHeaderFieldNameReference(
// static
QpackInstructionWithValues QpackInstructionWithValues::LiteralHeaderField(
- QuicStringPiece name,
- QuicStringPiece value) {
+ quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value) {
QpackInstructionWithValues instruction_with_values;
instruction_with_values.instruction_ = QpackLiteralHeaderFieldInstruction();
instruction_with_values.name_ = name;
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h
index 0ff18bff254..d63a1e26ba5 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h
@@ -11,7 +11,7 @@
#include <vector>
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -151,10 +151,10 @@ class QUIC_EXPORT_PRIVATE QpackInstructionWithValues {
static QpackInstructionWithValues InsertWithNameReference(
bool is_static,
uint64_t name_index,
- QuicStringPiece value);
+ quiche::QuicheStringPiece value);
static QpackInstructionWithValues InsertWithoutNameReference(
- QuicStringPiece name,
- QuicStringPiece value);
+ quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value);
static QpackInstructionWithValues Duplicate(uint64_t index);
static QpackInstructionWithValues SetDynamicTableCapacity(uint64_t capacity);
@@ -172,16 +172,17 @@ class QUIC_EXPORT_PRIVATE QpackInstructionWithValues {
static QpackInstructionWithValues LiteralHeaderFieldNameReference(
bool is_static,
uint64_t index,
- QuicStringPiece value);
- static QpackInstructionWithValues LiteralHeaderField(QuicStringPiece name,
- QuicStringPiece value);
+ quiche::QuicheStringPiece value);
+ static QpackInstructionWithValues LiteralHeaderField(
+ quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value);
const QpackInstruction* instruction() const { return instruction_; }
bool s_bit() const { return s_bit_; }
uint64_t varint() const { return varint_; }
uint64_t varint2() const { return varint2_; }
- QuicStringPiece name() const { return name_; }
- QuicStringPiece value() const { return value_; }
+ quiche::QuicheStringPiece name() const { return name_; }
+ quiche::QuicheStringPiece value() const { return value_; }
// Used by QpackEncoder, because in the first pass it stores absolute indices,
// which are converted into relative indices in the second pass after base is
@@ -198,8 +199,8 @@ class QUIC_EXPORT_PRIVATE QpackInstructionWithValues {
bool s_bit_;
uint64_t varint_;
uint64_t varint2_;
- QuicStringPiece name_;
- QuicStringPiece value_;
+ quiche::QuicheStringPiece name_;
+ quiche::QuicheStringPiece value_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_offline_decoder_bin.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_offline_decoder_bin.cc
index 327816e8cb2..c1c002fd913 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_offline_decoder_bin.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_offline_decoder_bin.cc
@@ -7,8 +7,8 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_offline_decoder.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
int main(int argc, char* argv[]) {
const char* usage =
@@ -25,8 +25,8 @@ int main(int argc, char* argv[]) {
size_t i;
size_t success_count = 0;
for (i = 0; 2 * i < args.size(); ++i) {
- const quic::QuicStringPiece input_filename(args[2 * i]);
- const quic::QuicStringPiece expected_headers_filename(args[2 * i + 1]);
+ const quiche::QuicheStringPiece input_filename(args[2 * i]);
+ const quiche::QuicheStringPiece expected_headers_filename(args[2 * i + 1]);
// Every file represents a different connection,
// therefore every file needs a fresh decoding context.
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.cc
index c9e19d2d013..cf20bde3c60 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.cc
@@ -12,6 +12,7 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_required_insert_count.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -45,7 +46,7 @@ QpackProgressiveDecoder::~QpackProgressiveDecoder() {
}
}
-void QpackProgressiveDecoder::Decode(QuicStringPiece data) {
+void QpackProgressiveDecoder::Decode(quiche::QuicheStringPiece data) {
DCHECK(decoding_);
if (data.empty() || error_detected_) {
@@ -113,7 +114,7 @@ bool QpackProgressiveDecoder::OnInstructionDecoded(
return DoLiteralHeaderFieldInstruction();
}
-void QpackProgressiveDecoder::OnError(QuicStringPiece error_message) {
+void QpackProgressiveDecoder::OnError(quiche::QuicheStringPiece error_message) {
DCHECK(!error_detected_);
error_detected_ = true;
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.h
index 6599c1a3ff8..f9c0224c637 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.h
@@ -14,7 +14,7 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -32,8 +32,8 @@ class QUIC_EXPORT_PRIVATE QpackProgressiveDecoder
// Called when a new header name-value pair is decoded. Multiple values for
// a given name will be emitted as multiple calls to OnHeader.
- virtual void OnHeaderDecoded(QuicStringPiece name,
- QuicStringPiece value) = 0;
+ virtual void OnHeaderDecoded(quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value) = 0;
// Called when the header block is completely decoded.
// Indicates the total number of bytes in this block.
@@ -46,7 +46,8 @@ class QUIC_EXPORT_PRIVATE QpackProgressiveDecoder
// Called when a decoding error has occurred. No other methods will be
// called afterwards. Implementations are allowed to destroy
// the QpackProgressiveDecoder instance synchronously.
- virtual void OnDecodingErrorDetected(QuicStringPiece error_message) = 0;
+ virtual void OnDecodingErrorDetected(
+ quiche::QuicheStringPiece error_message) = 0;
};
// Interface for keeping track of blocked streams for the purpose of enforcing
@@ -89,7 +90,7 @@ class QUIC_EXPORT_PRIVATE QpackProgressiveDecoder
~QpackProgressiveDecoder() override;
// Provide a data fragment to decode.
- void Decode(QuicStringPiece data);
+ void Decode(quiche::QuicheStringPiece data);
// Signal that the entire header block has been received and passed in
// through Decode(). No methods must be called afterwards.
@@ -97,7 +98,7 @@ class QUIC_EXPORT_PRIVATE QpackProgressiveDecoder
// QpackInstructionDecoder::Delegate implementation.
bool OnInstructionDecoded(const QpackInstruction* instruction) override;
- void OnError(QuicStringPiece error_message) override;
+ void OnError(quiche::QuicheStringPiece error_message) override;
// QpackHeaderTable::Observer implementation.
void OnInsertCountReachedThreshold() override;
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_receive_stream.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_receive_stream.cc
index 59203986b7d..d2fc88b9ecd 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_receive_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_receive_stream.cc
@@ -5,6 +5,7 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_receive_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_session.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
QpackReceiveStream::QpackReceiveStream(PendingStream* pending,
@@ -13,11 +14,9 @@ QpackReceiveStream::QpackReceiveStream(PendingStream* pending,
receiver_(receiver) {}
void QpackReceiveStream::OnStreamReset(const QuicRstStreamFrame& /*frame*/) {
- // TODO(renjietang) Change the error code to H/3 specific
- // HTTP_CLOSED_CRITICAL_STREAM.
- session()->connection()->CloseConnection(
- QUIC_INVALID_STREAM_ID, "Attempt to reset Qpack receive stream",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ stream_delegate()->OnStreamError(
+ QUIC_HTTP_CLOSED_CRITICAL_STREAM,
+ "RESET_STREAM received for QPACK receive stream");
}
void QpackReceiveStream::OnDataAvailable() {
@@ -25,7 +24,7 @@ void QpackReceiveStream::OnDataAvailable() {
while (!reading_stopped() && sequencer()->GetReadableRegion(&iov)) {
DCHECK(!sequencer()->IsClosed());
- receiver_->Decode(QuicStringPiece(
+ receiver_->Decode(quiche::QuicheStringPiece(
reinterpret_cast<const char*>(iov.iov_base), iov.iov_len));
sequencer()->MarkConsumed(iov.iov_len);
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_receive_stream_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_receive_stream_test.cc
index af02f64798e..bc47d9d9d17 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_receive_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_receive_stream_test.cc
@@ -8,6 +8,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
@@ -61,7 +62,7 @@ class QpackReceiveStreamTest : public QuicTestWithParam<TestParams> {
: GetNthServerInitiatedUnidirectionalStreamId(
session_.transport_version(), 3);
char type[] = {0x03};
- QuicStreamFrame data1(id, false, 0, QuicStringPiece(type, 1));
+ QuicStreamFrame data1(id, false, 0, quiche::QuicheStringPiece(type, 1));
session_.OnStreamFrame(data1);
qpack_receive_stream_ =
QuicSpdySessionPeer::GetQpackDecoderReceiveStream(&session_);
@@ -85,7 +86,8 @@ TEST_P(QpackReceiveStreamTest, ResetQpackReceiveStream) {
QuicRstStreamFrame rst_frame(kInvalidControlFrameId,
qpack_receive_stream_->id(),
QUIC_STREAM_CANCELLED, 1234);
- EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID, _, _));
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_HTTP_CLOSED_CRITICAL_STREAM, _, _));
qpack_receive_stream_->OnStreamReset(rst_frame);
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_required_insert_count_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_required_insert_count_test.cc
index a84548d7606..fce7de9af01 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_required_insert_count_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_required_insert_count_test.cc
@@ -4,8 +4,8 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_required_insert_count.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
namespace quic {
namespace test {
@@ -50,7 +50,7 @@ struct {
{600, 100, 500}};
TEST(QpackRequiredInsertCountTest, QpackDecodeRequiredInsertCount) {
- for (size_t i = 0; i < QUIC_ARRAYSIZE(kTestData); ++i) {
+ for (size_t i = 0; i < QUICHE_ARRAYSIZE(kTestData); ++i) {
const uint64_t required_insert_count = kTestData[i].required_insert_count;
const uint64_t max_entries = kTestData[i].max_entries;
const uint64_t total_number_of_inserts =
@@ -109,7 +109,7 @@ struct {
{601, 100, 500}};
TEST(QpackRequiredInsertCountTest, DecodeRequiredInsertCountError) {
- for (size_t i = 0; i < QUIC_ARRAYSIZE(kInvalidTestData); ++i) {
+ for (size_t i = 0; i < QUICHE_ARRAYSIZE(kInvalidTestData); ++i) {
uint64_t decoded_required_insert_count = 0;
EXPECT_FALSE(QpackDecodeRequiredInsertCount(
kInvalidTestData[i].encoded_required_insert_count,
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_round_trip_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_round_trip_test.cc
index f0dc797fa3b..8625baa3c5c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_round_trip_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_round_trip_test.cc
@@ -5,11 +5,11 @@
#include <string>
#include <tuple>
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_decoder_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "net/third_party/quiche/src/spdy/core/spdy_header_block.h"
using ::testing::Values;
@@ -126,7 +126,7 @@ TEST_P(QpackRoundTripTest, StaticTable) {
TEST_P(QpackRoundTripTest, ValueHasNullCharacter) {
spdy::SpdyHeaderBlock header_list;
- header_list["foo"] = QuicStringPiece("bar\0bar\0baz", 11);
+ header_list["foo"] = quiche::QuicheStringPiece("bar\0bar\0baz", 11);
spdy::SpdyHeaderBlock output = EncodeThenDecode(header_list);
EXPECT_EQ(header_list, output);
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.cc
index 50fe687cdd3..15525b593d5 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.cc
@@ -5,7 +5,8 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_session.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
QpackSendStream::QpackSendStream(QuicStreamId id,
@@ -16,14 +17,17 @@ QpackSendStream::QpackSendStream(QuicStreamId id,
stream_type_sent_(false) {}
void QpackSendStream::OnStreamReset(const QuicRstStreamFrame& /*frame*/) {
- // TODO(renjietang) Change the error code to H/3 specific
- // HTTP_CLOSED_CRITICAL_STREAM.
- session()->connection()->CloseConnection(
- QUIC_INVALID_STREAM_ID, "Attempt to reset qpack send stream",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ QUIC_BUG << "OnStreamReset() called for write unidirectional stream.";
}
-void QpackSendStream::WriteStreamData(QuicStringPiece data) {
+bool QpackSendStream::OnStopSending(uint16_t /* code */) {
+ stream_delegate()->OnStreamError(
+ QUIC_HTTP_CLOSED_CRITICAL_STREAM,
+ "STOP_SENDING received for QPACK send stream");
+ return false;
+}
+
+void QpackSendStream::WriteStreamData(quiche::QuicheStringPiece data) {
QuicConnection::ScopedPacketFlusher flusher(session()->connection());
MaybeSendStreamType();
WriteOrBufferData(data, false, nullptr);
@@ -32,10 +36,10 @@ void QpackSendStream::WriteStreamData(QuicStringPiece data) {
void QpackSendStream::MaybeSendStreamType() {
if (!stream_type_sent_) {
char type[sizeof(http3_stream_type_)];
- QuicDataWriter writer(QUIC_ARRAYSIZE(type), type);
+ QuicDataWriter writer(QUICHE_ARRAYSIZE(type), type);
writer.WriteVarInt62(http3_stream_type_);
- WriteOrBufferData(QuicStringPiece(writer.data(), writer.length()), false,
- nullptr);
+ WriteOrBufferData(quiche::QuicheStringPiece(writer.data(), writer.length()),
+ false, nullptr);
stream_type_sent_ = true;
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.h
index 09c6020cf49..50d2808a46e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.h
@@ -10,7 +10,7 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_stream_sender_delegate.h"
#include "net/third_party/quiche/src/quic/core/quic_stream.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -30,9 +30,10 @@ class QUIC_EXPORT_PRIVATE QpackSendStream : public QuicStream,
QpackSendStream& operator=(const QpackSendStream&) = delete;
~QpackSendStream() override = default;
- // Overriding QuicStream::OnStreamReset to make sure QPACK stream is
- // never closed before connection.
+ // Overriding QuicStream::OnStopSending() to make sure QPACK stream is never
+ // closed before connection.
void OnStreamReset(const QuicRstStreamFrame& frame) override;
+ bool OnStopSending(uint16_t code) override;
// The send QPACK stream is write unidirectional, so this method
// should never be called.
@@ -40,7 +41,7 @@ class QUIC_EXPORT_PRIVATE QpackSendStream : public QuicStream,
// Writes the instructions to peer. The stream type will be sent
// before the first instruction so that the peer can open an qpack stream.
- void WriteStreamData(QuicStringPiece data) override;
+ void WriteStreamData(quiche::QuicheStringPiece data) override;
// TODO(b/112770235): Remove this method once QuicStreamIdManager supports
// creating HTTP/3 unidirectional streams dynamically.
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream_test.cc
index 9529f518149..c77a6218bca 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream_test.cc
@@ -9,6 +9,8 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
@@ -35,7 +37,7 @@ struct TestParams {
// Used by ::testing::PrintToStringParamName().
std::string PrintToString(const TestParams& tp) {
- return QuicStrCat(
+ return quiche::QuicheStrCat(
ParsedQuicVersionToString(tp.version), "_",
(tp.perspective == Perspective::IS_CLIENT ? "client" : "server"));
}
@@ -68,15 +70,14 @@ class QpackSendStreamTest : public QuicTestWithParam<TestParams> {
session_.config(), kMinimumFlowControlSendWindow);
QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesUnidirectional(
session_.config(), kMinimumFlowControlSendWindow);
- QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams(
- session_.config(), 3);
+ QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(session_.config(), 3);
session_.OnConfigNegotiated();
qpack_send_stream_ =
QuicSpdySessionPeer::GetQpackDecoderSendStream(&session_);
- ON_CALL(session_, WritevData(_, _, _, _, _))
- .WillByDefault(Invoke(MockQuicSession::ConsumeData));
+ ON_CALL(session_, WritevData(_, _, _, _, _, _))
+ .WillByDefault(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
}
Perspective perspective() const { return GetParam().perspective; }
@@ -95,21 +96,20 @@ INSTANTIATE_TEST_SUITE_P(Tests,
TEST_P(QpackSendStreamTest, WriteStreamTypeOnlyFirstTime) {
std::string data = "data";
- EXPECT_CALL(session_, WritevData(_, _, 1, _, _));
- EXPECT_CALL(session_, WritevData(_, _, data.length(), _, _));
- qpack_send_stream_->WriteStreamData(QuicStringPiece(data));
+ EXPECT_CALL(session_, WritevData(_, 1, _, _, _, _));
+ EXPECT_CALL(session_, WritevData(_, data.length(), _, _, _, _));
+ qpack_send_stream_->WriteStreamData(quiche::QuicheStringPiece(data));
- EXPECT_CALL(session_, WritevData(_, _, data.length(), _, _));
- qpack_send_stream_->WriteStreamData(QuicStringPiece(data));
- EXPECT_CALL(session_, WritevData(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(session_, WritevData(_, data.length(), _, _, _, _));
+ qpack_send_stream_->WriteStreamData(quiche::QuicheStringPiece(data));
+ EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(0);
qpack_send_stream_->MaybeSendStreamType();
}
-TEST_P(QpackSendStreamTest, ResetQpackStream) {
- QuicRstStreamFrame rst_frame(kInvalidControlFrameId, qpack_send_stream_->id(),
- QUIC_STREAM_CANCELLED, 1234);
- EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID, _, _));
- qpack_send_stream_->OnStreamReset(rst_frame);
+TEST_P(QpackSendStreamTest, StopSendingQpackStream) {
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_HTTP_CLOSED_CRITICAL_STREAM, _, _));
+ qpack_send_stream_->OnStopSending(QUIC_STREAM_CANCELLED);
}
TEST_P(QpackSendStreamTest, ReceiveDataOnSendStream) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_static_table.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_static_table.cc
index 98a24c7e32f..17138be94d5 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_static_table.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_static_table.cc
@@ -4,15 +4,15 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_static_table.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
namespace quic {
// The "constructor" for a QpackStaticEntry that computes the lengths at
// compile time.
#define STATIC_ENTRY(name, value) \
- { name, QUIC_ARRAYSIZE(name) - 1, value, QUIC_ARRAYSIZE(value) - 1 }
+ { name, QUICHE_ARRAYSIZE(name) - 1, value, QUICHE_ARRAYSIZE(value) - 1 }
const std::vector<QpackStaticEntry>& QpackStaticTableVector() {
static const auto* kQpackStaticTable = new std::vector<QpackStaticEntry>{
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_static_table_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_static_table_test.cc
index 1742502e35b..1376d2cd51a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_static_table_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_static_table_test.cc
@@ -6,9 +6,9 @@
#include <set>
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -32,7 +32,7 @@ TEST(QpackStaticTableTest, Initialize) {
EXPECT_EQ(QpackStaticTableVector().size(), static_index.size());
auto static_name_index = table.GetStaticNameIndex();
- std::set<QuicStringPiece> names;
+ std::set<quiche::QuicheStringPiece> names;
for (auto entry : static_index) {
names.insert(entry->name());
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_stream_receiver.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_stream_receiver.h
index 48f5aa30f4a..01c2d5f4237 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_stream_receiver.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_stream_receiver.h
@@ -6,7 +6,7 @@
#define QUICHE_QUIC_CORE_QPACK_QPACK_STREAM_RECEIVER_H_
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -16,7 +16,7 @@ class QUIC_EXPORT_PRIVATE QpackStreamReceiver {
virtual ~QpackStreamReceiver() = default;
// Decode data.
- virtual void Decode(QuicStringPiece data) = 0;
+ virtual void Decode(quiche::QuicheStringPiece data) = 0;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_stream_sender_delegate.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_stream_sender_delegate.h
index 616df98b9db..524b756653d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_stream_sender_delegate.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_stream_sender_delegate.h
@@ -6,7 +6,7 @@
#define QUICHE_QUIC_CORE_QPACK_QPACK_STREAM_SENDER_DELEGATE_H_
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -16,7 +16,7 @@ class QUIC_EXPORT_PRIVATE QpackStreamSenderDelegate {
virtual ~QpackStreamSenderDelegate() = default;
// Write data on the unidirectional stream.
- virtual void WriteStreamData(QuicStringPiece data) = 0;
+ virtual void WriteStreamData(quiche::QuicheStringPiece data) = 0;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list.cc
index c1387b99881..65d1b99e0a8 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace {
@@ -36,7 +37,7 @@ bool ValueSplittingHeaderList::const_iterator::operator!=(
const ValueSplittingHeaderList::const_iterator&
ValueSplittingHeaderList::const_iterator::operator++() {
- if (value_end_ == QuicStringPiece::npos) {
+ if (value_end_ == quiche::QuicheStringPiece::npos) {
// This was the last frament within |*header_list_iterator_|,
// move on to the next header element of |header_list_|.
++header_list_iterator_;
@@ -60,14 +61,15 @@ const ValueSplittingHeaderList::value_type*
}
void ValueSplittingHeaderList::const_iterator::UpdateHeaderField() {
- DCHECK(value_start_ != QuicStringPiece::npos);
+ DCHECK(value_start_ != quiche::QuicheStringPiece::npos);
if (header_list_iterator_ == header_list_->end()) {
return;
}
- const QuicStringPiece name = header_list_iterator_->first;
- const QuicStringPiece original_value = header_list_iterator_->second;
+ const quiche::QuicheStringPiece name = header_list_iterator_->first;
+ const quiche::QuicheStringPiece original_value =
+ header_list_iterator_->second;
if (name == kCookieKey) {
value_end_ = original_value.find(kCookieSeparator, value_start_);
@@ -75,12 +77,12 @@ void ValueSplittingHeaderList::const_iterator::UpdateHeaderField() {
value_end_ = original_value.find(kNonCookieSeparator, value_start_);
}
- const QuicStringPiece value =
+ const quiche::QuicheStringPiece value =
original_value.substr(value_start_, value_end_ - value_start_);
header_field_ = std::make_pair(name, value);
// Skip character after ';' separator if it is a space.
- if (name == kCookieKey && value_end_ != QuicStringPiece::npos &&
+ if (name == kCookieKey && value_end_ != quiche::QuicheStringPiece::npos &&
value_end_ + 1 < original_value.size() &&
original_value[value_end_ + 1] == kOptionalSpaceAfterCookieSeparator) {
++value_end_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list.h b/chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list.h
index fee30434af0..446548a23ab 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list.h
@@ -6,7 +6,7 @@
#define QUICHE_QUIC_CORE_QPACK_VALUE_SPLITTING_HEADER_LIST_H_
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "net/third_party/quiche/src/spdy/core/spdy_header_block.h"
namespace quic {
@@ -40,8 +40,8 @@ class QUIC_EXPORT_PRIVATE ValueSplittingHeaderList {
const spdy::SpdyHeaderBlock* const header_list_;
spdy::SpdyHeaderBlock::const_iterator header_list_iterator_;
- QuicStringPiece::size_type value_start_;
- QuicStringPiece::size_type value_end_;
+ quiche::QuicheStringPiece::size_type value_start_;
+ quiche::QuicheStringPiece::size_type value_end_;
value_type header_field_;
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list_test.cc
index bab52386512..c1da85c8cd0 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list_test.cc
@@ -4,8 +4,9 @@
#include "net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
@@ -16,7 +17,7 @@ using ::testing::Pair;
TEST(ValueSplittingHeaderListTest, Comparison) {
spdy::SpdyHeaderBlock block;
- block["foo"] = QuicStringPiece("bar\0baz", 7);
+ block["foo"] = quiche::QuicheStringPiece("bar\0baz", 7);
block["baz"] = "qux";
block["cookie"] = "foo; bar";
@@ -84,7 +85,7 @@ TEST(ValueSplittingHeaderListTest, Empty) {
TEST(ValueSplittingHeaderListTest, Split) {
struct {
const char* name;
- QuicStringPiece value;
+ quiche::QuicheStringPiece value;
std::vector<const char*> expected_values;
} kTestData[]{
// Empty value.
@@ -112,7 +113,7 @@ TEST(ValueSplittingHeaderListTest, Split) {
{"cookie", "; foobar; ", {"", "foobar", ""}},
};
- for (size_t i = 0; i < QUIC_ARRAYSIZE(kTestData); ++i) {
+ for (size_t i = 0; i < QUICHE_ARRAYSIZE(kTestData); ++i) {
spdy::SpdyHeaderBlock block;
block[kTestData[i].name] = kTestData[i].value;
@@ -130,9 +131,9 @@ TEST(ValueSplittingHeaderListTest, Split) {
TEST(ValueSplittingHeaderListTest, MultipleFields) {
spdy::SpdyHeaderBlock block;
- block["foo"] = QuicStringPiece("bar\0baz\0", 8);
+ block["foo"] = quiche::QuicheStringPiece("bar\0baz\0", 8);
block["cookie"] = "foo; bar";
- block["bar"] = QuicStringPiece("qux\0foo", 7);
+ block["bar"] = quiche::QuicheStringPiece("qux\0foo", 7);
ValueSplittingHeaderList headers(&block);
EXPECT_THAT(headers, ElementsAre(Pair("foo", "bar"), Pair("foo", "baz"),
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_arena_scoped_ptr_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_arena_scoped_ptr_test.cc
index 5b7548a5c53..cd0780fe508 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_arena_scoped_ptr_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_arena_scoped_ptr_test.cc
@@ -13,7 +13,7 @@ namespace {
enum class TestParam { kFromHeap, kFromArena };
struct TestObject {
- explicit TestObject(uintptr_t value) : value(value) { buffer.resize(1024); }
+ explicit TestObject(uintptr_t value) : value(value) { buffer.resize(1200); }
uintptr_t value;
// Ensure that we have a non-trivial destructor that will leak memory if it's
@@ -51,7 +51,7 @@ class QuicArenaScopedPtrParamTest : public QuicTestWithParam<TestParam> {
}
private:
- QuicOneBlockArena<1024> arena_;
+ QuicOneBlockArena<1200> arena_;
};
INSTANTIATE_TEST_SUITE_P(QuicArenaScopedPtrParamTest,
@@ -69,7 +69,7 @@ TEST_P(QuicArenaScopedPtrParamTest, NullObjects) {
}
TEST_P(QuicArenaScopedPtrParamTest, FromArena) {
- QuicOneBlockArena<1024> arena_;
+ QuicOneBlockArena<1200> arena_;
EXPECT_TRUE(arena_.New<TestObject>(0).is_from_arena());
EXPECT_FALSE(
QuicArenaScopedPtr<TestObject>(new TestObject(0)).is_from_arena());
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_bandwidth.cc b/chromium/net/third_party/quiche/src/quic/core/quic_bandwidth.cc
index 9fcc3b986ae..ad2c03289a6 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_bandwidth.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_bandwidth.cc
@@ -7,14 +7,16 @@
#include <cinttypes>
#include <string>
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
std::string QuicBandwidth::ToDebuggingValue() const {
if (bits_per_second_ < 80000) {
- return QuicStringPrintf("%" PRId64 " bits/s (%" PRId64 " bytes/s)",
- bits_per_second_, bits_per_second_ / 8);
+ return quiche::QuicheStringPrintf("%" PRId64 " bits/s (%" PRId64
+ " bytes/s)",
+ bits_per_second_, bits_per_second_ / 8);
}
double divisor;
@@ -32,9 +34,9 @@ std::string QuicBandwidth::ToDebuggingValue() const {
double bits_per_second_with_unit = bits_per_second_ / divisor;
double bytes_per_second_with_unit = bits_per_second_with_unit / 8;
- return QuicStringPrintf("%.2f %cbits/s (%.2f %cbytes/s)",
- bits_per_second_with_unit, unit,
- bytes_per_second_with_unit, unit);
+ return quiche::QuicheStringPrintf("%.2f %cbits/s (%.2f %cbytes/s)",
+ bits_per_second_with_unit, unit,
+ bytes_per_second_with_unit, unit);
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_bandwidth.h b/chromium/net/third_party/quiche/src/quic/core/quic_bandwidth.h
index afd31b22e1b..e3e0cd1d8ba 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_bandwidth.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_bandwidth.h
@@ -54,8 +54,8 @@ class QUIC_EXPORT_PRIVATE QuicBandwidth {
// Create a new QuicBandwidth based on the bytes per the elapsed delta.
static inline QuicBandwidth FromBytesAndTimeDelta(QuicByteCount bytes,
QuicTime::Delta delta) {
- return QuicBandwidth((bytes * kNumMicrosPerSecond) /
- delta.ToMicroseconds() * 8);
+ return QuicBandwidth((8 * bytes * kNumMicrosPerSecond) /
+ delta.ToMicroseconds());
}
inline int64_t ToBitsPerSecond() const { return bits_per_second_; }
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_buffer_allocator.h b/chromium/net/third_party/quiche/src/quic/core/quic_buffer_allocator.h
index 10df3692f37..4b0abf44568 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_buffer_allocator.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_buffer_allocator.h
@@ -7,6 +7,8 @@
#include <stddef.h>
+#include <memory>
+
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
namespace quic {
@@ -32,6 +34,28 @@ class QUIC_EXPORT_PRIVATE QuicBufferAllocator {
virtual void MarkAllocatorIdle() {}
};
+// A deleter that can be used to manage ownership of buffers allocated via
+// QuicBufferAllocator through std::unique_ptr.
+class QUIC_EXPORT_PRIVATE QuicBufferDeleter {
+ public:
+ explicit QuicBufferDeleter(QuicBufferAllocator* allocator)
+ : allocator_(allocator) {}
+
+ QuicBufferAllocator* allocator() { return allocator_; }
+ void operator()(char* buffer) { allocator_->Delete(buffer); }
+
+ private:
+ QuicBufferAllocator* allocator_;
+};
+
+using QuicUniqueBufferPtr = std::unique_ptr<char[], QuicBufferDeleter>;
+
+inline QuicUniqueBufferPtr MakeUniqueBuffer(QuicBufferAllocator* allocator,
+ size_t size) {
+ return QuicUniqueBufferPtr(allocator->New(size),
+ QuicBufferDeleter(allocator));
+}
+
} // namespace quic
#endif // QUICHE_QUIC_CORE_QUIC_BUFFER_ALLOCATOR_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.cc b/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.cc
index e4dd2333255..e363461cf8c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.cc
@@ -175,6 +175,12 @@ void QuicBufferedPacketStore::DiscardPackets(QuicConnectionId connection_id) {
connections_with_chlo_.erase(connection_id);
}
+void QuicBufferedPacketStore::DiscardAllPackets() {
+ undecryptable_packets_.clear();
+ connections_with_chlo_.clear();
+ expiration_alarm_->Cancel();
+}
+
void QuicBufferedPacketStore::OnExpirationTimeout() {
QuicTime expiration_time = clock_->ApproximateNow() - connection_life_span_;
while (!undecryptable_packets_.empty()) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.h b/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.h
index 09bc2cc56c3..52d957e1a43 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.h
@@ -10,9 +10,9 @@
#include "net/third_party/quiche/src/quic/core/quic_alarm.h"
#include "net/third_party/quiche/src/quic/core/quic_alarm_factory.h"
+#include "net/third_party/quiche/src/quic/core/quic_clock.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
@@ -122,6 +122,9 @@ class QUIC_EXPORT_PRIVATE QuicBufferedPacketStore {
// Discards packets buffered for |connection_id|, if any.
void DiscardPackets(QuicConnectionId connection_id);
+ // Discards all the packets.
+ void DiscardAllPackets();
+
// Examines how long packets have been buffered in the store for each
// connection. If they stay too long, removes them for new coming packets and
// calls |visitor_|'s OnPotentialConnectionExpire().
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_circular_deque.h b/chromium/net/third_party/quiche/src/quic/core/quic_circular_deque.h
index 39eed8e6768..997740bf300 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_circular_deque.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_circular_deque.h
@@ -586,10 +586,10 @@ class QUIC_NO_EXPORT QuicCircularDeque {
pointer new_data = AllocatorTraits::allocate(
allocator_and_data_.allocator(), new_data_capacity);
- if (begin_ <= end_) {
+ if (begin_ < end_) {
// Not wrapped.
RelocateUnwrappedRange(begin_, end_, new_data);
- } else {
+ } else if (begin_ > end_) {
// Wrapped.
const size_t num_elements_before_wrap = data_capacity() - begin_;
RelocateUnwrappedRange(begin_, data_capacity(), new_data);
@@ -611,7 +611,9 @@ class QUIC_NO_EXPORT QuicCircularDeque {
typename std::enable_if<std::is_trivially_copyable<T_>::value, void>::type
RelocateUnwrappedRange(size_type begin, size_type end, pointer dest) const {
DCHECK_LE(begin, end) << "begin:" << begin << ", end:" << end;
- memcpy(dest, index_to_address(begin), sizeof(T) * (end - begin));
+ pointer src = index_to_address(begin);
+ DCHECK_NE(src, nullptr);
+ memcpy(dest, src, sizeof(T) * (end - begin));
DestroyRange(begin, end);
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_circular_deque_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_circular_deque_test.cc
index c1658985a48..19005f694e2 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_circular_deque_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_circular_deque_test.cc
@@ -16,6 +16,7 @@ using testing::ElementsAre;
namespace quic {
namespace test {
+namespace {
template <typename T, template <typename> class BaseAllocator = std::allocator>
class CountingAllocator : public BaseAllocator<T> {
@@ -105,7 +106,9 @@ void ShiftLeft(Deque* dq, bool emplace) {
}
}
-TEST(QuicCircularDeque, Empty) {
+class QuicCircularDequeTest : public QuicTest {};
+
+TEST_F(QuicCircularDequeTest, Empty) {
QuicCircularDeque<int> dq;
EXPECT_TRUE(dq.empty());
EXPECT_EQ(0u, dq.size());
@@ -125,7 +128,7 @@ TEST(QuicCircularDeque, Empty) {
EXPECT_QUIC_DEBUG_DEATH(dq[0], "");
}
-TEST(QuicCircularDeque, Constructor) {
+TEST_F(QuicCircularDequeTest, Constructor) {
QuicCircularDeque<int> dq;
EXPECT_TRUE(dq.empty());
@@ -173,7 +176,7 @@ TEST(QuicCircularDeque, Constructor) {
EXPECT_THAT(dq9, ElementsAre(3, 4, 5, 6, 7));
}
-TEST(QuicCircularDeque, Assign) {
+TEST_F(QuicCircularDequeTest, Assign) {
// assign()
QuicCircularDeque<int, 3, CountingAllocator<int>> dq;
dq.assign(7, 1);
@@ -264,7 +267,7 @@ TEST(QuicCircularDeque, Assign) {
EXPECT_TRUE(dq12.empty());
}
-TEST(QuicCircularDeque, Access) {
+TEST_F(QuicCircularDequeTest, Access) {
// at()
// operator[]
// front()
@@ -366,7 +369,7 @@ TEST(QuicCircularDeque, Access) {
EXPECT_EQ(1u, dq.get_allocator().allocate_count());
}
-TEST(QuicCircularDeque, Iterate) {
+TEST_F(QuicCircularDequeTest, Iterate) {
QuicCircularDeque<int> dq;
EXPECT_EQ(dq.begin(), dq.end());
EXPECT_EQ(dq.cbegin(), dq.cend());
@@ -428,7 +431,7 @@ TEST(QuicCircularDeque, Iterate) {
}
}
-TEST(QuicCircularDeque, Iterator) {
+TEST_F(QuicCircularDequeTest, Iterator) {
// Default constructed iterators of the same type compare equal.
EXPECT_EQ(QuicCircularDeque<int>::iterator(),
QuicCircularDeque<int>::iterator());
@@ -491,7 +494,7 @@ TEST(QuicCircularDeque, Iterator) {
}
}
-TEST(QuicCircularDeque, Resize) {
+TEST_F(QuicCircularDequeTest, Resize) {
QuicCircularDeque<int, 3, CountingAllocator<int>> dq;
dq.resize(8);
EXPECT_THAT(dq, ElementsAre(0, 0, 0, 0, 0, 0, 0, 0));
@@ -572,7 +575,7 @@ class Foo {
};
} // namespace
-TEST(QuicCircularDeque, RelocateNonTriviallyCopyable) {
+TEST_F(QuicCircularDequeTest, RelocateNonTriviallyCopyable) {
// When relocating non-trivially-copyable objects:
// - Move constructor is preferred, if available.
// - Copy constructor is used otherwise.
@@ -620,7 +623,7 @@ TEST(QuicCircularDeque, RelocateNonTriviallyCopyable) {
}
}
-TEST(QuicCircularDeque, PushPop) {
+TEST_F(QuicCircularDequeTest, PushPop) {
// (push|pop|emplace)_(back|front)
{
@@ -697,7 +700,7 @@ TEST(QuicCircularDeque, PushPop) {
}
}
-TEST(QuicCircularDeque, Allocation) {
+TEST_F(QuicCircularDequeTest, Allocation) {
CountingAllocator<int> alloc;
{
@@ -729,6 +732,7 @@ TEST(QuicCircularDeque, Allocation) {
EXPECT_EQ(7u, alloc.deallocate_count());
}
+} // namespace
} // namespace test
} // namespace quic
@@ -759,7 +763,9 @@ using UnswappableUnequalAllocator = quic::test::ConfigurableAllocator<
/*propagate_on_swap=*/std::false_type,
/*equality_result=*/false>;
-TEST(QuicCircularDeque, Swap) {
+using quic::test::QuicCircularDequeTest;
+
+TEST_F(QuicCircularDequeTest, Swap) {
using std::swap;
quic::QuicCircularDeque<int64_t, 3, SwappableAllocator<int64_t>> dq1, dq2;
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_clock.cc b/chromium/net/third_party/quiche/src/quic/core/quic_clock.cc
index 03851fa5809..e2287e9137a 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_clock.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_clock.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
+#include "net/third_party/quiche/src/quic/core/quic_clock.h"
#include <limits>
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_clock.h b/chromium/net/third_party/quiche/src/quic/core/quic_clock.h
index 80000177780..cef36dc8e3a 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_clock.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_clock.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_CLOCK_H_
-#define QUICHE_QUIC_PLATFORM_API_QUIC_CLOCK_H_
+#ifndef QUICHE_QUIC_CORE_QUIC_CLOCK_H_
+#define QUICHE_QUIC_CORE_QUIC_CLOCK_H_
#include "net/third_party/quiche/src/quic/core/quic_time.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
@@ -69,4 +69,4 @@ class QUIC_EXPORT_PRIVATE QuicClock {
} // namespace quic
-#endif // QUICHE_QUIC_PLATFORM_API_QUIC_CLOCK_H_
+#endif // QUICHE_QUIC_CORE_QUIC_CLOCK_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet.cc b/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet.cc
index 3dd9b24a4a4..6393f5d6c8a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet.cc
@@ -6,6 +6,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
namespace quic {
@@ -49,9 +50,7 @@ bool QuicCoalescedPacket::MaybeCoalescePacket(
QUIC_BUG << "Max packet length changes in the middle of the write path";
return false;
}
- if (!encrypted_buffers_[packet.encryption_level].empty() ||
- (packet.encryption_level == ENCRYPTION_INITIAL &&
- initial_packet_ != nullptr)) {
+ if (ContainsPacketOfEncryptionLevel(packet.encryption_level)) {
// Do not coalesce packets of the same encryption level.
return false;
}
@@ -116,4 +115,29 @@ bool QuicCoalescedPacket::CopyEncryptedBuffers(char* buffer,
return true;
}
+bool QuicCoalescedPacket::ContainsPacketOfEncryptionLevel(
+ EncryptionLevel level) const {
+ return !encrypted_buffers_[level].empty() ||
+ (level == ENCRYPTION_INITIAL && initial_packet_ != nullptr);
+}
+
+std::string QuicCoalescedPacket::ToString(size_t serialized_length) const {
+ // Total length and padding size.
+ std::string info = quiche::QuicheStrCat(
+ "total_length: ", serialized_length,
+ " padding_size: ", serialized_length - length_, " packets: {");
+ // Packets' encryption levels.
+ bool first_packet = true;
+ for (int8_t i = ENCRYPTION_INITIAL; i < NUM_ENCRYPTION_LEVELS; ++i) {
+ if (ContainsPacketOfEncryptionLevel(static_cast<EncryptionLevel>(i))) {
+ info = quiche::QuicheStrCat(
+ info, first_packet ? "" : ", ",
+ EncryptionLevelToString(static_cast<EncryptionLevel>(i)));
+ first_packet = false;
+ }
+ }
+ info = quiche::QuicheStrCat(info, "}");
+ return info;
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet.h b/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet.h
index f03f87544b9..1974f77c56b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet.h
@@ -34,6 +34,8 @@ class QUIC_EXPORT_PRIVATE QuicCoalescedPacket {
size_t buffer_len,
size_t* length_copied) const;
+ std::string ToString(size_t serialized_length) const;
+
const SerializedPacket* initial_packet() const {
return initial_packet_.get();
}
@@ -47,6 +49,9 @@ class QUIC_EXPORT_PRIVATE QuicCoalescedPacket {
QuicPacketLength max_packet_length() const { return max_packet_length_; }
private:
+ // Returns true if this coalesced packet contains packet of |level|.
+ bool ContainsPacketOfEncryptionLevel(EncryptionLevel level) const;
+
// self/peer addresses are set when trying to coalesce the first packet.
// Packets with different self/peer addresses cannot be coalesced.
QuicSocketAddress self_address_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet_test.cc
index 8213480bf91..0a7a51efc79 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet_test.cc
@@ -7,6 +7,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/test_tools/quiche_test_utils.h"
namespace quic {
namespace test {
@@ -14,6 +15,8 @@ namespace {
TEST(QuicCoalescedPacketTest, MaybeCoalescePacket) {
QuicCoalescedPacket coalesced;
+ EXPECT_EQ("total_length: 0 padding_size: 0 packets: {}",
+ coalesced.ToString(0));
SimpleBufferAllocator allocator;
EXPECT_EQ(0u, coalesced.length());
char buffer[1000];
@@ -29,6 +32,9 @@ TEST(QuicCoalescedPacketTest, MaybeCoalescePacket) {
&allocator, 1500));
EXPECT_EQ(1500u, coalesced.max_packet_length());
EXPECT_EQ(500u, coalesced.length());
+ EXPECT_EQ(
+ "total_length: 1500 padding_size: 1000 packets: {ENCRYPTION_INITIAL}",
+ coalesced.ToString(1500));
// Cannot coalesce packet of the same encryption level.
SerializedPacket packet2(QuicPacketNumber(2), PACKET_4BYTE_PACKET_NUMBER,
@@ -44,6 +50,10 @@ TEST(QuicCoalescedPacketTest, MaybeCoalescePacket) {
&allocator, 1500));
EXPECT_EQ(1500u, coalesced.max_packet_length());
EXPECT_EQ(1000u, coalesced.length());
+ EXPECT_EQ(
+ "total_length: 1500 padding_size: 500 packets: {ENCRYPTION_INITIAL, "
+ "ENCRYPTION_ZERO_RTT}",
+ coalesced.ToString(1500));
SerializedPacket packet4(QuicPacketNumber(4), PACKET_4BYTE_PACKET_NUMBER,
buffer, 500, false, false);
@@ -105,8 +115,8 @@ TEST(QuicCoalescedPacketTest, CopyEncryptedBuffers) {
char expected[1000];
memset(expected, 'a', 500);
memset(expected + 500, 'b', 500);
- test::CompareCharArraysWithHexError("copied buffers", copy_buffer,
- length_copied, expected, 1000);
+ quiche::test::CompareCharArraysWithHexError("copied buffers", copy_buffer,
+ length_copied, expected, 1000);
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_config.cc b/chromium/net/third_party/quiche/src/quic/core/quic_config.cc
index 3d8fe3fa318..d0087c46f09 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_config.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_config.cc
@@ -20,8 +20,8 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_macros.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_uint128.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -380,7 +380,7 @@ QuicErrorCode QuicFixedSocketAddress::ProcessPeerHello(
const CryptoHandshakeMessage& peer_hello,
HelloType /*hello_type*/,
std::string* error_details) {
- QuicStringPiece address;
+ quiche::QuicheStringPiece address;
if (!peer_hello.GetStringPiece(tag_, &address)) {
if (presence_ == PRESENCE_REQUIRED) {
*error_details = "Missing " + QuicTagToString(tag_);
@@ -404,7 +404,8 @@ QuicConfig::QuicConfig()
client_connection_options_(kCLOP, PRESENCE_OPTIONAL),
idle_network_timeout_seconds_(kICSL, PRESENCE_REQUIRED),
silent_close_(kSCLS, PRESENCE_OPTIONAL),
- max_incoming_bidirectional_streams_(kMIBS, PRESENCE_REQUIRED),
+ max_bidirectional_streams_(kMIBS, PRESENCE_REQUIRED),
+ max_unidirectional_streams_(kMIUS, PRESENCE_OPTIONAL),
bytes_for_connection_id_(kTCID, PRESENCE_OPTIONAL),
initial_round_trip_time_us_(kIRTT, PRESENCE_OPTIONAL),
initial_max_stream_data_bytes_incoming_bidirectional_(0,
@@ -418,7 +419,6 @@ QuicConfig::QuicConfig()
alternate_server_address_(kASAD, PRESENCE_OPTIONAL),
support_max_header_list_size_(kSMHL, PRESENCE_OPTIONAL),
stateless_reset_token_(kSRST, PRESENCE_OPTIONAL),
- max_incoming_unidirectional_streams_(kMIUS, PRESENCE_OPTIONAL),
max_ack_delay_ms_(kMAD, PRESENCE_OPTIONAL),
ack_delay_exponent_(kADE, PRESENCE_OPTIONAL),
max_packet_size_(0, PRESENCE_OPTIONAL),
@@ -515,38 +515,36 @@ bool QuicConfig::SilentClose() const {
return silent_close_.GetUint32() > 0;
}
-void QuicConfig::SetMaxIncomingBidirectionalStreamsToSend(
- uint32_t max_streams) {
- max_incoming_bidirectional_streams_.SetSendValue(max_streams);
+void QuicConfig::SetMaxBidirectionalStreamsToSend(uint32_t max_streams) {
+ max_bidirectional_streams_.SetSendValue(max_streams);
}
-uint32_t QuicConfig::GetMaxIncomingBidirectionalStreamsToSend() const {
- return max_incoming_bidirectional_streams_.GetSendValue();
+uint32_t QuicConfig::GetMaxBidirectionalStreamsToSend() const {
+ return max_bidirectional_streams_.GetSendValue();
}
-bool QuicConfig::HasReceivedMaxIncomingBidirectionalStreams() const {
- return max_incoming_bidirectional_streams_.HasReceivedValue();
+bool QuicConfig::HasReceivedMaxBidirectionalStreams() const {
+ return max_bidirectional_streams_.HasReceivedValue();
}
-uint32_t QuicConfig::ReceivedMaxIncomingBidirectionalStreams() const {
- return max_incoming_bidirectional_streams_.GetReceivedValue();
+uint32_t QuicConfig::ReceivedMaxBidirectionalStreams() const {
+ return max_bidirectional_streams_.GetReceivedValue();
}
-void QuicConfig::SetMaxIncomingUnidirectionalStreamsToSend(
- uint32_t max_streams) {
- max_incoming_unidirectional_streams_.SetSendValue(max_streams);
+void QuicConfig::SetMaxUnidirectionalStreamsToSend(uint32_t max_streams) {
+ max_unidirectional_streams_.SetSendValue(max_streams);
}
-uint32_t QuicConfig::GetMaxIncomingUnidirectionalStreamsToSend() const {
- return max_incoming_unidirectional_streams_.GetSendValue();
+uint32_t QuicConfig::GetMaxUnidirectionalStreamsToSend() const {
+ return max_unidirectional_streams_.GetSendValue();
}
-bool QuicConfig::HasReceivedMaxIncomingUnidirectionalStreams() const {
- return max_incoming_unidirectional_streams_.HasReceivedValue();
+bool QuicConfig::HasReceivedMaxUnidirectionalStreams() const {
+ return max_unidirectional_streams_.HasReceivedValue();
}
-uint32_t QuicConfig::ReceivedMaxIncomingUnidirectionalStreams() const {
- return max_incoming_unidirectional_streams_.GetReceivedValue();
+uint32_t QuicConfig::ReceivedMaxUnidirectionalStreams() const {
+ return max_unidirectional_streams_.GetReceivedValue();
}
void QuicConfig::SetMaxAckDelayToSendMs(uint32_t max_ack_delay_ms) {
@@ -828,8 +826,8 @@ void QuicConfig::SetDefaults() {
idle_network_timeout_seconds_.set(kMaximumIdleTimeoutSecs,
kDefaultIdleTimeoutSecs);
silent_close_.set(1, 0);
- SetMaxIncomingBidirectionalStreamsToSend(kDefaultMaxStreamsPerConnection);
- SetMaxIncomingUnidirectionalStreamsToSend(kDefaultMaxStreamsPerConnection);
+ SetMaxBidirectionalStreamsToSend(kDefaultMaxStreamsPerConnection);
+ SetMaxUnidirectionalStreamsToSend(kDefaultMaxStreamsPerConnection);
max_time_before_crypto_handshake_ =
QuicTime::Delta::FromSeconds(kMaxTimeForCryptoHandshakeSecs);
max_idle_time_before_crypto_handshake_ =
@@ -853,9 +851,9 @@ void QuicConfig::ToHandshakeMessage(
// Do not need a version check here, max...bi... will encode
// as "MIDS" -- the max initial dynamic streams tag -- if
// doing some version other than IETF QUIC.
- max_incoming_bidirectional_streams_.ToHandshakeMessage(out);
+ max_bidirectional_streams_.ToHandshakeMessage(out);
if (VersionHasIetfQuicFrames(transport_version)) {
- max_incoming_unidirectional_streams_.ToHandshakeMessage(out);
+ max_unidirectional_streams_.ToHandshakeMessage(out);
ack_delay_exponent_.ToHandshakeMessage(out);
}
if (GetQuicReloadableFlag(quic_negotiate_ack_delay_time)) {
@@ -889,12 +887,12 @@ QuicErrorCode QuicConfig::ProcessPeerHello(
silent_close_.ProcessPeerHello(peer_hello, hello_type, error_details);
}
if (error == QUIC_NO_ERROR) {
- error = max_incoming_bidirectional_streams_.ProcessPeerHello(
- peer_hello, hello_type, error_details);
+ error = max_bidirectional_streams_.ProcessPeerHello(peer_hello, hello_type,
+ error_details);
}
if (error == QUIC_NO_ERROR) {
- error = max_incoming_unidirectional_streams_.ProcessPeerHello(
- peer_hello, hello_type, error_details);
+ error = max_unidirectional_streams_.ProcessPeerHello(peer_hello, hello_type,
+ error_details);
}
if (error == QUIC_NO_ERROR) {
error = bytes_for_connection_id_.ProcessPeerHello(peer_hello, hello_type,
@@ -975,9 +973,9 @@ bool QuicConfig::FillTransportParameters(TransportParameters* params) const {
params->initial_max_stream_data_uni.set_value(
GetInitialMaxStreamDataBytesUnidirectionalToSend());
params->initial_max_streams_bidi.set_value(
- GetMaxIncomingBidirectionalStreamsToSend());
+ GetMaxBidirectionalStreamsToSend());
params->initial_max_streams_uni.set_value(
- GetMaxIncomingUnidirectionalStreamsToSend());
+ GetMaxUnidirectionalStreamsToSend());
if (GetQuicReloadableFlag(quic_negotiate_ack_delay_time)) {
QUIC_RELOADABLE_FLAG_COUNT_N(quic_negotiate_ack_delay_time, 3, 4);
params->max_ack_delay.set_value(kDefaultDelayedAckTimeMs);
@@ -1048,11 +1046,6 @@ QuicErrorCode QuicConfig::ProcessTransportParameters(
if (params.max_packet_size.IsValid()) {
max_packet_size_.SetReceivedValue(params.max_packet_size.value());
- if (ReceivedMaxPacketSize() < kMaxOutgoingPacketSize) {
- // TODO(dschinazi) act on this.
- QUIC_DLOG(ERROR) << "Ignoring peer's requested max packet size of "
- << ReceivedMaxPacketSize();
- }
}
if (params.max_datagram_frame_size.IsValid()) {
@@ -1064,10 +1057,10 @@ QuicErrorCode QuicConfig::ProcessTransportParameters(
initial_session_flow_control_window_bytes_.SetReceivedValue(
std::min<uint64_t>(params.initial_max_data.value(),
std::numeric_limits<uint32_t>::max()));
- max_incoming_bidirectional_streams_.SetReceivedValue(
+ max_bidirectional_streams_.SetReceivedValue(
std::min<uint64_t>(params.initial_max_streams_bidi.value(),
std::numeric_limits<uint32_t>::max()));
- max_incoming_unidirectional_streams_.SetReceivedValue(
+ max_unidirectional_streams_.SetReceivedValue(
std::min<uint64_t>(params.initial_max_streams_uni.value(),
std::numeric_limits<uint32_t>::max()));
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_config.h b/chromium/net/third_party/quiche/src/quic/core/quic_config.h
index de78d40144a..95a26cb0d8f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_config.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_config.h
@@ -305,25 +305,21 @@ class QUIC_EXPORT_PRIVATE QuicConfig {
bool SilentClose() const;
- // Configuration for the Google QUIC and IETF QUIC stream ID managers. Note
- // that the naming is a bit weird; it is from the perspective of the node
- // generating (sending) the configuration and, thus, The "incoming" counts are
- // the number of streams that the node sending the configuration is willing to
- // accept and therefore the number that the node receiving the confguration
- // can create .. the number of outbound streams that may be intiated..
- // There are two sets, one for unidirectional streams and one for
- // bidirectional. The bidirectional set also covers Google-QUICs
- // dynamic stream count (which are bidirectional streams).
- // TODO(b/142351095) rename these to improve clarity.
- void SetMaxIncomingBidirectionalStreamsToSend(uint32_t max_streams);
- uint32_t GetMaxIncomingBidirectionalStreamsToSend() const;
- bool HasReceivedMaxIncomingBidirectionalStreams() const;
- uint32_t ReceivedMaxIncomingBidirectionalStreams() const;
-
- void SetMaxIncomingUnidirectionalStreamsToSend(uint32_t max_streams);
- uint32_t GetMaxIncomingUnidirectionalStreamsToSend() const;
- bool HasReceivedMaxIncomingUnidirectionalStreams() const;
- uint32_t ReceivedMaxIncomingUnidirectionalStreams() const;
+ // Sets the max bidirectional stream count that this endpoint supports.
+ void SetMaxBidirectionalStreamsToSend(uint32_t max_streams);
+ uint32_t GetMaxBidirectionalStreamsToSend() const;
+
+ bool HasReceivedMaxBidirectionalStreams() const;
+ // Gets the max bidirectional stream limit imposed by the peer.
+ uint32_t ReceivedMaxBidirectionalStreams() const;
+
+ // Sets the max unidirectional stream count that this endpoint supports.
+ void SetMaxUnidirectionalStreamsToSend(uint32_t max_streams);
+ uint32_t GetMaxUnidirectionalStreamsToSend() const;
+
+ bool HasReceivedMaxUnidirectionalStreams() const;
+ // Gets the max unidirectional stream limit imposed by the peer.
+ uint32_t ReceivedMaxUnidirectionalStreams() const;
void set_max_time_before_crypto_handshake(
QuicTime::Delta max_time_before_crypto_handshake) {
@@ -529,10 +525,21 @@ class QUIC_EXPORT_PRIVATE QuicConfig {
QuicNegotiableUint32 idle_network_timeout_seconds_;
// Whether to use silent close. Defaults to 0 (false) and is otherwise true.
QuicNegotiableUint32 silent_close_;
- // Maximum number of incoming dynamic streams that a Google QUIC connection
- // can support or the maximum number of incoming bidirectional streams that
+ // Maximum number of dynamic streams that a Google QUIC connection
+ // can support or the maximum number of bidirectional streams that
// an IETF QUIC connection can support.
- QuicFixedUint32 max_incoming_bidirectional_streams_;
+ // The SendValue is the limit on peer-created streams that this endpoint is
+ // advertising.
+ // The ReceivedValue is the limit on locally-created streams that
+ // the peer advertised.
+ QuicFixedUint32 max_bidirectional_streams_;
+ // Maximum number of unidirectional streams that the connection can
+ // support.
+ // The SendValue is the limit on peer-created streams that this endpoint is
+ // advertising.
+ // The ReceivedValue is the limit on locally-created streams that the peer
+ // advertised.
+ QuicFixedUint32 max_unidirectional_streams_;
// The number of bytes required for the connection ID.
QuicFixedUint32 bytes_for_connection_id_;
// Initial round trip time estimate in microseconds.
@@ -569,10 +576,6 @@ class QUIC_EXPORT_PRIVATE QuicConfig {
// packet to be processed.
QuicTagVector create_session_tag_indicators_;
- // Maximum number of incoming unidirectional streams that the connection can
- // support.
- QuicFixedUint32 max_incoming_unidirectional_streams_;
-
// Maximum ack delay. The sent value is the value used on this node.
// The received value is the value received from the peer and used by
// the peer.
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection.cc b/chromium/net/third_party/quiche/src/quic/core/quic_connection.cc
index 9349bf234fd..f83dbdd8950 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_connection.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_connection.cc
@@ -23,6 +23,7 @@
#include "net/third_party/quiche/src/quic/core/quic_bandwidth.h"
#include "net/third_party/quiche/src/quic/core/quic_config.h"
#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
@@ -34,9 +35,10 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
@@ -65,7 +67,6 @@ class AckAlarmDelegate : public QuicAlarm::Delegate {
if (connection_->SupportsMultiplePacketNumberSpaces()) {
connection_->SendAllPendingAcks();
} else {
- DCHECK(!connection_->GetUpdatedAckFrame().ack_frame->packets.Empty());
connection_->SendAck();
}
}
@@ -194,8 +195,8 @@ bool PacketCanReplaceConnectionId(const QuicPacketHeader& header,
Perspective perspective) {
return perspective == Perspective::IS_CLIENT &&
header.form == IETF_QUIC_LONG_HEADER_PACKET &&
- QuicUtils::VariableLengthConnectionIdAllowedForVersion(
- header.version.transport_version) &&
+ header.version.IsKnown() &&
+ header.version.AllowsVariableLengthConnectionIds() &&
(header.long_packet_type == INITIAL ||
header.long_packet_type == RETRY);
}
@@ -302,13 +303,14 @@ QuicConnection::QuicConnection(
clock_,
random_generator_,
&stats_,
- GetDefaultCongestionControlType(),
- kNack),
+ GetDefaultCongestionControlType()),
version_negotiated_(false),
perspective_(perspective),
connected_(true),
can_truncate_connection_ids_(perspective == Perspective::IS_SERVER),
mtu_probe_count_(0),
+ previous_validated_mtu_(0),
+ peer_max_packet_size_(kDefaultMaxPacketSizeTransportParam),
largest_received_packet_size_(0),
write_error_occurred_(false),
no_stop_waiting_frames_(
@@ -316,6 +318,7 @@ QuicConnection::QuicConnection(
consecutive_num_packets_with_no_retransmittable_frames_(0),
max_consecutive_num_packets_with_no_retransmittable_frames_(
kMaxConsecutiveNonRetransmittablePackets),
+ bundle_retransmittable_with_pto_ack_(false),
fill_up_link_during_probing_(false),
probing_retransmission_pending_(false),
stateless_reset_token_received_(false),
@@ -325,16 +328,16 @@ QuicConnection::QuicConnection(
processing_ack_frame_(false),
supports_release_time_(false),
release_time_into_future_(QuicTime::Delta::Zero()),
- retry_has_been_parsed_(false),
+ drop_incoming_retry_packets_(false),
max_consecutive_ptos_(0),
bytes_received_before_address_validation_(0),
bytes_sent_before_address_validation_(0),
address_validated_(false),
- quic_version_negotiated_by_default_at_server_(
- GetQuicReloadableFlag(quic_version_negotiated_by_default_at_server)),
- use_handshake_delegate_(
- GetQuicReloadableFlag(quic_use_handshaker_delegate) ||
- version().handshake_protocol == PROTOCOL_TLS1_3) {
+ blackhole_detector_(this, &arena_, alarm_factory_),
+ idle_network_detector_(this,
+ clock_->ApproximateNow(),
+ &arena_,
+ alarm_factory_) {
QUIC_DLOG(INFO) << ENDPOINT << "Created connection with server connection ID "
<< server_connection_id
<< " and version: " << ParsedQuicVersionToString(version());
@@ -344,9 +347,6 @@ QuicConnection::QuicConnection(
<< "QuicConnection: attempted to use server connection ID "
<< server_connection_id << " which is invalid with version "
<< QuicVersionToString(transport_version());
- if (use_handshake_delegate_) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_use_handshaker_delegate);
- }
framer_.set_visitor(this);
stats_.connection_creation_time = clock_->ApproximateNow();
@@ -372,11 +372,10 @@ QuicConnection::QuicConnection(
supported_versions.size() == 1);
InstallInitialCrypters(server_connection_id_);
- if (quic_version_negotiated_by_default_at_server() &&
- perspective_ == Perspective::IS_SERVER) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_version_negotiated_by_default_at_server);
- version_negotiated_ = true;
- framer_.InferPacketHeaderTypeFromVersion();
+ // On the server side, version negotiation has been done by the dispatcher,
+ // and the server connection is created with the right version.
+ if (perspective_ == Perspective::IS_SERVER) {
+ SetVersionNegotiated();
}
}
@@ -446,11 +445,9 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) {
}
if (config.HasClientSentConnectionOption(k7PTO, perspective_)) {
max_consecutive_ptos_ = 6;
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_pto, 3, 8);
}
if (config.HasClientSentConnectionOption(k8PTO, perspective_)) {
max_consecutive_ptos_ = 7;
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_pto, 4, 8);
}
}
if (config.HasClientSentConnectionOption(kNSTP, perspective_)) {
@@ -469,6 +466,15 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) {
framer_.set_process_timestamps(true);
uber_received_packet_manager_.set_save_timestamps(true);
}
+ if (GetQuicReloadableFlag(quic_bundle_retransmittable_with_pto_ack) &&
+ config.HasClientSentConnectionOption(kEACK, perspective_)) {
+ bundle_retransmittable_with_pto_ack_ = true;
+ }
+ if (config.HasReceivedMaxPacketSize()) {
+ peer_max_packet_size_ = config.ReceivedMaxPacketSize();
+ packet_creator_.SetMaxPacketLength(
+ GetLimitedMaxPacketSize(packet_creator_.max_packet_length()));
+ }
supports_release_time_ =
writer_ != nullptr && writer_->SupportsReleaseTime() &&
@@ -509,6 +515,15 @@ void QuicConnection::AdjustNetworkParameters(
sent_packet_manager_.AdjustNetworkParameters(params);
}
+void QuicConnection::SetLossDetectionTuner(
+ std::unique_ptr<LossDetectionTunerInterface> tuner) {
+ sent_packet_manager_.SetLossDetectionTuner(std::move(tuner));
+}
+
+void QuicConnection::OnConfigNegotiated() {
+ sent_packet_manager_.OnConfigNegotiated();
+}
+
QuicBandwidth QuicConnection::MaxPacingRate() const {
return sent_packet_manager_.MaxPacingRate();
}
@@ -606,7 +621,7 @@ void QuicConnection::OnVersionNegotiationPacket(
}
if (QuicContainsValue(packet.versions, version())) {
- const std::string error_details = QuicStrCat(
+ const std::string error_details = quiche::QuicheStrCat(
"Server already supports client's version ",
ParsedQuicVersionToString(version()),
" and should have accepted the connection instead of sending {",
@@ -620,7 +635,7 @@ void QuicConnection::OnVersionNegotiationPacket(
server_supported_versions_ = packet.versions;
CloseConnection(
QUIC_INVALID_VERSION,
- QuicStrCat(
+ quiche::QuicheStrCat(
"Client may support one of the versions in the server's list, but "
"it's going to close the connection anyway. Supported versions: {",
ParsedQuicVersionVectorToString(framer_.supported_versions()),
@@ -630,28 +645,40 @@ void QuicConnection::OnVersionNegotiationPacket(
}
// Handles retry for client connection.
-void QuicConnection::OnRetryPacket(QuicConnectionId original_connection_id,
- QuicConnectionId new_connection_id,
- QuicStringPiece retry_token) {
+void QuicConnection::OnRetryPacket(
+ QuicConnectionId original_connection_id,
+ QuicConnectionId new_connection_id,
+ quiche::QuicheStringPiece retry_token,
+ quiche::QuicheStringPiece retry_integrity_tag,
+ quiche::QuicheStringPiece retry_without_tag) {
DCHECK_EQ(Perspective::IS_CLIENT, perspective_);
- if (original_connection_id != server_connection_id_) {
- QUIC_DLOG(ERROR) << "Ignoring RETRY with original connection ID "
- << original_connection_id << " not matching expected "
- << server_connection_id_ << " token "
- << QuicTextUtils::HexEncode(retry_token);
- return;
+ if (version().HasRetryIntegrityTag()) {
+ if (!CryptoUtils::ValidateRetryIntegrityTag(
+ version(), server_connection_id_, retry_without_tag,
+ retry_integrity_tag)) {
+ QUIC_DLOG(ERROR) << "Ignoring RETRY with invalid integrity tag";
+ return;
+ }
+ } else {
+ if (original_connection_id != server_connection_id_) {
+ QUIC_DLOG(ERROR) << "Ignoring RETRY with original connection ID "
+ << original_connection_id << " not matching expected "
+ << server_connection_id_ << " token "
+ << quiche::QuicheTextUtils::HexEncode(retry_token);
+ return;
+ }
}
- if (retry_has_been_parsed_) {
- QUIC_DLOG(ERROR) << "Ignoring non-first RETRY with token "
- << QuicTextUtils::HexEncode(retry_token);
+ if (drop_incoming_retry_packets_) {
+ QUIC_DLOG(ERROR) << "Ignoring RETRY with token "
+ << quiche::QuicheTextUtils::HexEncode(retry_token);
return;
}
- retry_has_been_parsed_ = true;
+ drop_incoming_retry_packets_ = true;
stats_.retry_packet_processed = true;
QUIC_DLOG(INFO) << "Received RETRY, replacing connection ID "
<< server_connection_id_ << " with " << new_connection_id
<< ", received token "
- << QuicTextUtils::HexEncode(retry_token);
+ << quiche::QuicheTextUtils::HexEncode(retry_token);
server_connection_id_ = new_connection_id;
packet_creator_.SetServerConnectionId(server_connection_id_);
packet_creator_.SetRetryToken(retry_token);
@@ -679,6 +706,11 @@ void QuicConnection::AddIncomingConnectionId(QuicConnectionId connection_id) {
bool QuicConnection::OnUnauthenticatedPublicHeader(
const QuicPacketHeader& header) {
+ // As soon as we receive an initial we start ignoring subsequent retries.
+ if (header.version_flag && header.long_packet_type == INITIAL) {
+ drop_incoming_retry_packets_ = true;
+ }
+
QuicConnectionId server_connection_id =
GetServerConnectionIdAsRecipient(header, perspective_);
@@ -758,31 +790,6 @@ bool QuicConnection::OnUnauthenticatedHeader(const QuicPacketHeader& header) {
return false;
}
- if (!quic_version_negotiated_by_default_at_server()) {
- if (!version_negotiated_ && perspective_ == Perspective::IS_SERVER) {
- if (!header.version_flag) {
- // Packets should have the version flag till version negotiation is
- // done.
- std::string error_details =
- QuicStrCat(ENDPOINT, "Packet ", header.packet_number.ToUint64(),
- " without version flag before version negotiated.");
- QUIC_DLOG(WARNING) << error_details;
- CloseConnection(QUIC_INVALID_VERSION, error_details,
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- return false;
- } else {
- DCHECK_EQ(header.version, version());
- version_negotiated_ = true;
- framer_.InferPacketHeaderTypeFromVersion();
- visitor_->OnSuccessfulVersionNegotiation(version());
- if (debug_visitor_ != nullptr) {
- debug_visitor_->OnSuccessfulVersionNegotiation(version());
- }
- }
- DCHECK(version_negotiated_);
- }
- }
-
return true;
}
@@ -802,17 +809,7 @@ void QuicConnection::OnDecryptedPacket(EncryptionLevel level) {
address_validated_ = true;
}
- if (use_handshake_delegate_) {
- visitor_->OnPacketDecrypted(level);
- return;
- }
-
- // Once the server receives a forward secure packet, the handshake is
- // confirmed.
- if (level == ENCRYPTION_FORWARD_SECURE &&
- perspective_ == Perspective::IS_SERVER) {
- OnHandshakeComplete();
- }
+ visitor_->OnPacketDecrypted(level);
}
QuicSocketAddress QuicConnection::GetEffectivePeerAddressFromCurrentPacket()
@@ -882,7 +879,7 @@ bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) {
// frames, since the processing may result in sending a bundled ack.
uber_received_packet_manager_.RecordPacketReceived(
last_decrypted_packet_level_, last_header_,
- time_of_last_received_packet_);
+ GetTimeOfLastReceivedPacket());
DCHECK(connected_);
return true;
}
@@ -962,11 +959,11 @@ bool QuicConnection::OnAckFrameStart(QuicPacketNumber largest_acked,
return true;
}
- if (!GetLargestSentPacket().IsInitialized() ||
- largest_acked > GetLargestSentPacket()) {
+ if (!sent_packet_manager_.GetLargestSentPacket().IsInitialized() ||
+ largest_acked > sent_packet_manager_.GetLargestSentPacket()) {
QUIC_DLOG(WARNING) << ENDPOINT
<< "Peer's observed unsent packet:" << largest_acked
- << " vs " << GetLargestSentPacket()
+ << " vs " << sent_packet_manager_.GetLargestSentPacket()
<< ". SupportsMultiplePacketNumberSpaces():"
<< SupportsMultiplePacketNumberSpaces()
<< ", last_decrypted_packet_level_:"
@@ -983,7 +980,7 @@ bool QuicConnection::OnAckFrameStart(QuicPacketNumber largest_acked,
}
processing_ack_frame_ = true;
sent_packet_manager_.OnAckFrameStart(largest_acked, ack_delay_time,
- time_of_last_received_packet_);
+ GetTimeOfLastReceivedPacket());
return true;
}
@@ -1026,8 +1023,10 @@ bool QuicConnection::OnAckFrameEnd(QuicPacketNumber start) {
QUIC_DLOG(INFO) << ENDPOINT << "Received an old ack frame: ignoring";
return true;
}
+ const bool one_rtt_packet_was_acked =
+ sent_packet_manager_.one_rtt_packet_acked();
const AckResult ack_result = sent_packet_manager_.OnAckFrameEnd(
- time_of_last_received_packet_, last_header_.packet_number,
+ GetTimeOfLastReceivedPacket(), last_header_.packet_number,
last_decrypted_packet_level_);
if (ack_result != PACKETS_NEWLY_ACKED &&
ack_result != NO_PACKETS_NEWLY_ACKED) {
@@ -1038,6 +1037,10 @@ bool QuicConnection::OnAckFrameEnd(QuicPacketNumber start) {
<< QuicUtils::AckResultToString(ack_result);
return false;
}
+ if (SupportsMultiplePacketNumberSpaces() && !one_rtt_packet_was_acked &&
+ sent_packet_manager_.one_rtt_packet_acked()) {
+ visitor_->OnOneRttPacketAcknowledged();
+ }
// Cancel the send alarm because new packets likely have been acked, which
// may change the congestion window and/or pacing rate. Canceling the alarm
// causes CanWrite to recalculate the next send time.
@@ -1189,13 +1192,6 @@ bool QuicConnection::OnPathChallengeFrame(const QuicPathChallengeFrame& frame) {
// response.
received_path_challenge_payloads_.push_back(frame.data_buffer);
- // For VERSION 99 we define a "Padded PATH CHALLENGE" to be the same thing
- // as a PADDED PING -- it will start a connectivity check and prevent
- // connection migration. Insofar as the connectivity check and connection
- // migration are concerned, logically the PATH CHALLENGE is the same as the
- // PING, so as a stopgap, tell the FSM that determines whether we have a
- // Padded PING or not that we received a PING.
- UpdatePacketContent(FIRST_FRAME_IS_PING);
should_last_packet_instigate_acks_ = true;
return true;
}
@@ -1212,7 +1208,6 @@ bool QuicConnection::OnPathResponseFrame(const QuicPathResponseFrame& frame) {
}
// Have received the matching PATH RESPONSE, saved payload no longer valid.
transmitted_connectivity_probe_payload_ = nullptr;
- UpdatePacketContent(FIRST_FRAME_IS_PING);
return true;
}
@@ -1268,7 +1263,7 @@ bool QuicConnection::OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) {
if (debug_visitor_ != nullptr) {
debug_visitor_->OnMaxStreamsFrame(frame);
}
- return visitor_->OnMaxStreamsFrame(frame);
+ return visitor_->OnMaxStreamsFrame(frame) && connected_;
}
bool QuicConnection::OnStreamsBlockedFrame(
@@ -1276,7 +1271,7 @@ bool QuicConnection::OnStreamsBlockedFrame(
if (debug_visitor_ != nullptr) {
debug_visitor_->OnStreamsBlockedFrame(frame);
}
- return visitor_->OnStreamsBlockedFrame(frame);
+ return visitor_->OnStreamsBlockedFrame(frame) && connected_;
}
bool QuicConnection::OnGoAwayFrame(const QuicGoAwayFrame& frame) {
@@ -1307,7 +1302,7 @@ bool QuicConnection::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) {
UpdatePacketContent(NOT_PADDED_PING);
if (debug_visitor_ != nullptr) {
- debug_visitor_->OnWindowUpdateFrame(frame, time_of_last_received_packet_);
+ debug_visitor_->OnWindowUpdateFrame(frame, GetTimeOfLastReceivedPacket());
}
QUIC_DVLOG(1) << ENDPOINT << "WINDOW_UPDATE_FRAME received " << frame;
visitor_->OnWindowUpdateFrame(frame);
@@ -1349,7 +1344,29 @@ bool QuicConnection::OnMessageFrame(const QuicMessageFrame& frame) {
debug_visitor_->OnMessageFrame(frame);
}
visitor_->OnMessageReceived(
- QuicStringPiece(frame.data, frame.message_length));
+ quiche::QuicheStringPiece(frame.data, frame.message_length));
+ should_last_packet_instigate_acks_ = true;
+ return connected_;
+}
+
+bool QuicConnection::OnHandshakeDoneFrame(const QuicHandshakeDoneFrame& frame) {
+ DCHECK(connected_ && VersionHasIetfQuicFrames(transport_version()));
+
+ if (perspective_ == Perspective::IS_SERVER) {
+ CloseConnection(IETF_QUIC_PROTOCOL_VIOLATION,
+ "Server received handshake done frame.",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
+ }
+
+ // Since a handshake done frame was received, this is not a connectivity
+ // probe. A probe only contains a PING and full padding.
+ UpdatePacketContent(NOT_PADDED_PING);
+
+ if (debug_visitor_ != nullptr) {
+ debug_visitor_->OnHandshakeDoneFrame(frame);
+ }
+ visitor_->OnHandshakeDoneReceived();
should_last_packet_instigate_acks_ = true;
return connected_;
}
@@ -1380,6 +1397,7 @@ void QuicConnection::OnPacketComplete() {
}
if (IsCurrentPacketConnectivityProbing()) {
+ DCHECK(!version().HasIetfQuicFrames());
++stats_.num_connectivity_probing_received;
}
@@ -1396,12 +1414,7 @@ void QuicConnection::OnPacketComplete() {
<< IsCurrentPacketConnectivityProbing();
if (IsCurrentPacketConnectivityProbing()) {
- QUIC_DVLOG(1) << ENDPOINT << "Received a connectivity probing packet for "
- << GetServerConnectionIdAsRecipient(last_header_,
- perspective_)
- << " from ip:port: " << last_packet_source_address_.ToString()
- << " to ip:port: "
- << last_packet_destination_address_.ToString();
+ DCHECK(!version().HasIetfQuicFrames());
visitor_->OnPacketReceived(last_packet_destination_address_,
last_packet_source_address_,
/*is_connectivity_probe=*/true);
@@ -1418,57 +1431,36 @@ void QuicConnection::OnPacketComplete() {
visitor_->OnPacketReceived(last_packet_destination_address_,
last_packet_source_address_,
/*is_connectivity_probe=*/false);
- } else {
- // This node is not a client (is a server) AND the received packet was
- // NOT connectivity-probing. If the packet had PATH CHALLENGES, send
- // appropriate RESPONSE. Then deal with possible peer migration.
- if (VersionHasIetfQuicFrames(transport_version()) &&
- !received_path_challenge_payloads_.empty()) {
- // If a PATH CHALLENGE was in a "Padded PING (or PATH CHALLENGE)"
- // then it is taken care of above. This handles the case where a PATH
- // CHALLENGE appeared someplace else (eg, the peer randomly added a PATH
- // CHALLENGE frame to some other packet.
- // There was at least one PATH CHALLENGE in the received packet,
- // Generate the required PATH RESPONSE.
- SendGenericPathProbePacket(nullptr, last_packet_source_address_,
- /* is_response= */ true);
- }
-
- if (last_header_.packet_number == GetLargestReceivedPacket()) {
- direct_peer_address_ = last_packet_source_address_;
- if (current_effective_peer_migration_type_ != NO_CHANGE) {
- // TODO(fayang): When multiple packet number spaces is supported, only
- // start peer migration for the application data.
- StartEffectivePeerMigration(current_effective_peer_migration_type_);
- }
+ } else if (version().HasIetfQuicFrames() &&
+ !received_path_challenge_payloads_.empty()) {
+ if (current_effective_peer_migration_type_ != NO_CHANGE) {
+ // TODO(b/150095588): change the stats to
+ // num_valid_path_challenge_received.
+ ++stats_.num_connectivity_probing_received;
+ }
+ // If the packet contains PATH CHALLENGE, send appropriate RESPONSE.
+ // There was at least one PATH CHALLENGE in the received packet,
+ // Generate the required PATH RESPONSE.
+ SendGenericPathProbePacket(nullptr, last_packet_source_address_,
+ /* is_response=*/true);
+ } else if (last_header_.packet_number == GetLargestReceivedPacket()) {
+ direct_peer_address_ = last_packet_source_address_;
+ if (current_effective_peer_migration_type_ != NO_CHANGE) {
+ // TODO(fayang): When multiple packet number spaces is supported, only
+ // start peer migration for the application data.
+ StartEffectivePeerMigration(current_effective_peer_migration_type_);
}
}
current_effective_peer_migration_type_ = NO_CHANGE;
- // Some encryption levels share a packet number space, it is therefore
- // possible for us to want to ack some packets even though we do not yet
- // have the appropriate keys to encrypt the acks. In this scenario we
- // do not update the ACK timeout. This can happen for example with
- // IETF QUIC on the server when we receive 0-RTT packets and do not yet
- // have 1-RTT keys (0-RTT packets are acked at the 1-RTT level).
- // Note that this could cause slight performance degradations in the edge
- // case where one packet is received, then the encrypter is installed,
- // then a second packet is received; as that could cause the ACK for the
- // second packet to be delayed instead of immediate. This is currently
- // considered to be small enough of an edge case to not be optimized for.
- if (!SupportsMultiplePacketNumberSpaces() ||
- framer_.HasEncrypterOfEncryptionLevel(QuicUtils::GetEncryptionLevel(
- QuicUtils::GetPacketNumberSpace(last_decrypted_packet_level_)))) {
- uber_received_packet_manager_.MaybeUpdateAckTimeout(
- should_last_packet_instigate_acks_, last_decrypted_packet_level_,
- last_header_.packet_number, time_of_last_received_packet_,
- clock_->ApproximateNow(), sent_packet_manager_.GetRttStats());
- } else {
- QUIC_DLOG(INFO) << ENDPOINT << "Not updating ACK timeout for "
- << EncryptionLevelToString(last_decrypted_packet_level_)
- << " as we do not have the corresponding encrypter";
- }
+ // For IETF QUIC, it is guaranteed that TLS will give connection the
+ // corresponding write key before read key. In other words, connection should
+ // never process a packet while an ACK for it cannot be encrypted.
+ uber_received_packet_manager_.MaybeUpdateAckTimeout(
+ should_last_packet_instigate_acks_, last_decrypted_packet_level_,
+ last_header_.packet_number, GetTimeOfLastReceivedPacket(),
+ clock_->ApproximateNow(), sent_packet_manager_.GetRttStats());
ClearLastFrames();
CloseIfTooManyOutstandingSentPackets();
@@ -1501,17 +1493,20 @@ void QuicConnection::CloseIfTooManyOutstandingSentPackets() {
sent_packet_manager_.GetLeastUnacked() + max_tracked_packets_) {
CloseConnection(
QUIC_TOO_MANY_OUTSTANDING_SENT_PACKETS,
- QuicStrCat("More than ", max_tracked_packets_,
- " outstanding, least_unacked: ",
- sent_packet_manager_.GetLeastUnacked().ToUint64(),
- ", packets_processed: ", stats_.packets_processed,
- ", last_decrypted_packet_level: ",
- EncryptionLevelToString(last_decrypted_packet_level_)),
+ quiche::QuicheStrCat(
+ "More than ", max_tracked_packets_, " outstanding, least_unacked: ",
+ sent_packet_manager_.GetLeastUnacked().ToUint64(),
+ ", packets_processed: ", stats_.packets_processed,
+ ", last_decrypted_packet_level: ",
+ EncryptionLevelToString(last_decrypted_packet_level_)),
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
}
}
const QuicFrame QuicConnection::GetUpdatedAckFrame() {
+ DCHECK(!uber_received_packet_manager_.IsAckFrameEmpty(
+ QuicUtils::GetPacketNumberSpace(encryption_level_)))
+ << "Try to retrieve an empty ACK frame";
return uber_received_packet_manager_.GetUpdatedAckFrame(
QuicUtils::GetPacketNumberSpace(encryption_level_),
clock_->ApproximateNow());
@@ -1576,7 +1571,7 @@ void QuicConnection::SendVersionNegotiationPacket(bool ietf_quic,
QUIC_DVLOG(2) << ENDPOINT << "Sending version negotiation packet: {"
<< ParsedQuicVersionVectorToString(framer_.supported_versions())
<< "}, " << (ietf_quic ? "" : "!") << "ietf_quic:" << std::endl
- << QuicTextUtils::HexDump(QuicStringPiece(
+ << quiche::QuicheTextUtils::HexDump(quiche::QuicheStringPiece(
version_packet->data(), version_packet->length()));
WriteResult result = writer_->WritePacket(
version_packet->data(), version_packet->length(), self_address().host(),
@@ -1693,15 +1688,16 @@ const QuicConnectionStats& QuicConnection::GetStats() {
stats_.srtt_us = srtt.ToMicroseconds();
stats_.estimated_bandwidth = sent_packet_manager_.BandwidthEstimate();
- if (GetQuicReloadableFlag(quic_log_ack_aggregation_stats)) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_log_ack_aggregation_stats);
- sent_packet_manager_.GetSendAlgorithm()->PopulateConnectionStats(&stats_);
- }
+ sent_packet_manager_.GetSendAlgorithm()->PopulateConnectionStats(&stats_);
stats_.max_packet_size = packet_creator_.max_packet_length();
stats_.max_received_packet_size = largest_received_packet_size_;
return stats_;
}
+void QuicConnection::ResetHasNonAppLimitedSampleAfterHandshakeCompletion() {
+ stats_.has_non_app_limited_sample = false;
+}
+
void QuicConnection::OnCoalescedPacket(const QuicEncryptedPacket& packet) {
QueueCoalescedPacket(packet);
}
@@ -1753,8 +1749,8 @@ void QuicConnection::ProcessUdpPacket(const QuicSocketAddress& self_address,
}
QUIC_DVLOG(2) << ENDPOINT << "Received encrypted " << packet.length()
<< " bytes:" << std::endl
- << QuicTextUtils::HexDump(
- QuicStringPiece(packet.data(), packet.length()));
+ << quiche::QuicheTextUtils::HexDump(quiche::QuicheStringPiece(
+ packet.data(), packet.length()));
QUIC_BUG_IF(current_packet_data_ != nullptr)
<< "ProcessUdpPacket must not be called while processing a packet.";
if (debug_visitor_ != nullptr) {
@@ -1799,9 +1795,14 @@ void QuicConnection::ProcessUdpPacket(const QuicSocketAddress& self_address,
<< " too far from current time:"
<< clock_->ApproximateNow().ToDebuggingValue();
}
- time_of_last_received_packet_ = packet.receipt_time();
+ if (use_idle_network_detector_) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_idle_network_detector, 1, 6);
+ idle_network_detector_.OnPacketReceived(packet.receipt_time());
+ } else {
+ time_of_last_received_packet_ = packet.receipt_time();
+ }
QUIC_DVLOG(1) << ENDPOINT << "time of last received packet: "
- << time_of_last_received_packet_.ToDebuggingValue();
+ << GetTimeOfLastReceivedPacket().ToDebuggingValue();
ScopedPacketFlusher flusher(this);
if (!framer_.ProcessPacket(packet)) {
@@ -2056,6 +2057,13 @@ void QuicConnection::NeuterUnencryptedPackets() {
sent_packet_manager_.NeuterUnencryptedPackets();
// This may have changed the retransmission timer, so re-arm it.
SetRetransmissionAlarm();
+ if (SupportsMultiplePacketNumberSpaces()) {
+ // Stop sending ack of initial packet number space.
+ uber_received_packet_manager_.ResetAckStates(ENCRYPTION_INITIAL);
+ // Re-arm ack alarm.
+ ack_alarm_->Update(uber_received_packet_manager_.GetEarliestAckTimeout(),
+ kAlarmGranularity);
+ }
}
bool QuicConnection::ShouldGeneratePacket(
@@ -2141,7 +2149,7 @@ bool QuicConnection::CanWrite(HasRetransmittableData retransmittable) {
return true;
}
// Cannot send packet now because delay is too far in the future.
- send_alarm_->Update(now + delay, QuicTime::Delta::FromMilliseconds(1));
+ send_alarm_->Update(now + delay, kAlarmGranularity);
QUIC_DVLOG(1) << ENDPOINT << "Delaying sending " << delay.ToMilliseconds()
<< "ms";
return false;
@@ -2164,8 +2172,11 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return true;
}
- SerializedPacketFate fate = DeterminePacketFate(
- /*is_mtu_discovery=*/packet->encrypted_length > long_term_mtu_);
+
+ const bool is_mtu_discovery = QuicUtils::ContainsFrameType(
+ packet->nonretransmittable_frames, MTU_DISCOVERY_FRAME);
+
+ SerializedPacketFate fate = DeterminePacketFate(is_mtu_discovery);
// Termination packets are encrypted and saved, so don't exit early.
const bool is_termination_packet = IsTerminationPacket(*packet);
QuicPacketNumber packet_number = packet->packet_number;
@@ -2183,10 +2194,8 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
new QuicEncryptedPacket(buffer_copy, encrypted_length, true));
}
- const bool looks_like_mtu_probe = packet->retransmittable_frames.empty() &&
- packet->encrypted_length > long_term_mtu_;
DCHECK_LE(encrypted_length, kMaxOutgoingPacketSize);
- if (!looks_like_mtu_probe) {
+ if (!is_mtu_discovery) {
DCHECK_LE(encrypted_length, packet_creator_.max_packet_length());
}
QUIC_DVLOG(1) << ENDPOINT << "Sending packet " << packet_number << " : "
@@ -2198,7 +2207,7 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
<< ", encrypted length:" << encrypted_length
<< ", fate: " << SerializedPacketFateToString(fate);
QUIC_DVLOG(2) << ENDPOINT << "packet(" << packet_number << "): " << std::endl
- << QuicTextUtils::HexDump(QuicStringPiece(
+ << quiche::QuicheTextUtils::HexDump(quiche::QuicheStringPiece(
packet->encrypted_buffer, encrypted_length));
// Measure the RTT from before the write begins to avoid underestimating the
@@ -2257,6 +2266,16 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
result = writer_->WritePacket(packet->encrypted_buffer, encrypted_length,
self_address().host(), peer_address(),
per_packet_options_);
+ // This is a work around for an issue with linux UDP GSO batch writers.
+ // When sending a GSO packet with 2 segments, if the first segment is
+ // larger than the path MTU, instead of EMSGSIZE, the linux kernel returns
+ // EINVAL, which translates to WRITE_STATUS_ERROR and causes conneciton to
+ // be closed. By manually flush the writer here, the MTU probe is sent in
+ // a normal(non-GSO) packet, so the kernel can return EMSGSIZE and we will
+ // not close the connection.
+ if (is_mtu_discovery && writer_->IsBatchMode()) {
+ result = writer_->Flush();
+ }
break;
case FAILED_TO_WRITE_COALESCED_PACKET:
// Failed to send existing coalesced packet when determining packet fate,
@@ -2291,7 +2310,7 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
// In some cases, an MTU probe can cause EMSGSIZE. This indicates that the
// MTU discovery is permanently unsuccessful.
- if (IsMsgTooBig(result) && looks_like_mtu_probe) {
+ if (IsMsgTooBig(result) && is_mtu_discovery) {
// When MSG_TOO_BIG is returned, the system typically knows what the
// actual MTU is, so there is no need to probe further.
// TODO(wub): Reduce max packet size to a safe default, or the actual MTU.
@@ -2305,11 +2324,19 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
}
if (IsWriteError(result.status)) {
- OnWriteError(result.error_code);
QUIC_LOG_FIRST_N(ERROR, 10)
- << ENDPOINT << "failed writing packet " << packet_number << " of "
+ << ENDPOINT << "Failed writing packet " << packet_number << " of "
<< encrypted_length << " bytes from " << self_address().host() << " to "
- << peer_address() << ", with error code " << result.error_code;
+ << peer_address() << ", with error code " << result.error_code
+ << ". long_term_mtu_:" << long_term_mtu_
+ << ", previous_validated_mtu_:" << previous_validated_mtu_
+ << ", max_packet_length():" << max_packet_length()
+ << ", is_mtu_discovery:" << is_mtu_discovery;
+ if (ShouldIgnoreWriteError()) {
+ return true;
+ }
+
+ OnWriteError(result.error_code);
return false;
}
@@ -2318,19 +2345,37 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
debug_visitor_->OnPacketSent(*packet, packet->transmission_type,
packet_send_time);
}
- if (IsRetransmittable(*packet) == HAS_RETRANSMITTABLE_DATA) {
- if (!is_path_degrading_ && !path_degrading_alarm_->IsSet()) {
+ if (IsRetransmittable(*packet) == HAS_RETRANSMITTABLE_DATA &&
+ !is_termination_packet) {
+ // Start blackhole/path degrading detections if the sent packet is not
+ // termination packet and contains retransmittable data.
+ if (use_blackhole_detector_) {
+ // Do not restart detection if detection is in progress indicating no
+ // forward progress has been made since last event (i.e., packet was sent
+ // or new packets were acknowledged).
+ if (!blackhole_detector_.IsDetectionInProgress()) {
+ // Try to start detections if no detection in progress. This could
+ // because either both detections are inactive when sending last packet
+ // or this connection just gets out of quiescence.
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_blackhole_detector, 1, 4);
+ blackhole_detector_.RestartDetection(GetPathDegradingDeadline(),
+ GetNetworkBlackholeDeadline());
+ }
+ } else if (!is_path_degrading_ && !path_degrading_alarm_->IsSet()) {
// This is the first retransmittable packet on the working path.
// Start the path degrading alarm to detect new path degrading.
SetPathDegradingAlarm();
}
- // Update |time_of_first_packet_sent_after_receiving_| if this is the
- // first packet sent after the last packet was received. If it were
- // updated on every sent packet, then sending into a black hole might
- // never timeout.
- if (time_of_first_packet_sent_after_receiving_ <
- time_of_last_received_packet_) {
+ if (use_idle_network_detector_) {
+ idle_network_detector_.OnPacketSent(packet_send_time);
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_idle_network_detector, 2, 6);
+ } else if (time_of_first_packet_sent_after_receiving_ <
+ time_of_last_received_packet_) {
+ // Update |time_of_first_packet_sent_after_receiving_| if this is the
+ // first packet sent after the last packet was received. If it were
+ // updated on every sent packet, then sending into a black hole might
+ // never timeout.
time_of_first_packet_sent_after_receiving_ = packet_send_time;
}
}
@@ -2385,6 +2430,11 @@ void QuicConnection::FlushPackets() {
WriteResult result = writer_->Flush();
+ QUIC_HISTOGRAM_ENUM("QuicConnection.FlushPacketStatus", result.status,
+ WRITE_STATUS_NUM_VALUES,
+ "Status code returned by writer_->Flush() in "
+ "QuicConnection::FlushPackets.");
+
if (HandleWriteBlocked()) {
DCHECK_EQ(WRITE_STATUS_BLOCKED, result.status)
<< "Unexpected flush result:" << result;
@@ -2392,7 +2442,7 @@ void QuicConnection::FlushPackets() {
return;
}
- if (IsWriteError(result.status)) {
+ if (IsWriteError(result.status) && !ShouldIgnoreWriteError()) {
OnWriteError(result.error_code);
}
}
@@ -2423,6 +2473,20 @@ bool QuicConnection::ShouldDiscardPacket(const SerializedPacket& packet) {
return false;
}
+bool QuicConnection::ShouldIgnoreWriteError() {
+ if (!GetQuicReloadableFlag(quic_ignore_one_write_error_after_mtu_probe) ||
+ previous_validated_mtu_ == 0) {
+ return false;
+ }
+
+ QUIC_CODE_COUNT(quic_ignore_one_write_error_after_mtu_probe);
+ SetMaxPacketLength(previous_validated_mtu_);
+ mtu_discoverer_.Disable();
+ mtu_discovery_alarm_->Cancel();
+ previous_validated_mtu_ = 0;
+ return true;
+}
+
void QuicConnection::OnWriteError(int error_code) {
if (write_error_occurred_) {
// A write error already occurred. The connection is being closed.
@@ -2430,7 +2494,7 @@ void QuicConnection::OnWriteError(int error_code) {
}
write_error_occurred_ = true;
- const std::string error_details = QuicStrCat(
+ const std::string error_details = quiche::QuicheStrCat(
"Write failed with error: ", error_code, " (", strerror(error_code), ")");
QUIC_LOG_FIRST_N(ERROR, 2) << ENDPOINT << error_details;
switch (error_code) {
@@ -2452,9 +2516,7 @@ void QuicConnection::OnWriteError(int error_code) {
}
char* QuicConnection::GetPacketBuffer() {
- if (version().CanSendCoalescedPackets() &&
- sent_packet_manager_.handshake_state() <
- QuicSentPacketManager::HANDSHAKE_CONFIRMED) {
+ if (version().CanSendCoalescedPackets() && !IsHandshakeConfirmed()) {
// Do not use writer's packet buffer for coalesced packets which may contain
// multiple QUIC packets.
return nullptr;
@@ -2522,9 +2584,9 @@ void QuicConnection::OnCongestionChange() {
void QuicConnection::OnPathMtuIncreased(QuicPacketLength packet_size) {
if (packet_size > max_packet_length()) {
- const QuicByteCount old_max_packet_length = max_packet_length();
+ previous_validated_mtu_ = max_packet_length();
SetMaxPacketLength(packet_size);
- mtu_discoverer_.OnMaxPacketLengthUpdated(old_max_packet_length,
+ mtu_discoverer_.OnMaxPacketLengthUpdated(previous_validated_mtu_,
max_packet_length());
}
}
@@ -2533,11 +2595,19 @@ void QuicConnection::OnHandshakeComplete() {
sent_packet_manager_.SetHandshakeConfirmed();
// This may have changed the retransmission timer, so re-arm it.
SetRetransmissionAlarm();
- // The client should immediately ack the SHLO to confirm the handshake is
- // complete with the server.
- if (perspective_ == Perspective::IS_CLIENT && ack_frame_updated()) {
- ack_alarm_->Update(clock_->ApproximateNow(), QuicTime::Delta::Zero());
+ if (!SupportsMultiplePacketNumberSpaces()) {
+ // The client should immediately ack the SHLO to confirm the handshake is
+ // complete with the server.
+ if (perspective_ == Perspective::IS_CLIENT && ack_frame_updated()) {
+ ack_alarm_->Update(clock_->ApproximateNow(), QuicTime::Delta::Zero());
+ }
+ return;
}
+ // Stop sending ack of handshake packet number space.
+ uber_received_packet_manager_.ResetAckStates(ENCRYPTION_HANDSHAKE);
+ // Re-arm ack alarm.
+ ack_alarm_->Update(uber_received_packet_manager_.GetEarliestAckTimeout(),
+ kAlarmGranularity);
}
void QuicConnection::SendOrQueuePacket(SerializedPacket* packet) {
@@ -2570,8 +2640,7 @@ void QuicConnection::SendAck() {
return;
}
ResetAckStates();
- if (consecutive_num_packets_with_no_retransmittable_frames_ <
- max_consecutive_num_packets_with_no_retransmittable_frames_) {
+ if (!ShouldBundleRetransmittableFrameWithAck()) {
return;
}
consecutive_num_packets_with_no_retransmittable_frames_ = 0;
@@ -2590,25 +2659,35 @@ void QuicConnection::OnPathDegradingTimeout() {
}
void QuicConnection::OnRetransmissionTimeout() {
- DCHECK(!sent_packet_manager_.unacked_packets().empty() ||
- (sent_packet_manager_.handshake_mode_disabled() &&
- !IsHandshakeComplete()));
- const QuicPacketNumber previous_created_packet_number =
- packet_creator_.packet_number();
- if (close_connection_after_five_rtos_ &&
- sent_packet_manager_.GetConsecutiveRtoCount() >= 4) {
- // Close on the 5th consecutive RTO, so after 4 previous RTOs have occurred.
- CloseConnection(QUIC_TOO_MANY_RTOS, "5 consecutive retransmission timeouts",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- return;
+#ifndef NDEBUG
+ if (sent_packet_manager_.unacked_packets().empty()) {
+ DCHECK(sent_packet_manager_.handshake_mode_disabled());
+ DCHECK(!IsHandshakeComplete());
}
- if (sent_packet_manager_.pto_enabled() && max_consecutive_ptos_ > 0 &&
- sent_packet_manager_.GetConsecutivePtoCount() >= max_consecutive_ptos_) {
- CloseConnection(QUIC_TOO_MANY_RTOS,
- QuicStrCat(max_consecutive_ptos_ + 1,
+#endif
+
+ QuicPacketNumber previous_created_packet_number =
+ packet_creator_.packet_number();
+ if (!use_blackhole_detector_) {
+ if (close_connection_after_five_rtos_ &&
+ sent_packet_manager_.GetConsecutiveRtoCount() >= 4) {
+ // Close on the 5th consecutive RTO, so after 4 previous RTOs have
+ // occurred.
+ CloseConnection(QUIC_TOO_MANY_RTOS,
+ "5 consecutive retransmission timeouts",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return;
+ }
+ if (sent_packet_manager_.pto_enabled() && max_consecutive_ptos_ > 0 &&
+ sent_packet_manager_.GetConsecutivePtoCount() >=
+ max_consecutive_ptos_) {
+ CloseConnection(
+ QUIC_TOO_MANY_RTOS,
+ quiche::QuicheStrCat(max_consecutive_ptos_ + 1,
"consecutive retransmission timeouts"),
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- return;
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return;
+ }
}
const auto retransmission_mode =
@@ -2622,9 +2701,11 @@ void QuicConnection::OnRetransmissionTimeout() {
packet_creator_.SkipNPacketNumbers(
num_packet_numbers_to_skip, sent_packet_manager_.GetLeastUnacked(),
sent_packet_manager_.EstimateMaxPacketsInFlight(max_packet_length()));
- if (GetQuicReloadableFlag(quic_on_packet_numbers_skipped) &&
- debug_visitor_ != nullptr) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_on_packet_numbers_skipped);
+ if (GetQuicReloadableFlag(quic_send_ping_when_pto_skips_packet_number)) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_send_ping_when_pto_skips_packet_number);
+ previous_created_packet_number += num_packet_numbers_to_skip;
+ }
+ if (debug_visitor_ != nullptr) {
debug_visitor_->OnNPacketNumbersSkipped(num_packet_numbers_to_skip);
}
}
@@ -2650,17 +2731,11 @@ void QuicConnection::OnRetransmissionTimeout() {
retransmission_mode == QuicSentPacketManager::RTO_MODE ||
retransmission_mode == QuicSentPacketManager::PTO_MODE) &&
!visitor_->WillingAndAbleToWrite()) {
- // Send PING if timer fires in RTO or PTO mode but there is no data to
+ // Send PING if timer fires in TLP/RTO/PTO mode but there is no data to
// send.
- // When TLP fires, either new data or tail loss probe should be sent.
- // There is corner case where TLP fires after RTO because packets get
- // acked. Two packets are marked RTO_RETRANSMITTED, but the first packet
- // is retransmitted as two packets because of packet number length
- // increases (please see QuicConnectionTest.RtoPacketAsTwo).
- QUIC_DLOG_IF(WARNING,
- retransmission_mode == QuicSentPacketManager::TLP_MODE &&
- stats_.rto_count == 0)
- << "No packet gets sent when timer fires in TLP mode, sending PING";
+ QUIC_DLOG(INFO) << ENDPOINT
+ << "No packet gets sent when timer fires in mode "
+ << retransmission_mode << ", send PING";
DCHECK_LT(0u, sent_packet_manager_.pending_timer_transmission_count());
visitor_->SendPing();
}
@@ -2697,6 +2772,10 @@ void QuicConnection::SetEncrypter(EncryptionLevel level,
packet_creator_.SetEncrypter(level, std::move(encrypter));
}
+void QuicConnection::RemoveEncrypter(EncryptionLevel level) {
+ framer_.RemoveEncrypter(level);
+}
+
void QuicConnection::SetDiversificationNonce(
const DiversificationNonce& nonce) {
DCHECK_EQ(Perspective::IS_SERVER, perspective_);
@@ -2874,7 +2953,7 @@ void QuicConnection::CloseConnection(
void QuicConnection::SendConnectionClosePacket(QuicErrorCode error,
const std::string& details) {
- if (!GetQuicReloadableFlag(quic_close_all_encryptions_levels2)) {
+ if (!SupportsMultiplePacketNumberSpaces()) {
QUIC_DLOG(INFO) << ENDPOINT << "Sending connection close packet.";
SetDefaultEncryptionLevel(GetConnectionCloseEncryptionLevel());
if (version().CanSendCoalescedPackets()) {
@@ -2883,11 +2962,10 @@ void QuicConnection::SendConnectionClosePacket(QuicErrorCode error,
ClearQueuedPackets();
// If there was a packet write error, write the smallest close possible.
ScopedPacketFlusher flusher(this);
- // When multiple packet number spaces is supported, an ACK frame will be
- // bundled when connection is not write blocked.
- if (!SupportsMultiplePacketNumberSpaces() &&
- error != QUIC_PACKET_WRITE_ERROR &&
- !GetUpdatedAckFrame().ack_frame->packets.Empty()) {
+ // Always bundle an ACK with connection close for debugging purpose.
+ if (error != QUIC_PACKET_WRITE_ERROR &&
+ !uber_received_packet_manager_.IsAckFrameEmpty(
+ QuicUtils::GetPacketNumberSpace(encryption_level_))) {
SendAck();
}
QuicConnectionCloseFrame* frame;
@@ -2904,7 +2982,6 @@ void QuicConnection::SendConnectionClosePacket(QuicErrorCode error,
}
const EncryptionLevel current_encryption_level = encryption_level_;
ScopedPacketFlusher flusher(this);
- QUIC_RELOADABLE_FLAG_COUNT(quic_close_all_encryptions_levels2);
// Now that the connection is being closed, discard any unsent packets
// so the only packets to be sent will be connection close packets.
@@ -2922,15 +2999,16 @@ void QuicConnection::SendConnectionClosePacket(QuicErrorCode error,
QUIC_DLOG(INFO) << ENDPOINT << "Sending connection close packet at level: "
<< EncryptionLevelToString(level);
SetDefaultEncryptionLevel(level);
- // If there was a packet write error, write the smallest close possible.
- // When multiple packet number spaces are supported, an ACK frame will
- // be bundled by the ScopedPacketFlusher. Otherwise, an ACK must be sent
- // explicitly.
- if (!SupportsMultiplePacketNumberSpaces() &&
- error != QUIC_PACKET_WRITE_ERROR &&
- !GetUpdatedAckFrame().ack_frame->packets.Empty()) {
- SendAck();
+ // Bundle an ACK of the corresponding packet number space for debugging
+ // purpose.
+ if (error != QUIC_PACKET_WRITE_ERROR &&
+ !uber_received_packet_manager_.IsAckFrameEmpty(
+ QuicUtils::GetPacketNumberSpace(encryption_level_))) {
+ QuicFrames frames;
+ frames.push_back(GetUpdatedAckFrame());
+ packet_creator_.FlushAckFrame(frames);
}
+
auto* frame =
new QuicConnectionCloseFrame(transport_version(), error, details,
framer_.current_received_frame_type());
@@ -2967,6 +3045,7 @@ void QuicConnection::TearDownLocalConnectionState(
FlushPackets();
connected_ = false;
DCHECK(visitor_ != nullptr);
+ sent_packet_manager_.OnConnectionClosed();
visitor_->OnConnectionClosed(frame, source);
if (debug_visitor_ != nullptr) {
debug_visitor_->OnConnectionClosed(frame, source);
@@ -2987,6 +3066,14 @@ void QuicConnection::CancelAllAlarms() {
mtu_discovery_alarm_->Cancel();
path_degrading_alarm_->Cancel();
process_undecryptable_packets_alarm_->Cancel();
+ if (use_blackhole_detector_) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_blackhole_detector, 4, 4);
+ blackhole_detector_.StopDetection();
+ }
+ if (use_idle_network_detector_) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_idle_network_detector, 3, 6);
+ idle_network_detector_.StopDetection();
+ }
}
QuicByteCount QuicConnection::max_packet_length() const {
@@ -3031,6 +3118,11 @@ void QuicConnection::SetNetworkTimeouts(QuicTime::Delta handshake_timeout,
} else if (idle_timeout > QuicTime::Delta::FromSeconds(1)) {
idle_timeout = idle_timeout - QuicTime::Delta::FromSeconds(1);
}
+ if (use_idle_network_detector_) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_idle_network_detector, 4, 6);
+ idle_network_detector_.SetTimeouts(handshake_timeout, idle_timeout);
+ return;
+ }
handshake_timeout_ = handshake_timeout;
idle_network_timeout_ = idle_timeout;
@@ -3038,7 +3130,26 @@ void QuicConnection::SetNetworkTimeouts(QuicTime::Delta handshake_timeout,
}
void QuicConnection::CheckForTimeout() {
+ DCHECK(!use_idle_network_detector_);
QuicTime now = clock_->ApproximateNow();
+ if (!handshake_timeout_.IsInfinite()) {
+ QuicTime::Delta connected_duration = now - stats_.connection_creation_time;
+ QUIC_DVLOG(1) << ENDPOINT
+ << "connection time: " << connected_duration.ToMicroseconds()
+ << " handshake timeout: "
+ << handshake_timeout_.ToMicroseconds();
+ if (connected_duration >= handshake_timeout_) {
+ const std::string error_details = quiche::QuicheStrCat(
+ "Handshake timeout expired after ",
+ connected_duration.ToDebuggingValue(),
+ ". Timeout:", handshake_timeout_.ToDebuggingValue());
+ QUIC_DVLOG(1) << ENDPOINT << error_details;
+ CloseConnection(QUIC_HANDSHAKE_TIMEOUT, error_details,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return;
+ }
+ }
+
QuicTime time_of_last_packet =
std::max(time_of_last_received_packet_,
time_of_first_packet_sent_after_receiving_);
@@ -3054,7 +3165,9 @@ void QuicConnection::CheckForTimeout() {
<< " idle_network_timeout: "
<< idle_network_timeout_.ToMicroseconds();
if (idle_duration >= idle_network_timeout_) {
- const std::string error_details = "No recent network activity.";
+ const std::string error_details = quiche::QuicheStrCat(
+ "No recent network activity after ", idle_duration.ToDebuggingValue(),
+ ". Timeout:", idle_network_timeout_.ToDebuggingValue());
QUIC_DVLOG(1) << ENDPOINT << error_details;
if ((sent_packet_manager_.GetConsecutiveTlpCount() > 0 ||
sent_packet_manager_.GetConsecutiveRtoCount() > 0 ||
@@ -3068,25 +3181,11 @@ void QuicConnection::CheckForTimeout() {
return;
}
- if (!handshake_timeout_.IsInfinite()) {
- QuicTime::Delta connected_duration = now - stats_.connection_creation_time;
- QUIC_DVLOG(1) << ENDPOINT
- << "connection time: " << connected_duration.ToMicroseconds()
- << " handshake timeout: "
- << handshake_timeout_.ToMicroseconds();
- if (connected_duration >= handshake_timeout_) {
- const std::string error_details = "Handshake timeout expired.";
- QUIC_DVLOG(1) << ENDPOINT << error_details;
- CloseConnection(QUIC_HANDSHAKE_TIMEOUT, error_details,
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- return;
- }
- }
-
SetTimeoutAlarm();
}
void QuicConnection::SetTimeoutAlarm() {
+ DCHECK(!use_idle_network_detector_);
QuicTime time_of_last_packet =
std::max(time_of_last_received_packet_,
time_of_first_packet_sent_after_receiving_);
@@ -3144,7 +3243,7 @@ void QuicConnection::SetPingAlarm() {
// Use a shorter timeout if there are open streams, but nothing on the wire.
ping_alarm_->Update(
clock_->ApproximateNow() + retransmittable_on_wire_timeout,
- QuicTime::Delta::FromMilliseconds(1));
+ kAlarmGranularity);
if (max_aggressive_retransmittable_on_wire_ping_count != 0) {
consecutive_retransmittable_on_wire_ping_count_++;
}
@@ -3152,7 +3251,7 @@ void QuicConnection::SetPingAlarm() {
}
ping_alarm_->Update(clock_->ApproximateNow() + ping_timeout_,
- QuicTime::Delta::FromMilliseconds(1));
+ kAlarmGranularity);
}
void QuicConnection::SetRetransmissionAlarm() {
@@ -3168,16 +3267,17 @@ void QuicConnection::SetRetransmissionAlarm() {
}
retransmission_alarm_->Update(sent_packet_manager_.GetRetransmissionTime(),
- QuicTime::Delta::FromMilliseconds(1));
+ kAlarmGranularity);
}
void QuicConnection::SetPathDegradingAlarm() {
+ DCHECK(!use_blackhole_detector_);
if (perspective_ == Perspective::IS_SERVER) {
return;
}
const QuicTime::Delta delay = sent_packet_manager_.GetPathDegradingDelay();
path_degrading_alarm_->Update(clock_->ApproximateNow() + delay,
- QuicTime::Delta::FromMilliseconds(1));
+ kAlarmGranularity);
}
void QuicConnection::MaybeSetMtuAlarm(QuicPacketNumber sent_packet_number) {
@@ -3188,12 +3288,6 @@ void QuicConnection::MaybeSetMtuAlarm(QuicPacketNumber sent_packet_number) {
mtu_discovery_alarm_->Set(clock_->ApproximateNow());
}
-void QuicConnection::MaybeSetAckAlarmTo(QuicTime time) {
- if (!ack_alarm_->IsSet() || ack_alarm_->deadline() > time) {
- ack_alarm_->Update(time, QuicTime::Delta::Zero());
- }
-}
-
QuicConnection::ScopedPacketFlusher::ScopedPacketFlusher(
QuicConnection* connection)
: connection_(connection),
@@ -3222,8 +3316,9 @@ QuicConnection::ScopedPacketFlusher::~ScopedPacketFlusher() {
// Cancel ACK alarm if connection is write blocked, and ACK will be
// sent when connection gets unblocked.
connection_->ack_alarm_->Cancel();
- } else {
- connection_->MaybeSetAckAlarmTo(ack_timeout);
+ } else if (!connection_->ack_alarm_->IsSet() ||
+ connection_->ack_alarm_->deadline() > ack_timeout) {
+ connection_->ack_alarm_->Update(ack_timeout, QuicTime::Delta::Zero());
}
}
if (connection_->ack_alarm_->IsSet() &&
@@ -3345,6 +3440,9 @@ QuicByteCount QuicConnection::GetLimitedMaxPacketSize(
if (max_packet_size > writer_limit) {
max_packet_size = writer_limit;
}
+ if (max_packet_size > peer_max_packet_size_) {
+ max_packet_size = peer_max_packet_size_;
+ }
if (max_packet_size > kMaxOutgoingPacketSize) {
max_packet_size = kMaxOutgoingPacketSize;
}
@@ -3408,39 +3506,28 @@ bool QuicConnection::SendGenericPathProbePacket(
<< server_connection_id_;
OwningSerializedPacketPointer probing_packet;
- if (!VersionHasIetfQuicFrames(transport_version())) {
+ if (!version().HasIetfQuicFrames()) {
// Non-IETF QUIC, generate a padded ping regardless of whether this is a
// request or a response.
probing_packet = packet_creator_.SerializeConnectivityProbingPacket();
+ } else if (is_response) {
+ // IETF QUIC path response.
+ // Respond to path probe request using IETF QUIC PATH_RESPONSE frame.
+ probing_packet =
+ packet_creator_.SerializePathResponseConnectivityProbingPacket(
+ received_path_challenge_payloads_,
+ /*is_padded=*/false);
+ received_path_challenge_payloads_.clear();
} else {
- if (is_response) {
- // Respond using IETF QUIC PATH_RESPONSE frame
- if (IsCurrentPacketConnectivityProbing()) {
- // Pad the response if the request was a google connectivity probe
- // (padded).
- probing_packet =
- packet_creator_.SerializePathResponseConnectivityProbingPacket(
- received_path_challenge_payloads_, /* is_padded = */ true);
- received_path_challenge_payloads_.clear();
- } else {
- // Do not pad the response if the path challenge was not a google
- // connectivity probe.
- probing_packet =
- packet_creator_.SerializePathResponseConnectivityProbingPacket(
- received_path_challenge_payloads_,
- /* is_padded = */ false);
- received_path_challenge_payloads_.clear();
- }
- } else {
- // Request using IETF QUIC PATH_CHALLENGE frame
- transmitted_connectivity_probe_payload_ =
- std::make_unique<QuicPathFrameBuffer>();
- probing_packet =
- packet_creator_.SerializePathChallengeConnectivityProbingPacket(
- transmitted_connectivity_probe_payload_.get());
- if (!probing_packet) {
- transmitted_connectivity_probe_payload_ = nullptr;
- }
+ // IETF QUIC path challenge.
+ // Send a path probe request using IETF QUIC PATH_CHALLENGE frame.
+ transmitted_connectivity_probe_payload_ =
+ std::make_unique<QuicPathFrameBuffer>();
+ probing_packet =
+ packet_creator_.SerializePathChallengeConnectivityProbingPacket(
+ transmitted_connectivity_probe_payload_.get());
+ if (!probing_packet) {
+ transmitted_connectivity_probe_payload_ = nullptr;
}
}
@@ -3450,9 +3537,9 @@ bool QuicConnection::SendGenericPathProbePacket(
QUIC_DVLOG(2) << ENDPOINT
<< "Sending path probe packet for server connection ID "
<< server_connection_id_ << std::endl
- << QuicTextUtils::HexDump(
- QuicStringPiece(probing_packet->encrypted_buffer,
- probing_packet->encrypted_length));
+ << quiche::QuicheTextUtils::HexDump(quiche::QuicheStringPiece(
+ probing_packet->encrypted_buffer,
+ probing_packet->encrypted_length));
WriteResult result = probing_writer->WritePacket(
probing_packet->encrypted_buffer, probing_packet->encrypted_length,
self_address().host(), peer_address, per_packet_options_);
@@ -3553,11 +3640,11 @@ bool QuicConnection::ack_frame_updated() const {
return uber_received_packet_manager_.IsAckFrameUpdated();
}
-QuicStringPiece QuicConnection::GetCurrentPacket() {
+quiche::QuicheStringPiece QuicConnection::GetCurrentPacket() {
if (current_packet_data_ == nullptr) {
- return QuicStringPiece();
+ return quiche::QuicheStringPiece();
}
- return QuicStringPiece(current_packet_data_, last_size_);
+ return quiche::QuicheStringPiece(current_packet_data_, last_size_);
}
bool QuicConnection::MaybeConsiderAsMemoryCorruption(
@@ -3627,6 +3714,14 @@ void QuicConnection::CheckIfApplicationLimited() {
}
void QuicConnection::UpdatePacketContent(PacketContent type) {
+ // Packet content is tracked to identify connectivity probe in non-IETF
+ // version, where a connectivity probe is defined as
+ // - a padded PING packet with peer address change received by server,
+ // - a padded PING packet on new path received by client.
+ if (version().HasIetfQuicFrames()) {
+ return;
+ }
+
if (current_packet_content_ == NOT_PADDED_PING) {
// We have already learned the current packet is not a connectivity
// probing packet. Peer migration should have already been started earlier
@@ -3645,21 +3740,32 @@ void QuicConnection::UpdatePacketContent(PacketContent type) {
}
}
- // In Google QUIC we look for a packet with just a PING and PADDING.
- // For IETF QUIC, the packet must consist of just a PATH_CHALLENGE frame,
- // followed by PADDING. If the condition is met, mark things as
- // connectivity-probing, causing later processing to generate the correct
- // response.
+ // In Google QUIC, we look for a packet with just a PING and PADDING.
+ // If the condition is met, mark things as connectivity-probing, causing
+ // later processing to generate the correct response.
if (type == SECOND_FRAME_IS_PADDING &&
current_packet_content_ == FIRST_FRAME_IS_PING) {
current_packet_content_ = SECOND_FRAME_IS_PADDING;
if (perspective_ == Perspective::IS_SERVER) {
is_current_packet_connectivity_probing_ =
current_effective_peer_migration_type_ != NO_CHANGE;
+ QUIC_DLOG_IF(INFO, is_current_packet_connectivity_probing_)
+ << ENDPOINT
+ << "Detected connectivity probing packet. "
+ "current_effective_peer_migration_type_:"
+ << current_effective_peer_migration_type_;
} else {
is_current_packet_connectivity_probing_ =
(last_packet_source_address_ != peer_address_) ||
(last_packet_destination_address_ != self_address_);
+ QUIC_DLOG_IF(INFO, is_current_packet_connectivity_probing_)
+ << ENDPOINT
+ << "Detected connectivity probing packet. "
+ "last_packet_source_address_:"
+ << last_packet_source_address_ << ", peer_address_:" << peer_address_
+ << ", last_packet_destination_address_:"
+ << last_packet_destination_address_
+ << ", self_address_:" << self_address_;
}
return;
}
@@ -3692,7 +3798,23 @@ void QuicConnection::PostProcessAfterAckFrame(bool send_stop_waiting,
// Always reset the retransmission alarm when an ack comes in, since we now
// have a better estimate of the current rtt than when it was set.
SetRetransmissionAlarm();
- MaybeSetPathDegradingAlarm(acked_new_packet);
+ if (use_blackhole_detector_) {
+ if (acked_new_packet) {
+ is_path_degrading_ = false;
+ if (sent_packet_manager_.HasInFlightPackets()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_blackhole_detector, 2, 4);
+ // Restart detections if forward progress has been made.
+ blackhole_detector_.RestartDetection(GetPathDegradingDeadline(),
+ GetNetworkBlackholeDeadline());
+ } else {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_blackhole_detector, 3, 4);
+ // Stop detections in quiecense.
+ blackhole_detector_.StopDetection();
+ }
+ }
+ } else {
+ MaybeSetPathDegradingAlarm(acked_new_packet);
+ }
if (send_stop_waiting) {
++stop_waiting_count_;
@@ -3702,6 +3824,7 @@ void QuicConnection::PostProcessAfterAckFrame(bool send_stop_waiting,
}
void QuicConnection::MaybeSetPathDegradingAlarm(bool acked_new_packet) {
+ DCHECK(!use_blackhole_detector_);
if (!sent_packet_manager_.HasInFlightPackets()) {
// There are no retransmittable packets on the wire, so it's impossible to
// say if the connection has degraded.
@@ -3854,8 +3977,7 @@ void QuicConnection::SendAllPendingAcks() {
// Only try to bundle retransmittable data with ACK frame if default
// encryption level is forward secure.
if (encryption_level_ != ENCRYPTION_FORWARD_SECURE ||
- consecutive_num_packets_with_no_retransmittable_frames_ <
- max_consecutive_num_packets_with_no_retransmittable_frames_) {
+ !ShouldBundleRetransmittableFrameWithAck()) {
return;
}
consecutive_num_packets_with_no_retransmittable_frames_ = 0;
@@ -3868,6 +3990,22 @@ void QuicConnection::SendAllPendingAcks() {
visitor_->OnAckNeedsRetransmittableFrame();
}
+bool QuicConnection::ShouldBundleRetransmittableFrameWithAck() const {
+ if (consecutive_num_packets_with_no_retransmittable_frames_ >=
+ max_consecutive_num_packets_with_no_retransmittable_frames_) {
+ return true;
+ }
+ if (bundle_retransmittable_with_pto_ack_ &&
+ (sent_packet_manager_.GetConsecutiveRtoCount() > 0 ||
+ sent_packet_manager_.GetConsecutivePtoCount() > 0)) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_bundle_retransmittable_with_pto_ack);
+ // Bundle a retransmittable frame with an ACK if the PTO or RTO has fired
+ // in order to recover more quickly in cases of temporary network outage.
+ return true;
+ }
+ return false;
+}
+
bool QuicConnection::FlushCoalescedPacket() {
ScopedCoalescedPacketClearer clearer(&coalesced_packet_);
if (!version().CanSendCoalescedPackets()) {
@@ -3891,6 +4029,9 @@ bool QuicConnection::FlushCoalescedPacket() {
buffered_packets_.emplace_back(buffer, length,
coalesced_packet_.self_address(),
coalesced_packet_.peer_address());
+ if (debug_visitor_ != nullptr) {
+ debug_visitor_->OnCoalescedPacketSent(coalesced_packet_, length);
+ }
return true;
}
@@ -3911,6 +4052,9 @@ bool QuicConnection::FlushCoalescedPacket() {
coalesced_packet_.peer_address());
}
}
+ if (debug_visitor_ != nullptr) {
+ debug_visitor_->OnCoalescedPacketSent(coalesced_packet_, length);
+ }
// Account for added padding.
if (length > coalesced_packet_.length()) {
size_t padding_size = length - coalesced_packet_.length();
@@ -3960,14 +4104,6 @@ QuicPacketNumber QuicConnection::GetLargestReceivedPacketWithAck() const {
return largest_seen_packet_with_ack_;
}
-QuicPacketNumber QuicConnection::GetLargestSentPacket() const {
- if (SupportsMultiplePacketNumberSpaces()) {
- return sent_packet_manager_.GetLargestSentPacket(
- last_decrypted_packet_level_);
- }
- return sent_packet_manager_.GetLargestSentPacket();
-}
-
QuicPacketNumber QuicConnection::GetLargestAckedPacket() const {
if (SupportsMultiplePacketNumberSpaces()) {
return sent_packet_manager_.GetLargestAckedPacket(
@@ -3995,9 +4131,7 @@ bool QuicConnection::LimitedByAmplificationFactor() const {
SerializedPacketFate QuicConnection::DeterminePacketFate(
bool is_mtu_discovery) {
- if (version().CanSendCoalescedPackets() &&
- sent_packet_manager_.handshake_state() <
- QuicSentPacketManager::HANDSHAKE_CONFIRMED &&
+ if (version().CanSendCoalescedPackets() && !IsHandshakeConfirmed() &&
!is_mtu_discovery) {
// Before receiving ACK for any 1-RTT packets, always try to coalesce
// packet (except MTU discovery packet).
@@ -4013,6 +4147,15 @@ SerializedPacketFate QuicConnection::DeterminePacketFate(
return SEND_TO_WRITER;
}
+bool QuicConnection::IsHandshakeComplete() const {
+ return visitor_->GetHandshakeState() >= HANDSHAKE_COMPLETE;
+}
+
+bool QuicConnection::IsHandshakeConfirmed() const {
+ DCHECK_EQ(PROTOCOL_TLS1_3, version().handshake_protocol);
+ return visitor_->GetHandshakeState() == HANDSHAKE_CONFIRMED;
+}
+
size_t QuicConnection::min_received_before_ack_decimation() const {
return uber_received_packet_manager_.min_received_before_ack_decimation();
}
@@ -4058,5 +4201,111 @@ void QuicConnection::set_client_connection_id(
framer_.SetExpectedClientConnectionIdLength(client_connection_id_.length());
}
+void QuicConnection::OnPathDegradingDetected() {
+ DCHECK(use_blackhole_detector_);
+ is_path_degrading_ = true;
+ visitor_->OnPathDegrading();
+}
+
+void QuicConnection::OnBlackholeDetected() {
+ DCHECK(use_blackhole_detector_);
+ CloseConnection(QUIC_TOO_MANY_RTOS, "Network blackhole detected.",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+}
+
+void QuicConnection::OnHandshakeTimeout() {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_idle_network_detector, 5, 6);
+ DCHECK(use_idle_network_detector_);
+ const QuicTime::Delta duration =
+ clock_->ApproximateNow() - stats_.connection_creation_time;
+ const std::string error_details = quiche::QuicheStrCat(
+ "Handshake timeout expired after ", duration.ToDebuggingValue(),
+ ". Timeout:",
+ idle_network_detector_.handshake_timeout().ToDebuggingValue());
+ QUIC_DVLOG(1) << ENDPOINT << error_details;
+ CloseConnection(QUIC_HANDSHAKE_TIMEOUT, error_details,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+}
+
+void QuicConnection::OnIdleNetworkDetected() {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_idle_network_detector, 6, 6);
+ DCHECK(use_idle_network_detector_);
+ const QuicTime::Delta duration =
+ clock_->ApproximateNow() -
+ idle_network_detector_.last_network_activity_time();
+ const std::string error_details = quiche::QuicheStrCat(
+ "No recent network activity after ", duration.ToDebuggingValue(),
+ ". Timeout:",
+ idle_network_detector_.idle_network_timeout().ToDebuggingValue());
+ QUIC_DVLOG(1) << ENDPOINT << error_details;
+ if ((sent_packet_manager_.GetConsecutiveTlpCount() > 0 ||
+ sent_packet_manager_.GetConsecutiveRtoCount() > 0 ||
+ sent_packet_manager_.GetConsecutivePtoCount() > 0 ||
+ visitor_->ShouldKeepConnectionAlive())) {
+ CloseConnection(QUIC_NETWORK_IDLE_TIMEOUT, error_details,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return;
+ }
+ CloseConnection(QUIC_NETWORK_IDLE_TIMEOUT, error_details,
+ idle_timeout_connection_close_behavior_);
+}
+
+QuicTime QuicConnection::GetPathDegradingDeadline() const {
+ DCHECK(use_blackhole_detector_);
+ if (!ShouldDetectPathDegrading()) {
+ return QuicTime::Zero();
+ }
+ return clock_->ApproximateNow() +
+ sent_packet_manager_.GetPathDegradingDelay();
+}
+
+bool QuicConnection::ShouldDetectPathDegrading() const {
+ DCHECK(use_blackhole_detector_);
+ if (!connected_) {
+ return false;
+ }
+ // No path degrading detection before handshake completes.
+ if (!GetHandshakeTimeout().IsInfinite()) {
+ return false;
+ }
+ return perspective_ == Perspective::IS_CLIENT && !is_path_degrading_;
+}
+
+QuicTime QuicConnection::GetNetworkBlackholeDeadline() const {
+ DCHECK(use_blackhole_detector_);
+ if (!ShouldDetectBlackhole()) {
+ return QuicTime::Zero();
+ }
+ return clock_->ApproximateNow() +
+ sent_packet_manager_.GetNetworkBlackholeDelay();
+}
+
+bool QuicConnection::ShouldDetectBlackhole() const {
+ DCHECK(use_blackhole_detector_);
+ if (!connected_) {
+ return false;
+ }
+ // No blackhole detection before handshake completes.
+ if (!GetHandshakeTimeout().IsInfinite()) {
+ return false;
+ }
+ return close_connection_after_five_rtos_ ||
+ (sent_packet_manager_.pto_enabled() && max_consecutive_ptos_ > 0);
+}
+
+QuicTime::Delta QuicConnection::GetHandshakeTimeout() const {
+ if (use_idle_network_detector_) {
+ return idle_network_detector_.handshake_timeout();
+ }
+ return handshake_timeout_;
+}
+
+QuicTime QuicConnection::GetTimeOfLastReceivedPacket() const {
+ if (use_idle_network_detector_) {
+ return idle_network_detector_.time_of_last_received_packet();
+ }
+ return time_of_last_received_packet_;
+}
+
#undef ENDPOINT // undef for jumbo builds
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection.h b/chromium/net/third_party/quiche/src/quic/core/quic_connection.h
index abd836f4c6d..a6be992badd 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_connection.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_connection.h
@@ -31,10 +31,13 @@
#include "net/third_party/quiche/src/quic/core/quic_alarm.h"
#include "net/third_party/quiche/src/quic/core/quic_alarm_factory.h"
#include "net/third_party/quiche/src/quic/core/quic_blocked_writer_interface.h"
+#include "net/third_party/quiche/src/quic/core/quic_circular_deque.h"
#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
#include "net/third_party/quiche/src/quic/core/quic_connection_stats.h"
#include "net/third_party/quiche/src/quic/core/quic_framer.h"
+#include "net/third_party/quiche/src/quic/core/quic_idle_network_detector.h"
#include "net/third_party/quiche/src/quic/core/quic_mtu_discovery.h"
+#include "net/third_party/quiche/src/quic/core/quic_network_blackhole_detector.h"
#include "net/third_party/quiche/src/quic/core/quic_one_block_arena.h"
#include "net/third_party/quiche/src/quic/core/quic_packet_creator.h"
#include "net/third_party/quiche/src/quic/core/quic_packet_writer.h"
@@ -46,7 +49,8 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -86,7 +90,10 @@ class QUIC_EXPORT_PRIVATE QuicConnectionVisitorInterface {
virtual void OnGoAway(const QuicGoAwayFrame& frame) = 0;
// Called when |message| has been received.
- virtual void OnMessageReceived(QuicStringPiece message) = 0;
+ virtual void OnMessageReceived(quiche::QuicheStringPiece message) = 0;
+
+ // Called when a HANDSHAKE_DONE frame has been received.
+ virtual void OnHandshakeDoneReceived() = 0;
// Called when a MAX_STREAMS frame has been received from the peer.
virtual bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) = 0;
@@ -159,6 +166,9 @@ class QUIC_EXPORT_PRIVATE QuicConnectionVisitorInterface {
// change is allowed.
virtual bool AllowSelfAddressChange() const = 0;
+ // Called to get current handshake state.
+ virtual HandshakeState GetHandshakeState() const = 0;
+
// Called when an ACK is received with a larger |largest_acked| than
// previously observed.
virtual void OnForwardProgressConfirmed() = 0;
@@ -168,6 +178,9 @@ class QUIC_EXPORT_PRIVATE QuicConnectionVisitorInterface {
// Called when a packet of encryption |level| has been successfully decrypted.
virtual void OnPacketDecrypted(EncryptionLevel level) = 0;
+
+ // Called when a 1RTT packet has been acknowledged.
+ virtual void OnOneRttPacketAcknowledged() = 0;
};
// Interface which gets callbacks from the QuicConnection at interesting
@@ -183,6 +196,11 @@ class QUIC_EXPORT_PRIVATE QuicConnectionDebugVisitor
TransmissionType /*transmission_type*/,
QuicTime /*sent_time*/) {}
+ // Called when a coalesced packet has been sent.
+ virtual void OnCoalescedPacketSent(
+ const QuicCoalescedPacket& /*coalesced_packet*/,
+ size_t /*length*/) {}
+
// Called when a PING frame has been sent.
virtual void OnPingSent() {}
@@ -260,6 +278,9 @@ class QUIC_EXPORT_PRIVATE QuicConnectionDebugVisitor
// Called when a MessageFrame has been parsed.
virtual void OnMessageFrame(const QuicMessageFrame& /*frame*/) {}
+ // Called when a HandshakeDoneFrame has been parsed.
+ virtual void OnHandshakeDoneFrame(const QuicHandshakeDoneFrame& /*frame*/) {}
+
// Called when a public reset packet has been received.
virtual void OnPublicResetPacket(const QuicPublicResetPacket& /*packet*/) {}
@@ -329,7 +350,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection
: public QuicFramerVisitorInterface,
public QuicBlockedWriterInterface,
public QuicPacketCreator::DelegateInterface,
- public QuicSentPacketManager::NetworkChangeVisitor {
+ public QuicSentPacketManager::NetworkChangeVisitor,
+ public QuicNetworkBlackholeDetector::Delegate,
+ public QuicIdleNetworkDetector::Delegate {
public:
// Constructs a new QuicConnection for |connection_id| and
// |initial_peer_address| using |writer| to write packets. |owns_writer|
@@ -374,6 +397,12 @@ class QUIC_EXPORT_PRIVATE QuicConnection
QuicTime::Delta rtt,
bool allow_cwnd_to_decrease);
+ // Install a loss detection tuner. Must be called before OnConfigNegotiated.
+ void SetLossDetectionTuner(
+ std::unique_ptr<LossDetectionTunerInterface> tuner);
+ // Called by the session when session->is_configured() becomes true.
+ void OnConfigNegotiated();
+
// Returns the max pacing rate for the connection.
virtual QuicBandwidth MaxPacingRate() const;
@@ -412,6 +441,11 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// Returns statistics tracked for this connection.
const QuicConnectionStats& GetStats();
+ // Mark stats_.has_non_app_limited_sample as false.
+ // TODO(b/151166631) Remove this once the proper fix in b/151166631 is rolled
+ // out.
+ void ResetHasNonAppLimitedSampleAfterHandshakeCompletion();
+
// Processes an incoming UDP packet (consisting of a QuicEncryptedPacket) from
// the peer.
// In a client, the packet may be "stray" and have a different connection ID
@@ -471,6 +505,15 @@ class QUIC_EXPORT_PRIVATE QuicConnection
return framer_.supported_versions();
}
+ // Mark version negotiated for this connection. Once called, the connection
+ // will ignore received version negotiation packets.
+ void SetVersionNegotiated() {
+ version_negotiated_ = true;
+ if (perspective_ == Perspective::IS_SERVER) {
+ framer_.InferPacketHeaderTypeFromVersion();
+ }
+ }
+
// From QuicFramerVisitorInterface
void OnError(QuicFramer* framer) override;
bool OnProtocolVersionMismatch(ParsedQuicVersion received_version) override;
@@ -480,7 +523,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection
const QuicVersionNegotiationPacket& packet) override;
void OnRetryPacket(QuicConnectionId original_connection_id,
QuicConnectionId new_connection_id,
- QuicStringPiece retry_token) override;
+ quiche::QuicheStringPiece retry_token,
+ quiche::QuicheStringPiece retry_integrity_tag,
+ quiche::QuicheStringPiece retry_without_tag) override;
bool OnUnauthenticatedPublicHeader(const QuicPacketHeader& header) override;
bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override;
void OnDecryptedPacket(EncryptionLevel level) override;
@@ -515,6 +560,7 @@ class QUIC_EXPORT_PRIVATE QuicConnection
const QuicRetireConnectionIdFrame& frame) override;
bool OnNewTokenFrame(const QuicNewTokenFrame& frame) override;
bool OnMessageFrame(const QuicMessageFrame& frame) override;
+ bool OnHandshakeDoneFrame(const QuicHandshakeDoneFrame& frame) override;
void OnPacketComplete() override;
bool IsValidStatelessResetToken(QuicUint128 token) const override;
void OnAuthenticatedIetfStatelessResetPacket(
@@ -533,6 +579,14 @@ class QUIC_EXPORT_PRIVATE QuicConnection
void OnCongestionChange() override;
void OnPathMtuIncreased(QuicPacketLength packet_size) override;
+ // QuicNetworkBlackholeDetector::Delegate
+ void OnPathDegradingDetected() override;
+ void OnBlackholeDetected() override;
+
+ // QuicIdleNetworkDetector::Delegate
+ void OnHandshakeTimeout() override;
+ void OnIdleNetworkDetected() override;
+
// Please note, this is not a const function. For logging purpose, please use
// ack_frame().
const QuicFrame GetUpdatedAckFrame();
@@ -646,6 +700,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection
void SetEncrypter(EncryptionLevel level,
std::unique_ptr<QuicEncrypter> encrypter);
+ // Called to remove encrypter of encryption |level|.
+ void RemoveEncrypter(EncryptionLevel level);
+
// SetNonceForPublicHeader sets the nonce that will be transmitted in the
// header of each packet encrypted at the initial encryption level decrypted.
// This should only be called on the server side.
@@ -782,7 +839,7 @@ class QUIC_EXPORT_PRIVATE QuicConnection
QuicConnectionHelperInterface* helper() { return helper_; }
QuicAlarmFactory* alarm_factory() { return alarm_factory_; }
- QuicStringPiece GetCurrentPacket();
+ quiche::QuicheStringPiece GetCurrentPacket();
const QuicFramer& framer() const { return framer_; }
@@ -860,10 +917,10 @@ class QUIC_EXPORT_PRIVATE QuicConnection
};
// Whether the handshake completes from this connection's perspective.
- bool IsHandshakeComplete() const {
- return sent_packet_manager_.handshake_state() >=
- QuicSentPacketManager::HANDSHAKE_COMPLETE;
- }
+ bool IsHandshakeComplete() const;
+
+ // Whether peer completes handshake. Only used with TLS handshake.
+ bool IsHandshakeConfirmed() const;
// Returns the largest received packet number sent by peer.
QuicPacketNumber GetLargestReceivedPacket() const;
@@ -891,12 +948,6 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// Called when version is considered negotiated.
void OnSuccessfulVersionNegotiation();
- bool quic_version_negotiated_by_default_at_server() const {
- return quic_version_negotiated_by_default_at_server_;
- }
-
- bool use_handshake_delegate() const { return use_handshake_delegate_; }
-
protected:
// Calls cancel() on all the alarms owned by this connection.
void CancelAllAlarms();
@@ -996,7 +1047,7 @@ class QUIC_EXPORT_PRIVATE QuicConnection
~BufferedPacket();
// encrypted_buffer is owned by buffered packet.
- QuicStringPiece encrypted_buffer;
+ quiche::QuicheStringPiece encrypted_buffer;
// Self and peer addresses when the packet is serialized.
const QuicSocketAddress self_address;
const QuicSocketAddress peer_address;
@@ -1077,9 +1128,6 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// |sent_packet_number| is the recently sent packet number.
void MaybeSetMtuAlarm(QuicPacketNumber sent_packet_number);
- // Sets ack alarm to |time| if ack alarm is not set or the deadline > time.
- void MaybeSetAckAlarmTo(QuicTime time);
-
HasRetransmittableData IsRetransmittable(const SerializedPacket& packet);
bool IsTerminationPacket(const SerializedPacket& packet);
@@ -1138,6 +1186,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// num_retransmittable_packets_received_since_last_ack_sent_ etc.
void ResetAckStates();
+ // Returns true if the ACK frame should be bundled with ACK-eliciting frame.
+ bool ShouldBundleRetransmittableFrameWithAck() const;
+
void PopulateStopWaitingFrame(QuicStopWaitingFrame* stop_waiting);
// Enables multiple packet number spaces support based on handshake protocol
@@ -1177,6 +1228,29 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// Whether connection is limited by amplification factor.
bool LimitedByAmplificationFactor() const;
+ // We've got a packet write error, should we ignore it?
+ // NOTE: This is not a const function - if return true, the max packet size is
+ // reverted to a previous(smaller) value to avoid write errors in the future.
+ bool ShouldIgnoreWriteError();
+
+ // Returns path degrading deadline. QuicTime::Zero() means no path degrading
+ // detection is needed.
+ QuicTime GetPathDegradingDeadline() const;
+
+ // Returns true if path degrading should be detected.
+ bool ShouldDetectPathDegrading() const;
+
+ // Returns network blackhole deadline. QuicTime::Zero() means no blackhole
+ // detection is needed.
+ QuicTime GetNetworkBlackholeDeadline() const;
+
+ // Returns true if network blackhole should be detected.
+ bool ShouldDetectBlackhole() const;
+
+ // Remove these two when deprecating quic_use_idle_network_detector.
+ QuicTime::Delta GetHandshakeTimeout() const;
+ QuicTime GetTimeOfLastReceivedPacket() const;
+
QuicFramer framer_;
// Contents received in the current packet, especially used to identify
@@ -1257,11 +1331,13 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// established, but which could not be decrypted. We buffer these on
// the assumption that they could not be processed because they were
// sent with the INITIAL encryption and the CHLO message was lost.
- QuicDeque<std::unique_ptr<QuicEncryptedPacket>> undecryptable_packets_;
+ QuicCircularDeque<std::unique_ptr<QuicEncryptedPacket>>
+ undecryptable_packets_;
// Collection of coalesced packets which were received while processing
// the current packet.
- QuicDeque<std::unique_ptr<QuicEncryptedPacket>> received_coalesced_packets_;
+ QuicCircularDeque<std::unique_ptr<QuicEncryptedPacket>>
+ received_coalesced_packets_;
// Maximum number of undecryptable packets the connection will store.
size_t max_undecryptable_packets_;
@@ -1327,12 +1403,15 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// An alarm that is scheduled when the connection can still write and there
// may be more data to send.
// An alarm that fires when the connection may have timed out.
+ // TODO(fayang): Remove this when deprecating quic_use_idle_network_detector.
QuicArenaScopedPtr<QuicAlarm> timeout_alarm_;
// An alarm that fires when a ping should be sent.
QuicArenaScopedPtr<QuicAlarm> ping_alarm_;
// An alarm that fires when an MTU probe should be sent.
QuicArenaScopedPtr<QuicAlarm> mtu_discovery_alarm_;
// An alarm that fires when this connection is considered degrading.
+ // TODO(fayang): Remove this when deprecating quic_use_blackhole_detector
+ // flag.
QuicArenaScopedPtr<QuicAlarm> path_degrading_alarm_;
// An alarm that fires to process undecryptable packets when new decyrption
// keys are available.
@@ -1343,6 +1422,8 @@ class QUIC_EXPORT_PRIVATE QuicConnection
QuicPacketCreator packet_creator_;
+ // TODO(fayang): Remove these two when deprecating
+ // quic_use_idle_network_detector.
// Network idle time before this connection is closed.
QuicTime::Delta idle_network_timeout_;
// The connection will wait this long for the handshake to complete.
@@ -1354,6 +1435,8 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// Timestamps used for timeouts.
// The time of the first retransmittable packet that was sent after the most
// recently received packet.
+ // TODO(fayang): Remove these two when deprecating
+ // quic_use_idle_network_detector.
QuicTime time_of_first_packet_sent_after_receiving_;
// The time that a packet is received for this connection. Initialized to
// connection creation time.
@@ -1393,6 +1476,13 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// The number of MTU probes already sent.
size_t mtu_probe_count_;
+ // The value of |long_term_mtu_| prior to the last successful MTU increase.
+ // 0 means either
+ // - MTU discovery has never been enabled, or
+ // - MTU discovery has been enabled, but the connection got a packet write
+ // error with a new (successfully probed) MTU, so it reverted
+ // |long_term_mtu_| to the value before the last increase.
+ QuicPacketLength previous_validated_mtu_;
// The value of the MTU regularly used by the connection. This is different
// from the value returned by max_packet_size(), as max_packet_size() returns
// the value of the MTU as currently used by the serializer, so if
@@ -1400,6 +1490,10 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// different.
QuicByteCount long_term_mtu_;
+ // The maximum UDP payload size that our peer has advertised support for.
+ // Defaults to kDefaultMaxPacketSizeTransportParam until received from peer.
+ QuicByteCount peer_max_packet_size_;
+
// The size of the largest packet received from peer.
QuicByteCount largest_received_packet_size_;
@@ -1418,6 +1512,10 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// from the peer. Default to kMaxConsecutiveNonRetransmittablePackets.
size_t max_consecutive_num_packets_with_no_retransmittable_frames_;
+ // If true, bundle an ack-eliciting frame with an ACK if the PTO or RTO alarm
+ // have previously fired.
+ bool bundle_retransmittable_with_pto_ack_;
+
// If true, the connection will fill up the pipe with extra data whenever the
// congestion controller needs it in order to make a bandwidth estimate. This
// is useful if the application pesistently underutilizes the link, but still
@@ -1461,15 +1559,15 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// Deque because the peer might no be using this implementation, and others
// might send a packet with more than one PATH_CHALLENGE, so all need to be
// saved and responded to.
- QuicDeque<QuicPathFrameBuffer> received_path_challenge_payloads_;
+ QuicCircularDeque<QuicPathFrameBuffer> received_path_challenge_payloads_;
// Set of connection IDs that should be accepted as destination on
// received packets. This is conceptually a set but is implemented as a
// vector to improve performance since it is expected to be very small.
std::vector<QuicConnectionId> incoming_connection_ids_;
- // Indicates whether a RETRY packet has been parsed.
- bool retry_has_been_parsed_;
+ // Indicates whether received RETRY packets should be dropped.
+ bool drop_incoming_retry_packets_;
// If max_consecutive_ptos_ > 0, close connection if consecutive PTOs is
// greater than max_consecutive_ptos.
@@ -1502,11 +1600,16 @@ class QUIC_EXPORT_PRIVATE QuicConnection
QuicConnectionMtuDiscoverer mtu_discoverer_;
- // Latched value of quic_version_negotiated_by_default_at_server.
- const bool quic_version_negotiated_by_default_at_server_;
+ QuicNetworkBlackholeDetector blackhole_detector_;
+
+ QuicIdleNetworkDetector idle_network_detector_;
+
+ const bool use_blackhole_detector_ =
+ GetQuicReloadableFlag(quic_use_blackhole_detector);
- // Latched value of quic_use_handshaker_delegate.
- const bool use_handshake_delegate_;
+ const bool use_idle_network_detector_ =
+ use_blackhole_detector_ &&
+ GetQuicReloadableFlag(quic_use_idle_network_detector);
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection_id.cc b/chromium/net/third_party/quiche/src/quic/core/quic_connection_id.cc
index 49e90b6bb38..7e31f16adb2 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_connection_id.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_connection_id.cc
@@ -17,8 +17,8 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
@@ -53,14 +53,6 @@ class QuicConnectionIdHasher {
QuicConnectionId::QuicConnectionId() : QuicConnectionId(nullptr, 0) {}
QuicConnectionId::QuicConnectionId(const char* data, uint8_t length) {
- static_assert(kQuicMaxConnectionIdAllVersionsLength <=
- std::numeric_limits<uint8_t>::max(),
- "kQuicMaxConnectionIdAllVersionsLength too high");
- if (length > kQuicMaxConnectionIdAllVersionsLength) {
- QUIC_BUG << "Attempted to create connection ID of length "
- << static_cast<int>(length);
- length = kQuicMaxConnectionIdAllVersionsLength;
- }
length_ = length;
if (length_ == 0) {
return;
@@ -109,11 +101,6 @@ uint8_t QuicConnectionId::length() const {
}
void QuicConnectionId::set_length(uint8_t length) {
- if (length > kQuicMaxConnectionIdAllVersionsLength) {
- QUIC_BUG << "Attempted to set connection ID length to "
- << static_cast<int>(length);
- length = kQuicMaxConnectionIdAllVersionsLength;
- }
char temporary_data[sizeof(data_short_)];
if (length > sizeof(data_short_)) {
if (length_ <= sizeof(data_short_)) {
@@ -152,7 +139,7 @@ std::string QuicConnectionId::ToString() const {
if (IsEmpty()) {
return std::string("0");
}
- return QuicTextUtils::HexEncode(data(), length_);
+ return quiche::QuicheTextUtils::HexEncode(data(), length_);
}
std::ostream& operator<<(std::ostream& os, const QuicConnectionId& v) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection_id.h b/chromium/net/third_party/quiche/src/quic/core/quic_connection_id.h
index 25af43def29..52d5e11a354 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_connection_id.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_connection_id.h
@@ -25,9 +25,6 @@ enum QuicConnectionIdIncluded : uint8_t {
CONNECTION_ID_ABSENT = 2,
};
-// Maximum connection ID length that we support in any packet or version.
-const uint8_t kQuicMaxConnectionIdAllVersionsLength = 20;
-
// Maximum connection ID length supported by versions that use the encoding from
// draft-ietf-quic-invariants-06.
const uint8_t kQuicMaxConnectionIdWithLengthPrefixLength = 20;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection_id_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_connection_id_test.cc
index df736309ff2..3fa7c020b40 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_connection_id_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_connection_id_test.cc
@@ -9,9 +9,9 @@
#include <string>
#include "net/third_party/quiche/src/quic/core/quic_types.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
namespace quic {
@@ -92,7 +92,7 @@ TEST_F(QuicConnectionIdTest, Hash) {
// Verify that any two all-zero connection IDs of different lengths never
// have the same hash.
- const char connection_id_bytes[kQuicMaxConnectionIdAllVersionsLength] = {};
+ const char connection_id_bytes[255] = {};
for (uint8_t i = 0; i < sizeof(connection_id_bytes) - 1; ++i) {
QuicConnectionId connection_id_i(connection_id_bytes, i);
for (uint8_t j = i + 1; j < sizeof(connection_id_bytes); ++j) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection_stats.h b/chromium/net/third_party/quiche/src/quic/core/quic_connection_stats.h
index c76d591602b..911ea6dac75 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_connection_stats.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_connection_stats.h
@@ -15,6 +15,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
namespace quic {
+
// Structure to hold stats for a QuicConnection.
struct QUIC_EXPORT_PRIVATE QuicConnectionStats {
QUIC_EXPORT_PRIVATE friend std::ostream& operator<<(
@@ -44,6 +45,11 @@ struct QUIC_EXPORT_PRIVATE QuicConnectionStats {
QuicPacketCount packets_spuriously_retransmitted = 0;
// Number of packets abandoned as lost by the loss detection algorithm.
QuicPacketCount packets_lost = 0;
+ QuicPacketCount packet_spuriously_detected_lost = 0;
+
+ // The sum of the detection time of all lost packets. The detection time of a
+ // lost packet is defined as: T(detection) - T(send).
+ QuicTime::Delta total_loss_detection_time = QuicTime::Delta::Zero();
// Number of times this connection went through the slow start phase.
uint32_t slowstart_count = 0;
@@ -60,6 +66,14 @@ struct QUIC_EXPORT_PRIVATE QuicConnectionStats {
// Time spent in slow start. Populated for BBRv1 and BBRv2.
QuicTimeAccumulator slowstart_duration;
+ // Number of PROBE_BW cycles. Populated for BBRv1 and BBRv2.
+ uint32_t bbr_num_cycles = 0;
+ // Number of PROBE_BW cycles shortened for reno coexistence. BBRv2 only.
+ uint32_t bbr_num_short_cycles_for_reno_coexistence = 0;
+ // Whether BBR exited STARTUP due to excessive loss. Populated for BBRv1 and
+ // BBRv2.
+ bool bbr_exit_startup_due_to_loss = false;
+
QuicPacketCount packets_dropped = 0; // Duplicate or less than least unacked.
// Packets that failed to decrypt when they were first received,
@@ -112,6 +126,13 @@ struct QUIC_EXPORT_PRIVATE QuicConnectionStats {
// Number of ack aggregation epochs. For the same number of bytes acked, the
// smaller this value, the more ack aggregation is going on.
uint64_t num_ack_aggregation_epochs = 0;
+
+ // Whether overshooting is detected (and pacing rate decreases) during start
+ // up with network parameters adjusted.
+ bool overshooting_detected_with_network_parameters_adjusted = false;
+
+ // Whether there is any non app-limited bandwidth sample.
+ bool has_non_app_limited_sample = false;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_connection_test.cc
index 3babced88b6..e5faa3586da 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_connection_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_connection_test.cc
@@ -22,13 +22,12 @@
#include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_error_code_wrappers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_reference_counted.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_random.h"
@@ -41,6 +40,9 @@
#include "net/third_party/quiche/src/quic/test_tools/simple_data_producer.h"
#include "net/third_party/quiche/src/quic/test_tools/simple_quic_framer.h"
#include "net/third_party/quiche/src/quic/test_tools/simple_session_notifier.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
using testing::_;
using testing::AnyNumber;
@@ -117,19 +119,21 @@ class TaggingEncrypter : public QuicEncrypter {
~TaggingEncrypter() override {}
// QuicEncrypter interface.
- bool SetKey(QuicStringPiece /*key*/) override { return true; }
+ bool SetKey(quiche::QuicheStringPiece /*key*/) override { return true; }
- bool SetNoncePrefix(QuicStringPiece /*nonce_prefix*/) override {
+ bool SetNoncePrefix(quiche::QuicheStringPiece /*nonce_prefix*/) override {
return true;
}
- bool SetIV(QuicStringPiece /*iv*/) override { return true; }
+ bool SetIV(quiche::QuicheStringPiece /*iv*/) override { return true; }
- bool SetHeaderProtectionKey(QuicStringPiece /*key*/) override { return true; }
+ bool SetHeaderProtectionKey(quiche::QuicheStringPiece /*key*/) override {
+ return true;
+ }
bool EncryptPacket(uint64_t /*packet_number*/,
- QuicStringPiece /*associated_data*/,
- QuicStringPiece plaintext,
+ quiche::QuicheStringPiece /*associated_data*/,
+ quiche::QuicheStringPiece plaintext,
char* output,
size_t* output_length,
size_t max_output_length) override {
@@ -146,7 +150,7 @@ class TaggingEncrypter : public QuicEncrypter {
}
std::string GenerateHeaderProtectionMask(
- QuicStringPiece /*sample*/) override {
+ quiche::QuicheStringPiece /*sample*/) override {
return std::string(5, 0);
}
@@ -162,9 +166,13 @@ class TaggingEncrypter : public QuicEncrypter {
return plaintext_size + kTagSize;
}
- QuicStringPiece GetKey() const override { return QuicStringPiece(); }
+ quiche::QuicheStringPiece GetKey() const override {
+ return quiche::QuicheStringPiece();
+ }
- QuicStringPiece GetNoncePrefix() const override { return QuicStringPiece(); }
+ quiche::QuicheStringPiece GetNoncePrefix() const override {
+ return quiche::QuicheStringPiece();
+ }
private:
enum {
@@ -181,17 +189,19 @@ class TaggingDecrypter : public QuicDecrypter {
~TaggingDecrypter() override {}
// QuicDecrypter interface
- bool SetKey(QuicStringPiece /*key*/) override { return true; }
+ bool SetKey(quiche::QuicheStringPiece /*key*/) override { return true; }
- bool SetNoncePrefix(QuicStringPiece /*nonce_prefix*/) override {
+ bool SetNoncePrefix(quiche::QuicheStringPiece /*nonce_prefix*/) override {
return true;
}
- bool SetIV(QuicStringPiece /*iv*/) override { return true; }
+ bool SetIV(quiche::QuicheStringPiece /*iv*/) override { return true; }
- bool SetHeaderProtectionKey(QuicStringPiece /*key*/) override { return true; }
+ bool SetHeaderProtectionKey(quiche::QuicheStringPiece /*key*/) override {
+ return true;
+ }
- bool SetPreliminaryKey(QuicStringPiece /*key*/) override {
+ bool SetPreliminaryKey(quiche::QuicheStringPiece /*key*/) override {
QUIC_BUG << "should not be called";
return false;
}
@@ -201,8 +211,8 @@ class TaggingDecrypter : public QuicDecrypter {
}
bool DecryptPacket(uint64_t /*packet_number*/,
- QuicStringPiece /*associated_data*/,
- QuicStringPiece ciphertext,
+ quiche::QuicheStringPiece /*associated_data*/,
+ quiche::QuicheStringPiece ciphertext,
char* output,
size_t* output_length,
size_t /*max_output_length*/) override {
@@ -225,13 +235,17 @@ class TaggingDecrypter : public QuicDecrypter {
size_t GetKeySize() const override { return 0; }
size_t GetNoncePrefixSize() const override { return 0; }
size_t GetIVSize() const override { return 0; }
- QuicStringPiece GetKey() const override { return QuicStringPiece(); }
- QuicStringPiece GetNoncePrefix() const override { return QuicStringPiece(); }
+ quiche::QuicheStringPiece GetKey() const override {
+ return quiche::QuicheStringPiece();
+ }
+ quiche::QuicheStringPiece GetNoncePrefix() const override {
+ return quiche::QuicheStringPiece();
+ }
// Use a distinct value starting with 0xFFFFFF, which is never used by TLS.
uint32_t cipher_id() const override { return 0xFFFFFFF0; }
protected:
- virtual uint8_t GetTag(QuicStringPiece ciphertext) {
+ virtual uint8_t GetTag(quiche::QuicheStringPiece ciphertext) {
return ciphertext.data()[ciphertext.size() - 1];
}
@@ -240,7 +254,7 @@ class TaggingDecrypter : public QuicDecrypter {
kTagSize = 12,
};
- bool CheckTag(QuicStringPiece ciphertext, uint8_t tag) {
+ bool CheckTag(quiche::QuicheStringPiece ciphertext, uint8_t tag) {
for (size_t i = ciphertext.size() - kTagSize; i < ciphertext.size(); i++) {
if (ciphertext.data()[i] != tag) {
return false;
@@ -259,7 +273,9 @@ class StrictTaggingDecrypter : public TaggingDecrypter {
~StrictTaggingDecrypter() override {}
// TaggingQuicDecrypter
- uint8_t GetTag(QuicStringPiece /*ciphertext*/) override { return tag_; }
+ uint8_t GetTag(quiche::QuicheStringPiece /*ciphertext*/) override {
+ return tag_;
+ }
// Use a distinct value starting with 0xFFFFFF, which is never used by TLS.
uint32_t cipher_id() const override { return 0xFFFFFFF1; }
@@ -324,24 +340,7 @@ class TestPacketWriter : public QuicPacketWriter {
TestPacketWriter(ParsedQuicVersion version, MockClock* clock)
: version_(version),
framer_(SupportedVersions(version_), Perspective::IS_SERVER),
- last_packet_size_(0),
- write_blocked_(false),
- write_should_fail_(false),
- block_on_next_flush_(false),
- block_on_next_write_(false),
- next_packet_too_large_(false),
- always_get_packet_too_large_(false),
- is_write_blocked_data_buffered_(false),
- is_batch_mode_(false),
- final_bytes_of_last_packet_(0),
- final_bytes_of_previous_packet_(0),
- use_tagging_decrypter_(false),
- packets_write_attempts_(0),
- connection_close_packets_(0),
- clock_(clock),
- write_pause_time_delta_(QuicTime::Delta::Zero()),
- max_packet_size_(kMaxOutgoingPacketSize),
- supports_release_time_(false) {
+ clock_(clock) {
QuicFramerPeer::SetLastSerializedServerConnectionId(framer_.framer(),
TestConnectionId());
framer_.framer()->SetInitialObfuscators(TestConnectionId());
@@ -369,6 +368,8 @@ class TestPacketWriter : public QuicPacketWriter {
framer_.framer()->InstallDecrypter(
ENCRYPTION_INITIAL, std::make_unique<TaggingDecrypter>());
framer_.framer()->InstallDecrypter(
+ ENCRYPTION_HANDSHAKE, std::make_unique<TaggingDecrypter>());
+ framer_.framer()->InstallDecrypter(
ENCRYPTION_ZERO_RTT, std::make_unique<TaggingDecrypter>());
framer_.framer()->InstallDecrypter(
ENCRYPTION_FORWARD_SECURE, std::make_unique<TaggingDecrypter>());
@@ -412,6 +413,10 @@ class TestPacketWriter : public QuicPacketWriter {
if (!write_pause_time_delta_.IsZero()) {
clock_->AdvanceTime(write_pause_time_delta_);
}
+ if (is_batch_mode_) {
+ bytes_buffered_ += last_packet_size_;
+ return WriteResult(WRITE_STATUS_OK, 0);
+ }
return WriteResult(WRITE_STATUS_OK, last_packet_size_);
}
@@ -441,12 +446,18 @@ class TestPacketWriter : public QuicPacketWriter {
}
WriteResult Flush() override {
+ flush_attempts_++;
if (block_on_next_flush_) {
block_on_next_flush_ = false;
SetWriteBlocked();
return WriteResult(WRITE_STATUS_BLOCKED, /*errno*/ -1);
}
- return WriteResult(WRITE_STATUS_OK, 0);
+ if (write_should_fail_) {
+ return WriteResult(WRITE_STATUS_ERROR, /*errno*/ -1);
+ }
+ int bytes_flushed = bytes_buffered_;
+ bytes_buffered_ = 0;
+ return WriteResult(WRITE_STATUS_OK, bytes_flushed);
}
void BlockOnNextFlush() { block_on_next_flush_ = true; }
@@ -554,7 +565,9 @@ class TestPacketWriter : public QuicPacketWriter {
void use_tagging_decrypter() { use_tagging_decrypter_ = true; }
- uint32_t packets_write_attempts() { return packets_write_attempts_; }
+ uint32_t packets_write_attempts() const { return packets_write_attempts_; }
+
+ uint32_t flush_attempts() const { return flush_attempts_; }
uint32_t connection_close_packets() const {
return connection_close_packets_;
@@ -579,27 +592,32 @@ class TestPacketWriter : public QuicPacketWriter {
private:
ParsedQuicVersion version_;
SimpleQuicFramer framer_;
- size_t last_packet_size_;
+ size_t last_packet_size_ = 0;
QuicPacketHeader last_packet_header_;
- bool write_blocked_;
- bool write_should_fail_;
- bool block_on_next_flush_;
- bool block_on_next_write_;
- bool next_packet_too_large_;
- bool always_get_packet_too_large_;
- bool is_write_blocked_data_buffered_;
- bool is_batch_mode_;
- uint32_t final_bytes_of_last_packet_;
- uint32_t final_bytes_of_previous_packet_;
- bool use_tagging_decrypter_;
- uint32_t packets_write_attempts_;
- uint32_t connection_close_packets_;
- MockClock* clock_;
+ bool write_blocked_ = false;
+ bool write_should_fail_ = false;
+ bool block_on_next_flush_ = false;
+ bool block_on_next_write_ = false;
+ bool next_packet_too_large_ = false;
+ bool always_get_packet_too_large_ = false;
+ bool is_write_blocked_data_buffered_ = false;
+ bool is_batch_mode_ = false;
+ // Number of times Flush() was called.
+ uint32_t flush_attempts_ = 0;
+ // (Batch mode only) Number of bytes buffered in writer. It is used as the
+ // return value of a successful Flush().
+ uint32_t bytes_buffered_ = 0;
+ uint32_t final_bytes_of_last_packet_ = 0;
+ uint32_t final_bytes_of_previous_packet_ = 0;
+ bool use_tagging_decrypter_ = false;
+ uint32_t packets_write_attempts_ = 0;
+ uint32_t connection_close_packets_ = 0;
+ MockClock* clock_ = nullptr;
// If non-zero, the clock will pause during WritePacket for this amount of
// time.
- QuicTime::Delta write_pause_time_delta_;
- QuicByteCount max_packet_size_;
- bool supports_release_time_;
+ QuicTime::Delta write_pause_time_delta_ = QuicTime::Delta::Zero();
+ QuicByteCount max_packet_size_ = kMaxOutgoingPacketSize;
+ bool supports_release_time_ = false;
};
class TestConnection : public QuicConnection {
@@ -673,7 +691,7 @@ class TestConnection : public QuicConnection {
}
QuicConsumedData SendStreamDataWithString(QuicStreamId id,
- QuicStringPiece data,
+ quiche::QuicheStringPiece data,
QuicStreamOffset offset,
StreamSendingState state) {
ScopedPacketFlusher flusher(this);
@@ -694,7 +712,7 @@ class TestConnection : public QuicConnection {
QuicConsumedData SendApplicationDataAtLevel(EncryptionLevel encryption_level,
QuicStreamId id,
- QuicStringPiece data,
+ quiche::QuicheStringPiece data,
QuicStreamOffset offset,
StreamSendingState state) {
ScopedPacketFlusher flusher(this);
@@ -731,7 +749,7 @@ class TestConnection : public QuicConnection {
// tests for some cases for this stream.
QuicConsumedData SendCryptoStreamData() {
QuicStreamOffset offset = 0;
- QuicStringPiece data("chlo");
+ quiche::QuicheStringPiece data("chlo");
if (!QuicVersionUsesCryptoFrames(transport_version())) {
return SendCryptoDataWithString(data, offset);
}
@@ -747,20 +765,26 @@ class TestConnection : public QuicConnection {
return QuicConsumedData(bytes_written, /*fin_consumed*/ false);
}
- QuicConsumedData SendCryptoDataWithString(QuicStringPiece data,
+ QuicConsumedData SendCryptoDataWithString(quiche::QuicheStringPiece data,
QuicStreamOffset offset) {
+ return SendCryptoDataWithString(data, offset, ENCRYPTION_INITIAL);
+ }
+
+ QuicConsumedData SendCryptoDataWithString(quiche::QuicheStringPiece data,
+ QuicStreamOffset offset,
+ EncryptionLevel encryption_level) {
if (!QuicVersionUsesCryptoFrames(transport_version())) {
return SendStreamDataWithString(
QuicUtils::GetCryptoStreamId(transport_version()), data, offset,
NO_FIN);
}
- producer_.SaveCryptoData(ENCRYPTION_INITIAL, offset, data);
+ producer_.SaveCryptoData(encryption_level, offset, data);
size_t bytes_written;
if (notifier_) {
bytes_written =
- notifier_->WriteCryptoData(ENCRYPTION_INITIAL, data.length(), offset);
+ notifier_->WriteCryptoData(encryption_level, data.length(), offset);
} else {
- bytes_written = QuicConnection::SendCryptoData(ENCRYPTION_INITIAL,
+ bytes_written = QuicConnection::SendCryptoData(encryption_level,
data.length(), offset);
}
return QuicConsumedData(bytes_written, /*fin_consumed*/ false);
@@ -820,6 +844,11 @@ class TestConnection : public QuicConnection {
}
TestAlarmFactory::TestAlarm* GetTimeoutAlarm() {
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector) &&
+ GetQuicReloadableFlag(quic_use_idle_network_detector)) {
+ return reinterpret_cast<TestAlarmFactory::TestAlarm*>(
+ QuicConnectionPeer::GetIdleNetworkDetectorAlarm(this));
+ }
return reinterpret_cast<TestAlarmFactory::TestAlarm*>(
QuicConnectionPeer::GetTimeoutAlarm(this));
}
@@ -839,6 +868,34 @@ class TestConnection : public QuicConnection {
QuicConnectionPeer::GetProcessUndecryptablePacketsAlarm(this));
}
+ TestAlarmFactory::TestAlarm* GetBlackholeDetectorAlarm() {
+ DCHECK(GetQuicReloadableFlag(quic_use_blackhole_detector));
+ return reinterpret_cast<TestAlarmFactory::TestAlarm*>(
+ QuicConnectionPeer::GetBlackholeDetectorAlarm(this));
+ }
+
+ void PathDegradingTimeout() {
+ DCHECK(PathDegradingDetectionInProgress());
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector)) {
+ GetBlackholeDetectorAlarm()->Fire();
+ } else {
+ GetPathDegradingAlarm()->Fire();
+ }
+ }
+
+ bool PathDegradingDetectionInProgress() {
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector)) {
+ return QuicConnectionPeer::GetPathDegradingDeadline(this).IsInitialized();
+ }
+ return GetPathDegradingAlarm()->IsSet();
+ }
+
+ bool BlackholeDetectionInProgress() {
+ DCHECK(GetQuicReloadableFlag(quic_use_blackhole_detector));
+ return QuicConnectionPeer::GetBlackholeDetectionDeadline(this)
+ .IsInitialized();
+ }
+
void SetMaxTailLossProbes(size_t max_tail_loss_probes) {
QuicSentPacketManagerPeer::SetMaxTailLossProbes(
QuicConnectionPeer::GetSentPacketManager(this), max_tail_loss_probes);
@@ -858,7 +915,7 @@ class TestConnection : public QuicConnection {
if (QuicConnectionPeer::GetSentPacketManager(this)->pto_enabled()) {
// PTO mode is default enabled for T099. And TLP/RTO related tests are
// stale.
- DCHECK_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99), version());
+ DCHECK_EQ(PROTOCOL_TLS1_3, version().handshake_protocol);
return true;
}
return false;
@@ -910,7 +967,7 @@ struct TestParams {
// Used by ::testing::PrintToStringParamName().
std::string PrintToString(const TestParams& p) {
- return QuicStrCat(
+ return quiche::QuicheStrCat(
ParsedQuicVersionToString(p.version), "_",
(p.ack_response == AckResponse::kDefer ? "defer" : "immediate"), "_",
(p.no_stop_waiting ? "No" : ""), "StopWaiting");
@@ -919,7 +976,6 @@ std::string PrintToString(const TestParams& p) {
// Constructs various test permutations.
std::vector<TestParams> GetTestParams() {
QuicFlagSaver flags;
- SetQuicReloadableFlag(quic_supports_tls_handshake, true);
std::vector<TestParams> params;
ParsedQuicVersionVector all_supported_versions = AllSupportedVersions();
for (size_t i = 0; i < all_supported_versions.size(); ++i) {
@@ -977,15 +1033,14 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
version()),
creator_(QuicConnectionPeer::GetPacketCreator(&connection_)),
manager_(QuicConnectionPeer::GetSentPacketManager(&connection_)),
- frame1_(0, false, 0, QuicStringPiece(data1)),
- frame2_(0, false, 3, QuicStringPiece(data2)),
- crypto_frame_(ENCRYPTION_INITIAL, 0, QuicStringPiece(data1)),
+ frame1_(0, false, 0, quiche::QuicheStringPiece(data1)),
+ frame2_(0, false, 3, quiche::QuicheStringPiece(data2)),
+ crypto_frame_(ENCRYPTION_INITIAL, 0, quiche::QuicheStringPiece(data1)),
packet_number_length_(PACKET_4BYTE_PACKET_NUMBER),
connection_id_included_(CONNECTION_ID_PRESENT),
notifier_(&connection_),
connection_close_frame_count_(0) {
QUIC_DVLOG(2) << "QuicConnectionTest(" << PrintToString(GetParam()) << ")";
- SetQuicReloadableFlag(quic_supports_tls_handshake, true);
connection_.set_defer_send_in_response_to_packets(GetParam().ack_response ==
AckResponse::kDefer);
framer_.SetInitialObfuscators(TestConnectionId());
@@ -1034,6 +1089,7 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
.Times(AnyNumber());
+ EXPECT_CALL(*send_algorithm_, OnPacketNeutered(_)).Times(AnyNumber());
EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
.WillRepeatedly(Return(kDefaultTCPMSS));
EXPECT_CALL(*send_algorithm_, PacingRate(_))
@@ -1059,12 +1115,14 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
EXPECT_CALL(visitor_, OnPacketReceived(_, _, _)).Times(AnyNumber());
EXPECT_CALL(visitor_, OnForwardProgressConfirmed()).Times(AnyNumber());
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)).Times(AnyNumber());
-
+ EXPECT_CALL(visitor_, OnOneRttPacketAcknowledged())
+ .Times(testing::AtMost(1));
EXPECT_CALL(*loss_algorithm_, GetLossTimeout())
.WillRepeatedly(Return(QuicTime::Zero()));
EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _, _))
.Times(AnyNumber());
-
+ EXPECT_CALL(visitor_, GetHandshakeState())
+ .WillRepeatedly(Return(HANDSHAKE_START));
if (connection_.version().KnowsWhichDecrypterToUse()) {
connection_.InstallDecrypter(
ENCRYPTION_FORWARD_SECURE,
@@ -1127,6 +1185,12 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
QuicSocketAddress peer_address) {
QuicFrames frames;
frames.push_back(QuicFrame(frame));
+ return ProcessFramesPacketWithAddresses(frames, self_address, peer_address);
+ }
+
+ void ProcessFramesPacketWithAddresses(QuicFrames frames,
+ QuicSocketAddress self_address,
+ QuicSocketAddress peer_address) {
QuicPacketCreatorPeer::SetSendVersionInPacket(
&peer_creator_,
QuicPacketCreatorPeer::GetEncryptionLevel(&peer_creator_) <
@@ -1179,6 +1243,14 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
size_t ProcessFramePacketAtLevel(uint64_t number,
QuicFrame frame,
EncryptionLevel level) {
+ QuicFrames frames;
+ frames.push_back(frame);
+ return ProcessFramesPacketAtLevel(number, frames, level);
+ }
+
+ size_t ProcessFramesPacketAtLevel(uint64_t number,
+ const QuicFrames& frames,
+ EncryptionLevel level) {
QuicPacketHeader header;
header.destination_connection_id = connection_id_;
header.packet_number_length = packet_number_length_;
@@ -1200,8 +1272,6 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
header.source_connection_id_included = CONNECTION_ID_PRESENT;
}
header.packet_number = QuicPacketNumber(number);
- QuicFrames frames;
- frames.push_back(frame);
std::unique_ptr<QuicPacket> packet(ConstructPacket(header, frames));
// Set the correct encryption level and encrypter on peer_creator and
// peer_framer, respectively.
@@ -1309,7 +1379,7 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
}
QuicByteCount SendStreamDataToPeer(QuicStreamId id,
- QuicStringPiece data,
+ quiche::QuicheStringPiece data,
QuicStreamOffset offset,
StreamSendingState state,
QuicPacketNumber* last_packet) {
@@ -1346,6 +1416,16 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
void SendPing() { notifier_.WriteOrBufferPing(); }
+ MessageStatus SendMessage(quiche::QuicheStringPiece message) {
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ QuicMemSliceStorage storage(nullptr, 0, nullptr, 0);
+ return connection_.SendMessage(
+ 1,
+ MakeSpan(connection_.helper()->GetStreamSendBufferAllocator(), message,
+ &storage),
+ false);
+ }
+
void ProcessAckPacket(uint64_t packet_number, QuicAckFrame* frame) {
if (packet_number > 1) {
QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, packet_number - 1);
@@ -1564,9 +1644,7 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
if (perspective == Perspective::IS_SERVER) {
connection_.set_can_truncate_connection_ids(true);
QuicConnectionPeer::SetNegotiatedVersion(&connection_);
- if (GetQuicReloadableFlag(quic_version_negotiated_by_default_at_server)) {
- connection_.OnSuccessfulVersionNegotiation();
- }
+ connection_.OnSuccessfulVersionNegotiation();
}
QuicFramerPeer::SetPerspective(&peer_framer_,
QuicUtils::InvertPerspective(perspective));
@@ -1635,6 +1713,9 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
// same overhead, either 12 bytes for ones using Google QUIC crypto, or 16
// bytes for ones using TLS.
connection_.SetEncrypter(ENCRYPTION_INITIAL, nullptr);
+ // Prevent packets from being coalesced.
+ EXPECT_CALL(visitor_, GetHandshakeState())
+ .WillRepeatedly(Return(HANDSHAKE_CONFIRMED));
EXPECT_TRUE(connection_.connected());
}
@@ -1719,7 +1800,7 @@ TEST_P(QuicConnectionTest, SelfAddressChangeAtClient) {
} else {
frame = QuicFrame(QuicStreamFrame(
QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
- 0u, QuicStringPiece()));
+ 0u, quiche::QuicheStringPiece()));
EXPECT_CALL(visitor_, OnStreamFrame(_));
}
ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
@@ -1750,7 +1831,7 @@ TEST_P(QuicConnectionTest, SelfAddressChangeAtServer) {
} else {
frame = QuicFrame(QuicStreamFrame(
QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
- 0u, QuicStringPiece()));
+ 0u, quiche::QuicheStringPiece()));
EXPECT_CALL(visitor_, OnStreamFrame(_));
}
ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
@@ -1779,7 +1860,7 @@ TEST_P(QuicConnectionTest, AllowSelfAddressChangeToMappedIpv4AddressAtServer) {
} else {
frame = QuicFrame(QuicStreamFrame(
QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
- 0u, QuicStringPiece()));
+ 0u, quiche::QuicheStringPiece()));
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(3);
}
QuicIpAddress host;
@@ -1788,8 +1869,8 @@ TEST_P(QuicConnectionTest, AllowSelfAddressChangeToMappedIpv4AddressAtServer) {
ProcessFramePacketWithAddresses(frame, self_address1, kPeerAddress);
// Cause self_address change to mapped Ipv4 address.
QuicIpAddress host2;
- host2.FromString(
- QuicStrCat("::ffff:", connection_.self_address().host().ToString()));
+ host2.FromString(quiche::QuicheStrCat(
+ "::ffff:", connection_.self_address().host().ToString()));
QuicSocketAddress self_address2(host2, connection_.self_address().port());
ProcessFramePacketWithAddresses(frame, self_address2, kPeerAddress);
EXPECT_TRUE(connection_.connected());
@@ -1816,7 +1897,7 @@ TEST_P(QuicConnectionTest, ClientAddressChangeAndPacketReordered) {
} else {
frame = QuicFrame(QuicStreamFrame(
QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
- 0u, QuicStringPiece()));
+ 0u, quiche::QuicheStringPiece()));
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
}
QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 5);
@@ -1856,7 +1937,7 @@ TEST_P(QuicConnectionTest, PeerAddressChangeAtServer) {
} else {
frame = QuicFrame(QuicStreamFrame(
QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
- 0u, QuicStringPiece()));
+ 0u, quiche::QuicheStringPiece()));
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
}
ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
@@ -1895,7 +1976,7 @@ TEST_P(QuicConnectionTest, EffectivePeerAddressChangeAtServer) {
} else {
frame = QuicFrame(QuicStreamFrame(
QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
- 0u, QuicStringPiece()));
+ 0u, quiche::QuicheStringPiece()));
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
}
ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
@@ -1958,7 +2039,7 @@ TEST_P(QuicConnectionTest, EffectivePeerAddressChangeAtServer) {
connection_.active_effective_peer_migration_type());
}
-TEST_P(QuicConnectionTest, ReceivePaddedPingAtServer) {
+TEST_P(QuicConnectionTest, ReceivePathProbeWithNoAddressChangeAtServer) {
set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
@@ -1978,7 +2059,7 @@ TEST_P(QuicConnectionTest, ReceivePaddedPingAtServer) {
} else {
frame = QuicFrame(QuicStreamFrame(
QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
- 0u, QuicStringPiece()));
+ 0u, quiche::QuicheStringPiece()));
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
}
ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
@@ -1990,17 +2071,8 @@ TEST_P(QuicConnectionTest, ReceivePaddedPingAtServer) {
// Process a padded PING or PATH CHALLENGE packet with no peer address change
// on server side will be ignored.
- OwningSerializedPacketPointer probing_packet;
- if (VersionHasIetfQuicFrames(version().transport_version)) {
- QuicPathFrameBuffer payload = {
- {0xde, 0xad, 0xbe, 0xef, 0xba, 0xdc, 0x0f, 0xfe}};
- probing_packet =
- QuicPacketCreatorPeer::SerializePathChallengeConnectivityProbingPacket(
- &peer_creator_, &payload);
- } else {
- probing_packet = QuicPacketCreatorPeer::SerializeConnectivityProbingPacket(
- &peer_creator_);
- }
+ OwningSerializedPacketPointer probing_packet = ConstructProbingPacket();
+
std::unique_ptr<QuicReceivedPacket> received(ConstructReceivedPacket(
QuicEncryptedPacket(probing_packet->encrypted_buffer,
probing_packet->encrypted_length),
@@ -2065,7 +2137,11 @@ TEST_P(QuicConnectionTest, DiscardQueuedPacketsAfterConnectionClose) {
EXPECT_EQ(0u, connection_.GetStats().packets_discarded);
}
-TEST_P(QuicConnectionTest, ReceiveConnectivityProbingAtServer) {
+// Receive a path probe request at the server side, i.e.,
+// in non-IETF version: receive a padded PING packet with a peer addess change;
+// in IETF version: receive a packet contains PATH CHALLENGE with peer address
+// change.
+TEST_P(QuicConnectionTest, ReceivePathProbingAtServer) {
set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
@@ -2085,7 +2161,7 @@ TEST_P(QuicConnectionTest, ReceiveConnectivityProbingAtServer) {
} else {
frame = QuicFrame(QuicStreamFrame(
QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
- 0u, QuicStringPiece()));
+ 0u, quiche::QuicheStringPiece()));
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
}
ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
@@ -2093,8 +2169,13 @@ TEST_P(QuicConnectionTest, ReceiveConnectivityProbingAtServer) {
EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(0);
- EXPECT_CALL(visitor_, OnPacketReceived(_, _, true)).Times(1);
-
+ if (!GetParam().version.HasIetfQuicFrames()) {
+ EXPECT_CALL(visitor_,
+ OnPacketReceived(_, _, /*is_connectivity_probe=*/true))
+ .Times(1);
+ } else {
+ EXPECT_CALL(visitor_, OnPacketReceived(_, _, _)).Times(0);
+ }
// Process a padded PING packet from a new peer address on server side
// is effectively receiving a connectivity probing.
const QuicSocketAddress kNewPeerAddress =
@@ -2123,7 +2204,90 @@ TEST_P(QuicConnectionTest, ReceiveConnectivityProbingAtServer) {
EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
}
-TEST_P(QuicConnectionTest, ReceiveReorderedConnectivityProbingAtServer) {
+// Receive a padded PING packet with a port change on server side.
+TEST_P(QuicConnectionTest, ReceivePaddedPingWithPortChangeAtServer) {
+ set_perspective(Perspective::IS_SERVER);
+ QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
+ EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
+
+ // Clear direct_peer_address.
+ QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
+ // Clear effective_peer_address, it is the same as direct_peer_address for
+ // this test.
+ QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
+ QuicSocketAddress());
+ EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
+
+ QuicFrame frame;
+ if (GetParam().version.UsesCryptoFrames()) {
+ frame = QuicFrame(&crypto_frame_);
+ EXPECT_CALL(visitor_, OnCryptoFrame(_)).Times(AnyNumber());
+ } else {
+ frame = QuicFrame(QuicStreamFrame(
+ QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
+ 0u, quiche::QuicheStringPiece()));
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
+ }
+ ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
+ EXPECT_EQ(kPeerAddress, connection_.peer_address());
+ EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
+
+ if (GetParam().version.HasIetfQuicFrames()) {
+ // In IETF version, a padded PING packet with port change is not taken as
+ // connectivity probe.
+ EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(1);
+ EXPECT_CALL(visitor_, OnPacketReceived(_, _, _)).Times(0);
+ } else {
+ // In non-IETF version, process a padded PING packet from a new peer
+ // address on server side is effectively receiving a connectivity probing.
+ EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(0);
+ EXPECT_CALL(visitor_,
+ OnPacketReceived(_, _, /*is_connectivity_probe=*/true))
+ .Times(1);
+ }
+ const QuicSocketAddress kNewPeerAddress =
+ QuicSocketAddress(QuicIpAddress::Loopback6(), /*port=*/23456);
+
+ QuicFrames frames;
+ // Write a PING frame, which has no data payload.
+ QuicPingFrame ping_frame;
+ frames.push_back(QuicFrame(ping_frame));
+
+ // Add padding to the rest of the packet.
+ QuicPaddingFrame padding_frame;
+ frames.push_back(QuicFrame(padding_frame));
+
+ uint64_t num_probing_received =
+ connection_.GetStats().num_connectivity_probing_received;
+
+ ProcessFramesPacketWithAddresses(frames, kSelfAddress, kNewPeerAddress);
+
+ if (GetParam().version.HasIetfQuicFrames()) {
+ // Padded PING with port changen is not considered as connectivity probe but
+ // a PORT CHANGE.
+ EXPECT_EQ(num_probing_received,
+ connection_.GetStats().num_connectivity_probing_received);
+ EXPECT_EQ(kNewPeerAddress, connection_.peer_address());
+ EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
+ } else {
+ EXPECT_EQ(num_probing_received + 1,
+ connection_.GetStats().num_connectivity_probing_received);
+ EXPECT_EQ(kPeerAddress, connection_.peer_address());
+ EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
+ }
+
+ // Process another packet with the old peer address on server side.
+ if (GetParam().version.HasIetfQuicFrames()) {
+ EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(1);
+ } else {
+ EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(0);
+ }
+ ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
+ EXPECT_EQ(kPeerAddress, connection_.peer_address());
+ EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
+}
+
+TEST_P(QuicConnectionTest, ReceiveReorderedPathProbingAtServer) {
set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
@@ -2143,7 +2307,7 @@ TEST_P(QuicConnectionTest, ReceiveReorderedConnectivityProbingAtServer) {
} else {
frame = QuicFrame(QuicStreamFrame(
QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
- 0u, QuicStringPiece()));
+ 0u, quiche::QuicheStringPiece()));
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
}
QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 5);
@@ -2155,7 +2319,13 @@ TEST_P(QuicConnectionTest, ReceiveReorderedConnectivityProbingAtServer) {
QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 4);
EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(0);
- EXPECT_CALL(visitor_, OnPacketReceived(_, _, true)).Times(1);
+ if (!GetParam().version.HasIetfQuicFrames()) {
+ EXPECT_CALL(visitor_,
+ OnPacketReceived(_, _, /*is_connectivity_probe=*/true))
+ .Times(1);
+ } else {
+ EXPECT_CALL(visitor_, OnPacketReceived(_, _, _)).Times(0);
+ }
// Process a padded PING packet from a new peer address on server side
// is effectively receiving a connectivity probing, even if a newer packet has
@@ -2199,7 +2369,7 @@ TEST_P(QuicConnectionTest, MigrateAfterProbingAtServer) {
} else {
frame = QuicFrame(QuicStreamFrame(
QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
- 0u, QuicStringPiece()));
+ 0u, quiche::QuicheStringPiece()));
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
}
ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
@@ -2207,7 +2377,13 @@ TEST_P(QuicConnectionTest, MigrateAfterProbingAtServer) {
EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(0);
- EXPECT_CALL(visitor_, OnPacketReceived(_, _, true)).Times(1);
+ if (!GetParam().version.HasIetfQuicFrames()) {
+ EXPECT_CALL(visitor_,
+ OnPacketReceived(_, _, /*is_connectivity_probe=*/true))
+ .Times(1);
+ } else {
+ EXPECT_CALL(visitor_, OnPacketReceived(_, _, _)).Times(0);
+ }
// Process a padded PING packet from a new peer address on server side
// is effectively receiving a connectivity probing.
@@ -2252,7 +2428,7 @@ TEST_P(QuicConnectionTest, ReceivePaddedPingAtClient) {
} else {
frame = QuicFrame(QuicStreamFrame(
QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
- 0u, QuicStringPiece()));
+ 0u, quiche::QuicheStringPiece()));
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
}
ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
@@ -2279,7 +2455,13 @@ TEST_P(QuicConnectionTest, ReceivePaddedPingAtClient) {
EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
}
-TEST_P(QuicConnectionTest, ReceiveConnectivityProbingAtClient) {
+TEST_P(QuicConnectionTest, ReceiveConnectivityProbingResponseAtClient) {
+ // TODO(b/150095484): add test coverage for IETF to verify that client takes
+ // PATH RESPONSE with peer address change as correct validation on the new
+ // path.
+ if (GetParam().version.HasIetfQuicFrames()) {
+ return;
+ }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
set_perspective(Perspective::IS_CLIENT);
EXPECT_EQ(Perspective::IS_CLIENT, connection_.perspective());
@@ -2299,7 +2481,7 @@ TEST_P(QuicConnectionTest, ReceiveConnectivityProbingAtClient) {
} else {
frame = QuicFrame(QuicStreamFrame(
QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
- 0u, QuicStringPiece()));
+ 0u, quiche::QuicheStringPiece()));
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
}
ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
@@ -2309,7 +2491,13 @@ TEST_P(QuicConnectionTest, ReceiveConnectivityProbingAtClient) {
// Process a padded PING packet with a different self address on client side
// is effectively receiving a connectivity probing.
EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(0);
- EXPECT_CALL(visitor_, OnPacketReceived(_, _, true)).Times(1);
+ if (!GetParam().version.HasIetfQuicFrames()) {
+ EXPECT_CALL(visitor_,
+ OnPacketReceived(_, _, /*is_connectivity_probe=*/true))
+ .Times(1);
+ } else {
+ EXPECT_CALL(visitor_, OnPacketReceived(_, _, _)).Times(0);
+ }
const QuicSocketAddress kNewSelfAddress =
QuicSocketAddress(QuicIpAddress::Loopback6(), /*port=*/23456);
@@ -2349,7 +2537,7 @@ TEST_P(QuicConnectionTest, PeerAddressChangeAtClient) {
} else {
frame = QuicFrame(QuicStreamFrame(
QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
- 0u, QuicStringPiece()));
+ 0u, quiche::QuicheStringPiece()));
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
}
ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
@@ -2371,6 +2559,32 @@ TEST_P(QuicConnectionTest, MaxPacketSize) {
EXPECT_EQ(1350u, connection_.max_packet_length());
}
+TEST_P(QuicConnectionTest, PeerLowersMaxPacketSize) {
+ EXPECT_EQ(Perspective::IS_CLIENT, connection_.perspective());
+
+ // SetFromConfig is always called after construction from InitializeSession.
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ constexpr uint32_t kTestMaxPacketSize = 1233u;
+ QuicConfig config;
+ QuicConfigPeer::SetReceivedMaxPacketSize(&config, kTestMaxPacketSize);
+ connection_.SetFromConfig(config);
+
+ EXPECT_EQ(kTestMaxPacketSize, connection_.max_packet_length());
+}
+
+TEST_P(QuicConnectionTest, PeerCannotRaiseMaxPacketSize) {
+ EXPECT_EQ(Perspective::IS_CLIENT, connection_.perspective());
+
+ // SetFromConfig is always called after construction from InitializeSession.
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ constexpr uint32_t kTestMaxPacketSize = 1450u;
+ QuicConfig config;
+ QuicConfigPeer::SetReceivedMaxPacketSize(&config, kTestMaxPacketSize);
+ connection_.SetFromConfig(config);
+
+ EXPECT_EQ(kDefaultMaxPacketSize, connection_.max_packet_length());
+}
+
TEST_P(QuicConnectionTest, SmallerServerMaxPacketSize) {
TestConnection connection(TestConnectionId(), kPeerAddress, helper_.get(),
alarm_factory_.get(), writer_.get(),
@@ -2624,10 +2838,16 @@ TEST_P(QuicConnectionTest, OutOfOrderAckReceiptCausesNoAck) {
QuicAckFrame ack1 = InitAckFrame(1);
QuicAckFrame ack2 = InitAckFrame(2);
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
+ if (connection_.SupportsMultiplePacketNumberSpaces()) {
+ EXPECT_CALL(visitor_, OnOneRttPacketAcknowledged()).Times(1);
+ }
ProcessAckPacket(2, &ack2);
// Should ack immediately since we have missing packets.
EXPECT_EQ(2u, writer_->packets_write_attempts());
+ if (connection_.SupportsMultiplePacketNumberSpaces()) {
+ EXPECT_CALL(visitor_, OnOneRttPacketAcknowledged()).Times(0);
+ }
ProcessAckPacket(1, &ack1);
// Should not ack an ack filling a missing packet.
EXPECT_EQ(2u, writer_->packets_write_attempts());
@@ -2798,6 +3018,49 @@ TEST_P(QuicConnectionTest, AckNeedsRetransmittableFrames) {
EXPECT_EQ(1u, writer_->ping_frames().size());
}
+TEST_P(QuicConnectionTest, AckNeedsRetransmittableFramesAfterPto) {
+ SetQuicReloadableFlag(quic_bundle_retransmittable_with_pto_ack, true);
+ // Disable TLP so the RTO fires immediately.
+ connection_.SetMaxTailLossProbes(0);
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ QuicConfig config;
+ QuicTagVector connection_options;
+ connection_options.push_back(kEACK);
+ config.SetConnectionOptionsToSend(connection_options);
+ connection_.SetFromConfig(config);
+
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(10);
+
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(4);
+ // Receive packets 1 - 9.
+ for (size_t i = 1; i <= 9; ++i) {
+ ProcessDataPacket(i);
+ }
+
+ // Send a ping and fire the retransmission alarm.
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
+ SendPing();
+ QuicTime retransmission_time =
+ connection_.GetRetransmissionAlarm()->deadline();
+ clock_.AdvanceTime(retransmission_time - clock_.Now());
+ connection_.GetRetransmissionAlarm()->Fire();
+ ASSERT_TRUE(manager_->GetConsecutiveRtoCount() > 0 ||
+ manager_->GetConsecutivePtoCount() > 0);
+
+ // Process a packet, which requests a retransmittable frame be bundled
+ // with the ACK.
+ EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame())
+ .WillOnce(Invoke([this]() {
+ connection_.SendControlFrame(
+ QuicFrame(new QuicWindowUpdateFrame(1, 0, 0)));
+ }));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
+ ProcessDataPacket(11);
+ EXPECT_EQ(1u, writer_->window_update_frames().size());
+}
+
TEST_P(QuicConnectionTest, LeastUnackedLower) {
if (VersionHasIetfInvariantHeader(GetParam().version.transport_version)) {
return;
@@ -3177,7 +3440,8 @@ TEST_P(QuicConnectionTest, FramePackingSendv) {
EXPECT_EQ(0u, writer_->padding_frames().size());
QuicStreamFrame* frame = writer_->stream_frames()[0].get();
EXPECT_EQ(stream_id, frame->stream_id);
- EXPECT_EQ("ABCDEF", QuicStringPiece(frame->data_buffer, frame->data_length));
+ EXPECT_EQ("ABCDEF",
+ quiche::QuicheStringPiece(frame->data_buffer, frame->data_length));
}
TEST_P(QuicConnectionTest, FramePackingSendvQueued) {
@@ -3468,13 +3732,18 @@ TEST_P(QuicConnectionTest, RetransmitForQuicRstStreamNoErrorOnRTO) {
// Fire the RTO and verify that the RST_STREAM is resent, the stream data
// is sent.
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(2));
+ const size_t num_retransmissions =
+ connection_.SupportsMultiplePacketNumberSpaces() ? 1 : 2;
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .Times(AtLeast(num_retransmissions));
clock_.AdvanceTime(DefaultRetransmissionTime());
connection_.GetRetransmissionAlarm()->Fire();
size_t padding_frame_count = writer_->padding_frames().size();
EXPECT_EQ(padding_frame_count + 1u, writer_->frame_count());
- ASSERT_EQ(1u, writer_->rst_stream_frames().size());
- EXPECT_EQ(stream_id, writer_->rst_stream_frames().front().stream_id);
+ if (num_retransmissions == 2) {
+ ASSERT_EQ(1u, writer_->rst_stream_frames().size());
+ EXPECT_EQ(stream_id, writer_->rst_stream_frames().front().stream_id);
+ }
}
TEST_P(QuicConnectionTest, DoNotSendPendingRetransmissionForResetStream) {
@@ -3691,7 +3960,10 @@ TEST_P(QuicConnectionTest, RetransmitWriteBlockedAckedOriginalThenSent) {
writer_->SetWritable();
connection_.OnCanWrite();
EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
- EXPECT_FALSE(QuicConnectionPeer::HasRetransmittableFrames(&connection_, 2));
+ const uint64_t retransmission =
+ connection_.SupportsMultiplePacketNumberSpaces() ? 3 : 2;
+ EXPECT_FALSE(QuicConnectionPeer::HasRetransmittableFrames(&connection_,
+ retransmission));
}
TEST_P(QuicConnectionTest, AlarmsWhenWriteBlocked) {
@@ -3930,9 +4202,11 @@ TEST_P(QuicConnectionTest, TLP) {
// Simulate the retransmission alarm firing and sending a tlp,
// so send algorithm's OnRetransmissionTimeout is not called.
clock_.AdvanceTime(retransmission_time - clock_.Now());
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(2), _, _));
+ const QuicPacketNumber retransmission(
+ connection_.SupportsMultiplePacketNumberSpaces() ? 3 : 2);
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, retransmission, _, _));
connection_.GetRetransmissionAlarm()->Fire();
- EXPECT_EQ(QuicPacketNumber(2u), writer_->header().packet_number);
+ EXPECT_EQ(retransmission, writer_->header().packet_number);
// We do not raise the high water mark yet.
EXPECT_EQ(QuicPacketNumber(1u), stop_waiting()->least_unacked);
}
@@ -3983,6 +4257,8 @@ TEST_P(QuicConnectionTest, TailLossProbeDelayForNonStreamDataInTLPR) {
QuicTagVector options;
options.push_back(kTLPR);
config.SetConnectionOptionsToSend(options);
+ QuicConfigPeer::ReceiveIdleNetworkTimeout(&config, SERVER,
+ kDefaultIdleTimeoutSecs);
connection_.SetFromConfig(config);
connection_.SetMaxTailLossProbes(1);
@@ -3995,7 +4271,7 @@ TEST_P(QuicConnectionTest, TailLossProbeDelayForNonStreamDataInTLPR) {
EXPECT_TRUE(connection_.connected());
EXPECT_CALL(visitor_, ShouldKeepConnectionAlive())
.WillRepeatedly(Return(true));
- EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
EXPECT_FALSE(connection_.IsPathDegrading());
EXPECT_FALSE(connection_.GetPingAlarm()->IsSet());
@@ -4009,7 +4285,7 @@ TEST_P(QuicConnectionTest, TailLossProbeDelayForNonStreamDataInTLPR) {
// Path degrading alarm should be set when there is a retransmittable packet
// on the wire.
- EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_TRUE(connection_.PathDegradingDetectionInProgress());
// Verify the path degrading delay.
// First TLP with stream data.
@@ -4042,7 +4318,7 @@ TEST_P(QuicConnectionTest, TailLossProbeDelayForNonStreamDataInTLPR) {
// Path degrading alarm should be cancelled as there is no more
// reretransmittable packets on the wire.
- EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
// The ping alarm should be set to the retransmittable_on_wire_timeout.
EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
EXPECT_EQ(retransmittable_on_wire_timeout,
@@ -4056,7 +4332,7 @@ TEST_P(QuicConnectionTest, TailLossProbeDelayForNonStreamDataInTLPR) {
// The retransmission alarm and the path degrading alarm should be set as
// there is a retransmittable packet (PING) on the wire,
EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
- EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_TRUE(connection_.PathDegradingDetectionInProgress());
// Verify the retransmission delay.
QuicTime::Delta min_rto_timeout =
@@ -4506,7 +4782,7 @@ TEST_P(QuicConnectionTest, IdleTimeoutAfterFirstSentPacket) {
EXPECT_TRUE(connection_.connected());
// Advance the time and send the first packet to the peer.
- clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds(20));
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
QuicPacketNumber last_packet;
SendStreamDataToPeer(1, "foo", 0, NO_FIN, &last_packet);
EXPECT_EQ(QuicPacketNumber(1u), last_packet);
@@ -4519,7 +4795,10 @@ TEST_P(QuicConnectionTest, IdleTimeoutAfterFirstSentPacket) {
EXPECT_CALL(visitor_, OnConnectionClosed(_, _)).Times(0);
QuicTime::Delta delay = initial_ddl - clock_.ApproximateNow();
clock_.AdvanceTime(delay);
- connection_.GetTimeoutAlarm()->Fire();
+ if (!GetQuicReloadableFlag(quic_use_blackhole_detector) ||
+ !GetQuicReloadableFlag(quic_use_idle_network_detector)) {
+ connection_.GetTimeoutAlarm()->Fire();
+ }
// Verify the timeout alarm deadline is updated.
EXPECT_TRUE(connection_.connected());
EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet());
@@ -4608,8 +4887,11 @@ TEST_P(QuicConnectionTest, HandshakeTimeout) {
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
ProcessAckPacket(&frame);
- // Fire early to verify it wouldn't timeout yet.
- connection_.GetTimeoutAlarm()->Fire();
+ if (!GetQuicReloadableFlag(quic_use_blackhole_detector) ||
+ !GetQuicReloadableFlag(quic_use_idle_network_detector)) {
+ // Fire early to verify it wouldn't timeout yet.
+ connection_.GetTimeoutAlarm()->Fire();
+ }
EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet());
EXPECT_TRUE(connection_.connected());
@@ -4775,6 +5057,23 @@ TEST_P(QuicConnectionTest, SendMtuDiscoveryPacket) {
EXPECT_EQ(QuicPacketNumber(4u), creator_->packet_number());
}
+// Verifies that when a MTU probe packet is sent and buffered in a batch writer,
+// the writer is flushed immediately.
+TEST_P(QuicConnectionTest, BatchWriterFlushedAfterMtuDiscoveryPacket) {
+ writer_->SetBatchMode(true);
+ MtuDiscoveryTestInit();
+
+ // Send an MTU probe.
+ const size_t target_mtu = kDefaultMaxPacketSize + 100;
+ QuicByteCount mtu_probe_size;
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .WillOnce(SaveArg<3>(&mtu_probe_size));
+ const uint32_t prior_flush_attempts = writer_->flush_attempts();
+ connection_.SendMtuDiscoveryPacket(target_mtu);
+ EXPECT_EQ(target_mtu, mtu_probe_size);
+ EXPECT_EQ(writer_->flush_attempts(), prior_flush_attempts + 1);
+}
+
// Tests whether MTU discovery does not happen when it is not explicitly enabled
// by the connection options.
TEST_P(QuicConnectionTest, MtuDiscoveryDisabled) {
@@ -4834,6 +5133,7 @@ TEST_P(QuicConnectionTest, MtuDiscoveryEnabled) {
EXPECT_EQ(1u, connection_.mtu_probe_count());
QuicStreamOffset stream_offset = packets_between_probes_base;
+ QuicByteCount last_probe_size = 0;
for (size_t num_probes = 1; num_probes < kMtuDiscoveryAttempts;
++num_probes) {
// Send just enough packets without triggering the next probe.
@@ -4860,11 +5160,103 @@ TEST_P(QuicConnectionTest, MtuDiscoveryEnabled) {
EXPECT_EQ(new_probe_size, connection_.max_packet_length());
EXPECT_EQ(0u, connection_.GetBytesInFlight());
+ last_probe_size = probe_size;
probe_size = new_probe_size;
}
// The last probe size should be equal to the target.
EXPECT_EQ(probe_size, kMtuDiscoveryTargetPacketSizeHigh);
+
+ if (GetQuicReloadableFlag(quic_ignore_one_write_error_after_mtu_probe)) {
+ writer_->SetShouldWriteFail();
+
+ // Ignore PACKET_WRITE_ERROR once.
+ SendStreamDataToPeer(3, "(", stream_offset++, NO_FIN, nullptr);
+ EXPECT_EQ(last_probe_size, connection_.max_packet_length());
+ EXPECT_TRUE(connection_.connected());
+
+ // Close connection on another PACKET_WRITE_ERROR.
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, _))
+ .WillOnce(Invoke(this, &QuicConnectionTest::SaveConnectionCloseFrame));
+ SendStreamDataToPeer(3, ")", stream_offset++, NO_FIN, nullptr);
+ EXPECT_EQ(last_probe_size, connection_.max_packet_length());
+ EXPECT_FALSE(connection_.connected());
+ EXPECT_THAT(saved_connection_close_frame_.quic_error_code,
+ IsError(QUIC_PACKET_WRITE_ERROR));
+ }
+}
+
+// After a successful MTU probe, one and only one write error should be ignored
+// if it happened in QuicConnection::FlushPacket.
+TEST_P(QuicConnectionTest,
+ MtuDiscoveryIgnoreOneWriteErrorInFlushAfterSuccessfulProbes) {
+ MtuDiscoveryTestInit();
+ writer_->SetBatchMode(true);
+
+ const QuicPacketCount packets_between_probes_base = 5;
+ set_packets_between_probes_base(packets_between_probes_base);
+
+ connection_.EnablePathMtuDiscovery(send_algorithm_);
+
+ const QuicByteCount original_max_packet_length =
+ connection_.max_packet_length();
+ // Send enough packets so that the next one triggers path MTU discovery.
+ for (QuicPacketCount i = 0; i < packets_between_probes_base - 1; i++) {
+ SendStreamDataToPeer(3, ".", i, NO_FIN, nullptr);
+ ASSERT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet());
+ }
+
+ // Trigger the probe.
+ SendStreamDataToPeer(3, "!", packets_between_probes_base - 1, NO_FIN,
+ nullptr);
+ ASSERT_TRUE(connection_.GetMtuDiscoveryAlarm()->IsSet());
+ QuicByteCount probe_size;
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .WillOnce(SaveArg<3>(&probe_size));
+ connection_.GetMtuDiscoveryAlarm()->Fire();
+
+ EXPECT_THAT(probe_size, InRange(connection_.max_packet_length(),
+ kMtuDiscoveryTargetPacketSizeHigh));
+
+ const QuicPacketNumber probe_packet_number =
+ FirstSendingPacketNumber() + packets_between_probes_base;
+ ASSERT_EQ(probe_packet_number, creator_->packet_number());
+
+ // Acknowledge all packets sent so far.
+ QuicAckFrame probe_ack = InitAckFrame(probe_packet_number);
+ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _))
+ .Times(AnyNumber());
+ ProcessAckPacket(&probe_ack);
+ EXPECT_EQ(probe_size, connection_.max_packet_length());
+ EXPECT_EQ(0u, connection_.GetBytesInFlight());
+
+ EXPECT_EQ(1u, connection_.mtu_probe_count());
+
+ if (GetQuicReloadableFlag(quic_ignore_one_write_error_after_mtu_probe)) {
+ writer_->SetShouldWriteFail();
+
+ // Ignore PACKET_WRITE_ERROR once.
+ {
+ QuicConnection::ScopedPacketFlusher flusher(&connection_);
+ // flusher's destructor will call connection_.FlushPackets, which should
+ // get a WRITE_STATUS_ERROR from the writer and ignore it.
+ }
+ EXPECT_EQ(original_max_packet_length, connection_.max_packet_length());
+ EXPECT_TRUE(connection_.connected());
+
+ // Close connection on another PACKET_WRITE_ERROR.
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, _))
+ .WillOnce(Invoke(this, &QuicConnectionTest::SaveConnectionCloseFrame));
+ {
+ QuicConnection::ScopedPacketFlusher flusher(&connection_);
+ // flusher's destructor will call connection_.FlushPackets, which should
+ // get a WRITE_STATUS_ERROR from the writer and ignore it.
+ }
+ EXPECT_EQ(original_max_packet_length, connection_.max_packet_length());
+ EXPECT_FALSE(connection_.connected());
+ EXPECT_THAT(saved_connection_close_frame_.quic_error_code,
+ IsError(QUIC_PACKET_WRITE_ERROR));
+ }
}
// Simulate the case where the first attempt to send a probe is write blocked,
@@ -5246,7 +5638,13 @@ TEST_P(QuicConnectionTest, TimeoutAfterSend) {
SendStreamDataToPeer(
GetNthClientInitiatedStreamId(1, connection_.transport_version()), "foo",
0, FIN, nullptr);
- EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector) &&
+ GetQuicReloadableFlag(quic_use_idle_network_detector)) {
+ EXPECT_EQ(default_timeout + five_ms,
+ connection_.GetTimeoutAlarm()->deadline());
+ } else {
+ EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
+ }
// Now send more data. This will not move the timeout because
// no data has been received since the previous write.
@@ -5254,13 +5652,22 @@ TEST_P(QuicConnectionTest, TimeoutAfterSend) {
SendStreamDataToPeer(
GetNthClientInitiatedStreamId(1, connection_.transport_version()), "foo",
3, FIN, nullptr);
- EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector) &&
+ GetQuicReloadableFlag(quic_use_idle_network_detector)) {
+ EXPECT_EQ(default_timeout + five_ms,
+ connection_.GetTimeoutAlarm()->deadline());
+ } else {
+ EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
+ }
// The original alarm will fire. We should not time out because we had a
// network event at t=5ms. The alarm will reregister.
clock_.AdvanceTime(initial_idle_timeout - five_ms - five_ms);
EXPECT_EQ(default_timeout, clock_.ApproximateNow());
- connection_.GetTimeoutAlarm()->Fire();
+ if (!GetQuicReloadableFlag(quic_use_blackhole_detector) ||
+ !GetQuicReloadableFlag(quic_use_idle_network_detector)) {
+ connection_.GetTimeoutAlarm()->Fire();
+ }
EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet());
EXPECT_TRUE(connection_.connected());
EXPECT_EQ(default_timeout + five_ms,
@@ -5309,7 +5716,13 @@ TEST_P(QuicConnectionTest, TimeoutAfterRetransmission) {
SendStreamDataToPeer(
GetNthClientInitiatedStreamId(1, connection_.transport_version()), "foo",
0, FIN, nullptr);
- EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector) &&
+ GetQuicReloadableFlag(quic_use_idle_network_detector)) {
+ EXPECT_EQ(default_timeout + five_ms,
+ connection_.GetTimeoutAlarm()->deadline());
+ } else {
+ EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
+ }
// Move forward 5 ms and receive a packet, which will move the timeout
// forward 5 ms more (but will not reschedule the alarm).
@@ -5338,7 +5751,10 @@ TEST_P(QuicConnectionTest, TimeoutAfterRetransmission) {
ASSERT_EQ(default_timeout.ToDebuggingValue(),
clock_.Now().ToDebuggingValue());
EXPECT_EQ(default_timeout, clock_.Now());
- connection_.GetTimeoutAlarm()->Fire();
+ if (!GetQuicReloadableFlag(quic_use_blackhole_detector) ||
+ !GetQuicReloadableFlag(quic_use_idle_network_detector)) {
+ connection_.GetTimeoutAlarm()->Fire();
+ }
EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet());
EXPECT_TRUE(connection_.connected());
ASSERT_EQ(final_timeout.ToDebuggingValue(),
@@ -5394,7 +5810,13 @@ TEST_P(QuicConnectionTest, NewTimeoutAfterSendSilentClose) {
SendStreamDataToPeer(
GetNthClientInitiatedStreamId(1, connection_.transport_version()), "foo",
0, FIN, nullptr);
- EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector) &&
+ GetQuicReloadableFlag(quic_use_idle_network_detector)) {
+ EXPECT_EQ(default_timeout + five_ms,
+ connection_.GetTimeoutAlarm()->deadline());
+ } else {
+ EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
+ }
// Now send more data. This will not move the timeout because
// no data has been received since the previous write.
@@ -5402,13 +5824,22 @@ TEST_P(QuicConnectionTest, NewTimeoutAfterSendSilentClose) {
SendStreamDataToPeer(
GetNthClientInitiatedStreamId(1, connection_.transport_version()), "foo",
3, FIN, nullptr);
- EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector) &&
+ GetQuicReloadableFlag(quic_use_idle_network_detector)) {
+ EXPECT_EQ(default_timeout + five_ms,
+ connection_.GetTimeoutAlarm()->deadline());
+ } else {
+ EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
+ }
// The original alarm will fire. We should not time out because we had a
// network event at t=5ms. The alarm will reregister.
clock_.AdvanceTime(default_idle_timeout - five_ms - five_ms);
EXPECT_EQ(default_timeout, clock_.ApproximateNow());
- connection_.GetTimeoutAlarm()->Fire();
+ if (!GetQuicReloadableFlag(quic_use_blackhole_detector) ||
+ !GetQuicReloadableFlag(quic_use_idle_network_detector)) {
+ connection_.GetTimeoutAlarm()->Fire();
+ }
EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet());
EXPECT_TRUE(connection_.connected());
EXPECT_EQ(default_timeout + five_ms,
@@ -5471,7 +5902,13 @@ TEST_P(QuicConnectionTest, TimeoutAfterSendSilentCloseAndTLP) {
SendStreamDataToPeer(
GetNthClientInitiatedStreamId(1, connection_.transport_version()), "foo",
0, FIN, nullptr);
- EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector) &&
+ GetQuicReloadableFlag(quic_use_idle_network_detector)) {
+ EXPECT_EQ(default_timeout + five_ms,
+ connection_.GetTimeoutAlarm()->deadline());
+ } else {
+ EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
+ }
// Retransmit the packet via tail loss probe.
clock_.AdvanceTime(connection_.GetRetransmissionAlarm()->deadline() -
@@ -5528,7 +5965,13 @@ TEST_P(QuicConnectionTest, TimeoutAfterSendSilentCloseWithOpenStreams) {
SendStreamDataToPeer(
GetNthClientInitiatedStreamId(1, connection_.transport_version()), "foo",
0, FIN, nullptr);
- EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector) &&
+ GetQuicReloadableFlag(quic_use_idle_network_detector)) {
+ EXPECT_EQ(default_timeout + five_ms,
+ connection_.GetTimeoutAlarm()->deadline());
+ } else {
+ EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
+ }
// Indicate streams are still open.
EXPECT_CALL(visitor_, ShouldKeepConnectionAlive())
@@ -5579,7 +6022,10 @@ TEST_P(QuicConnectionTest, TimeoutAfterReceive) {
// network event at t=5ms. The alarm will reregister.
clock_.AdvanceTime(initial_idle_timeout - five_ms);
EXPECT_EQ(default_timeout, clock_.ApproximateNow());
- connection_.GetTimeoutAlarm()->Fire();
+ if (!GetQuicReloadableFlag(quic_use_blackhole_detector) ||
+ !GetQuicReloadableFlag(quic_use_idle_network_detector)) {
+ connection_.GetTimeoutAlarm()->Fire();
+ }
EXPECT_TRUE(connection_.connected());
EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet());
EXPECT_EQ(default_timeout + five_ms,
@@ -5636,7 +6082,10 @@ TEST_P(QuicConnectionTest, TimeoutAfterReceiveNotSendWhenUnacked) {
// network event at t=5ms. The alarm will reregister.
clock_.AdvanceTime(initial_idle_timeout - five_ms);
EXPECT_EQ(default_timeout, clock_.ApproximateNow());
- connection_.GetTimeoutAlarm()->Fire();
+ if (!GetQuicReloadableFlag(quic_use_blackhole_detector) ||
+ !GetQuicReloadableFlag(quic_use_idle_network_detector)) {
+ connection_.GetTimeoutAlarm()->Fire();
+ }
EXPECT_TRUE(connection_.connected());
EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet());
EXPECT_EQ(default_timeout + five_ms,
@@ -5671,6 +6120,8 @@ TEST_P(QuicConnectionTest, TimeoutAfter5ClientRTOs) {
QuicTagVector connection_options;
connection_options.push_back(k5RTO);
config.SetConnectionOptionsToSend(connection_options);
+ QuicConfigPeer::ReceiveIdleNetworkTimeout(&config, SERVER,
+ kDefaultIdleTimeoutSecs);
connection_.SetFromConfig(config);
// Send stream data.
@@ -5685,6 +6136,10 @@ TEST_P(QuicConnectionTest, TimeoutAfter5ClientRTOs) {
EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet());
EXPECT_TRUE(connection_.connected());
}
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector)) {
+ EXPECT_CALL(visitor_, OnPathDegrading());
+ connection_.PathDegradingTimeout();
+ }
EXPECT_EQ(2u, connection_.sent_packet_manager().GetConsecutiveTlpCount());
EXPECT_EQ(4u, connection_.sent_packet_manager().GetConsecutiveRtoCount());
@@ -5692,7 +6147,12 @@ TEST_P(QuicConnectionTest, TimeoutAfter5ClientRTOs) {
EXPECT_CALL(visitor_,
OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1));
- connection_.GetRetransmissionAlarm()->Fire();
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector)) {
+ ASSERT_TRUE(connection_.BlackholeDetectionInProgress());
+ connection_.GetBlackholeDetectorAlarm()->Fire();
+ } else {
+ connection_.GetRetransmissionAlarm()->Fire();
+ }
EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
EXPECT_FALSE(connection_.connected());
TestConnectionCloseQuicErrorCode(QUIC_TOO_MANY_RTOS);
@@ -5843,8 +6303,7 @@ TEST_P(QuicConnectionTest, SendDelayedAfterQuiescence) {
QuicConnectionPeer::SetFastAckAfterQuiescence(&connection_, true);
// The beginning of the connection counts as quiescence.
- QuicTime ack_time =
- clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(1);
+ QuicTime ack_time = clock_.ApproximateNow() + kAlarmGranularity;
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
const uint8_t tag = 0x07;
@@ -5902,7 +6361,7 @@ TEST_P(QuicConnectionTest, SendDelayedAfterQuiescence) {
EXPECT_FALSE(writer_->ack_frames().empty());
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
- // Wait 1 second and enesure the ack alarm is set to 1ms in the future.
+ // Wait 1 second and ensure the ack alarm is set to 1ms in the future.
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(1);
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
@@ -6542,7 +7001,12 @@ TEST_P(QuicConnectionTest, SendDelayedAckOnHandshakeConfirmed) {
QuicConnectionPeer::SetPerspective(&connection_, Perspective::IS_CLIENT);
connection_.OnHandshakeComplete();
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
- EXPECT_EQ(clock_.ApproximateNow(), connection_.GetAckAlarm()->deadline());
+ if (connection_.SupportsMultiplePacketNumberSpaces()) {
+ EXPECT_EQ(clock_.ApproximateNow() + DefaultDelayedAckTime(),
+ connection_.GetAckAlarm()->deadline());
+ } else {
+ EXPECT_EQ(clock_.ApproximateNow(), connection_.GetAckAlarm()->deadline());
+ }
}
TEST_P(QuicConnectionTest, SendDelayedAckOnSecondPacket) {
@@ -7428,32 +7892,37 @@ TEST_P(QuicConnectionTest, SetRetransmissionAlarmForCryptoPacket) {
TEST_P(QuicConnectionTest, PathDegradingAlarmForCryptoPacket) {
EXPECT_TRUE(connection_.connected());
- EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
EXPECT_FALSE(connection_.IsPathDegrading());
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
connection_.SendCryptoStreamData();
- EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_TRUE(connection_.PathDegradingDetectionInProgress());
EXPECT_FALSE(connection_.IsPathDegrading());
QuicTime::Delta delay = QuicConnectionPeer::GetSentPacketManager(&connection_)
->GetPathDegradingDelay();
- EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
- clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector)) {
+ EXPECT_EQ(delay, connection_.GetBlackholeDetectorAlarm()->deadline() -
+ clock_.ApproximateNow());
+ } else {
+ EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
+ clock_.ApproximateNow());
+ }
// Fire the path degrading alarm, path degrading signal should be sent to
// the visitor.
EXPECT_CALL(visitor_, OnPathDegrading());
clock_.AdvanceTime(delay);
- connection_.GetPathDegradingAlarm()->Fire();
+ connection_.PathDegradingTimeout();
EXPECT_TRUE(connection_.IsPathDegrading());
- EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
}
// Includes regression test for b/69979024.
TEST_P(QuicConnectionTest, PathDegradingAlarmForNonCryptoPackets) {
EXPECT_TRUE(connection_.connected());
- EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
EXPECT_FALSE(connection_.IsPathDegrading());
const char data[] = "data";
@@ -7467,25 +7936,38 @@ TEST_P(QuicConnectionTest, PathDegradingAlarmForNonCryptoPackets) {
GetNthClientInitiatedStreamId(1, connection_.transport_version()), data,
offset, NO_FIN);
offset += data_size;
- EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_TRUE(connection_.PathDegradingDetectionInProgress());
// Check the deadline of the path degrading alarm.
QuicTime::Delta delay =
QuicConnectionPeer::GetSentPacketManager(&connection_)
->GetPathDegradingDelay();
- EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
- clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector)) {
+ EXPECT_EQ(delay, connection_.GetBlackholeDetectorAlarm()->deadline() -
+ clock_.ApproximateNow());
+ } else {
+ EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
+ clock_.ApproximateNow());
+ }
// Send a second packet. The path degrading alarm's deadline should remain
// the same.
// Regression test for b/69979024.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
QuicTime prev_deadline = connection_.GetPathDegradingAlarm()->deadline();
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector)) {
+ prev_deadline = connection_.GetBlackholeDetectorAlarm()->deadline();
+ }
connection_.SendStreamDataWithString(
GetNthClientInitiatedStreamId(1, connection_.transport_version()), data,
offset, NO_FIN);
offset += data_size;
- EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet());
- EXPECT_EQ(prev_deadline, connection_.GetPathDegradingAlarm()->deadline());
+ EXPECT_TRUE(connection_.PathDegradingDetectionInProgress());
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector)) {
+ EXPECT_EQ(prev_deadline,
+ connection_.GetBlackholeDetectorAlarm()->deadline());
+ } else {
+ EXPECT_EQ(prev_deadline, connection_.GetPathDegradingAlarm()->deadline());
+ }
// Now receive an ACK of the first packet. This should advance the path
// degrading alarm's deadline since forward progress has been made.
@@ -7497,12 +7979,17 @@ TEST_P(QuicConnectionTest, PathDegradingAlarmForNonCryptoPackets) {
QuicAckFrame frame = InitAckFrame(
{{QuicPacketNumber(1u + 2u * i), QuicPacketNumber(2u + 2u * i)}});
ProcessAckPacket(&frame);
- EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_TRUE(connection_.PathDegradingDetectionInProgress());
// Check the deadline of the path degrading alarm.
delay = QuicConnectionPeer::GetSentPacketManager(&connection_)
->GetPathDegradingDelay();
- EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
- clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector)) {
+ EXPECT_EQ(delay, connection_.GetBlackholeDetectorAlarm()->deadline() -
+ clock_.ApproximateNow());
+ } else {
+ EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
+ clock_.ApproximateNow());
+ }
if (i == 0) {
// Now receive an ACK of the second packet. Since there are no more
@@ -7512,14 +7999,14 @@ TEST_P(QuicConnectionTest, PathDegradingAlarmForNonCryptoPackets) {
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
frame = InitAckFrame({{QuicPacketNumber(2), QuicPacketNumber(3)}});
ProcessAckPacket(&frame);
- EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
} else {
// Advance time to the path degrading alarm's deadline and simulate
// firing the alarm.
clock_.AdvanceTime(delay);
EXPECT_CALL(visitor_, OnPathDegrading());
- connection_.GetPathDegradingAlarm()->Fire();
- EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
+ connection_.PathDegradingTimeout();
+ EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
}
}
EXPECT_TRUE(connection_.IsPathDegrading());
@@ -7535,7 +8022,7 @@ TEST_P(QuicConnectionTest, RetransmittableOnWireSetsPingAlarm) {
EXPECT_CALL(visitor_, ShouldKeepConnectionAlive())
.WillRepeatedly(Return(true));
- EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
EXPECT_FALSE(connection_.IsPathDegrading());
EXPECT_FALSE(connection_.GetPingAlarm()->IsSet());
@@ -7549,11 +8036,16 @@ TEST_P(QuicConnectionTest, RetransmittableOnWireSetsPingAlarm) {
// Now there's a retransmittable packet on the wire, so the path degrading
// alarm should be set.
// The retransmittable-on-wire alarm should not be set.
- EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_TRUE(connection_.PathDegradingDetectionInProgress());
QuicTime::Delta delay = QuicConnectionPeer::GetSentPacketManager(&connection_)
->GetPathDegradingDelay();
- EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
- clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector)) {
+ EXPECT_EQ(delay, connection_.GetBlackholeDetectorAlarm()->deadline() -
+ clock_.ApproximateNow());
+ } else {
+ EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
+ clock_.ApproximateNow());
+ }
ASSERT_TRUE(connection_.sent_packet_manager().HasInFlightPackets());
// The ping alarm is set for the ping timeout, not the shorter
// retransmittable_on_wire_timeout.
@@ -7572,7 +8064,7 @@ TEST_P(QuicConnectionTest, RetransmittableOnWireSetsPingAlarm) {
// No more retransmittable packets on the wire, so the path degrading alarm
// should be cancelled, and the ping alarm should be set to the
// retransmittable_on_wire_timeout.
- EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
EXPECT_EQ(retransmittable_on_wire_timeout,
connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
@@ -7586,11 +8078,16 @@ TEST_P(QuicConnectionTest, RetransmittableOnWireSetsPingAlarm) {
// Now there's a retransmittable packet (PING) on the wire, so the path
// degrading alarm should be set.
- EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_TRUE(connection_.PathDegradingDetectionInProgress());
delay = QuicConnectionPeer::GetSentPacketManager(&connection_)
->GetPathDegradingDelay();
- EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
- clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector)) {
+ EXPECT_EQ(delay, connection_.GetBlackholeDetectorAlarm()->deadline() -
+ clock_.ApproximateNow());
+ } else {
+ EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
+ clock_.ApproximateNow());
+ }
}
// This test verifies that the connection marks path as degrading and does not
@@ -7598,7 +8095,7 @@ TEST_P(QuicConnectionTest, RetransmittableOnWireSetsPingAlarm) {
// degraded path.
TEST_P(QuicConnectionTest, NoPathDegradingAlarmIfPathIsDegrading) {
EXPECT_TRUE(connection_.connected());
- EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
EXPECT_FALSE(connection_.IsPathDegrading());
const char data[] = "data";
@@ -7609,21 +8106,34 @@ TEST_P(QuicConnectionTest, NoPathDegradingAlarmIfPathIsDegrading) {
// the path degrading alarm should be set.
connection_.SendStreamDataWithString(1, data, offset, NO_FIN);
offset += data_size;
- EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_TRUE(connection_.PathDegradingDetectionInProgress());
// Check the deadline of the path degrading alarm.
QuicTime::Delta delay = QuicConnectionPeer::GetSentPacketManager(&connection_)
->GetPathDegradingDelay();
- EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
- clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector)) {
+ EXPECT_EQ(delay, connection_.GetBlackholeDetectorAlarm()->deadline() -
+ clock_.ApproximateNow());
+ } else {
+ EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
+ clock_.ApproximateNow());
+ }
// Send a second packet. The path degrading alarm's deadline should remain
// the same.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
QuicTime prev_deadline = connection_.GetPathDegradingAlarm()->deadline();
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector)) {
+ prev_deadline = connection_.GetBlackholeDetectorAlarm()->deadline();
+ }
connection_.SendStreamDataWithString(1, data, offset, NO_FIN);
offset += data_size;
- EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet());
- EXPECT_EQ(prev_deadline, connection_.GetPathDegradingAlarm()->deadline());
+ EXPECT_TRUE(connection_.PathDegradingDetectionInProgress());
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector)) {
+ EXPECT_EQ(prev_deadline,
+ connection_.GetBlackholeDetectorAlarm()->deadline());
+ } else {
+ EXPECT_EQ(prev_deadline, connection_.GetPathDegradingAlarm()->deadline());
+ }
// Now receive an ACK of the first packet. This should advance the path
// degrading alarm's deadline since forward progress has been made.
@@ -7633,29 +8143,34 @@ TEST_P(QuicConnectionTest, NoPathDegradingAlarmIfPathIsDegrading) {
QuicAckFrame frame =
InitAckFrame({{QuicPacketNumber(1u), QuicPacketNumber(2u)}});
ProcessAckPacket(&frame);
- EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_TRUE(connection_.PathDegradingDetectionInProgress());
// Check the deadline of the path degrading alarm.
delay = QuicConnectionPeer::GetSentPacketManager(&connection_)
->GetPathDegradingDelay();
- EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
- clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector)) {
+ EXPECT_EQ(delay, connection_.GetBlackholeDetectorAlarm()->deadline() -
+ clock_.ApproximateNow());
+ } else {
+ EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
+ clock_.ApproximateNow());
+ }
// Advance time to the path degrading alarm's deadline and simulate
// firing the path degrading alarm. This path will be considered as
// degrading.
clock_.AdvanceTime(delay);
EXPECT_CALL(visitor_, OnPathDegrading()).Times(1);
- connection_.GetPathDegradingAlarm()->Fire();
- EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
+ connection_.PathDegradingTimeout();
+ EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
EXPECT_TRUE(connection_.IsPathDegrading());
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
- EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
// Send a third packet. The path degrading alarm is no longer set but path
// should still be marked as degrading.
connection_.SendStreamDataWithString(1, data, offset, NO_FIN);
offset += data_size;
- EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
EXPECT_TRUE(connection_.IsPathDegrading());
}
@@ -7664,7 +8179,7 @@ TEST_P(QuicConnectionTest, NoPathDegradingAlarmIfPathIsDegrading) {
// after path has been marked degrading.
TEST_P(QuicConnectionTest, UnmarkPathDegradingOnForwardProgress) {
EXPECT_TRUE(connection_.connected());
- EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
EXPECT_FALSE(connection_.IsPathDegrading());
const char data[] = "data";
@@ -7675,21 +8190,34 @@ TEST_P(QuicConnectionTest, UnmarkPathDegradingOnForwardProgress) {
// the path degrading alarm should be set.
connection_.SendStreamDataWithString(1, data, offset, NO_FIN);
offset += data_size;
- EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_TRUE(connection_.PathDegradingDetectionInProgress());
// Check the deadline of the path degrading alarm.
QuicTime::Delta delay = QuicConnectionPeer::GetSentPacketManager(&connection_)
->GetPathDegradingDelay();
- EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
- clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector)) {
+ EXPECT_EQ(delay, connection_.GetBlackholeDetectorAlarm()->deadline() -
+ clock_.ApproximateNow());
+ } else {
+ EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
+ clock_.ApproximateNow());
+ }
// Send a second packet. The path degrading alarm's deadline should remain
// the same.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
QuicTime prev_deadline = connection_.GetPathDegradingAlarm()->deadline();
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector)) {
+ prev_deadline = connection_.GetBlackholeDetectorAlarm()->deadline();
+ }
connection_.SendStreamDataWithString(1, data, offset, NO_FIN);
offset += data_size;
- EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet());
- EXPECT_EQ(prev_deadline, connection_.GetPathDegradingAlarm()->deadline());
+ EXPECT_TRUE(connection_.PathDegradingDetectionInProgress());
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector)) {
+ EXPECT_EQ(prev_deadline,
+ connection_.GetBlackholeDetectorAlarm()->deadline());
+ } else {
+ EXPECT_EQ(prev_deadline, connection_.GetPathDegradingAlarm()->deadline());
+ }
// Now receive an ACK of the first packet. This should advance the path
// degrading alarm's deadline since forward progress has been made.
@@ -7699,28 +8227,33 @@ TEST_P(QuicConnectionTest, UnmarkPathDegradingOnForwardProgress) {
QuicAckFrame frame =
InitAckFrame({{QuicPacketNumber(1u), QuicPacketNumber(2u)}});
ProcessAckPacket(&frame);
- EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_TRUE(connection_.PathDegradingDetectionInProgress());
// Check the deadline of the path degrading alarm.
delay = QuicConnectionPeer::GetSentPacketManager(&connection_)
->GetPathDegradingDelay();
- EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
- clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector)) {
+ EXPECT_EQ(delay, connection_.GetBlackholeDetectorAlarm()->deadline() -
+ clock_.ApproximateNow());
+ } else {
+ EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
+ clock_.ApproximateNow());
+ }
// Advance time to the path degrading alarm's deadline and simulate
// firing the alarm.
clock_.AdvanceTime(delay);
EXPECT_CALL(visitor_, OnPathDegrading()).Times(1);
- connection_.GetPathDegradingAlarm()->Fire();
- EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
+ connection_.PathDegradingTimeout();
+ EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
EXPECT_TRUE(connection_.IsPathDegrading());
// Send a third packet. The path degrading alarm is no longer set but path
// should still be marked as degrading.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
- EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
connection_.SendStreamDataWithString(1, data, offset, NO_FIN);
offset += data_size;
- EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
EXPECT_TRUE(connection_.IsPathDegrading());
// Now receive an ACK of the second packet. This should unmark the path as
@@ -7730,7 +8263,7 @@ TEST_P(QuicConnectionTest, UnmarkPathDegradingOnForwardProgress) {
frame = InitAckFrame({{QuicPacketNumber(2), QuicPacketNumber(3)}});
ProcessAckPacket(&frame);
EXPECT_FALSE(connection_.IsPathDegrading());
- EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_TRUE(connection_.PathDegradingDetectionInProgress());
}
TEST_P(QuicConnectionTest, NoPathDegradingOnServer) {
@@ -7741,13 +8274,13 @@ TEST_P(QuicConnectionTest, NoPathDegradingOnServer) {
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
EXPECT_FALSE(connection_.IsPathDegrading());
- EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
// Send data.
const char data[] = "data";
connection_.SendStreamDataWithString(1, data, 0, NO_FIN);
EXPECT_FALSE(connection_.IsPathDegrading());
- EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
// Ack data.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
@@ -7756,7 +8289,7 @@ TEST_P(QuicConnectionTest, NoPathDegradingOnServer) {
InitAckFrame({{QuicPacketNumber(1u), QuicPacketNumber(2u)}});
ProcessAckPacket(&frame);
EXPECT_FALSE(connection_.IsPathDegrading());
- EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
}
TEST_P(QuicConnectionTest, NoPathDegradingAfterSendingAck) {
@@ -7770,7 +8303,7 @@ TEST_P(QuicConnectionTest, NoPathDegradingAfterSendingAck) {
EXPECT_FALSE(connection_.sent_packet_manager().unacked_packets().empty());
EXPECT_FALSE(connection_.sent_packet_manager().HasInFlightPackets());
EXPECT_FALSE(connection_.IsPathDegrading());
- EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_FALSE(connection_.PathDegradingDetectionInProgress());
}
TEST_P(QuicConnectionTest, MultipleCallsToCloseConnection) {
@@ -7939,6 +8472,8 @@ TEST_P(QuicConnectionTest, SendDataWhenApplicationLimited) {
EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(0);
ASSERT_EQ(0u, connection_.GetStats().packets_sent);
connection_.set_fill_up_link_during_probing(true);
+ EXPECT_CALL(visitor_, GetHandshakeState())
+ .WillRepeatedly(Return(HANDSHAKE_COMPLETE));
connection_.OnHandshakeComplete();
connection_.SendStreamData3();
@@ -7986,7 +8521,9 @@ TEST_P(QuicConnectionTest, DoNotForceSendingAckOnPacketTooLarge) {
}
TEST_P(QuicConnectionTest, CloseConnectionAllLevels) {
- SetQuicReloadableFlag(quic_close_all_encryptions_levels2, true);
+ if (!connection_.SupportsMultiplePacketNumberSpaces()) {
+ return;
+ }
EXPECT_CALL(visitor_, OnConnectionClosed(_, _));
const QuicErrorCode kQuicErrorCode = QUIC_INTERNAL_ERROR;
@@ -8024,7 +8561,9 @@ TEST_P(QuicConnectionTest, CloseConnectionAllLevels) {
}
TEST_P(QuicConnectionTest, CloseConnectionOneLevel) {
- SetQuicReloadableFlag(quic_close_all_encryptions_levels2, false);
+ if (connection_.SupportsMultiplePacketNumberSpaces()) {
+ return;
+ }
EXPECT_CALL(visitor_, OnConnectionClosed(_, _));
const QuicErrorCode kQuicErrorCode = QUIC_INTERNAL_ERROR;
@@ -8041,6 +8580,26 @@ TEST_P(QuicConnectionTest, CloseConnectionOneLevel) {
ASSERT_TRUE(writer_->coalesced_packet() == nullptr);
}
+TEST_P(QuicConnectionTest, DoNotPadServerInitialConnectionClose) {
+ if (!connection_.SupportsMultiplePacketNumberSpaces()) {
+ return;
+ }
+ set_perspective(Perspective::IS_SERVER);
+
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, _));
+ const QuicErrorCode kQuicErrorCode = QUIC_INTERNAL_ERROR;
+ connection_.CloseConnection(
+ kQuicErrorCode, "Some random error message",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+
+ EXPECT_EQ(2u, QuicConnectionPeer::GetNumEncryptionLevels(&connection_));
+
+ TestConnectionCloseQuicErrorCode(kQuicErrorCode);
+ EXPECT_EQ(1u, writer_->connection_close_frames().size());
+ EXPECT_TRUE(writer_->padding_frames().empty());
+ EXPECT_EQ(ENCRYPTION_INITIAL, writer_->framer()->last_decrypted_level());
+}
+
// Regression test for b/63620844.
TEST_P(QuicConnectionTest, FailedToWriteHandshakePacket) {
SimulateNextPacketTooLarge();
@@ -8608,7 +9167,7 @@ TEST_P(QuicConnectionTest, SendMessage) {
return;
}
std::string message(connection_.GetCurrentLargestMessagePayload() * 2, 'a');
- QuicStringPiece message_data(message);
+ quiche::QuicheStringPiece message_data(message);
QuicMemSliceStorage storage(nullptr, 0, nullptr, 0);
{
QuicConnection::ScopedPacketFlusher flusher(&connection_);
@@ -8621,7 +9180,7 @@ TEST_P(QuicConnectionTest, SendMessage) {
connection_.SendMessage(
1,
MakeSpan(connection_.helper()->GetStreamSendBufferAllocator(),
- QuicStringPiece(
+ quiche::QuicheStringPiece(
message_data.data(),
connection_.GetCurrentLargestMessagePayload()),
&storage),
@@ -8642,7 +9201,7 @@ TEST_P(QuicConnectionTest, SendMessage) {
connection_.SendMessage(
3,
MakeSpan(connection_.helper()->GetStreamSendBufferAllocator(),
- QuicStringPiece(
+ quiche::QuicheStringPiece(
message_data.data(),
connection_.GetCurrentLargestMessagePayload() + 1),
&storage),
@@ -8766,7 +9325,7 @@ TEST_P(QuicConnectionTest, StopProcessingGQuicPacketInIetfQuicConnection) {
} else {
frame = QuicFrame(QuicStreamFrame(
QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
- 0u, QuicStringPiece()));
+ 0u, quiche::QuicheStringPiece()));
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
}
ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
@@ -9087,7 +9646,7 @@ TEST_P(QuicConnectionTest, CheckConnectedBeforeFlush) {
} else {
frame = QuicFrame(QuicStreamFrame(
QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
- 0u, QuicStringPiece()));
+ 0u, quiche::QuicheStringPiece()));
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
}
ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
@@ -9301,7 +9860,6 @@ TEST_P(QuicConnectionTest, RtoForcesSendingPing) {
}
TEST_P(QuicConnectionTest, ProbeTimeout) {
- SetQuicReloadableFlag(quic_enable_pto, true);
QuicConfig config;
QuicTagVector connection_options;
connection_options.push_back(k2PTO);
@@ -9329,12 +9887,13 @@ TEST_P(QuicConnectionTest, ProbeTimeout) {
}
TEST_P(QuicConnectionTest, CloseConnectionAfter6ClientPTOs) {
- SetQuicReloadableFlag(quic_enable_pto, true);
QuicConfig config;
QuicTagVector connection_options;
connection_options.push_back(k1PTO);
connection_options.push_back(k6PTO);
config.SetConnectionOptionsToSend(connection_options);
+ QuicConfigPeer::ReceiveIdleNetworkTimeout(&config, SERVER,
+ kDefaultIdleTimeoutSecs);
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
connection_.SetFromConfig(config);
EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
@@ -9353,6 +9912,10 @@ TEST_P(QuicConnectionTest, CloseConnectionAfter6ClientPTOs) {
EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet());
EXPECT_TRUE(connection_.connected());
}
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector)) {
+ EXPECT_CALL(visitor_, OnPathDegrading());
+ connection_.PathDegradingTimeout();
+ }
EXPECT_EQ(0u, connection_.sent_packet_manager().GetConsecutiveTlpCount());
EXPECT_EQ(0u, connection_.sent_packet_manager().GetConsecutiveRtoCount());
@@ -9360,19 +9923,25 @@ TEST_P(QuicConnectionTest, CloseConnectionAfter6ClientPTOs) {
// Closes connection on 6th PTO.
EXPECT_CALL(visitor_,
OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
- connection_.GetRetransmissionAlarm()->Fire();
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector)) {
+ ASSERT_TRUE(connection_.BlackholeDetectionInProgress());
+ connection_.GetBlackholeDetectorAlarm()->Fire();
+ } else {
+ connection_.GetRetransmissionAlarm()->Fire();
+ }
EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
EXPECT_FALSE(connection_.connected());
TestConnectionCloseQuicErrorCode(QUIC_TOO_MANY_RTOS);
}
TEST_P(QuicConnectionTest, CloseConnectionAfter7ClientPTOs) {
- SetQuicReloadableFlag(quic_enable_pto, true);
QuicConfig config;
QuicTagVector connection_options;
connection_options.push_back(k2PTO);
connection_options.push_back(k7PTO);
config.SetConnectionOptionsToSend(connection_options);
+ QuicConfigPeer::ReceiveIdleNetworkTimeout(&config, SERVER,
+ kDefaultIdleTimeoutSecs);
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
connection_.SetFromConfig(config);
EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
@@ -9389,6 +9958,10 @@ TEST_P(QuicConnectionTest, CloseConnectionAfter7ClientPTOs) {
EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet());
EXPECT_TRUE(connection_.connected());
}
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector)) {
+ EXPECT_CALL(visitor_, OnPathDegrading());
+ connection_.PathDegradingTimeout();
+ }
EXPECT_EQ(0u, connection_.sent_packet_manager().GetConsecutiveTlpCount());
EXPECT_EQ(0u, connection_.sent_packet_manager().GetConsecutiveRtoCount());
@@ -9397,18 +9970,24 @@ TEST_P(QuicConnectionTest, CloseConnectionAfter7ClientPTOs) {
EXPECT_CALL(visitor_,
OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1));
- connection_.GetRetransmissionAlarm()->Fire();
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector)) {
+ ASSERT_TRUE(connection_.BlackholeDetectionInProgress());
+ connection_.GetBlackholeDetectorAlarm()->Fire();
+ } else {
+ connection_.GetRetransmissionAlarm()->Fire();
+ }
EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
EXPECT_FALSE(connection_.connected());
TestConnectionCloseQuicErrorCode(QUIC_TOO_MANY_RTOS);
}
TEST_P(QuicConnectionTest, CloseConnectionAfter8ClientPTOs) {
- SetQuicReloadableFlag(quic_enable_pto, true);
QuicConfig config;
QuicTagVector connection_options;
connection_options.push_back(k2PTO);
connection_options.push_back(k8PTO);
+ QuicConfigPeer::ReceiveIdleNetworkTimeout(&config, SERVER,
+ kDefaultIdleTimeoutSecs);
config.SetConnectionOptionsToSend(connection_options);
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
connection_.SetFromConfig(config);
@@ -9426,6 +10005,10 @@ TEST_P(QuicConnectionTest, CloseConnectionAfter8ClientPTOs) {
EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet());
EXPECT_TRUE(connection_.connected());
}
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector)) {
+ EXPECT_CALL(visitor_, OnPathDegrading());
+ connection_.PathDegradingTimeout();
+ }
EXPECT_EQ(0u, connection_.sent_packet_manager().GetConsecutiveTlpCount());
EXPECT_EQ(0u, connection_.sent_packet_manager().GetConsecutiveRtoCount());
@@ -9434,7 +10017,12 @@ TEST_P(QuicConnectionTest, CloseConnectionAfter8ClientPTOs) {
EXPECT_CALL(visitor_,
OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1));
- connection_.GetRetransmissionAlarm()->Fire();
+ if (GetQuicReloadableFlag(quic_use_blackhole_detector)) {
+ ASSERT_TRUE(connection_.BlackholeDetectionInProgress());
+ connection_.GetBlackholeDetectorAlarm()->Fire();
+ } else {
+ connection_.GetRetransmissionAlarm()->Fire();
+ }
EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
EXPECT_FALSE(connection_.connected());
TestConnectionCloseQuicErrorCode(QUIC_TOO_MANY_RTOS);
@@ -9444,6 +10032,7 @@ TEST_P(QuicConnectionTest, DeprecateHandshakeMode) {
if (!connection_.version().SupportsAntiAmplificationLimit()) {
return;
}
+ SetQuicReloadableFlag(quic_send_ping_when_pto_skips_packet_number, true);
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
@@ -9465,7 +10054,7 @@ TEST_P(QuicConnectionTest, DeprecateHandshakeMode) {
EXPECT_EQ(0u, connection_.GetStats().crypto_retransmit_count);
// PTO fires, verify a PING packet gets sent because there is no data to send.
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(2), _, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(3), _, _));
EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() { SendPing(); }));
connection_.GetRetransmissionAlarm()->Fire();
EXPECT_EQ(1u, connection_.GetStats().pto_count);
@@ -9595,8 +10184,6 @@ TEST_P(QuicConnectionTest, RtoPacketAsTwo) {
}
TEST_P(QuicConnectionTest, PtoSkipsPacketNumber) {
- SetQuicReloadableFlag(quic_enable_pto, true);
- SetQuicReloadableFlag(quic_skip_packet_number_for_pto, true);
QuicConfig config;
QuicTagVector connection_options;
connection_options.push_back(k1PTO);
@@ -9625,6 +10212,10 @@ TEST_P(QuicConnectionTest, SendCoalescedPackets) {
if (!connection_.version().CanSendCoalescedPackets()) {
return;
}
+ MockQuicConnectionDebugVisitor debug_visitor;
+ connection_.set_debug_visitor(&debug_visitor);
+ EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _)).Times(3);
+ EXPECT_CALL(debug_visitor, OnCoalescedPacketSent(_, _)).Times(1);
{
QuicConnection::ScopedPacketFlusher flusher(&connection_);
use_tagging_decrypter();
@@ -9659,6 +10250,285 @@ TEST_P(QuicConnectionTest, SendCoalescedPackets) {
EXPECT_NE(nullptr, writer_->coalesced_packet());
}
+TEST_P(QuicConnectionTest, ClientReceivedHandshakeDone) {
+ if (!connection_.version().HasHandshakeDone()) {
+ return;
+ }
+ EXPECT_CALL(visitor_, OnHandshakeDoneReceived());
+ QuicFrames frames;
+ frames.push_back(QuicFrame(QuicHandshakeDoneFrame()));
+ frames.push_back(QuicFrame(QuicPaddingFrame(-1)));
+ ProcessFramesPacketAtLevel(1, frames, ENCRYPTION_FORWARD_SECURE);
+}
+
+TEST_P(QuicConnectionTest, ServerReceivedHandshakeDone) {
+ if (!connection_.version().HasHandshakeDone()) {
+ return;
+ }
+ set_perspective(Perspective::IS_SERVER);
+ EXPECT_CALL(visitor_, OnHandshakeDoneReceived()).Times(0);
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF))
+ .WillOnce(Invoke(this, &QuicConnectionTest::SaveConnectionCloseFrame));
+ QuicFrames frames;
+ frames.push_back(QuicFrame(QuicHandshakeDoneFrame()));
+ frames.push_back(QuicFrame(QuicPaddingFrame(-1)));
+ ProcessFramesPacketAtLevel(1, frames, ENCRYPTION_FORWARD_SECURE);
+ EXPECT_EQ(1, connection_close_frame_count_);
+ EXPECT_THAT(saved_connection_close_frame_.quic_error_code,
+ IsError(IETF_QUIC_PROTOCOL_VIOLATION));
+}
+
+TEST_P(QuicConnectionTest, MultiplePacketNumberSpacePto) {
+ if (!connection_.SupportsMultiplePacketNumberSpaces()) {
+ return;
+ }
+ use_tagging_decrypter();
+ // Send handshake packet.
+ connection_.SetEncrypter(ENCRYPTION_HANDSHAKE,
+ std::make_unique<TaggingEncrypter>(0x02));
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_HANDSHAKE);
+ connection_.SendCryptoDataWithString("foo", 0, ENCRYPTION_HANDSHAKE);
+ EXPECT_EQ(0x02020202u, writer_->final_bytes_of_last_packet());
+
+ // Send application data.
+ connection_.SendApplicationDataAtLevel(ENCRYPTION_FORWARD_SECURE, 5, "data",
+ 0, NO_FIN);
+ EXPECT_EQ(0x01010101u, writer_->final_bytes_of_last_packet());
+ QuicTime retransmission_time =
+ connection_.GetRetransmissionAlarm()->deadline();
+ EXPECT_NE(QuicTime::Zero(), retransmission_time);
+
+ // Retransmit handshake data.
+ clock_.AdvanceTime(retransmission_time - clock_.Now());
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(4), _, _));
+ connection_.GetRetransmissionAlarm()->Fire();
+ EXPECT_EQ(0x02020202u, writer_->final_bytes_of_last_packet());
+
+ // Send application data.
+ connection_.SendApplicationDataAtLevel(ENCRYPTION_FORWARD_SECURE, 5, "data",
+ 4, NO_FIN);
+ EXPECT_EQ(0x01010101u, writer_->final_bytes_of_last_packet());
+ retransmission_time = connection_.GetRetransmissionAlarm()->deadline();
+ EXPECT_NE(QuicTime::Zero(), retransmission_time);
+
+ // Retransmit handshake data again.
+ clock_.AdvanceTime(retransmission_time - clock_.Now());
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(7), _, _));
+ connection_.GetRetransmissionAlarm()->Fire();
+ EXPECT_EQ(0x02020202u, writer_->final_bytes_of_last_packet());
+
+ // Discard handshake key.
+ connection_.OnHandshakeComplete();
+ retransmission_time = connection_.GetRetransmissionAlarm()->deadline();
+ EXPECT_NE(QuicTime::Zero(), retransmission_time);
+
+ // Retransmit application data.
+ clock_.AdvanceTime(retransmission_time - clock_.Now());
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(9), _, _));
+ connection_.GetRetransmissionAlarm()->Fire();
+ EXPECT_EQ(0x01010101u, writer_->final_bytes_of_last_packet());
+}
+
+TEST_P(QuicConnectionTest, ClientParsesRetry) {
+ if (!version().HasRetryIntegrityTag()) {
+ return;
+ }
+ if (version() !=
+ ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_DRAFT_25)) {
+ // TODO(dschinazi) generate retry packets for all versions once we have
+ // server-side support for generating these programmatically.
+ return;
+ }
+
+ // These values come from draft-ietf-quic-tls Appendix A.4.
+ char retry_packet[] = {0xff, 0xff, 0x00, 0x00, 0x19, 0x00, 0x08, 0xf0, 0x67,
+ 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5, 0x74, 0x6f, 0x6b,
+ 0x65, 0x6e, 0x1e, 0x5e, 0xc5, 0xb0, 0x14, 0xcb, 0xb1,
+ 0xf0, 0xfd, 0x93, 0xdf, 0x40, 0x48, 0xc4, 0x46, 0xa6};
+ char original_connection_id_bytes[] = {0x83, 0x94, 0xc8, 0xf0,
+ 0x3e, 0x51, 0x57, 0x08};
+ char new_connection_id_bytes[] = {0xf0, 0x67, 0xa5, 0x50,
+ 0x2a, 0x42, 0x62, 0xb5};
+ char retry_token_bytes[] = {0x74, 0x6f, 0x6b, 0x65, 0x6e};
+
+ QuicConnectionId original_connection_id(
+ original_connection_id_bytes,
+ QUICHE_ARRAYSIZE(original_connection_id_bytes));
+ QuicConnectionId new_connection_id(new_connection_id_bytes,
+ QUICHE_ARRAYSIZE(new_connection_id_bytes));
+
+ std::string retry_token(retry_token_bytes,
+ QUICHE_ARRAYSIZE(retry_token_bytes));
+
+ {
+ TestConnection connection1(
+ original_connection_id, kPeerAddress, helper_.get(),
+ alarm_factory_.get(), writer_.get(), Perspective::IS_CLIENT, version());
+ connection1.set_visitor(&visitor_);
+
+ connection1.ProcessUdpPacket(
+ kSelfAddress, kPeerAddress,
+ QuicReceivedPacket(retry_packet, QUICHE_ARRAYSIZE(retry_packet),
+ clock_.Now()));
+ EXPECT_TRUE(connection1.GetStats().retry_packet_processed);
+ EXPECT_EQ(connection1.connection_id(), new_connection_id);
+ EXPECT_EQ(QuicPacketCreatorPeer::GetRetryToken(
+ QuicConnectionPeer::GetPacketCreator(&connection1)),
+ retry_token);
+ }
+
+ // Now flip the last bit of the retry packet to prevent the integrity tag
+ // from validating correctly.
+ retry_packet[QUICHE_ARRAYSIZE(retry_packet) - 1] ^= 1;
+
+ {
+ TestConnection connection2(
+ original_connection_id, kPeerAddress, helper_.get(),
+ alarm_factory_.get(), writer_.get(), Perspective::IS_CLIENT, version());
+ connection2.set_visitor(&visitor_);
+
+ connection2.ProcessUdpPacket(
+ kSelfAddress, kPeerAddress,
+ QuicReceivedPacket(retry_packet, QUICHE_ARRAYSIZE(retry_packet),
+ clock_.Now()));
+ EXPECT_FALSE(connection2.GetStats().retry_packet_processed);
+ EXPECT_EQ(connection2.connection_id(), original_connection_id);
+ EXPECT_TRUE(QuicPacketCreatorPeer::GetRetryToken(
+ QuicConnectionPeer::GetPacketCreator(&connection2))
+ .empty());
+ }
+}
+
+// Regression test for http://crbug/1047977
+TEST_P(QuicConnectionTest, MaxStreamsFrameCausesConnectionClose) {
+ if (!VersionHasIetfQuicFrames(connection_.transport_version())) {
+ return;
+ }
+ // Received frame causes connection close.
+ EXPECT_CALL(visitor_, OnMaxStreamsFrame(_))
+ .WillOnce(InvokeWithoutArgs([this]() {
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, _));
+ connection_.CloseConnection(
+ QUIC_TOO_MANY_BUFFERED_CONTROL_FRAMES, "error",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return true;
+ }));
+ QuicFrames frames;
+ frames.push_back(QuicFrame(QuicMaxStreamsFrame()));
+ frames.push_back(QuicFrame(QuicPaddingFrame(-1)));
+ ProcessFramesPacketAtLevel(1, frames, ENCRYPTION_FORWARD_SECURE);
+}
+
+TEST_P(QuicConnectionTest, StreamsBlockedFrameCausesConnectionClose) {
+ if (!VersionHasIetfQuicFrames(connection_.transport_version())) {
+ return;
+ }
+ // Received frame causes connection close.
+ EXPECT_CALL(visitor_, OnStreamsBlockedFrame(_))
+ .WillOnce(InvokeWithoutArgs([this]() {
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, _));
+ connection_.CloseConnection(
+ QUIC_TOO_MANY_BUFFERED_CONTROL_FRAMES, "error",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return true;
+ }));
+ QuicFrames frames;
+ frames.push_back(
+ QuicFrame(QuicStreamsBlockedFrame(kInvalidControlFrameId, 10, false)));
+ frames.push_back(QuicFrame(QuicPaddingFrame(-1)));
+ ProcessFramesPacketAtLevel(1, frames, ENCRYPTION_FORWARD_SECURE);
+}
+
+TEST_P(QuicConnectionTest,
+ BundleAckWithConnectionCloseMultiplePacketNumberSpace) {
+ if (!connection_.SupportsMultiplePacketNumberSpaces()) {
+ return;
+ }
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+ EXPECT_CALL(visitor_, OnCryptoFrame(_)).Times(AnyNumber());
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
+ // Receives packet 1000 in initial data.
+ ProcessCryptoPacketAtLevel(1000, ENCRYPTION_INITIAL);
+ // Receives packet 2000 in application data.
+ ProcessDataPacketAtLevel(2000, false, ENCRYPTION_FORWARD_SECURE);
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, _));
+ const QuicErrorCode kQuicErrorCode = QUIC_INTERNAL_ERROR;
+ connection_.CloseConnection(
+ kQuicErrorCode, "Some random error message",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+
+ EXPECT_EQ(2u, QuicConnectionPeer::GetNumEncryptionLevels(&connection_));
+
+ TestConnectionCloseQuicErrorCode(kQuicErrorCode);
+ EXPECT_EQ(1u, writer_->connection_close_frames().size());
+ // Verify ack is bundled.
+ EXPECT_EQ(1u, writer_->ack_frames().size());
+
+ if (!connection_.version().CanSendCoalescedPackets()) {
+ // Each connection close packet should be sent in distinct UDP packets.
+ EXPECT_EQ(QuicConnectionPeer::GetNumEncryptionLevels(&connection_),
+ writer_->connection_close_packets());
+ EXPECT_EQ(QuicConnectionPeer::GetNumEncryptionLevels(&connection_),
+ writer_->packets_write_attempts());
+ return;
+ }
+
+ // A single UDP packet should be sent with multiple connection close packets
+ // coalesced together.
+ EXPECT_EQ(1u, writer_->packets_write_attempts());
+
+ // Only the first packet has been processed yet.
+ EXPECT_EQ(1u, writer_->connection_close_packets());
+
+ // ProcessPacket resets the visitor and frees the coalesced packet.
+ ASSERT_TRUE(writer_->coalesced_packet() != nullptr);
+ auto packet = writer_->coalesced_packet()->Clone();
+ writer_->framer()->ProcessPacket(*packet);
+ EXPECT_EQ(1u, writer_->connection_close_packets());
+ EXPECT_EQ(1u, writer_->connection_close_frames().size());
+ // Verify ack is bundled.
+ EXPECT_EQ(1u, writer_->ack_frames().size());
+ ASSERT_TRUE(writer_->coalesced_packet() == nullptr);
+}
+
+// Regression test for b/151220135.
+TEST_P(QuicConnectionTest, SendPingWhenSkipPacketNumberForPto) {
+ if (!VersionSupportsMessageFrames(connection_.transport_version())) {
+ return;
+ }
+ QuicConfig config;
+ QuicTagVector connection_options;
+ connection_options.push_back(kPTOS);
+ connection_options.push_back(k1PTO);
+ config.SetConnectionOptionsToSend(connection_options);
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ connection_.SetFromConfig(config);
+ EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
+
+ EXPECT_EQ(MESSAGE_STATUS_SUCCESS, SendMessage("message"));
+ EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
+
+ // Although there are bytes in flight, no packet gets sent on PTO firing.
+ if (GetQuicReloadableFlag(quic_send_ping_when_pto_skips_packet_number)) {
+ // PTO fires, verify a PING packet gets sent because there is no data to
+ // send.
+ EXPECT_CALL(*send_algorithm_,
+ OnPacketSent(_, _, QuicPacketNumber(3), _, _));
+ EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
+ SendPing();
+ }));
+ } else {
+ // No packet gets sent.
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
+ }
+ connection_.GetRetransmissionAlarm()->Fire();
+ if (GetQuicReloadableFlag(quic_send_ping_when_pto_skips_packet_number)) {
+ EXPECT_EQ(1u, connection_.GetStats().pto_count);
+ EXPECT_EQ(0u, connection_.GetStats().crypto_retransmit_count);
+ EXPECT_EQ(1u, writer_->ping_frames().size());
+ }
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_constants.h b/chromium/net/third_party/quiche/src/quic/core/quic_constants.h
index 3264c1532ff..15f0abbad5a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_constants.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_constants.h
@@ -50,6 +50,9 @@ const QuicByteCount kMaxGsoPacketSize = 65535 - 40 - 8;
// The maximal IETF DATAGRAM frame size we'll accept. Choosing 2^16 ensures
// that it is greater than the biggest frame we could ever fit in a QUIC packet.
const QuicByteCount kMaxAcceptedDatagramFrameSize = 65536;
+// Default value of the max_packet_size transport parameter if it is not
+// transmitted.
+const QuicByteCount kDefaultMaxPacketSizeTransportParam = 65527;
// Default maximum packet size used in the Linux TCP implementation.
// Used in QUIC for congestion window computations in bytes.
const QuicByteCount kDefaultTCPMSS = 1460;
@@ -102,6 +105,10 @@ const size_t kPublicFlagsSize = 1;
// Number of bytes reserved for version number in the packet header.
const size_t kQuicVersionSize = 4;
+// Length of the retry integrity tag in bytes.
+// https://tools.ietf.org/html/draft-ietf-quic-transport-25#section-17.2.5
+const size_t kRetryIntegrityTagLength = 16;
+
// Signifies that the QuicPacket will contain version of the protocol.
const bool kIncludeVersion = true;
// Signifies that the QuicPacket will include a diversification nonce.
@@ -223,7 +230,6 @@ const QuicByteCount kMaxStreamLength = (UINT64_C(1) << 62) - 1;
const uint64_t kMaxIetfVarInt = UINT64_C(0x3fffffffffffffff);
// The maximum stream id value that is supported - (2^32)-1
-// TODO(fkastenholz): Should update this to 64 bits for IETF Quic.
const QuicStreamId kMaxQuicStreamId = 0xffffffff;
// The maximum value that can be stored in a 32-bit QuicStreamCount.
@@ -248,6 +254,9 @@ const int kInitialRttMs = 100;
// packet is lost due to early retransmission by time based loss detection.
static const int kDefaultLossDelayShift = 2;
+// Default fraction (1/8) of an RTT when doing IETF loss detection.
+static const int kDefaultIetfLossDelayShift = 3;
+
// Maximum number of retransmittable packets received before sending an ack.
const QuicPacketCount kDefaultRetransmittablePacketsBeforeAck = 2;
// Wait for up to 10 retransmittable packets before sending an ack.
@@ -257,6 +266,9 @@ const QuicPacketCount kMaxRetransmittablePacketsBeforeAck = 10;
// rapidly increasing.
const QuicPacketCount kMinReceivedBeforeAckDecimation = 100;
+// The default alarm granularity assumed by QUIC code.
+const QuicTime::Delta kAlarmGranularity = QuicTime::Delta::FromMilliseconds(1);
+
// Packet number of first sending packet of a connection. Please note, this
// cannot be used as first received packet because peer can choose its starting
// packet number.
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.cc b/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.cc
index 3eed5e8d7ca..f4b01ff3333 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.cc
@@ -8,9 +8,11 @@
#include "net/third_party/quiche/src/quic/core/quic_constants.h"
#include "net/third_party/quiche/src/quic/core/quic_session.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
namespace quic {
@@ -22,6 +24,9 @@ const size_t kMaxNumControlFrames = 1000;
} // namespace
+#define ENDPOINT \
+ (session_->perspective() == Perspective::IS_SERVER ? "Server: " : "Client: ")
+
QuicControlFrameManager::QuicControlFrameManager(QuicSession* session)
: last_control_frame_id_(kInvalidControlFrameId),
least_unacked_(1),
@@ -41,9 +46,10 @@ void QuicControlFrameManager::WriteOrBufferQuicFrame(QuicFrame frame) {
if (control_frames_.size() > kMaxNumControlFrames) {
session_->connection()->CloseConnection(
QUIC_TOO_MANY_BUFFERED_CONTROL_FRAMES,
- QuicStrCat("More than ", kMaxNumControlFrames,
- "buffered control frames, least_unacked: ", least_unacked_,
- ", least_unsent_: ", least_unsent_),
+ quiche::QuicheStrCat(
+ "More than ", kMaxNumControlFrames,
+ "buffered control frames, least_unacked: ", least_unacked_,
+ ", least_unsent_: ", least_unsent_),
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return;
}
@@ -108,6 +114,12 @@ void QuicControlFrameManager::WriteOrBufferStopSending(uint16_t code,
new QuicStopSendingFrame(++last_control_frame_id_, stream_id, code)));
}
+void QuicControlFrameManager::WriteOrBufferHandshakeDone() {
+ QUIC_DVLOG(1) << "Writing HANDSHAKE_DONE";
+ WriteOrBufferQuicFrame(
+ QuicFrame(QuicHandshakeDoneFrame(++last_control_frame_id_)));
+}
+
void QuicControlFrameManager::WritePing() {
QUIC_DVLOG(1) << "Writing PING_FRAME";
if (HasBufferedFrames()) {
@@ -121,9 +133,10 @@ void QuicControlFrameManager::WritePing() {
if (control_frames_.size() > kMaxNumControlFrames) {
session_->connection()->CloseConnection(
QUIC_TOO_MANY_BUFFERED_CONTROL_FRAMES,
- QuicStrCat("More than ", kMaxNumControlFrames,
- "buffered control frames, least_unacked: ", least_unacked_,
- ", least_unsent_: ", least_unsent_),
+ quiche::QuicheStrCat(
+ "More than ", kMaxNumControlFrames,
+ "buffered control frames, least_unacked: ", least_unacked_,
+ ", least_unsent_: ", least_unsent_),
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return;
}
@@ -242,7 +255,10 @@ void QuicControlFrameManager::OnCanWrite() {
WriteBufferedFrames();
}
-bool QuicControlFrameManager::RetransmitControlFrame(const QuicFrame& frame) {
+bool QuicControlFrameManager::RetransmitControlFrame(const QuicFrame& frame,
+ TransmissionType type) {
+ DCHECK(type == PTO_RETRANSMISSION || type == RTO_RETRANSMISSION ||
+ type == TLP_RETRANSMISSION || type == PROBING_RETRANSMISSION);
QuicControlFrameId id = GetControlFrameId(frame);
if (id == kInvalidControlFrameId) {
// Frame does not have a valid control frame ID, ignore it. Returns true
@@ -265,7 +281,7 @@ bool QuicControlFrameManager::RetransmitControlFrame(const QuicFrame& frame) {
QuicFrame copy = CopyRetransmittableControlFrame(frame);
QUIC_DVLOG(1) << "control frame manager is forced to retransmit frame: "
<< frame;
- if (session_->WriteControlFrame(copy)) {
+ if (session_->WriteControlFrame(copy, type)) {
return true;
}
DeleteFrame(&copy);
@@ -273,12 +289,16 @@ bool QuicControlFrameManager::RetransmitControlFrame(const QuicFrame& frame) {
}
void QuicControlFrameManager::WriteBufferedFrames() {
+ DCHECK(session_->connection()->connected())
+ << ENDPOINT << "Try to write control frames when connection is closed.";
while (HasBufferedFrames()) {
- session_->SetTransmissionType(NOT_RETRANSMISSION);
+ if (!session_->write_with_transmission()) {
+ session_->SetTransmissionType(NOT_RETRANSMISSION);
+ }
QuicFrame frame_to_send =
control_frames_.at(least_unsent_ - least_unacked_);
QuicFrame copy = CopyRetransmittableControlFrame(frame_to_send);
- if (!session_->WriteControlFrame(copy)) {
+ if (!session_->WriteControlFrame(copy, NOT_RETRANSMISSION)) {
// Connection is write blocked.
DeleteFrame(&copy);
break;
@@ -291,7 +311,7 @@ void QuicControlFrameManager::WritePendingRetransmission() {
while (HasPendingRetransmission()) {
QuicFrame pending = NextPendingRetransmission();
QuicFrame copy = CopyRetransmittableControlFrame(pending);
- if (!session_->WriteControlFrame(copy)) {
+ if (!session_->WriteControlFrame(copy, LOSS_RETRANSMISSION)) {
// Connection is write blocked.
DeleteFrame(&copy);
break;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.h b/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.h
index a4c26780d40..ffd378ca2ae 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.h
@@ -8,7 +8,8 @@
#include <string>
#include "net/third_party/quiche/src/quic/core/frames/quic_frame.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
+#include "net/third_party/quiche/src/quic/core/quic_circular_deque.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
namespace quic {
@@ -66,6 +67,10 @@ class QUIC_EXPORT_PRIVATE QuicControlFrameManager {
// can not be sent immediately.
void WriteOrBufferStopSending(uint16_t code, QuicStreamId stream_id);
+ // Tries to send an HANDSHAKE_DONE frame. The frame is buffered if it can not
+ // be sent immediately.
+ void WriteOrBufferHandshakeDone();
+
// Sends a PING_FRAME. Do not send PING if there is buffered frames.
void WritePing();
@@ -82,7 +87,7 @@ class QUIC_EXPORT_PRIVATE QuicControlFrameManager {
// Retransmit |frame| if it is still outstanding. Returns false if the frame
// does not get retransmitted because the connection is blocked. Otherwise,
// returns true.
- bool RetransmitControlFrame(const QuicFrame& frame);
+ bool RetransmitControlFrame(const QuicFrame& frame, TransmissionType type);
// Returns true if |frame| is outstanding and waiting to be acked. Returns
// false otherwise.
@@ -125,7 +130,7 @@ class QUIC_EXPORT_PRIVATE QuicControlFrameManager {
// frame.
void WriteOrBufferQuicFrame(QuicFrame frame);
- QuicDeque<QuicFrame> control_frames_;
+ QuicCircularDeque<QuicFrame> control_frames_;
// Id of latest saved control frame. 0 if no control frame has been saved.
QuicControlFrameId last_control_frame_id_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager_test.cc
index e76e09ffb9a..f8e9932f4e5 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager_test.cc
@@ -6,6 +6,7 @@
#include <utility>
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
@@ -192,16 +193,19 @@ TEST_F(QuicControlFrameManagerTest, RetransmitControlFrame) {
manager_->OnControlFrameAcked(QuicFrame(&goaway_));
// Do not retransmit an acked frame.
EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
- EXPECT_TRUE(manager_->RetransmitControlFrame(QuicFrame(&goaway_)));
+ EXPECT_TRUE(manager_->RetransmitControlFrame(QuicFrame(&goaway_),
+ PTO_RETRANSMISSION));
// Retransmit control frame 3.
EXPECT_CALL(*connection_, SendControlFrame(_))
.WillOnce(Invoke(&ClearControlFrame));
- EXPECT_TRUE(manager_->RetransmitControlFrame(QuicFrame(&window_update_)));
+ EXPECT_TRUE(manager_->RetransmitControlFrame(QuicFrame(&window_update_),
+ PTO_RETRANSMISSION));
// Retransmit control frame 4, and connection is write blocked.
EXPECT_CALL(*connection_, SendControlFrame(_)).WillOnce(Return(false));
- EXPECT_FALSE(manager_->RetransmitControlFrame(QuicFrame(&window_update_)));
+ EXPECT_FALSE(manager_->RetransmitControlFrame(QuicFrame(&window_update_),
+ PTO_RETRANSMISSION));
}
TEST_F(QuicControlFrameManagerTest, DonotSendPingWithBufferedFrames) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.cc
index eaeabfec08f..e93fd071c07 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.cc
@@ -13,7 +13,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_client_stats.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
namespace quic {
@@ -69,7 +69,7 @@ QuicCryptoClientHandshaker::QuicCryptoClientHandshaker(
proof_verify_start_time_(QuicTime::Zero()),
num_scup_messages_received_(0),
encryption_established_(false),
- handshake_confirmed_(false),
+ one_rtt_keys_available_(false),
crypto_negotiated_params_(new QuicCryptoNegotiatedParameters) {}
QuicCryptoClientHandshaker::~QuicCryptoClientHandshaker() {
@@ -82,8 +82,8 @@ void QuicCryptoClientHandshaker::OnHandshakeMessage(
const CryptoHandshakeMessage& message) {
QuicCryptoHandshaker::OnHandshakeMessage(message);
if (message.tag() == kSCUP) {
- if (!handshake_confirmed()) {
- stream_->CloseConnectionWithDetails(
+ if (!one_rtt_keys_available()) {
+ stream_->OnUnrecoverableError(
QUIC_CRYPTO_UPDATE_BEFORE_HANDSHAKE_COMPLETE,
"Early SCUP disallowed");
return;
@@ -97,10 +97,9 @@ void QuicCryptoClientHandshaker::OnHandshakeMessage(
}
// Do not process handshake messages after the handshake is confirmed.
- if (handshake_confirmed()) {
- stream_->CloseConnectionWithDetails(
- QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE,
- "Unexpected handshake message");
+ if (one_rtt_keys_available()) {
+ stream_->OnUnrecoverableError(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE,
+ "Unexpected handshake message");
return;
}
@@ -118,12 +117,22 @@ int QuicCryptoClientHandshaker::num_sent_client_hellos() const {
}
bool QuicCryptoClientHandshaker::IsResumption() const {
- QUIC_BUG_IF(!handshake_confirmed_);
+ QUIC_BUG_IF(!one_rtt_keys_available_);
// While 0-RTT handshakes could be considered to be like resumption, QUIC
// Crypto doesn't have the same notion of a resumption like TLS does.
return false;
}
+bool QuicCryptoClientHandshaker::EarlyDataAccepted() const {
+ QUIC_BUG_IF(!one_rtt_keys_available_);
+ return num_client_hellos_ == 1;
+}
+
+bool QuicCryptoClientHandshaker::ReceivedInchoateReject() const {
+ QUIC_BUG_IF(!one_rtt_keys_available_);
+ return num_client_hellos_ >= 3;
+}
+
int QuicCryptoClientHandshaker::num_scup_messages_received() const {
return num_scup_messages_received_;
}
@@ -136,8 +145,8 @@ bool QuicCryptoClientHandshaker::encryption_established() const {
return encryption_established_;
}
-bool QuicCryptoClientHandshaker::handshake_confirmed() const {
- return handshake_confirmed_;
+bool QuicCryptoClientHandshaker::one_rtt_keys_available() const {
+ return one_rtt_keys_available_;
}
const QuicCryptoNegotiatedParameters&
@@ -149,6 +158,14 @@ CryptoMessageParser* QuicCryptoClientHandshaker::crypto_message_parser() {
return QuicCryptoHandshaker::crypto_message_parser();
}
+HandshakeState QuicCryptoClientHandshaker::GetHandshakeState() const {
+ return one_rtt_keys_available() ? HANDSHAKE_COMPLETE : HANDSHAKE_START;
+}
+
+void QuicCryptoClientHandshaker::OnHandshakeDoneReceived() {
+ DCHECK(false);
+}
+
size_t QuicCryptoClientHandshaker::BufferSizeLimitForLevel(
EncryptionLevel level) const {
return QuicCryptoHandshaker::BufferSizeLimitForLevel(level);
@@ -166,12 +183,12 @@ void QuicCryptoClientHandshaker::HandleServerConfigUpdateMessage(
crypto_negotiated_params_, &error_details);
if (error != QUIC_NO_ERROR) {
- stream_->CloseConnectionWithDetails(
+ stream_->OnUnrecoverableError(
error, "Server config update invalid: " + error_details);
return;
}
- DCHECK(handshake_confirmed());
+ DCHECK(one_rtt_keys_available());
if (proof_verify_callback_) {
proof_verify_callback_->Cancel();
}
@@ -211,8 +228,8 @@ void QuicCryptoClientHandshaker::DoHandshakeLoop(
break;
case STATE_IDLE:
// This means that the peer sent us a message that we weren't expecting.
- stream_->CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
- "Handshake in idle state");
+ stream_->OnUnrecoverableError(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
+ "Handshake in idle state");
return;
case STATE_INITIALIZE_SCUP:
DoInitializeServerConfigUpdate(cached);
@@ -248,10 +265,11 @@ void QuicCryptoClientHandshaker::DoSendCHLO(
session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
encryption_established_ = false;
if (num_client_hellos_ >= QuicCryptoClientStream::kMaxClientHellos) {
- stream_->CloseConnectionWithDetails(
+ stream_->OnUnrecoverableError(
QUIC_CRYPTO_TOO_MANY_REJECTS,
- QuicStrCat("More than ", QuicCryptoClientStream::kMaxClientHellos,
- " rejects"));
+ quiche::QuicheStrCat("More than ",
+ QuicCryptoClientStream::kMaxClientHellos,
+ " rejects"));
return;
}
num_client_hellos_++;
@@ -275,14 +293,13 @@ void QuicCryptoClientHandshaker::DoSendCHLO(
if (max_packet_size <= kFramingOverhead) {
QUIC_DLOG(DFATAL) << "max_packet_length (" << max_packet_size
<< ") has no room for framing overhead.";
- stream_->CloseConnectionWithDetails(QUIC_INTERNAL_ERROR,
- "max_packet_size too smalll");
+ stream_->OnUnrecoverableError(QUIC_INTERNAL_ERROR,
+ "max_packet_size too smalll");
return;
}
if (kClientHelloMinimumSize > max_packet_size - kFramingOverhead) {
QUIC_DLOG(DFATAL) << "Client hello won't fit in a single packet.";
- stream_->CloseConnectionWithDetails(QUIC_INTERNAL_ERROR,
- "CHLO too large");
+ stream_->OnUnrecoverableError(QUIC_INTERNAL_ERROR, "CHLO too large");
return;
}
next_state_ = STATE_RECV_REJ;
@@ -305,7 +322,7 @@ void QuicCryptoClientHandshaker::DoSendCHLO(
// Flush the cached config so that, if it's bad, the server has a
// chance to send us another in the future.
cached->InvalidateServerConfig();
- stream_->CloseConnectionWithDetails(error, error_details);
+ stream_->OnUnrecoverableError(error, error_details);
return;
}
chlo_hash_ = CryptoUtils::HashHandshakeMessage(out, Perspective::IS_CLIENT);
@@ -318,36 +335,16 @@ void QuicCryptoClientHandshaker::DoSendCHLO(
crypto_config_->pad_full_hello());
SendHandshakeMessage(out);
// Be prepared to decrypt with the new server write key.
- if (session()->use_handshake_delegate()) {
- delegate_->OnNewKeysAvailable(
- ENCRYPTION_ZERO_RTT,
- std::move(crypto_negotiated_params_->initial_crypters.decrypter),
- /*set_alternative_decrypter=*/true,
- /*latch_once_used=*/true,
- std::move(crypto_negotiated_params_->initial_crypters.encrypter));
- encryption_established_ = true;
- delegate_->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
- return;
- }
- if (session()->connection()->version().KnowsWhichDecrypterToUse()) {
- session()->connection()->InstallDecrypter(
- ENCRYPTION_ZERO_RTT,
- std::move(crypto_negotiated_params_->initial_crypters.decrypter));
- } else {
- session()->connection()->SetAlternativeDecrypter(
- ENCRYPTION_ZERO_RTT,
- std::move(crypto_negotiated_params_->initial_crypters.decrypter),
- true /* latch once used */);
- }
- // Send subsequent packets under encryption on the assumption that the
- // server will accept the handshake.
- session()->connection()->SetEncrypter(
+ delegate_->OnNewEncryptionKeyAvailable(
ENCRYPTION_ZERO_RTT,
std::move(crypto_negotiated_params_->initial_crypters.encrypter));
- session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
-
+ delegate_->OnNewDecryptionKeyAvailable(
+ ENCRYPTION_ZERO_RTT,
+ std::move(crypto_negotiated_params_->initial_crypters.decrypter),
+ /*set_alternative_decrypter=*/true,
+ /*latch_once_used=*/true);
encryption_established_ = true;
- session()->OnCryptoHandshakeEvent(QuicSession::ENCRYPTION_ESTABLISHED);
+ delegate_->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
}
void QuicCryptoClientHandshaker::DoReceiveREJ(
@@ -359,8 +356,8 @@ void QuicCryptoClientHandshaker::DoReceiveREJ(
// that we need.
if (in->tag() != kREJ) {
next_state_ = STATE_NONE;
- stream_->CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
- "Expected REJ");
+ stream_->OnUnrecoverableError(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
+ "Expected REJ");
return;
}
@@ -388,11 +385,7 @@ void QuicCryptoClientHandshaker::DoReceiveREJ(
// Receipt of a REJ message means that the server received the CHLO
// so we can cancel and retransmissions.
- if (session()->use_handshake_delegate()) {
- delegate_->NeuterUnencryptedData();
- } else {
- session()->NeuterUnencryptedData();
- }
+ delegate_->NeuterUnencryptedData();
std::string error_details;
QuicErrorCode error = crypto_config_->ProcessRejection(
@@ -402,7 +395,7 @@ void QuicCryptoClientHandshaker::DoReceiveREJ(
if (error != QUIC_NO_ERROR) {
next_state_ = STATE_NONE;
- stream_->CloseConnectionWithDetails(error, error_details);
+ stream_->OnUnrecoverableError(error, error_details);
return;
}
if (!cached->proof_valid()) {
@@ -472,9 +465,9 @@ void QuicCryptoClientHandshaker::DoVerifyProofComplete(
}
next_state_ = STATE_NONE;
QUIC_CLIENT_HISTOGRAM_BOOL("QuicVerifyProofFailed.HandshakeConfirmed",
- handshake_confirmed(), "");
- stream_->CloseConnectionWithDetails(
- QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_);
+ one_rtt_keys_available(), "");
+ stream_->OnUnrecoverableError(QUIC_PROOF_INVALID,
+ "Proof invalid: " + verify_error_details_);
return;
}
@@ -485,7 +478,7 @@ void QuicCryptoClientHandshaker::DoVerifyProofComplete(
} else {
SetCachedProofValid(cached);
cached->SetProofVerifyDetails(verify_details_.release());
- if (!handshake_confirmed()) {
+ if (!one_rtt_keys_available()) {
next_state_ = STATE_SEND_CHLO;
} else {
// TODO: Enable Expect-Staple. https://crbug.com/631101
@@ -506,8 +499,8 @@ void QuicCryptoClientHandshaker::DoReceiveSHLO(
// A reject message must be sent in ENCRYPTION_INITIAL.
if (session()->connection()->last_decrypted_level() != ENCRYPTION_INITIAL) {
// The rejection was sent encrypted!
- stream_->CloseConnectionWithDetails(
- QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT, "encrypted REJ message");
+ stream_->OnUnrecoverableError(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
+ "encrypted REJ message");
return;
}
next_state_ = STATE_RECV_REJ;
@@ -515,15 +508,17 @@ void QuicCryptoClientHandshaker::DoReceiveSHLO(
}
if (in->tag() != kSHLO) {
- stream_->CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
- "Expected SHLO or REJ");
+ stream_->OnUnrecoverableError(
+ QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
+ quiche::QuicheStrCat("Expected SHLO or REJ. Received: ",
+ QuicTagToString(in->tag())));
return;
}
if (session()->connection()->last_decrypted_level() == ENCRYPTION_INITIAL) {
// The server hello was sent without encryption.
- stream_->CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
- "unencrypted SHLO message");
+ stream_->OnUnrecoverableError(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
+ "unencrypted SHLO message");
return;
}
@@ -535,14 +530,14 @@ void QuicCryptoClientHandshaker::DoReceiveSHLO(
crypto_negotiated_params_, &error_details);
if (error != QUIC_NO_ERROR) {
- stream_->CloseConnectionWithDetails(
- error, "Server hello invalid: " + error_details);
+ stream_->OnUnrecoverableError(error,
+ "Server hello invalid: " + error_details);
return;
}
error = session()->config()->ProcessPeerHello(*in, SERVER, &error_details);
if (error != QUIC_NO_ERROR) {
- stream_->CloseConnectionWithDetails(
- error, "Server hello invalid: " + error_details);
+ stream_->OnUnrecoverableError(error,
+ "Server hello invalid: " + error_details);
return;
}
session()->OnConfigNegotiated();
@@ -552,33 +547,16 @@ void QuicCryptoClientHandshaker::DoReceiveSHLO(
// has been floated that the server shouldn't send packets encrypted
// with the FORWARD_SECURE key until it receives a FORWARD_SECURE
// packet from the client.
- if (session()->use_handshake_delegate()) {
- delegate_->OnNewKeysAvailable(
- ENCRYPTION_FORWARD_SECURE, std::move(crypters->decrypter),
- /*set_alternative_decrypter=*/true,
- /*latch_once_used=*/false, std::move(crypters->encrypter));
- handshake_confirmed_ = true;
- delegate_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
- delegate_->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
- delegate_->NeuterHandshakeData();
- return;
- }
-
- if (session()->connection()->version().KnowsWhichDecrypterToUse()) {
- session()->connection()->InstallDecrypter(ENCRYPTION_FORWARD_SECURE,
- std::move(crypters->decrypter));
- } else {
- session()->connection()->SetAlternativeDecrypter(
- ENCRYPTION_FORWARD_SECURE, std::move(crypters->decrypter),
- false /* don't latch */);
- }
- session()->connection()->SetEncrypter(ENCRYPTION_FORWARD_SECURE,
- std::move(crypters->encrypter));
- session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
-
- handshake_confirmed_ = true;
- session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
- session()->connection()->OnHandshakeComplete();
+ delegate_->OnNewEncryptionKeyAvailable(ENCRYPTION_FORWARD_SECURE,
+ std::move(crypters->encrypter));
+ delegate_->OnNewDecryptionKeyAvailable(ENCRYPTION_FORWARD_SECURE,
+ std::move(crypters->decrypter),
+ /*set_alternative_decrypter=*/true,
+ /*latch_once_used=*/false);
+ one_rtt_keys_available_ = true;
+ delegate_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ delegate_->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
+ delegate_->NeuterHandshakeData();
}
void QuicCryptoClientHandshaker::DoInitializeServerConfigUpdate(
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.h b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.h
index 467e5c87208..8c33ee91447 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.h
@@ -15,10 +15,10 @@
namespace quic {
-// An implementation of QuicCryptoClientStream::HandshakerDelegate which uses
+// An implementation of QuicCryptoClientStream::HandshakerInterface which uses
// QUIC crypto as the crypto handshake protocol.
class QUIC_EXPORT_PRIVATE QuicCryptoClientHandshaker
- : public QuicCryptoClientStream::HandshakerDelegate,
+ : public QuicCryptoClientStream::HandshakerInterface,
public QuicCryptoHandshaker {
public:
QuicCryptoClientHandshaker(
@@ -34,18 +34,23 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientHandshaker
~QuicCryptoClientHandshaker() override;
- // From QuicCryptoClientStream::HandshakerDelegate
+ // From QuicCryptoClientStream::HandshakerInterface
bool CryptoConnect() override;
int num_sent_client_hellos() const override;
bool IsResumption() const override;
+ bool EarlyDataAccepted() const override;
+ bool ReceivedInchoateReject() const override;
int num_scup_messages_received() const override;
std::string chlo_hash() const override;
bool encryption_established() const override;
- bool handshake_confirmed() const override;
+ bool one_rtt_keys_available() const override;
const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
const override;
CryptoMessageParser* crypto_message_parser() override;
+ HandshakeState GetHandshakeState() const override;
size_t BufferSizeLimitForLevel(EncryptionLevel level) const override;
+ void OnOneRttPacketAcknowledged() override {}
+ void OnHandshakeDoneReceived() override;
// From QuicCryptoHandshaker
void OnHandshakeMessage(const CryptoHandshakeMessage& message) override;
@@ -173,7 +178,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientHandshaker
int num_scup_messages_received_;
bool encryption_established_;
- bool handshake_confirmed_;
+ bool one_rtt_keys_available_;
QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters>
crypto_negotiated_params_;
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker_test.cc
index 43c7efa11db..92de76f300d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker_test.cc
@@ -9,12 +9,11 @@
#include "net/third_party/quiche/src/quic/core/proto/crypto_server_config_proto.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace {
-using ::testing::Test;
-
class TestProofHandler : public QuicCryptoClientStream::ProofHandler {
public:
~TestProofHandler() override {}
@@ -35,7 +34,7 @@ class InsecureProofVerifier : public ProofVerifier {
const uint16_t /*port*/,
const std::string& /*server_config*/,
QuicTransportVersion /*transport_version*/,
- QuicStringPiece /*chlo_hash*/,
+ quiche::QuicheStringPiece /*chlo_hash*/,
const std::vector<std::string>& /*certs*/,
const std::string& /*cert_sct*/,
const std::string& /*signature*/,
@@ -73,7 +72,7 @@ class DummyProofSource : public ProofSource {
const std::string& hostname,
const std::string& /*server_config*/,
QuicTransportVersion /*transport_version*/,
- QuicStringPiece /*chlo_hash*/,
+ quiche::QuicheStringPiece /*chlo_hash*/,
std::unique_ptr<Callback> callback) override {
QuicReferenceCountedPointer<ProofSource::Chain> chain =
GetCertChain(server_address, hostname);
@@ -96,9 +95,9 @@ class DummyProofSource : public ProofSource {
const QuicSocketAddress& /*server_address*/,
const std::string& /*hostname*/,
uint16_t /*signature_algorit*/,
- QuicStringPiece /*in*/,
+ quiche::QuicheStringPiece /*in*/,
std::unique_ptr<SignatureCallback> callback) override {
- callback->Run(true, "Dummy signature");
+ callback->Run(true, "Dummy signature", /*details=*/nullptr);
}
};
@@ -122,16 +121,19 @@ class Handshaker : public QuicCryptoClientHandshaker {
}
};
-class QuicCryptoClientHandshakerTest : public Test {
+class QuicCryptoClientHandshakerTest
+ : public QuicTestWithParam<ParsedQuicVersion> {
protected:
QuicCryptoClientHandshakerTest()
- : proof_handler_(),
+ : version_(GetParam()),
+ proof_handler_(),
helper_(),
alarm_factory_(),
server_id_("host", 123),
connection_(new test::MockQuicConnection(&helper_,
&alarm_factory_,
- Perspective::IS_CLIENT)),
+ Perspective::IS_CLIENT,
+ {version_})),
session_(connection_, false),
crypto_client_config_(std::make_unique<InsecureProofVerifier>()),
client_stream_(new QuicCryptoClientStream(server_id_,
@@ -164,6 +166,7 @@ class QuicCryptoClientHandshakerTest : public Test {
state_.SetProofValid();
}
+ ParsedQuicVersion version_;
TestProofHandler proof_handler_;
test::MockQuicConnectionHelper helper_;
test::MockAlarmFactory alarm_factory_;
@@ -177,19 +180,25 @@ class QuicCryptoClientHandshakerTest : public Test {
QuicCryptoClientConfig::CachedState state_;
};
-TEST_F(QuicCryptoClientHandshakerTest, TestSendFullPaddingInInchoateHello) {
+INSTANTIATE_TEST_SUITE_P(
+ QuicCryptoClientHandshakerTests,
+ QuicCryptoClientHandshakerTest,
+ ::testing::ValuesIn(AllSupportedVersionsWithQuicCrypto()),
+ ::testing::PrintToStringParamName());
+
+TEST_P(QuicCryptoClientHandshakerTest, TestSendFullPaddingInInchoateHello) {
handshaker_.DoSendCHLOTest(&state_);
EXPECT_TRUE(connection_->fully_pad_during_crypto_handshake());
}
-TEST_F(QuicCryptoClientHandshakerTest, TestDisabledPaddingInInchoateHello) {
+TEST_P(QuicCryptoClientHandshakerTest, TestDisabledPaddingInInchoateHello) {
crypto_client_config_.set_pad_inchoate_hello(false);
handshaker_.DoSendCHLOTest(&state_);
EXPECT_FALSE(connection_->fully_pad_during_crypto_handshake());
}
-TEST_F(QuicCryptoClientHandshakerTest,
+TEST_P(QuicCryptoClientHandshakerTest,
TestPaddingInFullHelloEvenIfInchoateDisabled) {
// Disable inchoate, but full hello should still be padded.
crypto_client_config_.set_pad_inchoate_hello(false);
@@ -200,7 +209,7 @@ TEST_F(QuicCryptoClientHandshakerTest,
EXPECT_TRUE(connection_->fully_pad_during_crypto_handshake());
}
-TEST_F(QuicCryptoClientHandshakerTest, TestNoPaddingInFullHelloWhenDisabled) {
+TEST_P(QuicCryptoClientHandshakerTest, TestNoPaddingInFullHelloWhenDisabled) {
crypto_client_config_.set_pad_full_hello(false);
InitializeServerParametersToEnableFullHello();
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.cc
index b30cd3a5112..62990c1faa5 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.cc
@@ -18,7 +18,6 @@
#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
namespace quic {
@@ -66,6 +65,14 @@ bool QuicCryptoClientStream::IsResumption() const {
return handshaker_->IsResumption();
}
+bool QuicCryptoClientStream::EarlyDataAccepted() const {
+ return handshaker_->EarlyDataAccepted();
+}
+
+bool QuicCryptoClientStream::ReceivedInchoateReject() const {
+ return handshaker_->ReceivedInchoateReject();
+}
+
int QuicCryptoClientStream::num_scup_messages_received() const {
return handshaker_->num_scup_messages_received();
}
@@ -74,8 +81,8 @@ bool QuicCryptoClientStream::encryption_established() const {
return handshaker_->encryption_established();
}
-bool QuicCryptoClientStream::handshake_confirmed() const {
- return handshaker_->handshake_confirmed();
+bool QuicCryptoClientStream::one_rtt_keys_available() const {
+ return handshaker_->one_rtt_keys_available();
}
const QuicCryptoNegotiatedParameters&
@@ -87,6 +94,10 @@ CryptoMessageParser* QuicCryptoClientStream::crypto_message_parser() {
return handshaker_->crypto_message_parser();
}
+HandshakeState QuicCryptoClientStream::GetHandshakeState() const {
+ return handshaker_->GetHandshakeState();
+}
+
size_t QuicCryptoClientStream::BufferSizeLimitForLevel(
EncryptionLevel level) const {
return handshaker_->BufferSizeLimitForLevel(level);
@@ -96,4 +107,12 @@ std::string QuicCryptoClientStream::chlo_hash() const {
return handshaker_->chlo_hash();
}
+void QuicCryptoClientStream::OnOneRttPacketAcknowledged() {
+ handshaker_->OnOneRttPacketAcknowledged();
+}
+
+void QuicCryptoClientStream::OnHandshakeDoneReceived() {
+ handshaker_->OnHandshakeDoneReceived();
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h
index 3f9b0af7747..5af0a663fd7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h
@@ -30,6 +30,9 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStreamBase : public QuicCryptoStream {
// is still connected.
virtual bool CryptoConnect() = 0;
+ // DEPRECATED: Use IsResumption, EarlyDataAccepted, and/or
+ // ReceivedInchoateReject instead.
+ //
// num_sent_client_hellos returns the number of client hello messages that
// have been sent. If the handshake has completed then this is one greater
// than the number of round-trips needed for the handshake.
@@ -42,6 +45,15 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStreamBase : public QuicCryptoStream {
// complete.
virtual bool IsResumption() const = 0;
+ // Returns true if early data (0-RTT) was accepted in the connection.
+ virtual bool EarlyDataAccepted() const = 0;
+
+ // Returns true if the client received an inchoate REJ during the handshake,
+ // extending the handshake by one round trip. This only applies for QUIC
+ // crypto handshakes. The equivalent feature in IETF QUIC is a Retry packet,
+ // but that is handled at the connection layer instead of the crypto layer.
+ virtual bool ReceivedInchoateReject() const = 0;
+
// The number of server config update messages received by the
// client. Does not count update messages that were received prior
// to handshake confirmation.
@@ -62,25 +74,28 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream
// the client a fallback ServerConfig.
static const int kMaxClientHellos = 4;
- // QuicCryptoClientStream creates a HandshakerDelegate at construction time
+ // QuicCryptoClientStream creates a HandshakerInterface at construction time
// based on the QuicTransportVersion of the connection. Different
- // HandshakerDelegates provide implementations of different crypto handshake
+ // HandshakerInterfaces provide implementations of different crypto handshake
// protocols. Currently QUIC crypto is the only protocol implemented; a future
- // HandshakerDelegate will use TLS as the handshake protocol.
+ // HandshakerInterface will use TLS as the handshake protocol.
// QuicCryptoClientStream delegates all of its public methods to its
- // HandshakerDelegate.
+ // HandshakerInterface.
//
// This setup of the crypto stream delegating its implementation to the
// handshaker results in the handshaker reading and writing bytes on the
// crypto stream, instead of the handshaker passing the stream bytes to send.
- class QUIC_EXPORT_PRIVATE HandshakerDelegate {
+ class QUIC_EXPORT_PRIVATE HandshakerInterface {
public:
- virtual ~HandshakerDelegate() {}
+ virtual ~HandshakerInterface() {}
// Performs a crypto handshake with the server. Returns true if the
// connection is still connected.
virtual bool CryptoConnect() = 0;
+ // DEPRECATED: Use IsResumption, EarlyDataAccepted, and/or
+ // ReceivedInchoateReject instead.
+ //
// num_sent_client_hellos returns the number of client hello messages that
// have been sent. If the handshake has completed then this is one greater
// than the number of round-trips needed for the handshake.
@@ -93,6 +108,15 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream
// complete.
virtual bool IsResumption() const = 0;
+ // Returns true if early data (0-RTT) was accepted in the connection.
+ virtual bool EarlyDataAccepted() const = 0;
+
+ // Returns true if the client received an inchoate REJ during the handshake,
+ // extending the handshake by one round trip. This only applies for QUIC
+ // crypto handshakes. The equivalent feature in IETF QUIC is a Retry packet,
+ // but that is handled at the connection layer instead of the crypto layer.
+ virtual bool ReceivedInchoateReject() const = 0;
+
// The number of server config update messages received by the
// client. Does not count update messages that were received prior
// to handshake confirmation.
@@ -104,8 +128,8 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream
// for the connection.
virtual bool encryption_established() const = 0;
- // Returns true once the crypto handshake has completed.
- virtual bool handshake_confirmed() const = 0;
+ // Returns true once 1RTT keys are available.
+ virtual bool one_rtt_keys_available() const = 0;
// Returns the parameters negotiated in the crypto handshake.
virtual const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
@@ -117,6 +141,15 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream
// Used by QuicCryptoStream to know how much unprocessed data can be
// buffered at each encryption level.
virtual size_t BufferSizeLimitForLevel(EncryptionLevel level) const = 0;
+
+ // Returns current handshake state.
+ virtual HandshakeState GetHandshakeState() const = 0;
+
+ // Called when a 1RTT packet has been acknowledged.
+ virtual void OnOneRttPacketAcknowledged() = 0;
+
+ // Called when handshake done has been received.
+ virtual void OnHandshakeDoneReceived() = 0;
};
// ProofHandler is an interface that handles callbacks from the crypto
@@ -152,27 +185,32 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream
bool CryptoConnect() override;
int num_sent_client_hellos() const override;
bool IsResumption() const override;
+ bool EarlyDataAccepted() const override;
+ bool ReceivedInchoateReject() const override;
int num_scup_messages_received() const override;
// From QuicCryptoStream
bool encryption_established() const override;
- bool handshake_confirmed() const override;
+ bool one_rtt_keys_available() const override;
const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
const override;
CryptoMessageParser* crypto_message_parser() override;
void OnPacketDecrypted(EncryptionLevel /*level*/) override {}
+ void OnOneRttPacketAcknowledged() override;
+ void OnHandshakeDoneReceived() override;
+ HandshakeState GetHandshakeState() const override;
size_t BufferSizeLimitForLevel(EncryptionLevel level) const override;
std::string chlo_hash() const;
protected:
- void set_handshaker(std::unique_ptr<HandshakerDelegate> handshaker) {
+ void set_handshaker(std::unique_ptr<HandshakerInterface> handshaker) {
handshaker_ = std::move(handshaker);
}
private:
- std::unique_ptr<HandshakerDelegate> handshaker_;
+ std::unique_ptr<HandshakerInterface> handshaker_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream_test.cc
index 827cb03e3a3..bcd6a1f536e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream_test.cc
@@ -14,7 +14,6 @@
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_server_id.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
@@ -23,6 +22,8 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/simple_quic_framer.h"
#include "net/third_party/quiche/src/quic/test_tools/simple_session_cache.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/test_tools/quiche_test_utils.h"
using testing::_;
@@ -45,13 +46,7 @@ class QuicCryptoClientStreamTest : public QuicTest {
CreateConnection();
}
- void CreateConnection() {
- connection_ =
- new PacketSavingConnection(&client_helper_, &alarm_factory_,
- Perspective::IS_CLIENT, supported_versions_);
- // Advance the time, because timers do not like uninitialized times.
- connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
-
+ void CreateSession() {
session_ = std::make_unique<TestQuicSpdyClientSession>(
connection_, DefaultQuicConfig(), supported_versions_, server_id_,
&crypto_config_);
@@ -60,8 +55,16 @@ class QuicCryptoClientStreamTest : public QuicTest {
{AlpnForVersion(connection_->version())})));
}
+ void CreateConnection() {
+ connection_ =
+ new PacketSavingConnection(&client_helper_, &alarm_factory_,
+ Perspective::IS_CLIENT, supported_versions_);
+ // Advance the time, because timers do not like uninitialized times.
+ connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
+ CreateSession();
+ }
+
void UseTlsHandshake() {
- SetQuicReloadableFlag(quic_supports_tls_handshake, true);
supported_versions_.clear();
for (ParsedQuicVersion version : AllSupportedVersions()) {
if (version.handshake_protocol != PROTOCOL_TLS1_3) {
@@ -71,6 +74,16 @@ class QuicCryptoClientStreamTest : public QuicTest {
}
}
+ void UseQuicCryptoHandshake() {
+ supported_versions_.clear();
+ for (ParsedQuicVersion version : AllSupportedVersions()) {
+ if (version.handshake_protocol != PROTOCOL_QUIC_CRYPTO) {
+ continue;
+ }
+ supported_versions_.push_back(version);
+ }
+ }
+
void CompleteCryptoHandshake() {
int proof_verify_details_calls = 1;
if (stream()->handshake_protocol() != PROTOCOL_TLS1_3) {
@@ -104,13 +117,13 @@ class QuicCryptoClientStreamTest : public QuicTest {
TEST_F(QuicCryptoClientStreamTest, NotInitiallyConected) {
EXPECT_FALSE(stream()->encryption_established());
- EXPECT_FALSE(stream()->handshake_confirmed());
+ EXPECT_FALSE(stream()->one_rtt_keys_available());
}
TEST_F(QuicCryptoClientStreamTest, ConnectedAfterSHLO) {
CompleteCryptoHandshake();
EXPECT_TRUE(stream()->encryption_established());
- EXPECT_TRUE(stream()->handshake_confirmed());
+ EXPECT_TRUE(stream()->one_rtt_keys_available());
EXPECT_FALSE(stream()->IsResumption());
}
@@ -120,7 +133,7 @@ TEST_F(QuicCryptoClientStreamTest, ConnectedAfterTlsHandshake) {
CompleteCryptoHandshake();
EXPECT_EQ(PROTOCOL_TLS1_3, stream()->handshake_protocol());
EXPECT_TRUE(stream()->encryption_established());
- EXPECT_TRUE(stream()->handshake_confirmed());
+ EXPECT_TRUE(stream()->one_rtt_keys_available());
EXPECT_FALSE(stream()->IsResumption());
}
@@ -137,7 +150,7 @@ TEST_F(QuicCryptoClientStreamTest,
connection_, stream(), AlpnForVersion(connection_->version()));
EXPECT_EQ(PROTOCOL_TLS1_3, stream()->handshake_protocol());
EXPECT_TRUE(stream()->encryption_established());
- EXPECT_TRUE(stream()->handshake_confirmed());
+ EXPECT_TRUE(stream()->one_rtt_keys_available());
}
TEST_F(QuicCryptoClientStreamTest, TlsResumption) {
@@ -151,7 +164,7 @@ TEST_F(QuicCryptoClientStreamTest, TlsResumption) {
EXPECT_EQ(PROTOCOL_TLS1_3, stream()->handshake_protocol());
EXPECT_TRUE(stream()->encryption_established());
- EXPECT_TRUE(stream()->handshake_confirmed());
+ EXPECT_TRUE(stream()->one_rtt_keys_available());
EXPECT_FALSE(stream()->IsResumption());
// Create a second connection
@@ -160,11 +173,13 @@ TEST_F(QuicCryptoClientStreamTest, TlsResumption) {
EXPECT_EQ(PROTOCOL_TLS1_3, stream()->handshake_protocol());
EXPECT_TRUE(stream()->encryption_established());
- EXPECT_TRUE(stream()->handshake_confirmed());
+ EXPECT_TRUE(stream()->one_rtt_keys_available());
EXPECT_TRUE(stream()->IsResumption());
}
TEST_F(QuicCryptoClientStreamTest, MessageAfterHandshake) {
+ UseQuicCryptoHandshake();
+ CreateConnection();
CompleteCryptoHandshake();
EXPECT_CALL(
@@ -176,6 +191,8 @@ TEST_F(QuicCryptoClientStreamTest, MessageAfterHandshake) {
}
TEST_F(QuicCryptoClientStreamTest, BadMessageType) {
+ UseQuicCryptoHandshake();
+ CreateConnection();
stream()->CryptoConnect();
message_.set_tag(kCHLO);
@@ -187,6 +204,8 @@ TEST_F(QuicCryptoClientStreamTest, BadMessageType) {
}
TEST_F(QuicCryptoClientStreamTest, NegotiatedParameters) {
+ UseQuicCryptoHandshake();
+ CreateConnection();
CompleteCryptoHandshake();
const QuicConfig* config = session_->config();
@@ -199,6 +218,8 @@ TEST_F(QuicCryptoClientStreamTest, NegotiatedParameters) {
}
TEST_F(QuicCryptoClientStreamTest, ExpiredServerConfig) {
+ UseQuicCryptoHandshake();
+ CreateConnection();
// Seed the config with a cached server config.
CompleteCryptoHandshake();
@@ -257,6 +278,8 @@ TEST_F(QuicCryptoClientStreamTest, InvalidCachedServerConfig) {
TEST_F(QuicCryptoClientStreamTest, ServerConfigUpdate) {
// Test that the crypto client stream can receive server config updates after
// the connection has been established.
+ UseQuicCryptoHandshake();
+ CreateConnection();
CompleteCryptoHandshake();
QuicCryptoClientConfig::CachedState* state =
@@ -297,9 +320,9 @@ TEST_F(QuicCryptoClientStreamTest, ServerConfigUpdate) {
EXPECT_EQ("xstk", state->source_address_token());
const std::string& cached_scfg = state->server_config();
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"scfg", cached_scfg.data(), cached_scfg.length(),
- reinterpret_cast<char*>(scfg), QUIC_ARRAYSIZE(scfg));
+ reinterpret_cast<char*>(scfg), QUICHE_ARRAYSIZE(scfg));
QuicStreamSequencer* sequencer = QuicStreamPeer::sequencer(stream());
EXPECT_FALSE(QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer));
@@ -308,6 +331,8 @@ TEST_F(QuicCryptoClientStreamTest, ServerConfigUpdate) {
TEST_F(QuicCryptoClientStreamTest, ServerConfigUpdateWithCert) {
// Test that the crypto client stream can receive and use server config
// updates with certificates after the connection has been established.
+ UseQuicCryptoHandshake();
+ CreateConnection();
CompleteCryptoHandshake();
// Build a server config update message with certificates
@@ -363,6 +388,8 @@ TEST_F(QuicCryptoClientStreamTest, ServerConfigUpdateWithCert) {
}
TEST_F(QuicCryptoClientStreamTest, ServerConfigUpdateBeforeHandshake) {
+ UseQuicCryptoHandshake();
+ CreateConnection();
EXPECT_CALL(
*connection_,
CloseConnection(QUIC_CRYPTO_UPDATE_BEFORE_HANDSHAKE_COMPLETE, _, _));
@@ -375,14 +402,13 @@ TEST_F(QuicCryptoClientStreamTest, ServerConfigUpdateBeforeHandshake) {
TEST_F(QuicCryptoClientStreamTest, PreferredVersion) {
// This mimics the case where client receives version negotiation packet, such
// that, the preferred version is different from the packets' version.
+ UseQuicCryptoHandshake();
connection_ = new PacketSavingConnection(
&client_helper_, &alarm_factory_, Perspective::IS_CLIENT,
ParsedVersionOfIndex(supported_versions_, 1));
connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
- session_ = std::make_unique<TestQuicSpdyClientSession>(
- connection_, DefaultQuicConfig(), supported_versions_, server_id_,
- &crypto_config_);
+ CreateSession();
CompleteCryptoHandshake();
// 2 CHLOs are sent.
ASSERT_EQ(2u, session_->sent_crypto_handshake_messages().size());
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_handshaker.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_handshaker.cc
deleted file mode 100644
index 755e35eb400..00000000000
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_handshaker.cc
+++ /dev/null
@@ -1,480 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/third_party/quiche/src/quic/core/quic_crypto_server_handshaker.h"
-
-#include <memory>
-#include <string>
-
-#include "third_party/boringssl/src/include/openssl/sha.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
-
-namespace quic {
-
-class QuicCryptoServerHandshaker::ProcessClientHelloCallback
- : public ProcessClientHelloResultCallback {
- public:
- ProcessClientHelloCallback(
- QuicCryptoServerHandshaker* parent,
- const QuicReferenceCountedPointer<
- ValidateClientHelloResultCallback::Result>& result)
- : parent_(parent), result_(result) {}
-
- void Run(
- QuicErrorCode error,
- const std::string& error_details,
- std::unique_ptr<CryptoHandshakeMessage> message,
- std::unique_ptr<DiversificationNonce> diversification_nonce,
- std::unique_ptr<ProofSource::Details> proof_source_details) override {
- if (parent_ == nullptr) {
- return;
- }
-
- parent_->FinishProcessingHandshakeMessageAfterProcessClientHello(
- *result_, error, error_details, std::move(message),
- std::move(diversification_nonce), std::move(proof_source_details));
- }
-
- void Cancel() { parent_ = nullptr; }
-
- private:
- QuicCryptoServerHandshaker* parent_;
- QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
- result_;
-};
-
-QuicCryptoServerHandshaker::QuicCryptoServerHandshaker(
- const QuicCryptoServerConfig* crypto_config,
- QuicCryptoServerStream* stream,
- QuicCompressedCertsCache* compressed_certs_cache,
- QuicSession* session,
- QuicCryptoServerStream::Helper* helper)
- : QuicCryptoHandshaker(stream, session),
- stream_(stream),
- session_(session),
- delegate_(session),
- crypto_config_(crypto_config),
- compressed_certs_cache_(compressed_certs_cache),
- signed_config_(new QuicSignedServerConfig),
- helper_(helper),
- num_handshake_messages_(0),
- num_handshake_messages_with_server_nonces_(0),
- send_server_config_update_cb_(nullptr),
- num_server_config_update_messages_sent_(0),
- zero_rtt_attempted_(false),
- chlo_packet_size_(0),
- validate_client_hello_cb_(nullptr),
- process_client_hello_cb_(nullptr),
- encryption_established_(false),
- handshake_confirmed_(false),
- crypto_negotiated_params_(new QuicCryptoNegotiatedParameters) {}
-
-QuicCryptoServerHandshaker::~QuicCryptoServerHandshaker() {
- CancelOutstandingCallbacks();
-}
-
-void QuicCryptoServerHandshaker::CancelOutstandingCallbacks() {
- // Detach from the validation callback. Calling this multiple times is safe.
- if (validate_client_hello_cb_ != nullptr) {
- validate_client_hello_cb_->Cancel();
- validate_client_hello_cb_ = nullptr;
- }
- if (send_server_config_update_cb_ != nullptr) {
- send_server_config_update_cb_->Cancel();
- send_server_config_update_cb_ = nullptr;
- }
- if (process_client_hello_cb_ != nullptr) {
- process_client_hello_cb_->Cancel();
- process_client_hello_cb_ = nullptr;
- }
-}
-
-void QuicCryptoServerHandshaker::OnHandshakeMessage(
- const CryptoHandshakeMessage& message) {
- QuicCryptoHandshaker::OnHandshakeMessage(message);
- ++num_handshake_messages_;
- chlo_packet_size_ = session()->connection()->GetCurrentPacket().length();
-
- // Do not process handshake messages after the handshake is confirmed.
- if (handshake_confirmed_) {
- stream_->CloseConnectionWithDetails(
- QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE,
- "Unexpected handshake message from client");
- return;
- }
-
- if (message.tag() != kCHLO) {
- stream_->CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
- "Handshake packet not CHLO");
- return;
- }
-
- if (validate_client_hello_cb_ != nullptr ||
- process_client_hello_cb_ != nullptr) {
- // Already processing some other handshake message. The protocol
- // does not allow for clients to send multiple handshake messages
- // before the server has a chance to respond.
- stream_->CloseConnectionWithDetails(
- QUIC_CRYPTO_MESSAGE_WHILE_VALIDATING_CLIENT_HELLO,
- "Unexpected handshake message while processing CHLO");
- return;
- }
-
- chlo_hash_ =
- CryptoUtils::HashHandshakeMessage(message, Perspective::IS_SERVER);
-
- std::unique_ptr<ValidateCallback> cb(new ValidateCallback(this));
- DCHECK(validate_client_hello_cb_ == nullptr);
- DCHECK(process_client_hello_cb_ == nullptr);
- validate_client_hello_cb_ = cb.get();
- crypto_config_->ValidateClientHello(
- message, GetClientAddress().host(),
- session()->connection()->self_address(), transport_version(),
- session()->connection()->clock(), signed_config_, std::move(cb));
-}
-
-void QuicCryptoServerHandshaker::FinishProcessingHandshakeMessage(
- QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
- result,
- std::unique_ptr<ProofSource::Details> details) {
- // Clear the callback that got us here.
- DCHECK(validate_client_hello_cb_ != nullptr);
- DCHECK(process_client_hello_cb_ == nullptr);
- validate_client_hello_cb_ = nullptr;
-
- std::unique_ptr<ProcessClientHelloCallback> cb(
- new ProcessClientHelloCallback(this, result));
- process_client_hello_cb_ = cb.get();
- ProcessClientHello(result, std::move(details), std::move(cb));
-}
-
-void QuicCryptoServerHandshaker::
- FinishProcessingHandshakeMessageAfterProcessClientHello(
- const ValidateClientHelloResultCallback::Result& result,
- QuicErrorCode error,
- const std::string& error_details,
- std::unique_ptr<CryptoHandshakeMessage> reply,
- std::unique_ptr<DiversificationNonce> diversification_nonce,
- std::unique_ptr<ProofSource::Details> /*proof_source_details*/) {
- // Clear the callback that got us here.
- DCHECK(process_client_hello_cb_ != nullptr);
- DCHECK(validate_client_hello_cb_ == nullptr);
- process_client_hello_cb_ = nullptr;
-
- const CryptoHandshakeMessage& message = result.client_hello;
- if (error != QUIC_NO_ERROR) {
- stream_->CloseConnectionWithDetails(error, error_details);
- return;
- }
-
- if (reply->tag() != kSHLO) {
- session()->connection()->set_fully_pad_crypto_handshake_packets(
- crypto_config_->pad_rej());
- SendHandshakeMessage(*reply);
- return;
- }
-
- // If we are returning a SHLO then we accepted the handshake. Now
- // process the negotiated configuration options as part of the
- // session config.
- QuicConfig* config = session()->config();
- OverrideQuicConfigDefaults(config);
- std::string process_error_details;
- const QuicErrorCode process_error =
- config->ProcessPeerHello(message, CLIENT, &process_error_details);
- if (process_error != QUIC_NO_ERROR) {
- stream_->CloseConnectionWithDetails(process_error, process_error_details);
- return;
- }
-
- session()->OnConfigNegotiated();
-
- config->ToHandshakeMessage(reply.get(), session()->transport_version());
-
- // Receiving a full CHLO implies the client is prepared to decrypt with
- // the new server write key. We can start to encrypt with the new server
- // write key.
- //
- // NOTE: the SHLO will be encrypted with the new server write key.
- if (session()->use_handshake_delegate()) {
- delegate_->OnNewKeysAvailable(
- ENCRYPTION_ZERO_RTT,
- std::move(crypto_negotiated_params_->initial_crypters.decrypter),
- /*set_alternative_decrypter=*/false,
- /*latch_once_used=*/false,
- std::move(crypto_negotiated_params_->initial_crypters.encrypter));
- delegate_->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
- delegate_->DiscardOldDecryptionKey(ENCRYPTION_INITIAL);
- } else {
- session()->connection()->SetEncrypter(
- ENCRYPTION_ZERO_RTT,
- std::move(crypto_negotiated_params_->initial_crypters.encrypter));
- session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
- // Set the decrypter immediately so that we no longer accept unencrypted
- // packets.
- if (session()->connection()->version().KnowsWhichDecrypterToUse()) {
- session()->connection()->InstallDecrypter(
- ENCRYPTION_ZERO_RTT,
- std::move(crypto_negotiated_params_->initial_crypters.decrypter));
- session()->connection()->RemoveDecrypter(ENCRYPTION_INITIAL);
- } else {
- session()->connection()->SetDecrypter(
- ENCRYPTION_ZERO_RTT,
- std::move(crypto_negotiated_params_->initial_crypters.decrypter));
- }
- }
- session()->connection()->SetDiversificationNonce(*diversification_nonce);
-
- session()->connection()->set_fully_pad_crypto_handshake_packets(
- crypto_config_->pad_shlo());
- SendHandshakeMessage(*reply);
- if (session()->use_handshake_delegate()) {
- delegate_->OnNewKeysAvailable(
- ENCRYPTION_FORWARD_SECURE,
- std::move(crypto_negotiated_params_->forward_secure_crypters.decrypter),
- /*set_alternative_decrypter=*/true,
- /*latch_once_used=*/false,
- std::move(
- crypto_negotiated_params_->forward_secure_crypters.encrypter));
- encryption_established_ = true;
- handshake_confirmed_ = true;
- delegate_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
- delegate_->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
- return;
- }
-
- session()->connection()->SetEncrypter(
- ENCRYPTION_FORWARD_SECURE,
- std::move(crypto_negotiated_params_->forward_secure_crypters.encrypter));
- session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
-
- if (session()->connection()->version().KnowsWhichDecrypterToUse()) {
- session()->connection()->InstallDecrypter(
- ENCRYPTION_FORWARD_SECURE,
- std::move(
- crypto_negotiated_params_->forward_secure_crypters.decrypter));
- } else {
- session()->connection()->SetAlternativeDecrypter(
- ENCRYPTION_FORWARD_SECURE,
- std::move(crypto_negotiated_params_->forward_secure_crypters.decrypter),
- false /* don't latch */);
- }
-
- encryption_established_ = true;
- handshake_confirmed_ = true;
- session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
-}
-
-void QuicCryptoServerHandshaker::SendServerConfigUpdate(
- const CachedNetworkParameters* cached_network_params) {
- if (!handshake_confirmed_) {
- return;
- }
-
- if (send_server_config_update_cb_ != nullptr) {
- QUIC_DVLOG(1)
- << "Skipped server config update since one is already in progress";
- return;
- }
-
- std::unique_ptr<SendServerConfigUpdateCallback> cb(
- new SendServerConfigUpdateCallback(this));
- send_server_config_update_cb_ = cb.get();
-
- crypto_config_->BuildServerConfigUpdateMessage(
- session()->transport_version(), chlo_hash_,
- previous_source_address_tokens_, session()->connection()->self_address(),
- GetClientAddress().host(), session()->connection()->clock(),
- session()->connection()->random_generator(), compressed_certs_cache_,
- *crypto_negotiated_params_, cached_network_params, std::move(cb));
-}
-
-QuicCryptoServerHandshaker::SendServerConfigUpdateCallback::
- SendServerConfigUpdateCallback(QuicCryptoServerHandshaker* parent)
- : parent_(parent) {}
-
-void QuicCryptoServerHandshaker::SendServerConfigUpdateCallback::Cancel() {
- parent_ = nullptr;
-}
-
-// From BuildServerConfigUpdateMessageResultCallback
-void QuicCryptoServerHandshaker::SendServerConfigUpdateCallback::Run(
- bool ok,
- const CryptoHandshakeMessage& message) {
- if (parent_ == nullptr) {
- return;
- }
- parent_->FinishSendServerConfigUpdate(ok, message);
-}
-
-void QuicCryptoServerHandshaker::FinishSendServerConfigUpdate(
- bool ok,
- const CryptoHandshakeMessage& message) {
- // Clear the callback that got us here.
- DCHECK(send_server_config_update_cb_ != nullptr);
- send_server_config_update_cb_ = nullptr;
-
- if (!ok) {
- QUIC_DVLOG(1) << "Server: Failed to build server config update (SCUP)!";
- return;
- }
-
- QUIC_DVLOG(1) << "Server: Sending server config update: "
- << message.DebugString();
- if (!QuicVersionUsesCryptoFrames(transport_version())) {
- const QuicData& data = message.GetSerialized();
- stream_->WriteOrBufferData(QuicStringPiece(data.data(), data.length()),
- false, nullptr);
- } else {
- SendHandshakeMessage(message);
- }
-
- ++num_server_config_update_messages_sent_;
-}
-
-uint8_t QuicCryptoServerHandshaker::NumHandshakeMessages() const {
- return num_handshake_messages_;
-}
-
-uint8_t QuicCryptoServerHandshaker::NumHandshakeMessagesWithServerNonces()
- const {
- return num_handshake_messages_with_server_nonces_;
-}
-
-int QuicCryptoServerHandshaker::NumServerConfigUpdateMessagesSent() const {
- return num_server_config_update_messages_sent_;
-}
-
-const CachedNetworkParameters*
-QuicCryptoServerHandshaker::PreviousCachedNetworkParams() const {
- return previous_cached_network_params_.get();
-}
-
-bool QuicCryptoServerHandshaker::ZeroRttAttempted() const {
- return zero_rtt_attempted_;
-}
-
-void QuicCryptoServerHandshaker::SetPreviousCachedNetworkParams(
- CachedNetworkParameters cached_network_params) {
- previous_cached_network_params_.reset(
- new CachedNetworkParameters(cached_network_params));
-}
-
-void QuicCryptoServerHandshaker::OnPacketDecrypted(EncryptionLevel level) {
- if (level == ENCRYPTION_FORWARD_SECURE) {
- delegate_->NeuterHandshakeData();
- }
-}
-
-bool QuicCryptoServerHandshaker::ShouldSendExpectCTHeader() const {
- return signed_config_->proof.send_expect_ct_header;
-}
-
-bool QuicCryptoServerHandshaker::GetBase64SHA256ClientChannelID(
- std::string* output) const {
- if (!encryption_established() ||
- crypto_negotiated_params_->channel_id.empty()) {
- return false;
- }
-
- const std::string& channel_id(crypto_negotiated_params_->channel_id);
- uint8_t digest[SHA256_DIGEST_LENGTH];
- SHA256(reinterpret_cast<const uint8_t*>(channel_id.data()), channel_id.size(),
- digest);
-
- QuicTextUtils::Base64Encode(digest, QUIC_ARRAYSIZE(digest), output);
- return true;
-}
-
-bool QuicCryptoServerHandshaker::encryption_established() const {
- return encryption_established_;
-}
-
-bool QuicCryptoServerHandshaker::handshake_confirmed() const {
- return handshake_confirmed_;
-}
-
-const QuicCryptoNegotiatedParameters&
-QuicCryptoServerHandshaker::crypto_negotiated_params() const {
- return *crypto_negotiated_params_;
-}
-
-CryptoMessageParser* QuicCryptoServerHandshaker::crypto_message_parser() {
- return QuicCryptoHandshaker::crypto_message_parser();
-}
-
-size_t QuicCryptoServerHandshaker::BufferSizeLimitForLevel(
- EncryptionLevel level) const {
- return QuicCryptoHandshaker::BufferSizeLimitForLevel(level);
-}
-
-void QuicCryptoServerHandshaker::ProcessClientHello(
- QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
- result,
- std::unique_ptr<ProofSource::Details> /*proof_source_details*/,
- std::unique_ptr<ProcessClientHelloResultCallback> done_cb) {
- const CryptoHandshakeMessage& message = result->client_hello;
- std::string error_details;
- if (!helper_->CanAcceptClientHello(
- message, GetClientAddress(), session()->connection()->peer_address(),
- session()->connection()->self_address(), &error_details)) {
- done_cb->Run(QUIC_HANDSHAKE_FAILED, error_details, nullptr, nullptr,
- nullptr);
- return;
- }
- if (!result->info.server_nonce.empty()) {
- ++num_handshake_messages_with_server_nonces_;
- }
-
- if (num_handshake_messages_ == 1) {
- // Client attempts zero RTT handshake by sending a non-inchoate CHLO.
- QuicStringPiece public_value;
- zero_rtt_attempted_ = message.GetStringPiece(kPUBS, &public_value);
- }
-
- // Store the bandwidth estimate from the client.
- if (result->cached_network_params.bandwidth_estimate_bytes_per_second() > 0) {
- previous_cached_network_params_.reset(
- new CachedNetworkParameters(result->cached_network_params));
- }
- previous_source_address_tokens_ = result->info.source_address_tokens;
-
- QuicConnection* connection = session()->connection();
- crypto_config_->ProcessClientHello(
- result, /*reject_only=*/false, connection->connection_id(),
- connection->self_address(), GetClientAddress(), connection->version(),
- session()->supported_versions(), connection->clock(),
- connection->random_generator(), compressed_certs_cache_,
- crypto_negotiated_params_, signed_config_,
- QuicCryptoStream::CryptoMessageFramingOverhead(
- transport_version(), connection->connection_id()),
- chlo_packet_size_, std::move(done_cb));
-}
-
-void QuicCryptoServerHandshaker::OverrideQuicConfigDefaults(
- QuicConfig* /*config*/) {}
-
-QuicCryptoServerHandshaker::ValidateCallback::ValidateCallback(
- QuicCryptoServerHandshaker* parent)
- : parent_(parent) {}
-
-void QuicCryptoServerHandshaker::ValidateCallback::Cancel() {
- parent_ = nullptr;
-}
-
-void QuicCryptoServerHandshaker::ValidateCallback::Run(
- QuicReferenceCountedPointer<Result> result,
- std::unique_ptr<ProofSource::Details> details) {
- if (parent_ != nullptr) {
- parent_->FinishProcessingHandshakeMessage(std::move(result),
- std::move(details));
- }
-}
-
-const QuicSocketAddress QuicCryptoServerHandshaker::GetClientAddress() {
- return session()->connection()->peer_address();
-}
-
-} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_handshaker.h b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_handshaker.h
deleted file mode 100644
index 4e1a1b895fd..00000000000
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_handshaker.h
+++ /dev/null
@@ -1,237 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_QUIC_CORE_QUIC_CRYPTO_SERVER_HANDSHAKER_H_
-#define QUICHE_QUIC_CORE_QUIC_CRYPTO_SERVER_HANDSHAKER_H_
-
-#include <string>
-
-#include "net/third_party/quiche/src/quic/core/proto/cached_network_parameters_proto.h"
-#include "net/third_party/quiche/src/quic/core/proto/source_address_token_proto.h"
-#include "net/third_party/quiche/src/quic/core/quic_crypto_handshaker.h"
-#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
-#include "net/third_party/quiche/src/quic/core/quic_session.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-
-namespace quic {
-
-namespace test {
-class QuicCryptoServerStreamPeer;
-} // namespace test
-
-class QUIC_EXPORT_PRIVATE QuicCryptoServerHandshaker
- : public QuicCryptoServerStream::HandshakerDelegate,
- public QuicCryptoHandshaker {
- public:
- // |crypto_config| must outlive the stream.
- // |session| must outlive the stream.
- // |helper| must outlive the stream.
- QuicCryptoServerHandshaker(const QuicCryptoServerConfig* crypto_config,
- QuicCryptoServerStream* stream,
- QuicCompressedCertsCache* compressed_certs_cache,
- QuicSession* session,
- QuicCryptoServerStream::Helper* helper);
- QuicCryptoServerHandshaker(const QuicCryptoServerHandshaker&) = delete;
- QuicCryptoServerHandshaker& operator=(const QuicCryptoServerHandshaker&) =
- delete;
-
- ~QuicCryptoServerHandshaker() override;
-
- // From HandshakerDelegate
- void CancelOutstandingCallbacks() override;
- bool GetBase64SHA256ClientChannelID(std::string* output) const override;
- void SendServerConfigUpdate(
- const CachedNetworkParameters* cached_network_params) override;
- uint8_t NumHandshakeMessages() const override;
- uint8_t NumHandshakeMessagesWithServerNonces() const override;
- int NumServerConfigUpdateMessagesSent() const override;
- const CachedNetworkParameters* PreviousCachedNetworkParams() const override;
- bool ZeroRttAttempted() const override;
- void SetPreviousCachedNetworkParams(
- CachedNetworkParameters cached_network_params) override;
- void OnPacketDecrypted(EncryptionLevel level) override;
- bool ShouldSendExpectCTHeader() const override;
-
- // From QuicCryptoStream
- bool encryption_established() const override;
- bool handshake_confirmed() const override;
- const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
- const override;
- CryptoMessageParser* crypto_message_parser() override;
- size_t BufferSizeLimitForLevel(EncryptionLevel level) const override;
-
- // From QuicCryptoHandshaker
- void OnHandshakeMessage(const CryptoHandshakeMessage& message) override;
-
- protected:
- virtual void ProcessClientHello(
- QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
- result,
- std::unique_ptr<ProofSource::Details> proof_source_details,
- std::unique_ptr<ProcessClientHelloResultCallback> done_cb);
-
- // Hook that allows the server to set QuicConfig defaults just
- // before going through the parameter negotiation step.
- virtual void OverrideQuicConfigDefaults(QuicConfig* config);
-
- // Returns client address used to generate and validate source address token.
- virtual const QuicSocketAddress GetClientAddress();
-
- // Returns the QuicSession that this stream belongs to.
- QuicSession* session() const { return session_; }
-
- void set_encryption_established(bool encryption_established) {
- encryption_established_ = encryption_established;
- }
-
- void set_handshake_confirmed(bool handshake_confirmed) {
- handshake_confirmed_ = handshake_confirmed;
- }
-
- private:
- friend class test::QuicCryptoServerStreamPeer;
-
- class QUIC_EXPORT_PRIVATE ValidateCallback
- : public ValidateClientHelloResultCallback {
- public:
- explicit ValidateCallback(QuicCryptoServerHandshaker* parent);
- ValidateCallback(const ValidateCallback&) = delete;
- ValidateCallback& operator=(const ValidateCallback&) = delete;
- // To allow the parent to detach itself from the callback before deletion.
- void Cancel();
-
- // From ValidateClientHelloResultCallback
- void Run(QuicReferenceCountedPointer<Result> result,
- std::unique_ptr<ProofSource::Details> details) override;
-
- private:
- QuicCryptoServerHandshaker* parent_;
- };
-
- class SendServerConfigUpdateCallback
- : public BuildServerConfigUpdateMessageResultCallback {
- public:
- explicit SendServerConfigUpdateCallback(QuicCryptoServerHandshaker* parent);
- SendServerConfigUpdateCallback(const SendServerConfigUpdateCallback&) =
- delete;
- void operator=(const SendServerConfigUpdateCallback&) = delete;
-
- // To allow the parent to detach itself from the callback before deletion.
- void Cancel();
-
- // From BuildServerConfigUpdateMessageResultCallback
- void Run(bool ok, const CryptoHandshakeMessage& message) override;
-
- private:
- QuicCryptoServerHandshaker* parent_;
- };
-
- // Invoked by ValidateCallback::RunImpl once initial validation of
- // the client hello is complete. Finishes processing of the client
- // hello message and handles handshake success/failure.
- void FinishProcessingHandshakeMessage(
- QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
- result,
- std::unique_ptr<ProofSource::Details> details);
-
- class ProcessClientHelloCallback;
- friend class ProcessClientHelloCallback;
-
- // Portion of FinishProcessingHandshakeMessage which executes after
- // ProcessClientHello has been called.
- void FinishProcessingHandshakeMessageAfterProcessClientHello(
- const ValidateClientHelloResultCallback::Result& result,
- QuicErrorCode error,
- const std::string& error_details,
- std::unique_ptr<CryptoHandshakeMessage> reply,
- std::unique_ptr<DiversificationNonce> diversification_nonce,
- std::unique_ptr<ProofSource::Details> proof_source_details);
-
- // Invoked by SendServerConfigUpdateCallback::RunImpl once the proof has been
- // received. |ok| indicates whether or not the proof was successfully
- // acquired, and |message| holds the partially-constructed message from
- // SendServerConfigUpdate.
- void FinishSendServerConfigUpdate(bool ok,
- const CryptoHandshakeMessage& message);
-
- // Returns the QuicTransportVersion of the connection.
- QuicTransportVersion transport_version() const {
- return session_->transport_version();
- }
-
- QuicCryptoServerStream* stream_;
-
- QuicSession* session_;
- HandshakerDelegateInterface* delegate_;
-
- // crypto_config_ contains crypto parameters for the handshake.
- const QuicCryptoServerConfig* crypto_config_;
-
- // compressed_certs_cache_ contains a set of most recently compressed certs.
- // Owned by QuicDispatcher.
- QuicCompressedCertsCache* compressed_certs_cache_;
-
- // Server's certificate chain and signature of the server config, as provided
- // by ProofSource::GetProof.
- QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
-
- // Hash of the last received CHLO message which can be used for generating
- // server config update messages.
- std::string chlo_hash_;
-
- // Pointer to the helper for this crypto stream. Must outlive this stream.
- QuicCryptoServerStream::Helper* helper_;
-
- // Number of handshake messages received by this stream.
- uint8_t num_handshake_messages_;
-
- // Number of handshake messages received by this stream that contain
- // server nonces (indicating that this is a non-zero-RTT handshake
- // attempt).
- uint8_t num_handshake_messages_with_server_nonces_;
-
- // Pointer to the active callback that will receive the result of
- // BuildServerConfigUpdateMessage and forward it to
- // FinishSendServerConfigUpdate. nullptr if no update message is currently
- // being built.
- SendServerConfigUpdateCallback* send_server_config_update_cb_;
-
- // Number of server config update (SCUP) messages sent by this stream.
- int num_server_config_update_messages_sent_;
-
- // If the client provides CachedNetworkParameters in the STK in the CHLO, then
- // store here, and send back in future STKs if we have no better bandwidth
- // estimate to send.
- std::unique_ptr<CachedNetworkParameters> previous_cached_network_params_;
-
- // Contains any source address tokens which were present in the CHLO.
- SourceAddressTokens previous_source_address_tokens_;
-
- // True if client attempts 0-rtt handshake (which can succeed or fail).
- bool zero_rtt_attempted_;
-
- // Size of the packet containing the most recently received CHLO.
- QuicByteCount chlo_packet_size_;
-
- // Pointer to the active callback that will receive the result of the client
- // hello validation request and forward it to FinishProcessingHandshakeMessage
- // for processing. nullptr if no handshake message is being validated. Note
- // that this field is mutually exclusive with process_client_hello_cb_.
- ValidateCallback* validate_client_hello_cb_;
-
- // Pointer to the active callback which will receive the results of
- // ProcessClientHello and forward it to
- // FinishProcessingHandshakeMessageAfterProcessClientHello. Note that this
- // field is mutually exclusive with validate_client_hello_cb_.
- ProcessClientHelloCallback* process_client_hello_cb_;
-
- bool encryption_established_;
- bool handshake_confirmed_;
- QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters>
- crypto_negotiated_params_;
-};
-
-} // namespace quic
-
-#endif // QUICHE_QUIC_CORE_QUIC_CRYPTO_SERVER_HANDSHAKER_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.cc
index bbc3b09d5c9..c651351702e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.cc
@@ -6,143 +6,440 @@
#include <memory>
#include <string>
-#include <utility>
-
-#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
-#include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.h"
-#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h"
-#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
-#include "net/third_party/quiche/src/quic/core/proto/cached_network_parameters_proto.h"
-#include "net/third_party/quiche/src/quic/core/quic_config.h"
-#include "net/third_party/quiche/src/quic/core/quic_crypto_server_handshaker.h"
-#include "net/third_party/quiche/src/quic/core/quic_packets.h"
-#include "net/third_party/quiche/src/quic/core/quic_session.h"
-#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+
+#include "third_party/boringssl/src/include/openssl/sha.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
-QuicCryptoServerStreamBase::QuicCryptoServerStreamBase(QuicSession* session)
- : QuicCryptoStream(session) {}
+class QuicCryptoServerStream::ProcessClientHelloCallback
+ : public ProcessClientHelloResultCallback {
+ public:
+ ProcessClientHelloCallback(
+ QuicCryptoServerStream* parent,
+ const QuicReferenceCountedPointer<
+ ValidateClientHelloResultCallback::Result>& result)
+ : parent_(parent), result_(result) {}
+
+ void Run(
+ QuicErrorCode error,
+ const std::string& error_details,
+ std::unique_ptr<CryptoHandshakeMessage> message,
+ std::unique_ptr<DiversificationNonce> diversification_nonce,
+ std::unique_ptr<ProofSource::Details> proof_source_details) override {
+ if (parent_ == nullptr) {
+ return;
+ }
+
+ parent_->FinishProcessingHandshakeMessageAfterProcessClientHello(
+ *result_, error, error_details, std::move(message),
+ std::move(diversification_nonce), std::move(proof_source_details));
+ }
+
+ void Cancel() { parent_ = nullptr; }
+
+ private:
+ QuicCryptoServerStream* parent_;
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
+ result_;
+};
QuicCryptoServerStream::QuicCryptoServerStream(
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache,
QuicSession* session,
- Helper* helper)
+ QuicCryptoServerStreamBase::Helper* helper)
: QuicCryptoServerStreamBase(session),
+ QuicCryptoHandshaker(this, session),
+ session_(session),
+ delegate_(session),
crypto_config_(crypto_config),
compressed_certs_cache_(compressed_certs_cache),
- helper_(helper) {
- DCHECK_EQ(Perspective::IS_SERVER, session->connection()->perspective());
-}
+ signed_config_(new QuicSignedServerConfig),
+ helper_(helper),
+ num_handshake_messages_(0),
+ num_handshake_messages_with_server_nonces_(0),
+ send_server_config_update_cb_(nullptr),
+ num_server_config_update_messages_sent_(0),
+ zero_rtt_attempted_(false),
+ chlo_packet_size_(0),
+ validate_client_hello_cb_(nullptr),
+ process_client_hello_cb_(nullptr),
+ encryption_established_(false),
+ one_rtt_keys_available_(false),
+ one_rtt_packet_decrypted_(false),
+ crypto_negotiated_params_(new QuicCryptoNegotiatedParameters) {}
-QuicCryptoServerStream::~QuicCryptoServerStream() {}
+QuicCryptoServerStream::~QuicCryptoServerStream() {
+ CancelOutstandingCallbacks();
+}
void QuicCryptoServerStream::CancelOutstandingCallbacks() {
- if (handshaker()) {
- handshaker()->CancelOutstandingCallbacks();
+ // Detach from the validation callback. Calling this multiple times is safe.
+ if (validate_client_hello_cb_ != nullptr) {
+ validate_client_hello_cb_->Cancel();
+ validate_client_hello_cb_ = nullptr;
+ }
+ if (send_server_config_update_cb_ != nullptr) {
+ send_server_config_update_cb_->Cancel();
+ send_server_config_update_cb_ = nullptr;
+ }
+ if (process_client_hello_cb_ != nullptr) {
+ process_client_hello_cb_->Cancel();
+ process_client_hello_cb_ = nullptr;
}
}
-bool QuicCryptoServerStream::GetBase64SHA256ClientChannelID(
- std::string* output) const {
- return handshaker()->GetBase64SHA256ClientChannelID(output);
+void QuicCryptoServerStream::OnHandshakeMessage(
+ const CryptoHandshakeMessage& message) {
+ QuicCryptoHandshaker::OnHandshakeMessage(message);
+ ++num_handshake_messages_;
+ chlo_packet_size_ = session()->connection()->GetCurrentPacket().length();
+
+ // Do not process handshake messages after the handshake is confirmed.
+ if (one_rtt_keys_available_) {
+ OnUnrecoverableError(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE,
+ "Unexpected handshake message from client");
+ return;
+ }
+
+ if (message.tag() != kCHLO) {
+ OnUnrecoverableError(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
+ "Handshake packet not CHLO");
+ return;
+ }
+
+ if (validate_client_hello_cb_ != nullptr ||
+ process_client_hello_cb_ != nullptr) {
+ // Already processing some other handshake message. The protocol
+ // does not allow for clients to send multiple handshake messages
+ // before the server has a chance to respond.
+ OnUnrecoverableError(QUIC_CRYPTO_MESSAGE_WHILE_VALIDATING_CLIENT_HELLO,
+ "Unexpected handshake message while processing CHLO");
+ return;
+ }
+
+ chlo_hash_ =
+ CryptoUtils::HashHandshakeMessage(message, Perspective::IS_SERVER);
+
+ std::unique_ptr<ValidateCallback> cb(new ValidateCallback(this));
+ DCHECK(validate_client_hello_cb_ == nullptr);
+ DCHECK(process_client_hello_cb_ == nullptr);
+ validate_client_hello_cb_ = cb.get();
+ crypto_config_->ValidateClientHello(
+ message, GetClientAddress().host(),
+ session()->connection()->self_address(), transport_version(),
+ session()->connection()->clock(), signed_config_, std::move(cb));
+}
+
+void QuicCryptoServerStream::FinishProcessingHandshakeMessage(
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
+ result,
+ std::unique_ptr<ProofSource::Details> details) {
+ // Clear the callback that got us here.
+ DCHECK(validate_client_hello_cb_ != nullptr);
+ DCHECK(process_client_hello_cb_ == nullptr);
+ validate_client_hello_cb_ = nullptr;
+
+ std::unique_ptr<ProcessClientHelloCallback> cb(
+ new ProcessClientHelloCallback(this, result));
+ process_client_hello_cb_ = cb.get();
+ ProcessClientHello(result, std::move(details), std::move(cb));
+}
+
+void QuicCryptoServerStream::
+ FinishProcessingHandshakeMessageAfterProcessClientHello(
+ const ValidateClientHelloResultCallback::Result& result,
+ QuicErrorCode error,
+ const std::string& error_details,
+ std::unique_ptr<CryptoHandshakeMessage> reply,
+ std::unique_ptr<DiversificationNonce> diversification_nonce,
+ std::unique_ptr<ProofSource::Details> /*proof_source_details*/) {
+ // Clear the callback that got us here.
+ DCHECK(process_client_hello_cb_ != nullptr);
+ DCHECK(validate_client_hello_cb_ == nullptr);
+ process_client_hello_cb_ = nullptr;
+
+ const CryptoHandshakeMessage& message = result.client_hello;
+ if (error != QUIC_NO_ERROR) {
+ OnUnrecoverableError(error, error_details);
+ return;
+ }
+
+ if (reply->tag() != kSHLO) {
+ session()->connection()->set_fully_pad_crypto_handshake_packets(
+ crypto_config_->pad_rej());
+ SendHandshakeMessage(*reply);
+ return;
+ }
+
+ // If we are returning a SHLO then we accepted the handshake. Now
+ // process the negotiated configuration options as part of the
+ // session config.
+ QuicConfig* config = session()->config();
+ OverrideQuicConfigDefaults(config);
+ std::string process_error_details;
+ const QuicErrorCode process_error =
+ config->ProcessPeerHello(message, CLIENT, &process_error_details);
+ if (process_error != QUIC_NO_ERROR) {
+ OnUnrecoverableError(process_error, process_error_details);
+ return;
+ }
+
+ session()->OnConfigNegotiated();
+
+ config->ToHandshakeMessage(reply.get(), session()->transport_version());
+
+ // Receiving a full CHLO implies the client is prepared to decrypt with
+ // the new server write key. We can start to encrypt with the new server
+ // write key.
+ //
+ // NOTE: the SHLO will be encrypted with the new server write key.
+ delegate_->OnNewEncryptionKeyAvailable(
+ ENCRYPTION_ZERO_RTT,
+ std::move(crypto_negotiated_params_->initial_crypters.encrypter));
+ delegate_->OnNewDecryptionKeyAvailable(
+ ENCRYPTION_ZERO_RTT,
+ std::move(crypto_negotiated_params_->initial_crypters.decrypter),
+ /*set_alternative_decrypter=*/false,
+ /*latch_once_used=*/false);
+ delegate_->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
+ delegate_->DiscardOldDecryptionKey(ENCRYPTION_INITIAL);
+ session()->connection()->SetDiversificationNonce(*diversification_nonce);
+
+ session()->connection()->set_fully_pad_crypto_handshake_packets(
+ crypto_config_->pad_shlo());
+ SendHandshakeMessage(*reply);
+ delegate_->OnNewEncryptionKeyAvailable(
+ ENCRYPTION_FORWARD_SECURE,
+ std::move(crypto_negotiated_params_->forward_secure_crypters.encrypter));
+ delegate_->OnNewDecryptionKeyAvailable(
+ ENCRYPTION_FORWARD_SECURE,
+ std::move(crypto_negotiated_params_->forward_secure_crypters.decrypter),
+ /*set_alternative_decrypter=*/true,
+ /*latch_once_used=*/false);
+ encryption_established_ = true;
+ one_rtt_keys_available_ = true;
+ delegate_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ delegate_->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
}
void QuicCryptoServerStream::SendServerConfigUpdate(
const CachedNetworkParameters* cached_network_params) {
- handshaker()->SendServerConfigUpdate(cached_network_params);
+ if (!one_rtt_keys_available_) {
+ return;
+ }
+
+ if (send_server_config_update_cb_ != nullptr) {
+ QUIC_DVLOG(1)
+ << "Skipped server config update since one is already in progress";
+ return;
+ }
+
+ std::unique_ptr<SendServerConfigUpdateCallback> cb(
+ new SendServerConfigUpdateCallback(this));
+ send_server_config_update_cb_ = cb.get();
+
+ crypto_config_->BuildServerConfigUpdateMessage(
+ session()->transport_version(), chlo_hash_,
+ previous_source_address_tokens_, session()->connection()->self_address(),
+ GetClientAddress().host(), session()->connection()->clock(),
+ session()->connection()->random_generator(), compressed_certs_cache_,
+ *crypto_negotiated_params_, cached_network_params, std::move(cb));
+}
+
+QuicCryptoServerStream::SendServerConfigUpdateCallback::
+ SendServerConfigUpdateCallback(QuicCryptoServerStream* parent)
+ : parent_(parent) {}
+
+void QuicCryptoServerStream::SendServerConfigUpdateCallback::Cancel() {
+ parent_ = nullptr;
}
-uint8_t QuicCryptoServerStream::NumHandshakeMessages() const {
- return handshaker()->NumHandshakeMessages();
+// From BuildServerConfigUpdateMessageResultCallback
+void QuicCryptoServerStream::SendServerConfigUpdateCallback::Run(
+ bool ok,
+ const CryptoHandshakeMessage& message) {
+ if (parent_ == nullptr) {
+ return;
+ }
+ parent_->FinishSendServerConfigUpdate(ok, message);
}
-uint8_t QuicCryptoServerStream::NumHandshakeMessagesWithServerNonces() const {
- return handshaker()->NumHandshakeMessagesWithServerNonces();
+void QuicCryptoServerStream::FinishSendServerConfigUpdate(
+ bool ok,
+ const CryptoHandshakeMessage& message) {
+ // Clear the callback that got us here.
+ DCHECK(send_server_config_update_cb_ != nullptr);
+ send_server_config_update_cb_ = nullptr;
+
+ if (!ok) {
+ QUIC_DVLOG(1) << "Server: Failed to build server config update (SCUP)!";
+ return;
+ }
+
+ QUIC_DVLOG(1) << "Server: Sending server config update: "
+ << message.DebugString();
+ if (!QuicVersionUsesCryptoFrames(transport_version())) {
+ const QuicData& data = message.GetSerialized();
+ WriteOrBufferData(quiche::QuicheStringPiece(data.data(), data.length()),
+ false, nullptr);
+ } else {
+ SendHandshakeMessage(message);
+ }
+
+ ++num_server_config_update_messages_sent_;
+}
+
+bool QuicCryptoServerStream::IsZeroRtt() const {
+ return num_handshake_messages_ == 1 &&
+ num_handshake_messages_with_server_nonces_ == 0;
}
int QuicCryptoServerStream::NumServerConfigUpdateMessagesSent() const {
- return handshaker()->NumServerConfigUpdateMessagesSent();
+ return num_server_config_update_messages_sent_;
}
const CachedNetworkParameters*
QuicCryptoServerStream::PreviousCachedNetworkParams() const {
- return handshaker()->PreviousCachedNetworkParams();
+ return previous_cached_network_params_.get();
}
bool QuicCryptoServerStream::ZeroRttAttempted() const {
- return handshaker()->ZeroRttAttempted();
+ return zero_rtt_attempted_;
}
void QuicCryptoServerStream::SetPreviousCachedNetworkParams(
CachedNetworkParameters cached_network_params) {
- handshaker()->SetPreviousCachedNetworkParams(cached_network_params);
+ previous_cached_network_params_.reset(
+ new CachedNetworkParameters(cached_network_params));
+}
+
+void QuicCryptoServerStream::OnPacketDecrypted(EncryptionLevel level) {
+ if (level == ENCRYPTION_FORWARD_SECURE) {
+ one_rtt_packet_decrypted_ = true;
+ delegate_->NeuterHandshakeData();
+ }
+}
+
+void QuicCryptoServerStream::OnHandshakeDoneReceived() {
+ DCHECK(false);
}
bool QuicCryptoServerStream::ShouldSendExpectCTHeader() const {
- return handshaker()->ShouldSendExpectCTHeader();
+ return signed_config_->proof.send_expect_ct_header;
}
-bool QuicCryptoServerStream::encryption_established() const {
- if (!handshaker()) {
+bool QuicCryptoServerStream::GetBase64SHA256ClientChannelID(
+ std::string* output) const {
+ if (!encryption_established() ||
+ crypto_negotiated_params_->channel_id.empty()) {
return false;
}
- return handshaker()->encryption_established();
+
+ const std::string& channel_id(crypto_negotiated_params_->channel_id);
+ uint8_t digest[SHA256_DIGEST_LENGTH];
+ SHA256(reinterpret_cast<const uint8_t*>(channel_id.data()), channel_id.size(),
+ digest);
+
+ quiche::QuicheTextUtils::Base64Encode(digest, QUICHE_ARRAYSIZE(digest),
+ output);
+ return true;
}
-bool QuicCryptoServerStream::handshake_confirmed() const {
- if (!handshaker()) {
- return false;
- }
- return handshaker()->handshake_confirmed();
+bool QuicCryptoServerStream::encryption_established() const {
+ return encryption_established_;
+}
+
+bool QuicCryptoServerStream::one_rtt_keys_available() const {
+ return one_rtt_keys_available_;
}
const QuicCryptoNegotiatedParameters&
QuicCryptoServerStream::crypto_negotiated_params() const {
- return handshaker()->crypto_negotiated_params();
+ return *crypto_negotiated_params_;
}
CryptoMessageParser* QuicCryptoServerStream::crypto_message_parser() {
- return handshaker()->crypto_message_parser();
+ return QuicCryptoHandshaker::crypto_message_parser();
}
-void QuicCryptoServerStream::OnPacketDecrypted(EncryptionLevel level) {
- handshaker()->OnPacketDecrypted(level);
+HandshakeState QuicCryptoServerStream::GetHandshakeState() const {
+ return one_rtt_packet_decrypted_ ? HANDSHAKE_COMPLETE : HANDSHAKE_START;
}
size_t QuicCryptoServerStream::BufferSizeLimitForLevel(
EncryptionLevel level) const {
- return handshaker()->BufferSizeLimitForLevel(level);
-}
-
-void QuicCryptoServerStream::OnSuccessfulVersionNegotiation(
- const ParsedQuicVersion& version) {
- DCHECK_EQ(version, session()->connection()->version());
- CHECK(!handshaker_);
- switch (session()->connection()->version().handshake_protocol) {
- case PROTOCOL_QUIC_CRYPTO:
- handshaker_ = std::make_unique<QuicCryptoServerHandshaker>(
- crypto_config_, this, compressed_certs_cache_, session(), helper_);
- break;
- case PROTOCOL_TLS1_3:
- handshaker_ = std::make_unique<TlsServerHandshaker>(
- this, session(), crypto_config_->ssl_ctx(),
- crypto_config_->proof_source());
- break;
- case PROTOCOL_UNSUPPORTED:
- QUIC_BUG << "Attempting to create QuicCryptoServerStream for unknown "
- "handshake protocol";
- }
-}
-
-QuicCryptoServerStream::HandshakerDelegate* QuicCryptoServerStream::handshaker()
- const {
- return handshaker_.get();
+ return QuicCryptoHandshaker::BufferSizeLimitForLevel(level);
+}
+
+void QuicCryptoServerStream::ProcessClientHello(
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
+ result,
+ std::unique_ptr<ProofSource::Details> /*proof_source_details*/,
+ std::unique_ptr<ProcessClientHelloResultCallback> done_cb) {
+ const CryptoHandshakeMessage& message = result->client_hello;
+ std::string error_details;
+ if (!helper_->CanAcceptClientHello(
+ message, GetClientAddress(), session()->connection()->peer_address(),
+ session()->connection()->self_address(), &error_details)) {
+ done_cb->Run(QUIC_HANDSHAKE_FAILED, error_details, nullptr, nullptr,
+ nullptr);
+ return;
+ }
+ if (!result->info.server_nonce.empty()) {
+ ++num_handshake_messages_with_server_nonces_;
+ }
+
+ if (num_handshake_messages_ == 1) {
+ // Client attempts zero RTT handshake by sending a non-inchoate CHLO.
+ quiche::QuicheStringPiece public_value;
+ zero_rtt_attempted_ = message.GetStringPiece(kPUBS, &public_value);
+ }
+
+ // Store the bandwidth estimate from the client.
+ if (result->cached_network_params.bandwidth_estimate_bytes_per_second() > 0) {
+ previous_cached_network_params_.reset(
+ new CachedNetworkParameters(result->cached_network_params));
+ }
+ previous_source_address_tokens_ = result->info.source_address_tokens;
+
+ QuicConnection* connection = session()->connection();
+ crypto_config_->ProcessClientHello(
+ result, /*reject_only=*/false, connection->connection_id(),
+ connection->self_address(), GetClientAddress(), connection->version(),
+ session()->supported_versions(), connection->clock(),
+ connection->random_generator(), compressed_certs_cache_,
+ crypto_negotiated_params_, signed_config_,
+ QuicCryptoStream::CryptoMessageFramingOverhead(
+ transport_version(), connection->connection_id()),
+ chlo_packet_size_, std::move(done_cb));
+}
+
+void QuicCryptoServerStream::OverrideQuicConfigDefaults(
+ QuicConfig* /*config*/) {}
+
+QuicCryptoServerStream::ValidateCallback::ValidateCallback(
+ QuicCryptoServerStream* parent)
+ : parent_(parent) {}
+
+void QuicCryptoServerStream::ValidateCallback::Cancel() {
+ parent_ = nullptr;
+}
+
+void QuicCryptoServerStream::ValidateCallback::Run(
+ QuicReferenceCountedPointer<Result> result,
+ std::unique_ptr<ProofSource::Details> details) {
+ if (parent_ != nullptr) {
+ parent_->FinishProcessingHandshakeMessage(std::move(result),
+ std::move(details));
+ }
+}
+
+const QuicSocketAddress QuicCryptoServerStream::GetClientAddress() {
+ return session()->connection()->peer_address();
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h
index d80c495e413..fd14d27a270 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h
@@ -5,195 +5,237 @@
#ifndef QUICHE_QUIC_CORE_QUIC_CRYPTO_SERVER_STREAM_H_
#define QUICHE_QUIC_CORE_QUIC_CRYPTO_SERVER_STREAM_H_
-#include <cstdint>
-#include <memory>
#include <string>
-#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
-#include "net/third_party/quiche/src/quic/core/crypto/quic_compressed_certs_cache.h"
-#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h"
-#include "net/third_party/quiche/src/quic/core/quic_config.h"
+#include "net/third_party/quiche/src/quic/core/proto/cached_network_parameters_proto.h"
+#include "net/third_party/quiche/src/quic/core/proto/source_address_token_proto.h"
#include "net/third_party/quiche/src/quic/core/quic_crypto_handshaker.h"
-#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
+#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h"
#include "net/third_party/quiche/src/quic/core/quic_session.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
namespace quic {
-class CachedNetworkParameters;
-class CryptoHandshakeMessage;
-class QuicCryptoServerConfig;
-class QuicCryptoServerStreamBase;
-
-// TODO(alyssar) see what can be moved out of QuicCryptoServerStream with
-// various code and test refactoring.
-class QUIC_EXPORT_PRIVATE QuicCryptoServerStreamBase : public QuicCryptoStream {
- public:
- explicit QuicCryptoServerStreamBase(QuicSession* session);
-
- ~QuicCryptoServerStreamBase() override {}
-
- // Cancel any outstanding callbacks, such as asynchronous validation of client
- // hello.
- virtual void CancelOutstandingCallbacks() = 0;
-
- // GetBase64SHA256ClientChannelID sets |*output| to the base64 encoded,
- // SHA-256 hash of the client's ChannelID key and returns true, if the client
- // presented a ChannelID. Otherwise it returns false.
- virtual bool GetBase64SHA256ClientChannelID(std::string* output) const = 0;
-
- virtual int NumServerConfigUpdateMessagesSent() const = 0;
-
- // Sends the latest server config and source-address token to the client.
- virtual void SendServerConfigUpdate(
- const CachedNetworkParameters* cached_network_params) = 0;
-
- // These are all accessors and setters to their respective counters.
- virtual uint8_t NumHandshakeMessages() const = 0;
- virtual uint8_t NumHandshakeMessagesWithServerNonces() const = 0;
- virtual bool ZeroRttAttempted() const = 0;
- virtual const CachedNetworkParameters* PreviousCachedNetworkParams()
- const = 0;
- virtual void SetPreviousCachedNetworkParams(
- CachedNetworkParameters cached_network_params) = 0;
-};
+namespace test {
+class QuicCryptoServerStreamPeer;
+} // namespace test
class QUIC_EXPORT_PRIVATE QuicCryptoServerStream
- : public QuicCryptoServerStreamBase {
+ : public QuicCryptoServerStreamBase,
+ public QuicCryptoHandshaker {
public:
- // QuicCryptoServerStream creates a HandshakerDelegate at construction time
- // based on the QuicTransportVersion of the connection. Different
- // HandshakerDelegates provide implementations of different crypto handshake
- // protocols. Currently QUIC crypto is the only protocol implemented; a future
- // HandshakerDelegate will use TLS as the handshake protocol.
- // QuicCryptoServerStream delegates all of its public methods to its
- // HandshakerDelegate.
- //
- // This setup of the crypto stream delegating its implementation to the
- // handshaker results in the handshaker reading and writing bytes on the
- // crypto stream, instead of the handshake rpassing the stream bytes to send.
- class QUIC_EXPORT_PRIVATE HandshakerDelegate {
- public:
- virtual ~HandshakerDelegate() {}
-
- // Cancel any outstanding callbacks, such as asynchronous validation of
- // client hello.
- virtual void CancelOutstandingCallbacks() = 0;
-
- // GetBase64SHA256ClientChannelID sets |*output| to the base64 encoded,
- // SHA-256 hash of the client's ChannelID key and returns true, if the
- // client presented a ChannelID. Otherwise it returns false.
- virtual bool GetBase64SHA256ClientChannelID(std::string* output) const = 0;
-
- // Sends the latest server config and source-address token to the client.
- virtual void SendServerConfigUpdate(
- const CachedNetworkParameters* cached_network_params) = 0;
-
- // These are all accessors and setters to their respective counters.
- virtual uint8_t NumHandshakeMessages() const = 0;
- virtual uint8_t NumHandshakeMessagesWithServerNonces() const = 0;
- virtual int NumServerConfigUpdateMessagesSent() const = 0;
- virtual const CachedNetworkParameters* PreviousCachedNetworkParams()
- const = 0;
- virtual bool ZeroRttAttempted() const = 0;
- virtual void SetPreviousCachedNetworkParams(
- CachedNetworkParameters cached_network_params) = 0;
- virtual void OnPacketDecrypted(EncryptionLevel level) = 0;
-
- // NOTE: Indicating that the Expect-CT header should be sent here presents a
- // layering violation to some extent. The Expect-CT header only applies to
- // HTTP connections, while this class can be used for non-HTTP applications.
- // However, it is exposed here because that is the only place where the
- // configuration for the certificate used in the connection is accessible.
- virtual bool ShouldSendExpectCTHeader() const = 0;
-
- // Returns true once any encrypter (initial/0RTT or final/1RTT) has been set
- // for the connection.
- virtual bool encryption_established() const = 0;
-
- // Returns true once the crypto handshake has completed.
- virtual bool handshake_confirmed() const = 0;
-
- // Returns the parameters negotiated in the crypto handshake.
- virtual const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
- const = 0;
-
- // Used by QuicCryptoStream to parse data received on this stream.
- virtual CryptoMessageParser* crypto_message_parser() = 0;
-
- // Used by QuicCryptoStream to know how much unprocessed data can be
- // buffered at each encryption level.
- virtual size_t BufferSizeLimitForLevel(EncryptionLevel level) const = 0;
- };
-
- class QUIC_EXPORT_PRIVATE Helper {
- public:
- virtual ~Helper() {}
-
- // Returns true if |message|, which was received on |self_address| is
- // acceptable according to the visitor's policy. Otherwise, returns false
- // and populates |error_details|.
- virtual bool CanAcceptClientHello(const CryptoHandshakeMessage& message,
- const QuicSocketAddress& client_address,
- const QuicSocketAddress& peer_address,
- const QuicSocketAddress& self_address,
- std::string* error_details) const = 0;
- };
-
- // |crypto_config| must outlive the stream.
- // |session| must outlive the stream.
- // |helper| must outlive the stream.
- QuicCryptoServerStream(const QuicCryptoServerConfig* crypto_config,
- QuicCompressedCertsCache* compressed_certs_cache,
- QuicSession* session,
- Helper* helper);
QuicCryptoServerStream(const QuicCryptoServerStream&) = delete;
QuicCryptoServerStream& operator=(const QuicCryptoServerStream&) = delete;
~QuicCryptoServerStream() override;
- // From QuicCryptoServerStreamBase
+ // From HandshakerInterface
void CancelOutstandingCallbacks() override;
bool GetBase64SHA256ClientChannelID(std::string* output) const override;
void SendServerConfigUpdate(
const CachedNetworkParameters* cached_network_params) override;
- uint8_t NumHandshakeMessages() const override;
- uint8_t NumHandshakeMessagesWithServerNonces() const override;
+ bool IsZeroRtt() const override;
int NumServerConfigUpdateMessagesSent() const override;
const CachedNetworkParameters* PreviousCachedNetworkParams() const override;
bool ZeroRttAttempted() const override;
void SetPreviousCachedNetworkParams(
CachedNetworkParameters cached_network_params) override;
+ void OnPacketDecrypted(EncryptionLevel level) override;
+ void OnOneRttPacketAcknowledged() override {}
+ void OnHandshakeDoneReceived() override;
+ bool ShouldSendExpectCTHeader() const override;
- // NOTE: Indicating that the Expect-CT header should be sent here presents
- // a layering violation to some extent. The Expect-CT header only applies to
- // HTTP connections, while this class can be used for non-HTTP applications.
- // However, it is exposed here because that is the only place where the
- // configuration for the certificate used in the connection is accessible.
- bool ShouldSendExpectCTHeader() const;
-
+ // From QuicCryptoStream
bool encryption_established() const override;
- bool handshake_confirmed() const override;
+ bool one_rtt_keys_available() const override;
const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
const override;
CryptoMessageParser* crypto_message_parser() override;
- void OnPacketDecrypted(EncryptionLevel level) override;
+ HandshakeState GetHandshakeState() const override;
size_t BufferSizeLimitForLevel(EncryptionLevel level) const override;
- void OnSuccessfulVersionNegotiation(
- const ParsedQuicVersion& version) override;
+
+ // From QuicCryptoHandshaker
+ void OnHandshakeMessage(const CryptoHandshakeMessage& message) override;
protected:
- // Provided so that subclasses can provide their own handshaker.
- virtual HandshakerDelegate* handshaker() const;
+ QUIC_EXPORT_PRIVATE friend std::unique_ptr<QuicCryptoServerStreamBase>
+ CreateCryptoServerStream(const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache,
+ QuicSession* session,
+ QuicCryptoServerStreamBase::Helper* helper);
+
+ // |crypto_config| must outlive the stream.
+ // |session| must outlive the stream.
+ // |helper| must outlive the stream.
+ QuicCryptoServerStream(const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache,
+ QuicSession* session,
+ QuicCryptoServerStreamBase::Helper* helper);
+
+ virtual void ProcessClientHello(
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
+ result,
+ std::unique_ptr<ProofSource::Details> proof_source_details,
+ std::unique_ptr<ProcessClientHelloResultCallback> done_cb);
+
+ // Hook that allows the server to set QuicConfig defaults just
+ // before going through the parameter negotiation step.
+ virtual void OverrideQuicConfigDefaults(QuicConfig* config);
+
+ // Returns client address used to generate and validate source address token.
+ virtual const QuicSocketAddress GetClientAddress();
+
+ // Returns the QuicSession that this stream belongs to.
+ QuicSession* session() const { return session_; }
+
+ void set_encryption_established(bool encryption_established) {
+ encryption_established_ = encryption_established;
+ }
+
+ void set_one_rtt_keys_available(bool one_rtt_keys_available) {
+ one_rtt_keys_available_ = one_rtt_keys_available;
+ }
private:
- std::unique_ptr<HandshakerDelegate> handshaker_;
+ friend class test::QuicCryptoServerStreamPeer;
+
+ class QUIC_EXPORT_PRIVATE ValidateCallback
+ : public ValidateClientHelloResultCallback {
+ public:
+ explicit ValidateCallback(QuicCryptoServerStream* parent);
+ ValidateCallback(const ValidateCallback&) = delete;
+ ValidateCallback& operator=(const ValidateCallback&) = delete;
+ // To allow the parent to detach itself from the callback before deletion.
+ void Cancel();
+
+ // From ValidateClientHelloResultCallback
+ void Run(QuicReferenceCountedPointer<Result> result,
+ std::unique_ptr<ProofSource::Details> details) override;
+
+ private:
+ QuicCryptoServerStream* parent_;
+ };
+
+ class SendServerConfigUpdateCallback
+ : public BuildServerConfigUpdateMessageResultCallback {
+ public:
+ explicit SendServerConfigUpdateCallback(QuicCryptoServerStream* parent);
+ SendServerConfigUpdateCallback(const SendServerConfigUpdateCallback&) =
+ delete;
+ void operator=(const SendServerConfigUpdateCallback&) = delete;
- // Arguments from QuicCryptoServerStream constructor that might need to be
- // passed to the HandshakerDelegate constructor in its late construction.
+ // To allow the parent to detach itself from the callback before deletion.
+ void Cancel();
+
+ // From BuildServerConfigUpdateMessageResultCallback
+ void Run(bool ok, const CryptoHandshakeMessage& message) override;
+
+ private:
+ QuicCryptoServerStream* parent_;
+ };
+
+ // Invoked by ValidateCallback::RunImpl once initial validation of
+ // the client hello is complete. Finishes processing of the client
+ // hello message and handles handshake success/failure.
+ void FinishProcessingHandshakeMessage(
+ QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
+ result,
+ std::unique_ptr<ProofSource::Details> details);
+
+ class ProcessClientHelloCallback;
+ friend class ProcessClientHelloCallback;
+
+ // Portion of FinishProcessingHandshakeMessage which executes after
+ // ProcessClientHello has been called.
+ void FinishProcessingHandshakeMessageAfterProcessClientHello(
+ const ValidateClientHelloResultCallback::Result& result,
+ QuicErrorCode error,
+ const std::string& error_details,
+ std::unique_ptr<CryptoHandshakeMessage> reply,
+ std::unique_ptr<DiversificationNonce> diversification_nonce,
+ std::unique_ptr<ProofSource::Details> proof_source_details);
+
+ // Invoked by SendServerConfigUpdateCallback::RunImpl once the proof has been
+ // received. |ok| indicates whether or not the proof was successfully
+ // acquired, and |message| holds the partially-constructed message from
+ // SendServerConfigUpdate.
+ void FinishSendServerConfigUpdate(bool ok,
+ const CryptoHandshakeMessage& message);
+
+ // Returns the QuicTransportVersion of the connection.
+ QuicTransportVersion transport_version() const {
+ return session_->transport_version();
+ }
+
+ QuicSession* session_;
+ HandshakerDelegateInterface* delegate_;
+
+ // crypto_config_ contains crypto parameters for the handshake.
const QuicCryptoServerConfig* crypto_config_;
+
+ // compressed_certs_cache_ contains a set of most recently compressed certs.
+ // Owned by QuicDispatcher.
QuicCompressedCertsCache* compressed_certs_cache_;
- Helper* helper_;
+
+ // Server's certificate chain and signature of the server config, as provided
+ // by ProofSource::GetProof.
+ QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
+
+ // Hash of the last received CHLO message which can be used for generating
+ // server config update messages.
+ std::string chlo_hash_;
+
+ // Pointer to the helper for this crypto stream. Must outlive this stream.
+ QuicCryptoServerStreamBase::Helper* helper_;
+
+ // Number of handshake messages received by this stream.
+ uint8_t num_handshake_messages_;
+
+ // Number of handshake messages received by this stream that contain
+ // server nonces (indicating that this is a non-zero-RTT handshake
+ // attempt).
+ uint8_t num_handshake_messages_with_server_nonces_;
+
+ // Pointer to the active callback that will receive the result of
+ // BuildServerConfigUpdateMessage and forward it to
+ // FinishSendServerConfigUpdate. nullptr if no update message is currently
+ // being built.
+ SendServerConfigUpdateCallback* send_server_config_update_cb_;
+
+ // Number of server config update (SCUP) messages sent by this stream.
+ int num_server_config_update_messages_sent_;
+
+ // If the client provides CachedNetworkParameters in the STK in the CHLO, then
+ // store here, and send back in future STKs if we have no better bandwidth
+ // estimate to send.
+ std::unique_ptr<CachedNetworkParameters> previous_cached_network_params_;
+
+ // Contains any source address tokens which were present in the CHLO.
+ SourceAddressTokens previous_source_address_tokens_;
+
+ // True if client attempts 0-rtt handshake (which can succeed or fail).
+ bool zero_rtt_attempted_;
+
+ // Size of the packet containing the most recently received CHLO.
+ QuicByteCount chlo_packet_size_;
+
+ // Pointer to the active callback that will receive the result of the client
+ // hello validation request and forward it to FinishProcessingHandshakeMessage
+ // for processing. nullptr if no handshake message is being validated. Note
+ // that this field is mutually exclusive with process_client_hello_cb_.
+ ValidateCallback* validate_client_hello_cb_;
+
+ // Pointer to the active callback which will receive the results of
+ // ProcessClientHello and forward it to
+ // FinishProcessingHandshakeMessageAfterProcessClientHello. Note that this
+ // field is mutually exclusive with validate_client_hello_cb_.
+ ProcessClientHelloCallback* process_client_hello_cb_;
+
+ bool encryption_established_;
+ bool one_rtt_keys_available_;
+ bool one_rtt_packet_decrypted_;
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters>
+ crypto_negotiated_params_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.cc
new file mode 100644
index 00000000000..0a77ca7aee9
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.cc
@@ -0,0 +1,51 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
+#include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.h"
+#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h"
+#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
+#include "net/third_party/quiche/src/quic/core/proto/cached_network_parameters_proto.h"
+#include "net/third_party/quiche/src/quic/core/quic_config.h"
+#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
+#include "net/third_party/quiche/src/quic/core/quic_packets.h"
+#include "net/third_party/quiche/src/quic/core/quic_session.h"
+#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+
+namespace quic {
+
+QuicCryptoServerStreamBase::QuicCryptoServerStreamBase(QuicSession* session)
+ : QuicCryptoStream(session) {}
+
+std::unique_ptr<QuicCryptoServerStreamBase> CreateCryptoServerStream(
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache,
+ QuicSession* session,
+ QuicCryptoServerStreamBase::Helper* helper) {
+ switch (session->connection()->version().handshake_protocol) {
+ case PROTOCOL_QUIC_CRYPTO:
+ return std::unique_ptr<QuicCryptoServerStream>(new QuicCryptoServerStream(
+ crypto_config, compressed_certs_cache, session, helper));
+ case PROTOCOL_TLS1_3:
+ return std::unique_ptr<TlsServerHandshaker>(new TlsServerHandshaker(
+ session, crypto_config->ssl_ctx(), crypto_config->proof_source()));
+ case PROTOCOL_UNSUPPORTED:
+ break;
+ }
+ QUIC_BUG << "Unknown handshake protocol: "
+ << static_cast<int>(
+ session->connection()->version().handshake_protocol);
+ return nullptr;
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h
new file mode 100644
index 00000000000..cdf12a3143d
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h
@@ -0,0 +1,92 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_CORE_QUIC_CRYPTO_SERVER_STREAM_BASE_H_
+#define QUICHE_QUIC_CORE_QUIC_CRYPTO_SERVER_STREAM_BASE_H_
+
+#include <cstdint>
+#include <memory>
+#include <string>
+
+#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
+#include "net/third_party/quiche/src/quic/core/crypto/quic_compressed_certs_cache.h"
+#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h"
+#include "net/third_party/quiche/src/quic/core/quic_config.h"
+#include "net/third_party/quiche/src/quic/core/quic_crypto_handshaker.h"
+#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
+#include "net/third_party/quiche/src/quic/core/quic_session.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+
+namespace quic {
+
+class CachedNetworkParameters;
+class CryptoHandshakeMessage;
+class QuicCryptoServerConfig;
+class QuicCryptoServerStreamBase;
+
+// TODO(alyssar) see what can be moved out of QuicCryptoServerStream with
+// various code and test refactoring.
+class QUIC_EXPORT_PRIVATE QuicCryptoServerStreamBase : public QuicCryptoStream {
+ public:
+ explicit QuicCryptoServerStreamBase(QuicSession* session);
+
+ class QUIC_EXPORT_PRIVATE Helper {
+ public:
+ virtual ~Helper() {}
+
+ // Returns true if |message|, which was received on |self_address| is
+ // acceptable according to the visitor's policy. Otherwise, returns false
+ // and populates |error_details|.
+ virtual bool CanAcceptClientHello(const CryptoHandshakeMessage& message,
+ const QuicSocketAddress& client_address,
+ const QuicSocketAddress& peer_address,
+ const QuicSocketAddress& self_address,
+ std::string* error_details) const = 0;
+ };
+
+ ~QuicCryptoServerStreamBase() override {}
+
+ // Cancel any outstanding callbacks, such as asynchronous validation of client
+ // hello.
+ virtual void CancelOutstandingCallbacks() = 0;
+
+ // GetBase64SHA256ClientChannelID sets |*output| to the base64 encoded,
+ // SHA-256 hash of the client's ChannelID key and returns true, if the client
+ // presented a ChannelID. Otherwise it returns false.
+ virtual bool GetBase64SHA256ClientChannelID(std::string* output) const = 0;
+
+ virtual int NumServerConfigUpdateMessagesSent() const = 0;
+
+ // Sends the latest server config and source-address token to the client.
+ virtual void SendServerConfigUpdate(
+ const CachedNetworkParameters* cached_network_params) = 0;
+
+ virtual bool IsZeroRtt() const = 0;
+ virtual bool ZeroRttAttempted() const = 0;
+ virtual const CachedNetworkParameters* PreviousCachedNetworkParams()
+ const = 0;
+ virtual void SetPreviousCachedNetworkParams(
+ CachedNetworkParameters cached_network_params) = 0;
+
+ // NOTE: Indicating that the Expect-CT header should be sent here presents
+ // a layering violation to some extent. The Expect-CT header only applies to
+ // HTTP connections, while this class can be used for non-HTTP applications.
+ // However, it is exposed here because that is the only place where the
+ // configuration for the certificate used in the connection is accessible.
+ virtual bool ShouldSendExpectCTHeader() const = 0;
+};
+
+// Creates an appropriate QuicCryptoServerStream for the provided parameters,
+// including the version used by |session|. |crypto_config|, |session|, and
+// |helper| must all outlive the stream. The caller takes ownership of the
+// returned object.
+QUIC_EXPORT_PRIVATE std::unique_ptr<QuicCryptoServerStreamBase>
+CreateCryptoServerStream(const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache,
+ QuicSession* session,
+ QuicCryptoServerStreamBase::Helper* helper);
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_QUIC_CRYPTO_SERVER_STREAM_BASE_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream_test.cc
index 2f7055da328..60882b861e2 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream_test.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
+#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h"
#include <map>
#include <memory>
@@ -32,6 +32,7 @@
#include "net/third_party/quiche/src/quic/test_tools/fake_proof_source.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_crypto_server_config_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
class QuicConnection;
@@ -92,21 +93,18 @@ class QuicCryptoServerStreamTest : public QuicTestWithParam<bool> {
EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _))
.Times(testing::AnyNumber());
EXPECT_CALL(*server_session_, SelectAlpn(_))
- .WillRepeatedly([this](const std::vector<QuicStringPiece>& alpns) {
- return std::find(
- alpns.cbegin(), alpns.cend(),
- AlpnForVersion(server_session_->connection()->version()));
- });
+ .WillRepeatedly(
+ [this](const std::vector<quiche::QuicheStringPiece>& alpns) {
+ return std::find(
+ alpns.cbegin(), alpns.cend(),
+ AlpnForVersion(server_session_->connection()->version()));
+ });
crypto_test_utils::SetupCryptoServerConfigForTest(
server_connection_->clock(), server_connection_->random_generator(),
&server_crypto_config_);
- if (!GetQuicReloadableFlag(quic_version_negotiated_by_default_at_server)) {
- server_session_->GetMutableCryptoStream()->OnSuccessfulVersionNegotiation(
- supported_versions_.front());
- }
}
- QuicCryptoServerStream* server_stream() {
+ QuicCryptoServerStreamBase* server_stream() {
return server_session_->GetMutableCryptoStream();
}
@@ -154,6 +152,28 @@ class QuicCryptoServerStreamTest : public QuicTestWithParam<bool> {
server_connection_, server_stream(), 0);
}
+ void UseTlsHandshake() {
+ client_options_.only_tls_versions = true;
+ supported_versions_.clear();
+ for (ParsedQuicVersion version : AllSupportedVersions()) {
+ if (version.handshake_protocol != PROTOCOL_TLS1_3) {
+ continue;
+ }
+ supported_versions_.push_back(version);
+ }
+ }
+
+ void UseQuicCryptoHandshake() {
+ client_options_.only_quic_crypto_versions = true;
+ supported_versions_.clear();
+ for (ParsedQuicVersion version : AllSupportedVersions()) {
+ if (version.handshake_protocol != PROTOCOL_QUIC_CRYPTO) {
+ continue;
+ }
+ supported_versions_.push_back(version);
+ }
+ }
+
protected:
// Every connection gets its own MockQuicConnectionHelper and
// MockAlarmFactory, tracked separately from the server and client state so
@@ -188,7 +208,7 @@ INSTANTIATE_TEST_SUITE_P(Tests,
TEST_P(QuicCryptoServerStreamTest, NotInitiallyConected) {
Initialize();
EXPECT_FALSE(server_stream()->encryption_established());
- EXPECT_FALSE(server_stream()->handshake_confirmed());
+ EXPECT_FALSE(server_stream()->one_rtt_keys_available());
}
TEST_P(QuicCryptoServerStreamTest, ConnectedAfterCHLO) {
@@ -196,29 +216,24 @@ TEST_P(QuicCryptoServerStreamTest, ConnectedAfterCHLO) {
// test should send:
// * One to get a source-address token and certificates.
// * One to complete the handshake.
+ UseQuicCryptoHandshake();
Initialize();
EXPECT_EQ(2, CompleteCryptoHandshake());
EXPECT_TRUE(server_stream()->encryption_established());
- EXPECT_TRUE(server_stream()->handshake_confirmed());
+ EXPECT_TRUE(server_stream()->one_rtt_keys_available());
}
TEST_P(QuicCryptoServerStreamTest, ConnectedAfterTlsHandshake) {
- SetQuicReloadableFlag(quic_supports_tls_handshake, true);
- client_options_.only_tls_versions = true;
- supported_versions_.clear();
- for (QuicTransportVersion transport_version :
- AllSupportedTransportVersions()) {
- supported_versions_.push_back(
- ParsedQuicVersion(PROTOCOL_TLS1_3, transport_version));
- }
+ UseTlsHandshake();
Initialize();
CompleteCryptoHandshake();
EXPECT_EQ(PROTOCOL_TLS1_3, server_stream()->handshake_protocol());
EXPECT_TRUE(server_stream()->encryption_established());
- EXPECT_TRUE(server_stream()->handshake_confirmed());
+ EXPECT_TRUE(server_stream()->one_rtt_keys_available());
}
TEST_P(QuicCryptoServerStreamTest, ForwardSecureAfterCHLO) {
+ UseQuicCryptoHandshake();
Initialize();
InitializeFakeClient();
@@ -226,7 +241,7 @@ TEST_P(QuicCryptoServerStreamTest, ForwardSecureAfterCHLO) {
// information.
AdvanceHandshakeWithFakeClient();
EXPECT_FALSE(server_stream()->encryption_established());
- EXPECT_FALSE(server_stream()->handshake_confirmed());
+ EXPECT_FALSE(server_stream()->one_rtt_keys_available());
// Now do another handshake, with the blocking SHLO connection option.
InitializeServer();
@@ -234,12 +249,13 @@ TEST_P(QuicCryptoServerStreamTest, ForwardSecureAfterCHLO) {
AdvanceHandshakeWithFakeClient();
EXPECT_TRUE(server_stream()->encryption_established());
- EXPECT_TRUE(server_stream()->handshake_confirmed());
+ EXPECT_TRUE(server_stream()->one_rtt_keys_available());
EXPECT_EQ(ENCRYPTION_FORWARD_SECURE,
server_session_->connection()->encryption_level());
}
TEST_P(QuicCryptoServerStreamTest, ZeroRTT) {
+ UseQuicCryptoHandshake();
Initialize();
InitializeFakeClient();
@@ -271,6 +287,7 @@ TEST_P(QuicCryptoServerStreamTest, ZeroRTT) {
}
TEST_P(QuicCryptoServerStreamTest, FailByPolicy) {
+ UseQuicCryptoHandshake();
Initialize();
InitializeFakeClient();
@@ -283,6 +300,7 @@ TEST_P(QuicCryptoServerStreamTest, FailByPolicy) {
}
TEST_P(QuicCryptoServerStreamTest, MessageAfterHandshake) {
+ UseQuicCryptoHandshake();
Initialize();
CompleteCryptoHandshake();
EXPECT_CALL(
@@ -294,6 +312,7 @@ TEST_P(QuicCryptoServerStreamTest, MessageAfterHandshake) {
}
TEST_P(QuicCryptoServerStreamTest, BadMessageType) {
+ UseQuicCryptoHandshake();
Initialize();
message_.set_tag(kSHLO);
@@ -312,6 +331,7 @@ TEST_P(QuicCryptoServerStreamTest, OnlySendSCUPAfterHandshakeComplete) {
}
TEST_P(QuicCryptoServerStreamTest, SendSCUPAfterHandshakeComplete) {
+ UseQuicCryptoHandshake();
Initialize();
InitializeFakeClient();
@@ -349,6 +369,7 @@ INSTANTIATE_TEST_SUITE_P(MoreTests,
::testing::PrintToStringParamName());
TEST_P(QuicCryptoServerStreamTestWithFailingProofSource, Test) {
+ UseQuicCryptoHandshake();
Initialize();
InitializeFakeClient();
@@ -359,7 +380,7 @@ TEST_P(QuicCryptoServerStreamTestWithFailingProofSource, Test) {
// Regression test for b/31521252, in which a crash would happen here.
AdvanceHandshakeWithFakeClient();
EXPECT_FALSE(server_stream()->encryption_established());
- EXPECT_FALSE(server_stream()->handshake_confirmed());
+ EXPECT_FALSE(server_stream()->one_rtt_keys_available());
}
class QuicCryptoServerStreamTestWithFakeProofSource
@@ -387,16 +408,27 @@ INSTANTIATE_TEST_SUITE_P(YetMoreTests,
// connection in close succession could cause a crash, especially when the use
// of Mentat signing meant that it took a while for each CHLO to be processed.
TEST_P(QuicCryptoServerStreamTestWithFakeProofSource, MultipleChlo) {
+ UseQuicCryptoHandshake();
Initialize();
GetFakeProofSource()->Activate();
EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _))
.WillOnce(testing::Return(true));
+ // The methods below use a PROTOCOL_QUIC_CRYPTO version so we pick the
+ // first one from the list of supported versions.
+ QuicTransportVersion transport_version = QUIC_VERSION_UNSUPPORTED;
+ for (const ParsedQuicVersion& version : AllSupportedVersions()) {
+ if (version.handshake_protocol == PROTOCOL_QUIC_CRYPTO) {
+ transport_version = version.transport_version;
+ break;
+ }
+ }
+ ASSERT_NE(QUIC_VERSION_UNSUPPORTED, transport_version);
+
// Create a minimal CHLO
MockClock clock;
- QuicTransportVersion version = AllSupportedTransportVersions().front();
CryptoHandshakeMessage chlo = crypto_test_utils::GenerateDefaultInchoateCHLO(
- &clock, version, &server_crypto_config_);
+ &clock, transport_version, &server_crypto_config_);
// Send in the CHLO, and check that a callback is now pending in the
// ProofSource.
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.cc
index e22e830d381..094613c7395 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.cc
@@ -10,11 +10,13 @@
#include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
#include "net/third_party/quiche/src/quic/core/quic_session.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_optional.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -33,10 +35,11 @@ QuicCryptoStream::QuicCryptoStream(QuicSession* session)
QuicVersionUsesCryptoFrames(session->transport_version())
? CRYPTO
: BIDIRECTIONAL),
- substreams_{{this, ENCRYPTION_INITIAL},
- {this, ENCRYPTION_HANDSHAKE},
- {this, ENCRYPTION_ZERO_RTT},
- {this, ENCRYPTION_FORWARD_SECURE}} {
+ substreams_{{{this, ENCRYPTION_INITIAL},
+ {this, ENCRYPTION_HANDSHAKE},
+ {this, ENCRYPTION_ZERO_RTT},
+ {this, ENCRYPTION_FORWARD_SECURE}}},
+ writevdata_at_level_(GetQuicReloadableFlag(quic_writevdata_at_level)) {
// The crypto stream is exempt from connection level flow control.
DisableConnectionFlowControlForThisStream();
}
@@ -72,17 +75,11 @@ void QuicCryptoStream::OnCryptoFrame(const QuicCryptoFrame& frame) {
<< "Versions less than 47 shouldn't receive CRYPTO frames";
EncryptionLevel level = session()->connection()->last_decrypted_level();
substreams_[level].sequencer.OnCryptoFrame(frame);
- EncryptionLevel frame_level;
- if (GetQuicReloadableFlag(quic_use_connection_encryption_level)) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_use_connection_encryption_level);
- frame_level = level;
- } else {
- frame_level = frame.level;
- }
+ EncryptionLevel frame_level = level;
if (substreams_[level].sequencer.NumBytesBuffered() >
BufferSizeLimitForLevel(frame_level)) {
- CloseConnectionWithDetails(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA,
- "Too much crypto data received");
+ OnUnrecoverableError(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA,
+ "Too much crypto data received");
}
}
@@ -90,8 +87,7 @@ void QuicCryptoStream::OnStreamFrame(const QuicStreamFrame& frame) {
if (QuicVersionUsesCryptoFrames(session()->transport_version())) {
QUIC_PEER_BUG
<< "Crypto data received in stream frame instead of crypto frame";
- CloseConnectionWithDetails(QUIC_INVALID_STREAM_DATA,
- "Unexpected stream frame");
+ OnUnrecoverableError(QUIC_INVALID_STREAM_DATA, "Unexpected stream frame");
}
QuicStream::OnStreamFrame(frame);
}
@@ -113,14 +109,15 @@ void QuicCryptoStream::OnDataAvailableInSequencer(
EncryptionLevel level) {
struct iovec iov;
while (sequencer->GetReadableRegion(&iov)) {
- QuicStringPiece data(static_cast<char*>(iov.iov_base), iov.iov_len);
+ quiche::QuicheStringPiece data(static_cast<char*>(iov.iov_base),
+ iov.iov_len);
if (!crypto_message_parser()->ProcessInput(data, level)) {
- CloseConnectionWithDetails(crypto_message_parser()->error(),
- crypto_message_parser()->error_detail());
+ OnUnrecoverableError(crypto_message_parser()->error(),
+ crypto_message_parser()->error_detail());
return;
}
sequencer->MarkConsumed(iov.iov_len);
- if (handshake_confirmed() &&
+ if (one_rtt_keys_available() &&
crypto_message_parser()->InputBytesRemaining() == 0) {
// If the handshake is complete and the current message has been fully
// processed then no more handshake messages are likely to arrive soon
@@ -130,11 +127,11 @@ void QuicCryptoStream::OnDataAvailableInSequencer(
}
}
-bool QuicCryptoStream::ExportKeyingMaterial(QuicStringPiece label,
- QuicStringPiece context,
+bool QuicCryptoStream::ExportKeyingMaterial(quiche::QuicheStringPiece label,
+ quiche::QuicheStringPiece context,
size_t result_len,
std::string* result) const {
- if (!handshake_confirmed()) {
+ if (!one_rtt_keys_available()) {
QUIC_DLOG(ERROR) << "ExportKeyingMaterial was called before forward-secure"
<< "encryption was established.";
return false;
@@ -145,7 +142,7 @@ bool QuicCryptoStream::ExportKeyingMaterial(QuicStringPiece label,
}
void QuicCryptoStream::WriteCryptoData(EncryptionLevel level,
- QuicStringPiece data) {
+ quiche::QuicheStringPiece data) {
if (!QuicVersionUsesCryptoFrames(session()->transport_version())) {
// The QUIC crypto handshake takes care of setting the appropriate
// encryption level before writing data. Since that is the only handshake
@@ -168,19 +165,16 @@ void QuicCryptoStream::WriteCryptoData(EncryptionLevel level,
QUIC_BUG << "Writing too much crypto handshake data";
// TODO(nharper): Switch this to an IETF QUIC error code, possibly
// INTERNAL_ERROR?
- CloseConnectionWithDetails(QUIC_STREAM_LENGTH_OVERFLOW,
- "Writing too much crypto handshake data");
+ OnUnrecoverableError(QUIC_STREAM_LENGTH_OVERFLOW,
+ "Writing too much crypto handshake data");
}
if (had_buffered_data) {
// Do not try to write if there is buffered data.
return;
}
- EncryptionLevel current_level = session()->connection()->encryption_level();
- session()->connection()->SetDefaultEncryptionLevel(level);
- size_t bytes_consumed =
- session()->connection()->SendCryptoData(level, data.length(), offset);
- session()->connection()->SetDefaultEncryptionLevel(current_level);
+ size_t bytes_consumed = stream_delegate()->SendCryptoData(
+ level, data.length(), offset, NOT_RETRANSMISSION);
send_buffer->OnStreamDataConsumed(bytes_consumed);
}
@@ -188,21 +182,23 @@ size_t QuicCryptoStream::BufferSizeLimitForLevel(EncryptionLevel) const {
return GetQuicFlag(FLAGS_quic_max_buffered_crypto_bytes);
}
-void QuicCryptoStream::OnSuccessfulVersionNegotiation(
- const ParsedQuicVersion& /*version*/) {}
-
bool QuicCryptoStream::OnCryptoFrameAcked(const QuicCryptoFrame& frame,
QuicTime::Delta /*ack_delay_time*/) {
QuicByteCount newly_acked_length = 0;
if (!substreams_[frame.level].send_buffer.OnStreamDataAcked(
frame.offset, frame.data_length, &newly_acked_length)) {
- CloseConnectionWithDetails(QUIC_INTERNAL_ERROR,
- "Trying to ack unsent crypto data.");
+ OnUnrecoverableError(QUIC_INTERNAL_ERROR,
+ "Trying to ack unsent crypto data.");
return false;
}
return newly_acked_length > 0;
}
+void QuicCryptoStream::OnStreamReset(const QuicRstStreamFrame& /*frame*/) {
+ stream_delegate()->OnStreamError(QUIC_INVALID_STREAM_ID,
+ "Attempt to reset crypto stream");
+}
+
void QuicCryptoStream::NeuterUnencryptedStreamData() {
if (!QuicVersionUsesCryptoFrames(session()->transport_version())) {
for (const auto& interval : bytes_consumed_[ENCRYPTION_INITIAL]) {
@@ -252,23 +248,19 @@ bool QuicCryptoStream::HasPendingCryptoRetransmission() const {
void QuicCryptoStream::WritePendingCryptoRetransmission() {
QUIC_BUG_IF(!QuicVersionUsesCryptoFrames(session()->transport_version()))
<< "Versions less than 47 don't write CRYPTO frames";
- EncryptionLevel current_encryption_level =
- session()->connection()->encryption_level();
for (EncryptionLevel level :
{ENCRYPTION_INITIAL, ENCRYPTION_ZERO_RTT, ENCRYPTION_FORWARD_SECURE}) {
QuicStreamSendBuffer* send_buffer = &substreams_[level].send_buffer;
- session()->connection()->SetDefaultEncryptionLevel(level);
while (send_buffer->HasPendingRetransmission()) {
auto pending = send_buffer->NextPendingRetransmission();
- size_t bytes_consumed = session()->connection()->SendCryptoData(
- level, pending.length, pending.offset);
+ size_t bytes_consumed = stream_delegate()->SendCryptoData(
+ level, pending.length, pending.offset, HANDSHAKE_RETRANSMISSION);
send_buffer->OnStreamDataRetransmitted(pending.offset, bytes_consumed);
if (bytes_consumed < pending.length) {
break;
}
}
}
- session()->connection()->SetDefaultEncryptionLevel(current_encryption_level);
}
void QuicCryptoStream::WritePendingRetransmission() {
@@ -291,24 +283,33 @@ void QuicCryptoStream::WritePendingRetransmission() {
pending.offset = retransmission.begin()->min();
pending.length =
retransmission.begin()->max() - retransmission.begin()->min();
- EncryptionLevel current_encryption_level =
- session()->connection()->encryption_level();
- // Set appropriate encryption level.
- session()->connection()->SetDefaultEncryptionLevel(
- retransmission_encryption_level);
- QuicConsumedData consumed = session()->WritevData(
- this, id(), pending.length, pending.offset, NO_FIN);
- QUIC_DVLOG(1) << ENDPOINT << "stream " << id()
- << " tries to retransmit stream data [" << pending.offset
- << ", " << pending.offset + pending.length
- << ") with encryption level: "
- << retransmission_encryption_level
- << ", consumed: " << consumed;
- OnStreamFrameRetransmitted(pending.offset, consumed.bytes_consumed,
- consumed.fin_consumed);
- // Restore encryption level.
- session()->connection()->SetDefaultEncryptionLevel(
- current_encryption_level);
+ QuicConsumedData consumed(0, false);
+ if (!writevdata_at_level_) {
+ EncryptionLevel current_encryption_level =
+ session()->connection()->encryption_level();
+ // Set appropriate encryption level.
+ session()->connection()->SetDefaultEncryptionLevel(
+ retransmission_encryption_level);
+ consumed = stream_delegate()->WritevData(
+ id(), pending.length, pending.offset, NO_FIN,
+ HANDSHAKE_RETRANSMISSION, QuicheNullOpt);
+ QUIC_DVLOG(1) << ENDPOINT << "stream " << id()
+ << " tries to retransmit stream data [" << pending.offset
+ << ", " << pending.offset + pending.length
+ << ") with encryption level: "
+ << retransmission_encryption_level
+ << ", consumed: " << consumed;
+ OnStreamFrameRetransmitted(pending.offset, consumed.bytes_consumed,
+ consumed.fin_consumed);
+ // Restore encryption level.
+ session()->connection()->SetDefaultEncryptionLevel(
+ current_encryption_level);
+ } else {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_writevdata_at_level, 1, 2);
+ consumed = RetransmitStreamDataAtLevel(pending.offset, pending.length,
+ retransmission_encryption_level,
+ HANDSHAKE_RETRANSMISSION);
+ }
if (consumed.bytes_consumed < pending.length) {
// The connection is write blocked.
break;
@@ -318,7 +319,9 @@ void QuicCryptoStream::WritePendingRetransmission() {
bool QuicCryptoStream::RetransmitStreamData(QuicStreamOffset offset,
QuicByteCount data_length,
- bool /*fin*/) {
+ bool /*fin*/,
+ TransmissionType type) {
+ DCHECK_EQ(HANDSHAKE_RETRANSMISSION, type);
QuicIntervalSet<QuicStreamOffset> retransmission(offset,
offset + data_length);
// Determine the encryption level to send data. This only needs to be once as
@@ -336,21 +339,30 @@ bool QuicCryptoStream::RetransmitStreamData(QuicStreamOffset offset,
for (const auto& interval : retransmission) {
QuicStreamOffset retransmission_offset = interval.min();
QuicByteCount retransmission_length = interval.max() - interval.min();
- // Set appropriate encryption level.
- session()->connection()->SetDefaultEncryptionLevel(send_encryption_level);
- QuicConsumedData consumed = session()->WritevData(
- this, id(), retransmission_length, retransmission_offset, NO_FIN);
- QUIC_DVLOG(1) << ENDPOINT << "stream " << id()
- << " is forced to retransmit stream data ["
- << retransmission_offset << ", "
- << retransmission_offset + retransmission_length
- << "), with encryption level: " << send_encryption_level
- << ", consumed: " << consumed;
- OnStreamFrameRetransmitted(retransmission_offset, consumed.bytes_consumed,
- consumed.fin_consumed);
- // Restore encryption level.
- session()->connection()->SetDefaultEncryptionLevel(
- current_encryption_level);
+ QuicConsumedData consumed(0, false);
+ if (!writevdata_at_level_) {
+ // Set appropriate encryption level.
+ session()->connection()->SetDefaultEncryptionLevel(send_encryption_level);
+ consumed = stream_delegate()->WritevData(id(), retransmission_length,
+ retransmission_offset, NO_FIN,
+ type, QuicheNullOpt);
+ QUIC_DVLOG(1) << ENDPOINT << "stream " << id()
+ << " is forced to retransmit stream data ["
+ << retransmission_offset << ", "
+ << retransmission_offset + retransmission_length
+ << "), with encryption level: " << send_encryption_level
+ << ", consumed: " << consumed;
+ OnStreamFrameRetransmitted(retransmission_offset, consumed.bytes_consumed,
+ consumed.fin_consumed);
+ // Restore encryption level.
+ session()->connection()->SetDefaultEncryptionLevel(
+ current_encryption_level);
+ } else {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_writevdata_at_level, 2, 2);
+ consumed = RetransmitStreamDataAtLevel(retransmission_offset,
+ retransmission_length,
+ send_encryption_level, type);
+ }
if (consumed.bytes_consumed < retransmission_length) {
// The connection is write blocked.
return false;
@@ -360,6 +372,28 @@ bool QuicCryptoStream::RetransmitStreamData(QuicStreamOffset offset,
return true;
}
+QuicConsumedData QuicCryptoStream::RetransmitStreamDataAtLevel(
+ QuicStreamOffset retransmission_offset,
+ QuicByteCount retransmission_length,
+ EncryptionLevel encryption_level,
+ TransmissionType type) {
+ DCHECK_EQ(HANDSHAKE_RETRANSMISSION, type);
+ DCHECK(writevdata_at_level_);
+ const auto consumed = stream_delegate()->WritevData(
+ id(), retransmission_length, retransmission_offset, NO_FIN, type,
+ encryption_level);
+ QUIC_DVLOG(1) << ENDPOINT << "stream " << id()
+ << " is forced to retransmit stream data ["
+ << retransmission_offset << ", "
+ << retransmission_offset + retransmission_length
+ << "), with encryption level: " << encryption_level
+ << ", consumed: " << consumed;
+ OnStreamFrameRetransmitted(retransmission_offset, consumed.bytes_consumed,
+ consumed.fin_consumed);
+
+ return consumed;
+}
+
uint64_t QuicCryptoStream::crypto_bytes_read() const {
if (!QuicVersionUsesCryptoFrames(session()->transport_version())) {
return stream_bytes_read();
@@ -390,7 +424,8 @@ void QuicCryptoStream::OnCryptoFrameLost(QuicCryptoFrame* crypto_frame) {
crypto_frame->offset, crypto_frame->data_length);
}
-void QuicCryptoStream::RetransmitData(QuicCryptoFrame* crypto_frame) {
+void QuicCryptoStream::RetransmitData(QuicCryptoFrame* crypto_frame,
+ TransmissionType type) {
QUIC_BUG_IF(!QuicVersionUsesCryptoFrames(session()->transport_version()))
<< "Versions less than 47 don't retransmit CRYPTO frames";
QuicIntervalSet<QuicStreamOffset> retransmission(
@@ -401,28 +436,23 @@ void QuicCryptoStream::RetransmitData(QuicCryptoFrame* crypto_frame) {
if (retransmission.Empty()) {
return;
}
- EncryptionLevel current_encryption_level =
- session()->connection()->encryption_level();
for (const auto& interval : retransmission) {
size_t retransmission_offset = interval.min();
size_t retransmission_length = interval.max() - interval.min();
- session()->connection()->SetDefaultEncryptionLevel(crypto_frame->level);
- size_t bytes_consumed = session()->connection()->SendCryptoData(
- crypto_frame->level, retransmission_length, retransmission_offset);
+ size_t bytes_consumed = stream_delegate()->SendCryptoData(
+ crypto_frame->level, retransmission_length, retransmission_offset,
+ type);
send_buffer->OnStreamDataRetransmitted(retransmission_offset,
bytes_consumed);
if (bytes_consumed < retransmission_length) {
break;
}
}
- session()->connection()->SetDefaultEncryptionLevel(current_encryption_level);
}
void QuicCryptoStream::WriteBufferedCryptoFrames() {
QUIC_BUG_IF(!QuicVersionUsesCryptoFrames(session()->transport_version()))
<< "Versions less than 47 don't use CRYPTO frames";
- EncryptionLevel current_encryption_level =
- session()->connection()->encryption_level();
for (EncryptionLevel level :
{ENCRYPTION_INITIAL, ENCRYPTION_ZERO_RTT, ENCRYPTION_FORWARD_SECURE}) {
QuicStreamSendBuffer* send_buffer = &substreams_[level].send_buffer;
@@ -432,16 +462,15 @@ void QuicCryptoStream::WriteBufferedCryptoFrames() {
// No buffered data for this encryption level.
continue;
}
- session()->connection()->SetDefaultEncryptionLevel(level);
- size_t bytes_consumed = session()->connection()->SendCryptoData(
- level, data_length, send_buffer->stream_bytes_written());
+ size_t bytes_consumed = stream_delegate()->SendCryptoData(
+ level, data_length, send_buffer->stream_bytes_written(),
+ NOT_RETRANSMISSION);
send_buffer->OnStreamDataConsumed(bytes_consumed);
if (bytes_consumed < data_length) {
// Connection is write blocked.
break;
}
}
- session()->connection()->SetDefaultEncryptionLevel(current_encryption_level);
}
bool QuicCryptoStream::HasBufferedCryptoFrames() const {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.h b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.h
index 357303a65bb..82f81fe9832 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.h
@@ -5,6 +5,7 @@
#ifndef QUICHE_QUIC_CORE_QUIC_CRYPTO_STREAM_H_
#define QUICHE_QUIC_CORE_QUIC_CRYPTO_STREAM_H_
+#include <array>
#include <cstddef>
#include <string>
@@ -13,8 +14,9 @@
#include "net/third_party/quiche/src/quic/core/quic_config.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_stream.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -55,23 +57,26 @@ class QUIC_EXPORT_PRIVATE QuicCryptoStream : public QuicStream {
bool OnCryptoFrameAcked(const QuicCryptoFrame& frame,
QuicTime::Delta ack_delay_time);
+ void OnStreamReset(const QuicRstStreamFrame& frame) override;
+
// Performs key extraction to derive a new secret of |result_len| bytes
// dependent on |label|, |context|, and the stream's negotiated subkey secret.
// Returns false if the handshake has not been confirmed or the parameters are
// invalid (e.g. |label| contains null bytes); returns true on success.
- bool ExportKeyingMaterial(QuicStringPiece label,
- QuicStringPiece context,
+ bool ExportKeyingMaterial(quiche::QuicheStringPiece label,
+ quiche::QuicheStringPiece context,
size_t result_len,
std::string* result) const;
// Writes |data| to the QuicStream at level |level|.
- virtual void WriteCryptoData(EncryptionLevel level, QuicStringPiece data);
+ virtual void WriteCryptoData(EncryptionLevel level,
+ quiche::QuicheStringPiece data);
// Returns true once an encrypter has been set for the connection.
virtual bool encryption_established() const = 0;
// Returns true once the crypto handshake has completed.
- virtual bool handshake_confirmed() const = 0;
+ virtual bool one_rtt_keys_available() const = 0;
// Returns the parameters negotiated in the crypto handshake.
virtual const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
@@ -83,14 +88,19 @@ class QUIC_EXPORT_PRIVATE QuicCryptoStream : public QuicStream {
// Called when a packet of encryption |level| has been successfully decrypted.
virtual void OnPacketDecrypted(EncryptionLevel level) = 0;
+ // Called when a 1RTT packet has been acknowledged.
+ virtual void OnOneRttPacketAcknowledged() = 0;
+
+ // Called when a handshake done frame has been received.
+ virtual void OnHandshakeDoneReceived() = 0;
+
+ // Returns current handshake state.
+ virtual HandshakeState GetHandshakeState() const = 0;
+
// Returns the maximum number of bytes that can be buffered at a particular
// encryption level |level|.
virtual size_t BufferSizeLimitForLevel(EncryptionLevel level) const;
- // Called when the underlying QuicConnection has agreed upon a QUIC version to
- // use.
- virtual void OnSuccessfulVersionNegotiation(const ParsedQuicVersion& version);
-
// Called to cancel retransmission of unencrypted crypto stream data.
void NeuterUnencryptedStreamData();
@@ -111,7 +121,15 @@ class QUIC_EXPORT_PRIVATE QuicCryptoStream : public QuicStream {
// Override to send unacked crypto data with the appropriate encryption level.
bool RetransmitStreamData(QuicStreamOffset offset,
QuicByteCount data_length,
- bool fin) override;
+ bool fin,
+ TransmissionType type) override;
+
+ // Sends stream retransmission data at |encryption_level|.
+ QuicConsumedData RetransmitStreamDataAtLevel(
+ QuicStreamOffset retransmission_offset,
+ QuicByteCount retransmission_length,
+ EncryptionLevel encryption_level,
+ TransmissionType type);
// Returns the number of bytes of handshake data that have been received from
// the peer in either CRYPTO or STREAM frames.
@@ -135,7 +153,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoStream : public QuicStream {
// Called to retransmit any outstanding data in the range indicated by the
// encryption level, offset, and length in |crypto_frame|.
- void RetransmitData(QuicCryptoFrame* crypto_frame);
+ void RetransmitData(QuicCryptoFrame* crypto_frame, TransmissionType type);
// Called to write buffered crypto frames.
void WriteBufferedCryptoFrames();
@@ -178,7 +196,10 @@ class QUIC_EXPORT_PRIVATE QuicCryptoStream : public QuicStream {
// Keeps state for data sent/received in CRYPTO frames at each encryption
// level.
- CryptoSubstream substreams_[NUM_ENCRYPTION_LEVELS];
+ std::array<CryptoSubstream, NUM_ENCRYPTION_LEVELS> substreams_;
+
+ // Latched value of gfe2_reloadable_flag_quic_writevdata_at_level.
+ const bool writevdata_at_level_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream_test.cc
index 25d9cc17ae1..436e572308b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream_test.cc
@@ -47,7 +47,7 @@ class MockQuicCryptoStream : public QuicCryptoStream,
std::vector<CryptoHandshakeMessage>* messages() { return &messages_; }
bool encryption_established() const override { return false; }
- bool handshake_confirmed() const override { return false; }
+ bool one_rtt_keys_available() const override { return false; }
const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
const override {
@@ -57,6 +57,9 @@ class MockQuicCryptoStream : public QuicCryptoStream,
return QuicCryptoHandshaker::crypto_message_parser();
}
void OnPacketDecrypted(EncryptionLevel /*level*/) override {}
+ void OnOneRttPacketAcknowledged() override {}
+ void OnHandshakeDoneReceived() override {}
+ HandshakeState GetHandshakeState() const override { return HANDSHAKE_START; }
private:
QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
@@ -98,7 +101,7 @@ class QuicCryptoStreamTest : public QuicTest {
TEST_F(QuicCryptoStreamTest, NotInitiallyConected) {
EXPECT_FALSE(stream_->encryption_established());
- EXPECT_FALSE(stream_->handshake_confirmed());
+ EXPECT_FALSE(stream_->one_rtt_keys_available());
}
TEST_F(QuicCryptoStreamTest, ProcessRawData) {
@@ -154,20 +157,18 @@ TEST_F(QuicCryptoStreamTest, RetransmitCryptoData) {
std::string data(1350, 'a');
EXPECT_CALL(
session_,
- WritevData(_,
- QuicUtils::GetCryptoStreamId(connection_->transport_version()),
- 1350, 0, _))
- .WillOnce(Invoke(MockQuicSession::ConsumeData));
+ WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+ 1350, 0, _, _, _))
+ .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
stream_->WriteOrBufferData(data, false, nullptr);
// Send [1350, 2700) in ENCRYPTION_ZERO_RTT.
connection_->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
EXPECT_EQ(ENCRYPTION_ZERO_RTT, connection_->encryption_level());
EXPECT_CALL(
session_,
- WritevData(_,
- QuicUtils::GetCryptoStreamId(connection_->transport_version()),
- 1350, 1350, _))
- .WillOnce(Invoke(MockQuicSession::ConsumeData));
+ WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+ 1350, 1350, _, _, _))
+ .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
stream_->WriteOrBufferData(data, false, nullptr);
connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level());
@@ -179,24 +180,21 @@ TEST_F(QuicCryptoStreamTest, RetransmitCryptoData) {
stream_->OnStreamFrameLost(1200, 800, false);
EXPECT_CALL(
session_,
- WritevData(_,
- QuicUtils::GetCryptoStreamId(connection_->transport_version()),
- 1000, 0, _))
- .WillOnce(Invoke(MockQuicSession::ConsumeData));
+ WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+ 1000, 0, _, _, _))
+ .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
// Verify [1200, 2000) are sent in [1200, 1350) and [1350, 2000) because of
// they are in different encryption levels.
EXPECT_CALL(
session_,
- WritevData(_,
- QuicUtils::GetCryptoStreamId(connection_->transport_version()),
- 150, 1200, _))
- .WillOnce(Invoke(MockQuicSession::ConsumeData));
+ WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+ 150, 1200, _, _, _))
+ .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
EXPECT_CALL(
session_,
- WritevData(_,
- QuicUtils::GetCryptoStreamId(connection_->transport_version()),
- 650, 1350, _))
- .WillOnce(Invoke(MockQuicSession::ConsumeData));
+ WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+ 650, 1350, _, _, _))
+ .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
stream_->OnCanWrite();
EXPECT_FALSE(stream_->HasPendingRetransmission());
// Verify connection's encryption level has restored.
@@ -264,20 +262,18 @@ TEST_F(QuicCryptoStreamTest, NeuterUnencryptedStreamData) {
std::string data(1350, 'a');
EXPECT_CALL(
session_,
- WritevData(_,
- QuicUtils::GetCryptoStreamId(connection_->transport_version()),
- 1350, 0, _))
- .WillOnce(Invoke(MockQuicSession::ConsumeData));
+ WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+ 1350, 0, _, _, _))
+ .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
stream_->WriteOrBufferData(data, false, nullptr);
// Send [1350, 2700) in ENCRYPTION_ZERO_RTT.
connection_->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
EXPECT_EQ(ENCRYPTION_ZERO_RTT, connection_->encryption_level());
EXPECT_CALL(
session_,
- WritevData(_,
- QuicUtils::GetCryptoStreamId(connection_->transport_version()),
- 1350, 1350, _))
- .WillOnce(Invoke(MockQuicSession::ConsumeData));
+ WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+ 1350, 1350, _, _, _))
+ .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
stream_->WriteOrBufferData(data, false, nullptr);
// Lost [0, 1350).
@@ -350,20 +346,18 @@ TEST_F(QuicCryptoStreamTest, RetransmitStreamData) {
std::string data(1350, 'a');
EXPECT_CALL(
session_,
- WritevData(_,
- QuicUtils::GetCryptoStreamId(connection_->transport_version()),
- 1350, 0, _))
- .WillOnce(Invoke(MockQuicSession::ConsumeData));
+ WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+ 1350, 0, _, _, _))
+ .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
stream_->WriteOrBufferData(data, false, nullptr);
// Send [1350, 2700) in ENCRYPTION_ZERO_RTT.
connection_->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
EXPECT_EQ(ENCRYPTION_ZERO_RTT, connection_->encryption_level());
EXPECT_CALL(
session_,
- WritevData(_,
- QuicUtils::GetCryptoStreamId(connection_->transport_version()),
- 1350, 1350, _))
- .WillOnce(Invoke(MockQuicSession::ConsumeData));
+ WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+ 1350, 1350, _, _, _))
+ .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
stream_->WriteOrBufferData(data, false, nullptr);
connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level());
@@ -371,46 +365,45 @@ TEST_F(QuicCryptoStreamTest, RetransmitStreamData) {
// Ack [2000, 2500).
QuicByteCount newly_acked_length = 0;
stream_->OnStreamFrameAcked(2000, 500, false, QuicTime::Delta::Zero(),
- &newly_acked_length);
+ QuicTime::Zero(), &newly_acked_length);
EXPECT_EQ(500u, newly_acked_length);
// Force crypto stream to send [1350, 2700) and only [1350, 1500) is consumed.
EXPECT_CALL(
session_,
- WritevData(_,
- QuicUtils::GetCryptoStreamId(connection_->transport_version()),
- 650, 1350, _))
+ WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+ 650, 1350, _, _, _))
.WillOnce(InvokeWithoutArgs([this]() {
- return MockQuicSession::ConsumeData(
- stream_,
+ return session_.ConsumeData(
QuicUtils::GetCryptoStreamId(connection_->transport_version()), 150,
- 1350, NO_FIN);
+ 1350, NO_FIN, HANDSHAKE_RETRANSMISSION, QuicheNullOpt);
}));
- EXPECT_FALSE(stream_->RetransmitStreamData(1350, 1350, false));
+ EXPECT_FALSE(stream_->RetransmitStreamData(1350, 1350, false,
+ HANDSHAKE_RETRANSMISSION));
// Verify connection's encryption level has restored.
EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level());
// Force session to send [1350, 1500) again and all data is consumed.
EXPECT_CALL(
session_,
- WritevData(_,
- QuicUtils::GetCryptoStreamId(connection_->transport_version()),
- 650, 1350, _))
- .WillOnce(Invoke(MockQuicSession::ConsumeData));
+ WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+ 650, 1350, _, _, _))
+ .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
EXPECT_CALL(
session_,
- WritevData(_,
- QuicUtils::GetCryptoStreamId(connection_->transport_version()),
- 200, 2500, _))
- .WillOnce(Invoke(MockQuicSession::ConsumeData));
- EXPECT_TRUE(stream_->RetransmitStreamData(1350, 1350, false));
+ WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+ 200, 2500, _, _, _))
+ .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
+ EXPECT_TRUE(stream_->RetransmitStreamData(1350, 1350, false,
+ HANDSHAKE_RETRANSMISSION));
// Verify connection's encryption level has restored.
EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level());
- EXPECT_CALL(session_, WritevData(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(0);
// Force to send an empty frame.
- EXPECT_TRUE(stream_->RetransmitStreamData(0, 0, false));
+ EXPECT_TRUE(
+ stream_->RetransmitStreamData(0, 0, false, HANDSHAKE_RETRANSMISSION));
}
TEST_F(QuicCryptoStreamTest, RetransmitStreamDataWithCryptoFrames) {
@@ -448,7 +441,7 @@ TEST_F(QuicCryptoStreamTest, RetransmitStreamDataWithCryptoFrames) {
.WillOnce(Invoke(connection_,
&MockQuicConnection::QuicConnection_SendCryptoData));
QuicCryptoFrame frame_to_retransmit(ENCRYPTION_ZERO_RTT, 0, 150);
- stream_->RetransmitData(&frame_to_retransmit);
+ stream_->RetransmitData(&frame_to_retransmit, HANDSHAKE_RETRANSMISSION);
// Verify connection's encryption level has restored.
EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level());
@@ -461,14 +454,14 @@ TEST_F(QuicCryptoStreamTest, RetransmitStreamDataWithCryptoFrames) {
.WillOnce(Invoke(connection_,
&MockQuicConnection::QuicConnection_SendCryptoData));
frame_to_retransmit = QuicCryptoFrame(ENCRYPTION_ZERO_RTT, 0, 1350);
- stream_->RetransmitData(&frame_to_retransmit);
+ stream_->RetransmitData(&frame_to_retransmit, HANDSHAKE_RETRANSMISSION);
// Verify connection's encryption level has restored.
EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level());
EXPECT_CALL(*connection_, SendCryptoData(_, _, _)).Times(0);
// Force to send an empty frame.
QuicCryptoFrame empty_frame(ENCRYPTION_FORWARD_SECURE, 0, 0);
- stream_->RetransmitData(&empty_frame);
+ stream_->RetransmitData(&empty_frame, HANDSHAKE_RETRANSMISSION);
}
// Regression test for b/115926584.
@@ -479,9 +472,8 @@ TEST_F(QuicCryptoStreamTest, HasUnackedCryptoData) {
std::string data(1350, 'a');
EXPECT_CALL(
session_,
- WritevData(_,
- QuicUtils::GetCryptoStreamId(connection_->transport_version()),
- 1350, 0, _))
+ WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+ 1350, 0, _, _, _))
.WillOnce(testing::Return(QuicConsumedData(0, false)));
stream_->WriteOrBufferData(data, false, nullptr);
EXPECT_FALSE(stream_->IsWaitingForAcks());
@@ -491,10 +483,9 @@ TEST_F(QuicCryptoStreamTest, HasUnackedCryptoData) {
EXPECT_CALL(
session_,
- WritevData(_,
- QuicUtils::GetCryptoStreamId(connection_->transport_version()),
- 1350, 0, _))
- .WillOnce(Invoke(MockQuicSession::ConsumeData));
+ WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+ 1350, 0, _, _, _))
+ .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
stream_->OnCanWrite();
EXPECT_TRUE(stream_->IsWaitingForAcks());
EXPECT_TRUE(session_.HasUnackedCryptoData());
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_data_reader.cc b/chromium/net/third_party/quiche/src/quic/core/quic_data_reader.cc
index 17fb6cdafc3..c82e051c342 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_data_reader.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_data_reader.cc
@@ -8,13 +8,14 @@
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
-QuicDataReader::QuicDataReader(QuicStringPiece data)
- : QuicDataReader(data.data(), data.length(), quiche::NETWORK_BYTE_ORDER) {}
+QuicDataReader::QuicDataReader(quiche::QuicheStringPiece data)
+ : quiche::QuicheDataReader(data) {}
QuicDataReader::QuicDataReader(const char* data, const size_t len)
: QuicDataReader(data, len, quiche::NETWORK_BYTE_ORDER) {}
@@ -22,58 +23,7 @@ QuicDataReader::QuicDataReader(const char* data, const size_t len)
QuicDataReader::QuicDataReader(const char* data,
const size_t len,
quiche::Endianness endianness)
- : data_(data), len_(len), pos_(0), endianness_(endianness) {}
-
-bool QuicDataReader::ReadUInt8(uint8_t* result) {
- return ReadBytes(result, sizeof(*result));
-}
-
-bool QuicDataReader::ReadUInt16(uint16_t* result) {
- if (!ReadBytes(result, sizeof(*result))) {
- return false;
- }
- if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
- *result = quiche::QuicheEndian::NetToHost16(*result);
- }
- return true;
-}
-
-bool QuicDataReader::ReadUInt32(uint32_t* result) {
- if (!ReadBytes(result, sizeof(*result))) {
- return false;
- }
- if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
- *result = quiche::QuicheEndian::NetToHost32(*result);
- }
- return true;
-}
-
-bool QuicDataReader::ReadUInt64(uint64_t* result) {
- if (!ReadBytes(result, sizeof(*result))) {
- return false;
- }
- if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
- *result = quiche::QuicheEndian::NetToHost64(*result);
- }
- return true;
-}
-
-bool QuicDataReader::ReadBytesToUInt64(size_t num_bytes, uint64_t* result) {
- *result = 0u;
- if (num_bytes > sizeof(*result)) {
- return false;
- }
- if (endianness_ == quiche::HOST_BYTE_ORDER) {
- return ReadBytes(result, num_bytes);
- }
-
- if (!ReadBytes(reinterpret_cast<char*>(result) + sizeof(*result) - num_bytes,
- num_bytes)) {
- return false;
- }
- *result = quiche::QuicheEndian::NetToHost64(*result);
- return true;
-}
+ : quiche::QuicheDataReader(data, len, endianness) {}
bool QuicDataReader::ReadUFloat16(uint64_t* result) {
uint16_t value;
@@ -108,40 +58,8 @@ bool QuicDataReader::ReadUFloat16(uint64_t* result) {
return true;
}
-bool QuicDataReader::ReadStringPiece16(QuicStringPiece* result) {
- // Read resultant length.
- uint16_t result_len;
- if (!ReadUInt16(&result_len)) {
- // OnFailure() already called.
- return false;
- }
-
- return ReadStringPiece(result, result_len);
-}
-
-bool QuicDataReader::ReadStringPiece(QuicStringPiece* result, size_t size) {
- // Make sure that we have enough data to read.
- if (!CanRead(size)) {
- OnFailure();
- return false;
- }
-
- // Set result.
- *result = QuicStringPiece(data_ + pos_, size);
-
- // Iterate.
- pos_ += size;
-
- return true;
-}
-
bool QuicDataReader::ReadConnectionId(QuicConnectionId* connection_id,
uint8_t length) {
- if (length > kQuicMaxConnectionIdAllVersionsLength) {
- QUIC_BUG << "Attempted to read connection ID with length too high "
- << static_cast<int>(length);
- return false;
- }
if (length == 0) {
connection_id->set_length(0);
return true;
@@ -164,63 +82,13 @@ bool QuicDataReader::ReadLengthPrefixedConnectionId(
if (!ReadUInt8(&connection_id_length)) {
return false;
}
- if (connection_id_length > kQuicMaxConnectionIdAllVersionsLength) {
- return false;
- }
return ReadConnectionId(connection_id, connection_id_length);
}
-bool QuicDataReader::ReadTag(uint32_t* tag) {
- return ReadBytes(tag, sizeof(*tag));
-}
-
-QuicStringPiece QuicDataReader::ReadRemainingPayload() {
- QuicStringPiece payload = PeekRemainingPayload();
- pos_ = len_;
- return payload;
-}
-
-QuicStringPiece QuicDataReader::PeekRemainingPayload() const {
- return QuicStringPiece(data_ + pos_, len_ - pos_);
-}
-
-QuicStringPiece QuicDataReader::FullPayload() const {
- return QuicStringPiece(data_, len_);
-}
-
-bool QuicDataReader::ReadBytes(void* result, size_t size) {
- // Make sure that we have enough data to read.
- if (!CanRead(size)) {
- OnFailure();
- return false;
- }
-
- // Read into result.
- memcpy(result, data_ + pos_, size);
-
- // Iterate.
- pos_ += size;
-
- return true;
-}
-
-bool QuicDataReader::Seek(size_t size) {
- if (!CanRead(size)) {
- OnFailure();
- return false;
- }
- pos_ += size;
- return true;
-}
-
-bool QuicDataReader::IsDoneReading() const {
- return len_ == pos_;
-}
-
QuicVariableLengthIntegerLength QuicDataReader::PeekVarInt62Length() {
- DCHECK_EQ(endianness_, quiche::NETWORK_BYTE_ORDER);
+ DCHECK_EQ(endianness(), quiche::NETWORK_BYTE_ORDER);
const unsigned char* next =
- reinterpret_cast<const unsigned char*>(data_ + pos_);
+ reinterpret_cast<const unsigned char*>(data() + pos());
if (BytesRemaining() == 0) {
return VARIABLE_LENGTH_INTEGER_LENGTH_0;
}
@@ -228,37 +96,6 @@ QuicVariableLengthIntegerLength QuicDataReader::PeekVarInt62Length() {
1 << ((*next & 0b11000000) >> 6));
}
-size_t QuicDataReader::BytesRemaining() const {
- return len_ - pos_;
-}
-
-bool QuicDataReader::TruncateRemaining(size_t truncation_length) {
- if (truncation_length > BytesRemaining()) {
- return false;
- }
- len_ = pos_ + truncation_length;
- return true;
-}
-
-bool QuicDataReader::CanRead(size_t bytes) const {
- return bytes <= (len_ - pos_);
-}
-
-void QuicDataReader::OnFailure() {
- // Set our iterator to the end of the buffer so that further reads fail
- // immediately.
- pos_ = len_;
-}
-
-uint8_t QuicDataReader::PeekByte() const {
- if (pos_ >= len_) {
- QUIC_BUG << "Reading is done, cannot peek next byte. Tried to read pos = "
- << pos_ << " buffer length = " << len_;
- return 0;
- }
- return data_[pos_];
-}
-
// Read an IETF/QUIC formatted 62-bit Variable Length Integer.
//
// Performance notes
@@ -276,11 +113,11 @@ uint8_t QuicDataReader::PeekByte() const {
// Low-level optimization is useful here because this function will be
// called frequently, leading to outsize benefits.
bool QuicDataReader::ReadVarInt62(uint64_t* result) {
- DCHECK_EQ(endianness_, quiche::NETWORK_BYTE_ORDER);
+ DCHECK_EQ(endianness(), quiche::NETWORK_BYTE_ORDER);
size_t remaining = BytesRemaining();
const unsigned char* next =
- reinterpret_cast<const unsigned char*>(data_ + pos_);
+ reinterpret_cast<const unsigned char*>(data() + pos());
if (remaining != 0) {
switch (*next & 0xc0) {
case 0xc0:
@@ -294,7 +131,7 @@ bool QuicDataReader::ReadVarInt62(uint64_t* result) {
(static_cast<uint64_t>(*(next + 5)) << 16) +
(static_cast<uint64_t>(*(next + 6)) << 8) +
(static_cast<uint64_t>(*(next + 7)) << 0);
- pos_ += 8;
+ AdvancePos(8);
return true;
}
return false;
@@ -304,7 +141,7 @@ bool QuicDataReader::ReadVarInt62(uint64_t* result) {
if (remaining >= 4) {
*result = (((*(next)) & 0x3f) << 24) + (((*(next + 1)) << 16)) +
(((*(next + 2)) << 8)) + (((*(next + 3)) << 0));
- pos_ += 4;
+ AdvancePos(4);
return true;
}
return false;
@@ -313,7 +150,7 @@ bool QuicDataReader::ReadVarInt62(uint64_t* result) {
// Leading 0b01...... is 2 byte encoding
if (remaining >= 2) {
*result = (((*(next)) & 0x3f) << 8) + (*(next + 1));
- pos_ += 2;
+ AdvancePos(2);
return true;
}
return false;
@@ -321,29 +158,20 @@ bool QuicDataReader::ReadVarInt62(uint64_t* result) {
case 0x00:
// Leading 0b00...... is 1 byte encoding
*result = (*next) & 0x3f;
- pos_++;
+ AdvancePos(1);
return true;
}
}
return false;
}
-bool QuicDataReader::ReadVarIntU32(uint32_t* result) {
- uint64_t temp_uint64;
- // TODO(fkastenholz): We should disambiguate read-errors from
- // value errors.
- if (!this->ReadVarInt62(&temp_uint64)) {
+bool QuicDataReader::ReadStringPieceVarInt62(
+ quiche::QuicheStringPiece* result) {
+ uint64_t result_length;
+ if (!ReadVarInt62(&result_length)) {
return false;
}
- if (temp_uint64 > kMaxQuicStreamId) {
- return false;
- }
- *result = static_cast<uint32_t>(temp_uint64);
- return true;
-}
-
-std::string QuicDataReader::DebugString() const {
- return QuicStrCat(" { length: ", len_, ", position: ", pos_, " }");
+ return ReadStringPiece(result, result_length);
}
#undef ENDPOINT // undef for jumbo builds
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_data_reader.h b/chromium/net/third_party/quiche/src/quic/core/quic_data_reader.h
index acd30fda100..13499ea83dd 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_data_reader.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_data_reader.h
@@ -10,8 +10,9 @@
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/quiche_data_reader.h"
namespace quic {
@@ -29,11 +30,11 @@ namespace quic {
// trusted and it is up to the caller to throw away the failed instance and
// handle the error as appropriate. None of the Read*() methods should ever be
// called after failure, as they will also fail immediately.
-class QUIC_EXPORT_PRIVATE QuicDataReader {
+class QUIC_EXPORT_PRIVATE QuicDataReader : public quiche::QuicheDataReader {
public:
// Constructs a reader using NETWORK_BYTE_ORDER endianness.
// Caller must provide an underlying buffer to work on.
- explicit QuicDataReader(QuicStringPiece data);
+ explicit QuicDataReader(quiche::QuicheStringPiece data);
// Constructs a reader using NETWORK_BYTE_ORDER endianness.
// Caller must provide an underlying buffer to work on.
QuicDataReader(const char* data, const size_t len);
@@ -48,38 +49,11 @@ class QUIC_EXPORT_PRIVATE QuicDataReader {
// Empty destructor.
~QuicDataReader() {}
- // Reads an 8/16/32/64-bit unsigned integer into the given output
- // parameter. Forwards the internal iterator on success. Returns true on
- // success, false otherwise.
- bool ReadUInt8(uint8_t* result);
- bool ReadUInt16(uint16_t* result);
- bool ReadUInt32(uint32_t* result);
- bool ReadUInt64(uint64_t* result);
-
- // Set |result| to 0, then read |num_bytes| bytes in the correct byte order
- // into least significant bytes of |result|.
- bool ReadBytesToUInt64(size_t num_bytes, uint64_t* result);
-
// Reads a 16-bit unsigned float into the given output parameter.
// Forwards the internal iterator on success.
// Returns true on success, false otherwise.
bool ReadUFloat16(uint64_t* result);
- // Reads a string prefixed with 16-bit length into the given output parameter.
- //
- // NOTE: Does not copy but rather references strings in the underlying buffer.
- // This should be kept in mind when handling memory management!
- //
- // Forwards the internal iterator on success.
- // Returns true on success, false otherwise.
- bool ReadStringPiece16(QuicStringPiece* result);
-
- // Reads a given number of bytes into the given buffer. The buffer
- // must be of adequate size.
- // Forwards the internal iterator on success.
- // Returns true on success, false otherwise.
- bool ReadStringPiece(QuicStringPiece* result, size_t len);
-
// Reads connection ID into the given output parameter.
// Forwards the internal iterator on success.
// Returns true on success, false otherwise.
@@ -90,70 +64,10 @@ class QUIC_EXPORT_PRIVATE QuicDataReader {
// Returns true on success, false otherwise.
bool ReadLengthPrefixedConnectionId(QuicConnectionId* connection_id);
- // Reads tag represented as 32-bit unsigned integer into given output
- // parameter. Tags are in big endian on the wire (e.g., CHLO is
- // 'C','H','L','O') and are read in byte order, so tags in memory are in big
- // endian.
- bool ReadTag(uint32_t* tag);
-
- // Returns the remaining payload as a QuicStringPiece.
- //
- // NOTE: Does not copy but rather references strings in the underlying buffer.
- // This should be kept in mind when handling memory management!
- //
- // Forwards the internal iterator.
- QuicStringPiece ReadRemainingPayload();
-
- // Returns the remaining payload as a QuicStringPiece.
- //
- // NOTE: Does not copy but rather references strings in the underlying buffer.
- // This should be kept in mind when handling memory management!
- //
- // DOES NOT forward the internal iterator.
- QuicStringPiece PeekRemainingPayload() const;
-
- // Returns the entire payload as a QuicStringPiece.
- //
- // NOTE: Does not copy but rather references strings in the underlying buffer.
- // This should be kept in mind when handling memory management!
- //
- // DOES NOT forward the internal iterator.
- QuicStringPiece FullPayload() const;
-
- // Reads a given number of bytes into the given buffer. The buffer
- // must be of adequate size.
- // Forwards the internal iterator on success.
- // Returns true on success, false otherwise.
- bool ReadBytes(void* result, size_t size);
-
- // Skips over |size| bytes from the buffer and forwards the internal iterator.
- // Returns true if there are at least |size| bytes remaining to read, false
- // otherwise.
- bool Seek(size_t size);
-
- // Returns true if the entirety of the underlying buffer has been read via
- // Read*() calls.
- bool IsDoneReading() const;
-
// Returns the length in bytes of a variable length integer based on the next
// two bits available. Returns 1, 2, 4, or 8 on success, and 0 on failure.
QuicVariableLengthIntegerLength PeekVarInt62Length();
- // Returns the number of bytes remaining to be read.
- size_t BytesRemaining() const;
-
- // Truncates the reader down by reducing its internal length.
- // If called immediately after calling this, BytesRemaining will
- // return |truncation_length|. If truncation_length is less than the
- // current value of BytesRemaining, this does nothing and returns false.
- bool TruncateRemaining(size_t truncation_length);
-
- // Returns the next byte that to be read. Must not be called when there are no
- // bytes to be read.
- //
- // DOES NOT forward the internal iterator.
- uint8_t PeekByte() const;
-
// Read an IETF-encoded Variable Length Integer and place the result
// in |*result|.
// Returns true if it works, false if not. The only error is that
@@ -163,34 +77,15 @@ class QUIC_EXPORT_PRIVATE QuicDataReader {
// and that the integers in the range 0 ... (2^62)-1.
bool ReadVarInt62(uint64_t* result);
- // Convenience method that reads a uint32_t.
- // Attempts to read a varint into a uint32_t. using ReadVarInt62 and
- // returns false if there is a read error or if the value is
- // greater than (2^32)-1.
- bool ReadVarIntU32(uint32_t* result);
-
- std::string DebugString() const;
-
- private:
- // Returns true if the underlying buffer has enough room to read the given
- // amount of bytes.
- bool CanRead(size_t bytes) const;
-
- // To be called when a read fails for any reason.
- void OnFailure();
-
- // TODO(fkastenholz, b/73004262) change buffer_, et al, to be uint8_t, not
- // char. The data buffer that we're reading from.
- const char* data_;
-
- // The length of the data buffer that we're reading from.
- size_t len_;
-
- // The location of the next read from our data buffer.
- size_t pos_;
-
- // The endianness to read integers and floating numbers.
- quiche::Endianness endianness_;
+ // Reads a string prefixed with a Variable Length integer length into the
+ // given output parameter.
+ //
+ // NOTE: Does not copy but rather references strings in the underlying buffer.
+ // This should be kept in mind when handling memory management!
+ //
+ // Forwards the internal iterator on success.
+ // Returns true on success, false otherwise.
+ bool ReadStringPieceVarInt62(quiche::QuicheStringPiece* result);
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_data_writer.cc b/chromium/net/third_party/quiche/src/quic/core/quic_data_writer.cc
index d2d71133fe7..41c374cc6d6 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_data_writer.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_data_writer.cc
@@ -11,63 +11,22 @@
#include "net/third_party/quiche/src/quic/core/quic_constants.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
QuicDataWriter::QuicDataWriter(size_t size, char* buffer)
- : QuicDataWriter(size, buffer, quiche::NETWORK_BYTE_ORDER) {}
+ : quiche::QuicheDataWriter(size, buffer) {}
QuicDataWriter::QuicDataWriter(size_t size,
char* buffer,
quiche::Endianness endianness)
- : buffer_(buffer), capacity_(size), length_(0), endianness_(endianness) {}
+ : quiche::QuicheDataWriter(size, buffer, endianness) {}
QuicDataWriter::~QuicDataWriter() {}
-char* QuicDataWriter::data() {
- return buffer_;
-}
-
-bool QuicDataWriter::WriteUInt8(uint8_t value) {
- return WriteBytes(&value, sizeof(value));
-}
-
-bool QuicDataWriter::WriteUInt16(uint16_t value) {
- if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
- value = quiche::QuicheEndian::HostToNet16(value);
- }
- return WriteBytes(&value, sizeof(value));
-}
-
-bool QuicDataWriter::WriteUInt32(uint32_t value) {
- if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
- value = quiche::QuicheEndian::HostToNet32(value);
- }
- return WriteBytes(&value, sizeof(value));
-}
-
-bool QuicDataWriter::WriteUInt64(uint64_t value) {
- if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
- value = quiche::QuicheEndian::HostToNet64(value);
- }
- return WriteBytes(&value, sizeof(value));
-}
-
-bool QuicDataWriter::WriteBytesToUInt64(size_t num_bytes, uint64_t value) {
- if (num_bytes > sizeof(value)) {
- return false;
- }
- if (endianness_ == quiche::HOST_BYTE_ORDER) {
- return WriteBytes(&value, num_bytes);
- }
-
- value = quiche::QuicheEndian::HostToNet64(value);
- return WriteBytes(reinterpret_cast<char*>(&value) + sizeof(value) - num_bytes,
- num_bytes);
-}
-
bool QuicDataWriter::WriteUFloat16(uint64_t value) {
uint16_t result;
if (value < (UINT64_C(1) << kUFloat16MantissaEffectiveBits)) {
@@ -104,79 +63,12 @@ bool QuicDataWriter::WriteUFloat16(uint64_t value) {
result = static_cast<uint16_t>(value + (exponent << kUFloat16MantissaBits));
}
- if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
+ if (endianness() == quiche::NETWORK_BYTE_ORDER) {
result = quiche::QuicheEndian::HostToNet16(result);
}
return WriteBytes(&result, sizeof(result));
}
-bool QuicDataWriter::WriteStringPiece16(QuicStringPiece val) {
- if (val.size() > std::numeric_limits<uint16_t>::max()) {
- return false;
- }
- if (!WriteUInt16(static_cast<uint16_t>(val.size()))) {
- return false;
- }
- return WriteBytes(val.data(), val.size());
-}
-
-bool QuicDataWriter::WriteStringPiece(QuicStringPiece val) {
- return WriteBytes(val.data(), val.size());
-}
-
-char* QuicDataWriter::BeginWrite(size_t length) {
- if (length_ > capacity_) {
- return nullptr;
- }
-
- if (capacity_ - length_ < length) {
- return nullptr;
- }
-
-#ifdef ARCH_CPU_64_BITS
- DCHECK_LE(length, std::numeric_limits<uint32_t>::max());
-#endif
-
- return buffer_ + length_;
-}
-
-bool QuicDataWriter::WriteBytes(const void* data, size_t data_len) {
- char* dest = BeginWrite(data_len);
- if (!dest) {
- return false;
- }
-
- memcpy(dest, data, data_len);
-
- length_ += data_len;
- return true;
-}
-
-bool QuicDataWriter::WriteRepeatedByte(uint8_t byte, size_t count) {
- char* dest = BeginWrite(count);
- if (!dest) {
- return false;
- }
-
- memset(dest, byte, count);
-
- length_ += count;
- return true;
-}
-
-void QuicDataWriter::WritePadding() {
- DCHECK_LE(length_, capacity_);
- if (length_ > capacity_) {
- return;
- }
- memset(buffer_ + length_, 0x00, capacity_ - length_);
- length_ = capacity_;
-}
-
-bool QuicDataWriter::WritePaddingBytes(size_t count) {
- return WriteRepeatedByte(0x00, count);
-}
-
bool QuicDataWriter::WriteConnectionId(QuicConnectionId connection_id) {
if (connection_id.IsEmpty()) {
return true;
@@ -189,10 +81,6 @@ bool QuicDataWriter::WriteLengthPrefixedConnectionId(
return WriteUInt8(connection_id.length()) && WriteConnectionId(connection_id);
}
-bool QuicDataWriter::WriteTag(uint32_t tag) {
- return WriteBytes(&tag, sizeof(tag));
-}
-
bool QuicDataWriter::WriteRandomBytes(QuicRandom* random, size_t length) {
char* dest = BeginWrite(length);
if (!dest) {
@@ -200,17 +88,10 @@ bool QuicDataWriter::WriteRandomBytes(QuicRandom* random, size_t length) {
}
random->RandBytes(dest, length);
- length_ += length;
+ IncreaseLength(length);
return true;
}
-bool QuicDataWriter::Seek(size_t length) {
- if (!BeginWrite(length)) {
- return false;
- }
- length_ += length;
- return true;
-}
// Converts a uint64_t into an IETF/Quic formatted Variable Length
// Integer. IETF Variable Length Integers have 62 significant bits, so
@@ -230,10 +111,10 @@ bool QuicDataWriter::Seek(size_t length) {
// Low-level optimization is useful here because this function will be
// called frequently, leading to outsize benefits.
bool QuicDataWriter::WriteVarInt62(uint64_t value) {
- DCHECK_EQ(endianness_, quiche::NETWORK_BYTE_ORDER);
+ DCHECK_EQ(endianness(), quiche::NETWORK_BYTE_ORDER);
- size_t remaining = capacity_ - length_;
- char* next = buffer_ + length_;
+ size_t remaining_bytes = remaining();
+ char* next = buffer() + length();
if ((value & kVarInt62ErrorMask) == 0) {
// We know the high 2 bits are 0 so |value| is legal.
@@ -241,7 +122,7 @@ bool QuicDataWriter::WriteVarInt62(uint64_t value) {
if ((value & kVarInt62Mask8Bytes) != 0) {
// Someplace in the high-4 bytes is a 1-bit. Do an 8-byte
// encoding.
- if (remaining >= 8) {
+ if (remaining_bytes >= 8) {
*(next + 0) = ((value >> 56) & 0x3f) + 0xc0;
*(next + 1) = (value >> 48) & 0xff;
*(next + 2) = (value >> 40) & 0xff;
@@ -250,7 +131,7 @@ bool QuicDataWriter::WriteVarInt62(uint64_t value) {
*(next + 5) = (value >> 16) & 0xff;
*(next + 6) = (value >> 8) & 0xff;
*(next + 7) = value & 0xff;
- length_ += 8;
+ IncreaseLength(8);
return true;
}
return false;
@@ -260,12 +141,12 @@ bool QuicDataWriter::WriteVarInt62(uint64_t value) {
if ((value & kVarInt62Mask4Bytes) != 0) {
// The encoding will not fit into 2 bytes, Do a 4-byte
// encoding.
- if (remaining >= 4) {
+ if (remaining_bytes >= 4) {
*(next + 0) = ((value >> 24) & 0x3f) + 0x80;
*(next + 1) = (value >> 16) & 0xff;
*(next + 2) = (value >> 8) & 0xff;
*(next + 3) = value & 0xff;
- length_ += 4;
+ IncreaseLength(4);
return true;
}
return false;
@@ -278,18 +159,18 @@ bool QuicDataWriter::WriteVarInt62(uint64_t value) {
// are not 0)
if ((value & kVarInt62Mask2Bytes) != 0) {
// Do 2-byte encoding
- if (remaining >= 2) {
+ if (remaining_bytes >= 2) {
*(next + 0) = ((value >> 8) & 0x3f) + 0x40;
*(next + 1) = (value)&0xff;
- length_ += 2;
+ IncreaseLength(2);
return true;
}
return false;
}
- if (remaining >= 1) {
+ if (remaining_bytes >= 1) {
// Do 1-byte encoding
*next = (value & 0x3f);
- length_ += 1;
+ IncreaseLength(1);
return true;
}
return false;
@@ -301,10 +182,10 @@ bool QuicDataWriter::WriteVarInt62(uint64_t value) {
bool QuicDataWriter::WriteVarInt62(
uint64_t value,
QuicVariableLengthIntegerLength write_length) {
- DCHECK_EQ(endianness_, quiche::NETWORK_BYTE_ORDER);
+ DCHECK_EQ(endianness(), quiche::NETWORK_BYTE_ORDER);
- size_t remaining = capacity_ - length_;
- if (remaining < write_length) {
+ size_t remaining_bytes = remaining();
+ if (remaining_bytes < write_length) {
return false;
}
@@ -353,7 +234,7 @@ QuicVariableLengthIntegerLength QuicDataWriter::GetVarInt62Len(uint64_t value) {
}
bool QuicDataWriter::WriteStringPieceVarInt62(
- const QuicStringPiece& string_piece) {
+ const quiche::QuicheStringPiece& string_piece) {
if (!WriteVarInt62(string_piece.size())) {
return false;
}
@@ -365,8 +246,4 @@ bool QuicDataWriter::WriteStringPieceVarInt62(
return true;
}
-std::string QuicDataWriter::DebugString() const {
- return QuicStrCat(" { capacity: ", capacity_, ", length: ", length_, " }");
-}
-
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_data_writer.h b/chromium/net/third_party/quiche/src/quic/core/quic_data_writer.h
index 8f1b21defd5..3926c1a6aa5 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_data_writer.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_data_writer.h
@@ -10,8 +10,9 @@
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/quiche_data_writer.h"
namespace quic {
@@ -35,7 +36,7 @@ const uint64_t kVarInt62Mask2Bytes = UINT64_C(0x0000000000003fc0);
// The QuicDataWriter supports appending primitive values (int, string, etc)
// to a frame instance. The internal memory buffer is exposed as the "data"
// of the QuicDataWriter.
-class QUIC_EXPORT_PRIVATE QuicDataWriter {
+class QUIC_EXPORT_PRIVATE QuicDataWriter : public quiche::QuicheDataWriter {
public:
// Creates a QuicDataWriter where |buffer| is not owned
// using NETWORK_BYTE_ORDER endianness.
@@ -48,21 +49,9 @@ class QUIC_EXPORT_PRIVATE QuicDataWriter {
~QuicDataWriter();
- // Returns the size of the QuicDataWriter's data.
- size_t length() const { return length_; }
-
- // Retrieves the buffer from the QuicDataWriter without changing ownership.
- char* data();
-
// Methods for adding to the payload. These values are appended to the end
// of the QuicDataWriter payload.
- // Writes 8/16/32/64-bit unsigned integers.
- bool WriteUInt8(uint8_t value);
- bool WriteUInt16(uint16_t value);
- bool WriteUInt32(uint32_t value);
- bool WriteUInt64(uint64_t value);
-
// Write an unsigned-integer value per the IETF QUIC/Variable Length
// Integer encoding rules (see draft-ietf-quic-transport-08.txt).
// IETF Variable Length Integers have 62 significant bits, so the
@@ -80,7 +69,7 @@ class QUIC_EXPORT_PRIVATE QuicDataWriter {
// Writes a string piece as a consecutive length/content pair. The
// length is VarInt62 encoded.
- bool WriteStringPieceVarInt62(const QuicStringPiece& string_piece);
+ bool WriteStringPieceVarInt62(const quiche::QuicheStringPiece& string_piece);
// Utility function to return the number of bytes needed to encode
// the given value using IETF VarInt62 encoding. Returns the number
@@ -88,63 +77,18 @@ class QUIC_EXPORT_PRIVATE QuicDataWriter {
// is too large to encode.
static QuicVariableLengthIntegerLength GetVarInt62Len(uint64_t value);
- // Writes least significant |num_bytes| of a 64-bit unsigned integer in the
- // correct byte order.
- bool WriteBytesToUInt64(size_t num_bytes, uint64_t value);
-
// Write unsigned floating point corresponding to the value. Large values are
// clamped to the maximum representable (kUFloat16MaxValue). Values that can
// not be represented directly are rounded down.
bool WriteUFloat16(uint64_t value);
- bool WriteStringPiece(QuicStringPiece val);
- bool WriteStringPiece16(QuicStringPiece val);
- bool WriteBytes(const void* data, size_t data_len);
- bool WriteRepeatedByte(uint8_t byte, size_t count);
- // Fills the remaining buffer with null characters.
- void WritePadding();
- // Write padding of |count| bytes.
- bool WritePaddingBytes(size_t count);
-
// Write connection ID to the payload.
bool WriteConnectionId(QuicConnectionId connection_id);
// Write 8-bit length followed by connection ID to the payload.
bool WriteLengthPrefixedConnectionId(QuicConnectionId connection_id);
- // Write tag as a 32-bit unsigned integer to the payload. As tags are already
- // converted to big endian (e.g., CHLO is 'C','H','L','O') in memory by TAG or
- // MakeQuicTag and tags are written in byte order, so tags on the wire are
- // in big endian.
- bool WriteTag(uint32_t tag);
-
// Write |length| random bytes generated by |random|.
bool WriteRandomBytes(QuicRandom* random, size_t length);
-
- // Advance the writer's position for writing by |length| bytes without writing
- // anything. This method only makes sense to be used on a buffer that has
- // already been written to (and is having certain parts rewritten).
- bool Seek(size_t length);
-
- size_t capacity() const { return capacity_; }
-
- size_t remaining() const { return capacity_ - length_; }
-
- std::string DebugString() const;
-
- private:
- // Returns the location that the data should be written at, or nullptr if
- // there is not enough room. Call EndWrite with the returned offset and the
- // given length to pad out for the next write.
- char* BeginWrite(size_t length);
-
- // TODO(fkastenholz, b/73004262) change buffer_, et al, to be uint8_t, not
- // char.
- char* buffer_;
- size_t capacity_; // Allocation size of payload (or -1 if buffer is const).
- size_t length_; // Current length of the buffer.
-
- // The endianness to write integers and floating numbers.
- quiche::Endianness endianness_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_data_writer_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_data_writer_test.cc
index 104df8d42ee..e05af218994 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_data_writer_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_data_writer_test.cc
@@ -9,13 +9,17 @@
#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
#include "net/third_party/quiche/src/quic/core/quic_data_reader.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/test_tools/quiche_test_utils.h"
namespace quic {
namespace test {
@@ -33,7 +37,7 @@ struct TestParams {
// Used by ::testing::PrintToStringParamName().
std::string PrintToString(const TestParams& p) {
- return QuicStrCat(
+ return quiche::QuicheStrCat(
(p.endianness == quiche::NETWORK_BYTE_ORDER ? "Network" : "Host"),
"ByteOrder");
}
@@ -265,19 +269,19 @@ TEST_P(QuicDataWriterTest, WriteConnectionId) {
char big_endian[] = {
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
};
- EXPECT_EQ(connection_id.length(), QUIC_ARRAYSIZE(big_endian));
+ EXPECT_EQ(connection_id.length(), QUICHE_ARRAYSIZE(big_endian));
ASSERT_LE(connection_id.length(), 255);
char buffer[255];
QuicDataWriter writer(connection_id.length(), buffer, GetParam().endianness);
EXPECT_TRUE(writer.WriteConnectionId(connection_id));
- test::CompareCharArraysWithHexError("connection_id", buffer,
- connection_id.length(), big_endian,
- connection_id.length());
+ quiche::test::CompareCharArraysWithHexError(
+ "connection_id", buffer, connection_id.length(), big_endian,
+ connection_id.length());
QuicConnectionId read_connection_id;
QuicDataReader reader(buffer, connection_id.length(), GetParam().endianness);
- EXPECT_TRUE(
- reader.ReadConnectionId(&read_connection_id, QUIC_ARRAYSIZE(big_endian)));
+ EXPECT_TRUE(reader.ReadConnectionId(&read_connection_id,
+ QUICHE_ARRAYSIZE(big_endian)));
EXPECT_EQ(connection_id, read_connection_id);
}
@@ -287,35 +291,35 @@ TEST_P(QuicDataWriterTest, LengthPrefixedConnectionId) {
char length_prefixed_connection_id[] = {
0x08, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
};
- EXPECT_EQ(QUIC_ARRAYSIZE(length_prefixed_connection_id),
+ EXPECT_EQ(QUICHE_ARRAYSIZE(length_prefixed_connection_id),
kConnectionIdLengthSize + connection_id.length());
char buffer[kConnectionIdLengthSize + 255] = {};
- QuicDataWriter writer(QUIC_ARRAYSIZE(buffer), buffer);
+ QuicDataWriter writer(QUICHE_ARRAYSIZE(buffer), buffer);
EXPECT_TRUE(writer.WriteLengthPrefixedConnectionId(connection_id));
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"WriteLengthPrefixedConnectionId", buffer, writer.length(),
length_prefixed_connection_id,
- QUIC_ARRAYSIZE(length_prefixed_connection_id));
+ QUICHE_ARRAYSIZE(length_prefixed_connection_id));
// Verify that writing length then connection ID produces the same output.
- memset(buffer, 0, QUIC_ARRAYSIZE(buffer));
- QuicDataWriter writer2(QUIC_ARRAYSIZE(buffer), buffer);
+ memset(buffer, 0, QUICHE_ARRAYSIZE(buffer));
+ QuicDataWriter writer2(QUICHE_ARRAYSIZE(buffer), buffer);
EXPECT_TRUE(writer2.WriteUInt8(connection_id.length()));
EXPECT_TRUE(writer2.WriteConnectionId(connection_id));
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"Write length then ConnectionId", buffer, writer2.length(),
length_prefixed_connection_id,
- QUIC_ARRAYSIZE(length_prefixed_connection_id));
+ QUICHE_ARRAYSIZE(length_prefixed_connection_id));
QuicConnectionId read_connection_id;
- QuicDataReader reader(buffer, QUIC_ARRAYSIZE(buffer));
+ QuicDataReader reader(buffer, QUICHE_ARRAYSIZE(buffer));
EXPECT_TRUE(reader.ReadLengthPrefixedConnectionId(&read_connection_id));
EXPECT_EQ(connection_id, read_connection_id);
// Verify that reading length then connection ID produces the same output.
uint8_t read_connection_id_length2 = 33;
QuicConnectionId read_connection_id2;
- QuicDataReader reader2(buffer, QUIC_ARRAYSIZE(buffer));
+ QuicDataReader reader2(buffer, QUICHE_ARRAYSIZE(buffer));
ASSERT_TRUE(reader2.ReadUInt8(&read_connection_id_length2));
EXPECT_EQ(connection_id.length(), read_connection_id_length2);
EXPECT_TRUE(reader2.ReadConnectionId(&read_connection_id2,
@@ -326,7 +330,8 @@ TEST_P(QuicDataWriterTest, LengthPrefixedConnectionId) {
TEST_P(QuicDataWriterTest, EmptyConnectionIds) {
QuicConnectionId empty_connection_id = EmptyQuicConnectionId();
char buffer[2];
- QuicDataWriter writer(QUIC_ARRAYSIZE(buffer), buffer, GetParam().endianness);
+ QuicDataWriter writer(QUICHE_ARRAYSIZE(buffer), buffer,
+ GetParam().endianness);
EXPECT_TRUE(writer.WriteConnectionId(empty_connection_id));
EXPECT_TRUE(writer.WriteUInt8(1));
EXPECT_TRUE(writer.WriteConnectionId(empty_connection_id));
@@ -339,7 +344,8 @@ TEST_P(QuicDataWriterTest, EmptyConnectionIds) {
QuicConnectionId read_connection_id = TestConnectionId();
uint8_t read_byte;
- QuicDataReader reader(buffer, QUIC_ARRAYSIZE(buffer), GetParam().endianness);
+ QuicDataReader reader(buffer, QUICHE_ARRAYSIZE(buffer),
+ GetParam().endianness);
EXPECT_TRUE(reader.ReadConnectionId(&read_connection_id, 0));
EXPECT_EQ(read_connection_id, empty_connection_id);
EXPECT_TRUE(reader.ReadUInt8(&read_byte));
@@ -368,8 +374,8 @@ TEST_P(QuicDataWriterTest, WriteTag) {
char buffer[kBufferLength];
QuicDataWriter writer(kBufferLength, buffer, GetParam().endianness);
writer.WriteTag(kCHLO);
- test::CompareCharArraysWithHexError("CHLO", buffer, kBufferLength, CHLO,
- kBufferLength);
+ quiche::test::CompareCharArraysWithHexError("CHLO", buffer, kBufferLength,
+ CHLO, kBufferLength);
QuicTag read_chlo;
QuicDataReader reader(buffer, kBufferLength, GetParam().endianness);
@@ -385,7 +391,7 @@ TEST_P(QuicDataWriterTest, Write16BitUnsignedIntegers) {
uint16_t in_memory16 = 0x1122;
QuicDataWriter writer(2, buffer16, GetParam().endianness);
writer.WriteUInt16(in_memory16);
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"uint16_t", buffer16, 2,
GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian16
: little_endian16,
@@ -401,7 +407,7 @@ TEST_P(QuicDataWriterTest, Write16BitUnsignedIntegers) {
uint64_t in_memory16 = 0x0000000000001122;
QuicDataWriter writer(2, buffer16, GetParam().endianness);
writer.WriteBytesToUInt64(2, in_memory16);
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"uint16_t", buffer16, 2,
GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian16
: little_endian16,
@@ -421,7 +427,7 @@ TEST_P(QuicDataWriterTest, Write24BitUnsignedIntegers) {
uint64_t in_memory24 = 0x0000000000112233;
QuicDataWriter writer(3, buffer24, GetParam().endianness);
writer.WriteBytesToUInt64(3, in_memory24);
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"uint24", buffer24, 3,
GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian24
: little_endian24,
@@ -441,7 +447,7 @@ TEST_P(QuicDataWriterTest, Write32BitUnsignedIntegers) {
uint32_t in_memory32 = 0x11223344;
QuicDataWriter writer(4, buffer32, GetParam().endianness);
writer.WriteUInt32(in_memory32);
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"uint32_t", buffer32, 4,
GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian32
: little_endian32,
@@ -457,7 +463,7 @@ TEST_P(QuicDataWriterTest, Write32BitUnsignedIntegers) {
uint64_t in_memory32 = 0x11223344;
QuicDataWriter writer(4, buffer32, GetParam().endianness);
writer.WriteBytesToUInt64(4, in_memory32);
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"uint32_t", buffer32, 4,
GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian32
: little_endian32,
@@ -477,7 +483,7 @@ TEST_P(QuicDataWriterTest, Write40BitUnsignedIntegers) {
char buffer40[5];
QuicDataWriter writer(5, buffer40, GetParam().endianness);
writer.WriteBytesToUInt64(5, in_memory40);
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"uint40", buffer40, 5,
GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian40
: little_endian40,
@@ -496,7 +502,7 @@ TEST_P(QuicDataWriterTest, Write48BitUnsignedIntegers) {
char buffer48[6];
QuicDataWriter writer(6, buffer48, GetParam().endianness);
writer.WriteBytesToUInt64(6, in_memory48);
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"uint48", buffer48, 6,
GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian48
: little_endian48,
@@ -515,7 +521,7 @@ TEST_P(QuicDataWriterTest, Write56BitUnsignedIntegers) {
char buffer56[7];
QuicDataWriter writer(7, buffer56, GetParam().endianness);
writer.WriteBytesToUInt64(7, in_memory56);
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"uint56", buffer56, 7,
GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian56
: little_endian56,
@@ -536,7 +542,7 @@ TEST_P(QuicDataWriterTest, Write64BitUnsignedIntegers) {
char buffer64[8];
QuicDataWriter writer(8, buffer64, GetParam().endianness);
writer.WriteBytesToUInt64(8, in_memory64);
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"uint64_t", buffer64, 8,
GetParam().endianness == quiche::NETWORK_BYTE_ORDER
? AsChars(big_endian64)
@@ -550,7 +556,7 @@ TEST_P(QuicDataWriterTest, Write64BitUnsignedIntegers) {
QuicDataWriter writer2(8, buffer64, GetParam().endianness);
writer2.WriteUInt64(in_memory64);
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"uint64_t", buffer64, 8,
GetParam().endianness == quiche::NETWORK_BYTE_ORDER
? AsChars(big_endian64)
@@ -657,10 +663,10 @@ TEST_P(QuicDataWriterTest, WriteIntegers) {
TEST_P(QuicDataWriterTest, WriteBytes) {
char bytes[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
- char buf[QUIC_ARRAYSIZE(bytes)];
- QuicDataWriter writer(QUIC_ARRAYSIZE(buf), buf, GetParam().endianness);
- EXPECT_TRUE(writer.WriteBytes(bytes, QUIC_ARRAYSIZE(bytes)));
- for (unsigned int i = 0; i < QUIC_ARRAYSIZE(bytes); ++i) {
+ char buf[QUICHE_ARRAYSIZE(bytes)];
+ QuicDataWriter writer(QUICHE_ARRAYSIZE(buf), buf, GetParam().endianness);
+ EXPECT_TRUE(writer.WriteBytes(bytes, QUICHE_ARRAYSIZE(bytes)));
+ for (unsigned int i = 0; i < QUICHE_ARRAYSIZE(bytes); ++i) {
EXPECT_EQ(bytes[i], buf[i]);
}
}
@@ -1076,7 +1082,7 @@ TEST_P(QuicDataWriterTest, VarIntFixedLength) {
}
// Test encoding/decoding stream-id values.
-void EncodeDecodeStreamId(uint64_t value_in, bool expected_decode_result) {
+void EncodeDecodeStreamId(uint64_t value_in) {
char buffer[1 * kMultiVarCount];
memset(buffer, 0, sizeof(buffer));
@@ -1088,35 +1094,28 @@ void EncodeDecodeStreamId(uint64_t value_in, bool expected_decode_result) {
QuicDataReader reader(buffer, sizeof(buffer),
quiche::Endianness::NETWORK_BYTE_ORDER);
QuicStreamId received_stream_id;
- bool read_result = reader.ReadVarIntU32(&received_stream_id);
- EXPECT_EQ(expected_decode_result, read_result);
- if (read_result) {
- EXPECT_EQ(value_in, received_stream_id);
- }
+ uint64_t temp;
+ EXPECT_TRUE(reader.ReadVarInt62(&temp));
+ received_stream_id = static_cast<QuicStreamId>(temp);
+ EXPECT_EQ(value_in, received_stream_id);
}
// Test writing & reading stream-ids of various value.
TEST_P(QuicDataWriterTest, StreamId1) {
// Check a 1-byte QuicStreamId, should work
- EncodeDecodeStreamId(UINT64_C(0x15), true);
+ EncodeDecodeStreamId(UINT64_C(0x15));
// Check a 2-byte QuicStream ID. It should work.
- EncodeDecodeStreamId(UINT64_C(0x1567), true);
+ EncodeDecodeStreamId(UINT64_C(0x1567));
// Check a QuicStreamId that requires 4 bytes of encoding
// This should work.
- EncodeDecodeStreamId(UINT64_C(0x34567890), true);
+ EncodeDecodeStreamId(UINT64_C(0x34567890));
// Check a QuicStreamId that requires 8 bytes of encoding
// but whose value is in the acceptable range.
// This should work.
- EncodeDecodeStreamId(UINT64_C(0xf4567890), true);
-
- // Check QuicStreamIds that require 8 bytes of encoding
- // and whose value is not acceptable.
- // This should fail.
- EncodeDecodeStreamId(UINT64_C(0x100000000), false);
- EncodeDecodeStreamId(UINT64_C(0x3fffffffffffffff), false);
+ EncodeDecodeStreamId(UINT64_C(0xf4567890));
}
TEST_P(QuicDataWriterTest, WriteRandomBytes) {
@@ -1130,7 +1129,8 @@ TEST_P(QuicDataWriterTest, WriteRandomBytes) {
EXPECT_FALSE(writer.WriteRandomBytes(&random, 30));
EXPECT_TRUE(writer.WriteRandomBytes(&random, 20));
- test::CompareCharArraysWithHexError("random", buffer, 20, expected, 20);
+ quiche::test::CompareCharArraysWithHexError("random", buffer, 20, expected,
+ 20);
}
TEST_P(QuicDataWriterTest, PeekVarInt62Length) {
@@ -1161,25 +1161,7 @@ TEST_P(QuicDataWriterTest, PeekVarInt62Length) {
EXPECT_EQ(8, reader4.PeekVarInt62Length());
}
-TEST_P(QuicDataWriterTest, InvalidConnectionIdLengthRead) {
- static const uint8_t bad_connection_id_length = 200;
- static_assert(
- bad_connection_id_length > kQuicMaxConnectionIdAllVersionsLength,
- "bad lengths");
- char buffer[255] = {};
- QuicDataReader reader(buffer, sizeof(buffer));
- QuicConnectionId connection_id;
- bool ok;
- EXPECT_QUIC_BUG(
- ok = reader.ReadConnectionId(&connection_id, bad_connection_id_length),
- QuicStrCat("Attempted to read connection ID with length too high ",
- static_cast<int>(bad_connection_id_length)));
- EXPECT_FALSE(ok);
-}
-
-// Test that ReadVarIntU32 works properly. Tests a valid stream count
-// (a 32 bit number) and an invalid one (a >32 bit number)
-TEST_P(QuicDataWriterTest, ValidU32) {
+TEST_P(QuicDataWriterTest, ValidStreamCount) {
char buffer[1024];
memset(buffer, 0, sizeof(buffer));
QuicDataWriter writer(sizeof(buffer), static_cast<char*>(buffer),
@@ -1188,32 +1170,22 @@ TEST_P(QuicDataWriterTest, ValidU32) {
const QuicStreamCount write_stream_count = 0xffeeddcc;
EXPECT_TRUE(writer.WriteVarInt62(write_stream_count));
QuicStreamCount read_stream_count;
- EXPECT_TRUE(reader.ReadVarIntU32(&read_stream_count));
+ uint64_t temp;
+ EXPECT_TRUE(reader.ReadVarInt62(&temp));
+ read_stream_count = static_cast<QuicStreamId>(temp);
EXPECT_EQ(write_stream_count, read_stream_count);
}
-TEST_P(QuicDataWriterTest, InvalidU32) {
- char buffer[1024];
- memset(buffer, 0, sizeof(buffer));
- QuicDataWriter writer(sizeof(buffer), static_cast<char*>(buffer),
- quiche::Endianness::NETWORK_BYTE_ORDER);
- QuicDataReader reader(buffer, sizeof(buffer));
- EXPECT_TRUE(writer.WriteVarInt62(UINT64_C(0x1ffeeddcc)));
- QuicStreamCount read_stream_count = 123456;
- EXPECT_FALSE(reader.ReadVarIntU32(&read_stream_count));
- // If the value is bad, read_stream_count ought not change.
- EXPECT_EQ(123456u, read_stream_count);
-}
-
TEST_P(QuicDataWriterTest, Seek) {
char buffer[3] = {};
- QuicDataWriter writer(QUIC_ARRAYSIZE(buffer), buffer, GetParam().endianness);
+ QuicDataWriter writer(QUICHE_ARRAYSIZE(buffer), buffer,
+ GetParam().endianness);
EXPECT_TRUE(writer.WriteUInt8(42));
EXPECT_TRUE(writer.Seek(1));
EXPECT_TRUE(writer.WriteUInt8(3));
char expected[] = {42, 0, 3};
- for (size_t i = 0; i < QUIC_ARRAYSIZE(expected); ++i) {
+ for (size_t i = 0; i < QUICHE_ARRAYSIZE(expected); ++i) {
EXPECT_EQ(buffer[i], expected[i]);
}
}
@@ -1223,7 +1195,7 @@ TEST_P(QuicDataWriterTest, SeekTooFarFails) {
// Check that one can seek to the end of the writer, but not past.
{
- QuicDataWriter writer(QUIC_ARRAYSIZE(buffer), buffer,
+ QuicDataWriter writer(QUICHE_ARRAYSIZE(buffer), buffer,
GetParam().endianness);
EXPECT_TRUE(writer.Seek(20));
EXPECT_FALSE(writer.Seek(1));
@@ -1231,14 +1203,14 @@ TEST_P(QuicDataWriterTest, SeekTooFarFails) {
// Seeking several bytes past the end fails.
{
- QuicDataWriter writer(QUIC_ARRAYSIZE(buffer), buffer,
+ QuicDataWriter writer(QUICHE_ARRAYSIZE(buffer), buffer,
GetParam().endianness);
EXPECT_FALSE(writer.Seek(100));
}
// Seeking so far that arithmetic overflow could occur also fails.
{
- QuicDataWriter writer(QUIC_ARRAYSIZE(buffer), buffer,
+ QuicDataWriter writer(QUICHE_ARRAYSIZE(buffer), buffer,
GetParam().endianness);
EXPECT_TRUE(writer.Seek(10));
EXPECT_FALSE(writer.Seek(std::numeric_limits<size_t>::max()));
@@ -1252,28 +1224,47 @@ TEST_P(QuicDataWriterTest, PayloadReads) {
QuicDataReader reader(buffer, sizeof(buffer));
char first_read_buffer[4] = {};
EXPECT_TRUE(reader.ReadBytes(first_read_buffer, sizeof(first_read_buffer)));
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"first read", first_read_buffer, sizeof(first_read_buffer),
expected_first_read, sizeof(expected_first_read));
- QuicStringPiece peeked_remaining_payload = reader.PeekRemainingPayload();
- test::CompareCharArraysWithHexError(
+ quiche::QuicheStringPiece peeked_remaining_payload =
+ reader.PeekRemainingPayload();
+ quiche::test::CompareCharArraysWithHexError(
"peeked_remaining_payload", peeked_remaining_payload.data(),
peeked_remaining_payload.length(), expected_remaining,
sizeof(expected_remaining));
- QuicStringPiece full_payload = reader.FullPayload();
- test::CompareCharArraysWithHexError("full_payload", full_payload.data(),
- full_payload.length(), buffer,
- sizeof(buffer));
- QuicStringPiece read_remaining_payload = reader.ReadRemainingPayload();
- test::CompareCharArraysWithHexError(
+ quiche::QuicheStringPiece full_payload = reader.FullPayload();
+ quiche::test::CompareCharArraysWithHexError(
+ "full_payload", full_payload.data(), full_payload.length(), buffer,
+ sizeof(buffer));
+ quiche::QuicheStringPiece read_remaining_payload =
+ reader.ReadRemainingPayload();
+ quiche::test::CompareCharArraysWithHexError(
"read_remaining_payload", read_remaining_payload.data(),
read_remaining_payload.length(), expected_remaining,
sizeof(expected_remaining));
EXPECT_TRUE(reader.IsDoneReading());
- QuicStringPiece full_payload2 = reader.FullPayload();
- test::CompareCharArraysWithHexError("full_payload2", full_payload2.data(),
- full_payload2.length(), buffer,
- sizeof(buffer));
+ quiche::QuicheStringPiece full_payload2 = reader.FullPayload();
+ quiche::test::CompareCharArraysWithHexError(
+ "full_payload2", full_payload2.data(), full_payload2.length(), buffer,
+ sizeof(buffer));
+}
+
+TEST_P(QuicDataWriterTest, StringPieceVarInt62) {
+ char inner_buffer[16] = {1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16};
+ quiche::QuicheStringPiece inner_payload_write(inner_buffer,
+ sizeof(inner_buffer));
+ char buffer[sizeof(inner_buffer) + sizeof(uint8_t)] = {};
+ QuicDataWriter writer(sizeof(buffer), buffer);
+ EXPECT_TRUE(writer.WriteStringPieceVarInt62(inner_payload_write));
+ EXPECT_EQ(0u, writer.remaining());
+ QuicDataReader reader(buffer, sizeof(buffer));
+ quiche::QuicheStringPiece inner_payload_read;
+ EXPECT_TRUE(reader.ReadStringPieceVarInt62(&inner_payload_read));
+ quiche::test::CompareCharArraysWithHexError(
+ "inner_payload", inner_payload_write.data(), inner_payload_write.length(),
+ inner_payload_read.data(), inner_payload_read.length());
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_datagram_queue.cc b/chromium/net/third_party/quiche/src/quic/core/quic_datagram_queue.cc
new file mode 100644
index 00000000000..22a57cd8336
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_datagram_queue.cc
@@ -0,0 +1,87 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/quic_datagram_queue.h"
+
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
+#include "net/third_party/quiche/src/quic/core/quic_session.h"
+#include "net/third_party/quiche/src/quic/core/quic_time.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice_span.h"
+
+namespace quic {
+
+using quiche::QuicheOptional;
+
+constexpr float kExpiryInMinRtts = 1.25;
+constexpr float kMinPacingWindows = 4;
+
+QuicDatagramQueue::QuicDatagramQueue(QuicSession* session)
+ : session_(session), clock_(session->connection()->clock()) {}
+
+MessageStatus QuicDatagramQueue::SendOrQueueDatagram(QuicMemSlice datagram) {
+ // If the queue is non-empty, always queue the daragram. This ensures that
+ // the datagrams are sent in the same order that they were sent by the
+ // application.
+ if (queue_.empty()) {
+ QuicMemSliceSpan span(&datagram);
+ MessageResult result = session_->SendMessage(span);
+ if (result.status != MESSAGE_STATUS_BLOCKED) {
+ return result.status;
+ }
+ }
+
+ queue_.emplace_back(Datagram{std::move(datagram),
+ clock_->ApproximateNow() + GetMaxTimeInQueue()});
+ return MESSAGE_STATUS_BLOCKED;
+}
+
+QuicheOptional<MessageStatus> QuicDatagramQueue::TrySendingNextDatagram() {
+ RemoveExpiredDatagrams();
+ if (queue_.empty()) {
+ return QuicheOptional<MessageStatus>();
+ }
+
+ QuicMemSliceSpan span(&queue_.front().datagram);
+ MessageResult result = session_->SendMessage(span);
+ if (result.status != MESSAGE_STATUS_BLOCKED) {
+ queue_.pop_front();
+ }
+ return result.status;
+}
+
+size_t QuicDatagramQueue::SendDatagrams() {
+ size_t num_datagrams = 0;
+ for (;;) {
+ QuicheOptional<MessageStatus> status = TrySendingNextDatagram();
+ if (!status.has_value()) {
+ break;
+ }
+ if (*status == MESSAGE_STATUS_BLOCKED) {
+ break;
+ }
+ num_datagrams++;
+ }
+ return num_datagrams;
+}
+
+QuicTime::Delta QuicDatagramQueue::GetMaxTimeInQueue() const {
+ if (!max_time_in_queue_.IsZero()) {
+ return max_time_in_queue_;
+ }
+
+ const QuicTime::Delta min_rtt =
+ session_->connection()->sent_packet_manager().GetRttStats()->min_rtt();
+ return std::max(kExpiryInMinRtts * min_rtt,
+ kMinPacingWindows * kAlarmGranularity);
+}
+
+void QuicDatagramQueue::RemoveExpiredDatagrams() {
+ QuicTime now = clock_->ApproximateNow();
+ while (!queue_.empty() && queue_.front().expiry <= now) {
+ queue_.pop_front();
+ }
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_datagram_queue.h b/chromium/net/third_party/quiche/src/quic/core/quic_datagram_queue.h
new file mode 100644
index 00000000000..ac78ad4f82b
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_datagram_queue.h
@@ -0,0 +1,69 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_CORE_QUIC_DATAGRAM_QUEUE_H_
+#define QUICHE_QUIC_CORE_QUIC_DATAGRAM_QUEUE_H_
+
+#include "net/third_party/quiche/src/quic/core/quic_circular_deque.h"
+#include "net/third_party/quiche/src/quic/core/quic_time.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_optional.h"
+
+namespace quic {
+
+class QuicSession;
+
+// Provides a way to buffer QUIC datagrams (messages) in case they cannot
+// be sent due to congestion control. Datagrams are buffered for a limited
+// amount of time, and deleted after that time passes.
+class QUIC_EXPORT_PRIVATE QuicDatagramQueue {
+ public:
+ // |session| is not owned and must outlive this object.
+ explicit QuicDatagramQueue(QuicSession* session);
+
+ // Adds the datagram to the end of the queue. May send it immediately; if
+ // not, MESSAGE_STATUS_BLOCKED is returned.
+ MessageStatus SendOrQueueDatagram(QuicMemSlice datagram);
+
+ // Attempts to send a single datagram from the queue. Returns the result of
+ // SendMessage(), or nullopt if there were no unexpired datagrams to send.
+ quiche::QuicheOptional<MessageStatus> TrySendingNextDatagram();
+
+ // Sends all of the unexpired datagrams until either the connection becomes
+ // write-blocked or the queue is empty. Returns the number of datagrams sent.
+ size_t SendDatagrams();
+
+ // Returns the amount of time a datagram is allowed to be in the queue before
+ // it is dropped. If not set explicitly using SetMaxTimeInQueue(), an
+ // RTT-based heuristic is used.
+ QuicTime::Delta GetMaxTimeInQueue() const;
+
+ void SetMaxTimeInQueue(QuicTime::Delta max_time_in_queue) {
+ max_time_in_queue_ = max_time_in_queue;
+ }
+
+ size_t queue_size() { return queue_.size(); }
+
+ bool empty() { return queue_.empty(); }
+
+ private:
+ struct QUIC_EXPORT_PRIVATE Datagram {
+ QuicMemSlice datagram;
+ QuicTime expiry;
+ };
+
+ // Removes expired datagrams from the front of the queue.
+ void RemoveExpiredDatagrams();
+
+ QuicSession* session_; // Not owned.
+ const QuicClock* clock_;
+
+ QuicTime::Delta max_time_in_queue_ = QuicTime::Delta::Zero();
+ QuicCircularDeque<Datagram> queue_;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_QUIC_DATAGRAM_QUEUE_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_datagram_queue_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_datagram_queue_test.cc
new file mode 100644
index 00000000000..34ccccc482e
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_datagram_queue_test.cc
@@ -0,0 +1,169 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/quic_datagram_queue.h"
+
+#include "net/third_party/quiche/src/quic/core/quic_buffer_allocator.h"
+#include "net/third_party/quiche/src/quic/core/quic_time.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_optional.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+
+namespace quic {
+namespace test {
+namespace {
+
+using quiche::QuicheOptional;
+
+using testing::_;
+using testing::ElementsAre;
+using testing::Return;
+
+class EstablishedCryptoStream : public MockQuicCryptoStream {
+ public:
+ using MockQuicCryptoStream::MockQuicCryptoStream;
+
+ bool encryption_established() const override { return true; }
+};
+
+class QuicDatagramQueueTest : public QuicTest {
+ public:
+ QuicDatagramQueueTest()
+ : connection_(new MockQuicConnection(&helper_,
+ &alarm_factory_,
+ Perspective::IS_CLIENT)),
+ session_(connection_),
+ queue_(&session_) {
+ session_.SetCryptoStream(new EstablishedCryptoStream(&session_));
+ }
+
+ QuicMemSlice CreateMemSlice(quiche::QuicheStringPiece data) {
+ QuicUniqueBufferPtr buffer =
+ MakeUniqueBuffer(helper_.GetStreamSendBufferAllocator(), data.size());
+ memcpy(buffer.get(), data.data(), data.size());
+ return QuicMemSlice(std::move(buffer), data.size());
+ }
+
+ protected:
+ MockQuicConnectionHelper helper_;
+ MockAlarmFactory alarm_factory_;
+ MockQuicConnection* connection_; // Owned by |session_|.
+ MockQuicSession session_;
+ QuicDatagramQueue queue_;
+};
+
+TEST_F(QuicDatagramQueueTest, SendDatagramImmediately) {
+ EXPECT_CALL(*connection_, SendMessage(_, _, _))
+ .WillOnce(Return(MESSAGE_STATUS_SUCCESS));
+ MessageStatus status = queue_.SendOrQueueDatagram(CreateMemSlice("test"));
+ EXPECT_EQ(MESSAGE_STATUS_SUCCESS, status);
+ EXPECT_EQ(0u, queue_.queue_size());
+}
+
+TEST_F(QuicDatagramQueueTest, SendDatagramAfterBuffering) {
+ EXPECT_CALL(*connection_, SendMessage(_, _, _))
+ .WillOnce(Return(MESSAGE_STATUS_BLOCKED));
+ MessageStatus initial_status =
+ queue_.SendOrQueueDatagram(CreateMemSlice("test"));
+ EXPECT_EQ(MESSAGE_STATUS_BLOCKED, initial_status);
+ EXPECT_EQ(1u, queue_.queue_size());
+
+ // Verify getting write blocked does not remove the datagram from the queue.
+ EXPECT_CALL(*connection_, SendMessage(_, _, _))
+ .WillOnce(Return(MESSAGE_STATUS_BLOCKED));
+ QuicheOptional<MessageStatus> status = queue_.TrySendingNextDatagram();
+ ASSERT_TRUE(status.has_value());
+ EXPECT_EQ(MESSAGE_STATUS_BLOCKED, *status);
+ EXPECT_EQ(1u, queue_.queue_size());
+
+ EXPECT_CALL(*connection_, SendMessage(_, _, _))
+ .WillOnce(Return(MESSAGE_STATUS_SUCCESS));
+ status = queue_.TrySendingNextDatagram();
+ ASSERT_TRUE(status.has_value());
+ EXPECT_EQ(MESSAGE_STATUS_SUCCESS, *status);
+ EXPECT_EQ(0u, queue_.queue_size());
+}
+
+TEST_F(QuicDatagramQueueTest, EmptyBuffer) {
+ QuicheOptional<MessageStatus> status = queue_.TrySendingNextDatagram();
+ EXPECT_FALSE(status.has_value());
+
+ size_t num_messages = queue_.SendDatagrams();
+ EXPECT_EQ(0u, num_messages);
+}
+
+TEST_F(QuicDatagramQueueTest, MultipleDatagrams) {
+ // Note that SendMessage() is called only once here, since all the remaining
+ // messages are automatically queued due to the queue being non-empty.
+ EXPECT_CALL(*connection_, SendMessage(_, _, _))
+ .WillOnce(Return(MESSAGE_STATUS_BLOCKED));
+ queue_.SendOrQueueDatagram(CreateMemSlice("a"));
+ queue_.SendOrQueueDatagram(CreateMemSlice("b"));
+ queue_.SendOrQueueDatagram(CreateMemSlice("c"));
+ queue_.SendOrQueueDatagram(CreateMemSlice("d"));
+ queue_.SendOrQueueDatagram(CreateMemSlice("e"));
+
+ EXPECT_CALL(*connection_, SendMessage(_, _, _))
+ .Times(5)
+ .WillRepeatedly(Return(MESSAGE_STATUS_SUCCESS));
+ size_t num_messages = queue_.SendDatagrams();
+ EXPECT_EQ(5u, num_messages);
+}
+
+TEST_F(QuicDatagramQueueTest, DefaultMaxTimeInQueue) {
+ EXPECT_EQ(QuicTime::Delta::Zero(),
+ connection_->sent_packet_manager().GetRttStats()->min_rtt());
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(4), queue_.GetMaxTimeInQueue());
+
+ RttStats* stats =
+ const_cast<RttStats*>(connection_->sent_packet_manager().GetRttStats());
+ stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
+ QuicTime::Delta::Zero(), helper_.GetClock()->Now());
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(125), queue_.GetMaxTimeInQueue());
+}
+
+TEST_F(QuicDatagramQueueTest, Expiry) {
+ constexpr QuicTime::Delta expiry = QuicTime::Delta::FromMilliseconds(100);
+ queue_.SetMaxTimeInQueue(expiry);
+
+ EXPECT_CALL(*connection_, SendMessage(_, _, _))
+ .WillOnce(Return(MESSAGE_STATUS_BLOCKED));
+ queue_.SendOrQueueDatagram(CreateMemSlice("a"));
+ helper_.AdvanceTime(0.6 * expiry);
+ queue_.SendOrQueueDatagram(CreateMemSlice("b"));
+ helper_.AdvanceTime(0.6 * expiry);
+ queue_.SendOrQueueDatagram(CreateMemSlice("c"));
+
+ std::vector<std::string> messages;
+ EXPECT_CALL(*connection_, SendMessage(_, _, _))
+ .WillRepeatedly([&messages](QuicMessageId /*id*/,
+ QuicMemSliceSpan message, bool /*flush*/) {
+ messages.push_back(std::string(message.GetData(0)));
+ return MESSAGE_STATUS_SUCCESS;
+ });
+ EXPECT_EQ(2u, queue_.SendDatagrams());
+ EXPECT_THAT(messages, ElementsAre("b", "c"));
+}
+
+TEST_F(QuicDatagramQueueTest, ExpireAll) {
+ constexpr QuicTime::Delta expiry = QuicTime::Delta::FromMilliseconds(100);
+ queue_.SetMaxTimeInQueue(expiry);
+
+ EXPECT_CALL(*connection_, SendMessage(_, _, _))
+ .WillOnce(Return(MESSAGE_STATUS_BLOCKED));
+ queue_.SendOrQueueDatagram(CreateMemSlice("a"));
+ queue_.SendOrQueueDatagram(CreateMemSlice("b"));
+ queue_.SendOrQueueDatagram(CreateMemSlice("c"));
+
+ helper_.AdvanceTime(100 * expiry);
+ EXPECT_CALL(*connection_, SendMessage(_, _, _)).Times(0);
+ EXPECT_EQ(0u, queue_.SendDatagrams());
+}
+
+} // namespace
+} // namespace test
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_default_packet_writer.cc b/chromium/net/third_party/quiche/src/quic/core/quic_default_packet_writer.cc
index d0929582471..42220050885 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_default_packet_writer.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_default_packet_writer.cc
@@ -4,7 +4,7 @@
#include "net/third_party/quiche/src/quic/core/quic_default_packet_writer.h"
-#include "net/quic/platform/impl/quic_socket_utils.h"
+#include "net/third_party/quiche/src/quic/core/quic_udp_socket.h"
namespace quic {
@@ -22,8 +22,11 @@ WriteResult QuicDefaultPacketWriter::WritePacket(
DCHECK(!write_blocked_);
DCHECK(nullptr == options)
<< "QuicDefaultPacketWriter does not accept any options.";
- WriteResult result = QuicSocketUtils::WritePacket(fd_, buffer, buf_len,
- self_address, peer_address);
+ QuicUdpPacketInfo packet_info;
+ packet_info.SetPeerAddress(peer_address);
+ packet_info.SetSelfIp(self_address);
+ WriteResult result =
+ QuicUdpSocketApi().WritePacket(fd_, buffer, buf_len, packet_info);
if (IsWriteBlockedStatus(result.status)) {
write_blocked_ = true;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.cc b/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.cc
index a1adda4c1b6..c160ced24b6 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.cc
@@ -21,8 +21,8 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_stack_trace.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
@@ -143,19 +143,6 @@ class StatelessConnectionTerminator {
framer_.set_data_producer(nullptr);
}
- // Serializes a packet containing CONNECTION_CLOSE frame and send it (without
- // adding connection to the time wait).
- void StatelesslyCloseConnection(const QuicSocketAddress& self_address,
- const QuicSocketAddress& peer_address,
- QuicErrorCode error_code,
- const std::string& error_details) {
- SerializeConnectionClosePacket(error_code, error_details);
-
- for (const auto& packet : *collector_.packets()) {
- time_wait_list_manager_->SendPacket(self_address, peer_address, *packet);
- }
- }
-
// Generates a packet containing a CONNECTION_CLOSE frame specifying
// |error_code| and |error_details| and add the connection to time wait.
void CloseConnection(QuicErrorCode error_code,
@@ -199,7 +186,7 @@ class ChloAlpnExtractor : public ChloExtractor::Delegate {
void OnChlo(QuicTransportVersion /*version*/,
QuicConnectionId /*server_connection_id*/,
const CryptoHandshakeMessage& chlo) override {
- QuicStringPiece alpn_value;
+ quiche::QuicheStringPiece alpn_value;
if (chlo.GetStringPiece(kALPN, &alpn_value)) {
alpn_ = std::string(alpn_value);
}
@@ -218,7 +205,7 @@ QuicDispatcher::QuicDispatcher(
const QuicCryptoServerConfig* crypto_config,
QuicVersionManager* version_manager,
std::unique_ptr<QuicConnectionHelperInterface> helper,
- std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
+ std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
std::unique_ptr<QuicAlarmFactory> alarm_factory,
uint8_t expected_server_connection_id_length)
: config_(config),
@@ -239,6 +226,8 @@ QuicDispatcher::QuicDispatcher(
expected_server_connection_id_length_(
expected_server_connection_id_length),
should_update_expected_server_connection_id_length_(false) {
+ QUIC_BUG_IF(GetSupportedVersions().empty())
+ << "Trying to create dispatcher without any supported versions";
QUIC_DLOG(INFO) << "Created QuicDispatcher with versions: "
<< ParsedQuicVersionVectorToString(GetSupportedVersions());
}
@@ -259,12 +248,12 @@ void QuicDispatcher::ProcessPacket(const QuicSocketAddress& self_address,
const QuicReceivedPacket& packet) {
QUIC_DVLOG(2) << "Dispatcher received encrypted " << packet.length()
<< " bytes:" << std::endl
- << QuicTextUtils::HexDump(
- QuicStringPiece(packet.data(), packet.length()));
+ << quiche::QuicheTextUtils::HexDump(quiche::QuicheStringPiece(
+ packet.data(), packet.length()));
ReceivedPacketInfo packet_info(self_address, peer_address, packet);
std::string detailed_error;
bool retry_token_present;
- QuicStringPiece retry_token;
+ quiche::QuicheStringPiece retry_token;
const QuicErrorCode error = QuicFramer::ParsePublicHeaderDispatcher(
packet, expected_server_connection_id_length_, &packet_info.form,
&packet_info.long_packet_type, &packet_info.version_flag,
@@ -281,8 +270,8 @@ void QuicDispatcher::ProcessPacket(const QuicSocketAddress& self_address,
if (packet_info.destination_connection_id.length() !=
expected_server_connection_id_length_ &&
!should_update_expected_server_connection_id_length_ &&
- !QuicUtils::VariableLengthConnectionIdAllowedForVersion(
- packet_info.version.transport_version)) {
+ packet_info.version.IsKnown() &&
+ !packet_info.version.AllowsVariableLengthConnectionIds()) {
SetLastError(QUIC_INVALID_PACKET_HEADER);
QUIC_DLOG(ERROR) << "Invalid Connection Id Length";
return;
@@ -325,8 +314,7 @@ QuicConnectionId QuicDispatcher::MaybeReplaceServerConnectionId(
if (server_connection_id.length() == expected_server_connection_id_length_) {
return server_connection_id;
}
- DCHECK(QuicUtils::VariableLengthConnectionIdAllowedForVersion(
- version.transport_version));
+ DCHECK(version.AllowsVariableLengthConnectionIds());
QuicConnectionId new_connection_id =
GenerateNewServerConnectionId(version, server_connection_id);
@@ -367,8 +355,7 @@ bool QuicDispatcher::MaybeDispatchPacket(
server_connection_id.length() < expected_server_connection_id_length_ &&
!allow_short_initial_server_connection_ids_) {
DCHECK(packet_info.version_flag);
- DCHECK(QuicUtils::VariableLengthConnectionIdAllowedForVersion(
- packet_info.version.transport_version));
+ DCHECK(packet_info.version.AllowsVariableLengthConnectionIds());
QUIC_DLOG(INFO) << "Packet with short destination connection ID "
<< server_connection_id << " expected "
<< static_cast<int>(expected_server_connection_id_length_);
@@ -427,6 +414,26 @@ bool QuicDispatcher::MaybeDispatchPacket(
}
// The packet has an unknown connection ID.
+ if (!accept_new_connections_ && packet_info.version_flag) {
+ // If not accepting new connections, reject packets with version which can
+ // potentially result in new connection creation. But if the packet doesn't
+ // have version flag, leave it to ValidityChecks() to reset it.
+ // By adding the connection to time wait list, following packets on this
+ // connection will not reach ShouldAcceptNewConnections().
+ StatelesslyTerminateConnection(
+ packet_info.destination_connection_id, packet_info.form,
+ packet_info.version_flag, packet_info.use_length_prefix,
+ packet_info.version, QUIC_HANDSHAKE_FAILED,
+ "Stop accepting new connections",
+ quic::QuicTimeWaitListManager::SEND_STATELESS_RESET);
+ // Time wait list will reject the packet correspondingly..
+ time_wait_list_manager()->ProcessPacket(
+ packet_info.self_address, packet_info.peer_address,
+ packet_info.destination_connection_id, packet_info.form,
+ GetPerPacketContext());
+ OnNewConnectionRejected();
+ return true;
+ }
// Unless the packet provides a version, assume that we can continue
// processing using our preferred version.
@@ -455,14 +462,9 @@ bool QuicDispatcher::MaybeDispatchPacket(
packet_info.form == IETF_QUIC_LONG_HEADER_PACKET &&
packet_info.long_packet_type == INITIAL &&
packet_info.packet.length() < kMinClientInitialPacketLength) {
- StatelessConnectionTerminator terminator(
- packet_info.destination_connection_id, packet_info.version,
- helper_.get(), time_wait_list_manager_.get());
- QUIC_DVLOG(1) << "Initial packet too small: "
+ QUIC_DVLOG(1) << "Dropping initial packet which is too short, length: "
<< packet_info.packet.length();
- terminator.StatelesslyCloseConnection(
- packet_info.self_address, packet_info.peer_address,
- IETF_QUIC_PROTOCOL_VIOLATION, "Initial packet too small");
+ QUIC_CODE_COUNT(quic_drop_small_initial_packets);
return true;
}
}
@@ -608,8 +610,15 @@ void QuicDispatcher::CleanUpSession(SessionMap::iterator it,
session_map_.erase(it);
}
+void QuicDispatcher::StartAcceptingNewConnections() {
+ accept_new_connections_ = true;
+}
+
void QuicDispatcher::StopAcceptingNewConnections() {
accept_new_connections_ = false;
+ // No more CHLO will arrive and buffered CHLOs shouldn't be able to create
+ // connections.
+ buffered_packets_.DiscardAllPackets();
}
std::unique_ptr<QuicPerPacketContext> QuicDispatcher::GetPerPacketContext()
@@ -621,7 +630,8 @@ void QuicDispatcher::DeleteSessions() {
if (!write_blocked_list_.empty()) {
for (const std::unique_ptr<QuicSession>& session : closed_session_list_) {
if (write_blocked_list_.erase(session->connection()) != 0) {
- QUIC_BUG << "QuicConnection was in WriteBlockedList before destruction";
+ QUIC_BUG << "QuicConnection was in WriteBlockedList before destruction "
+ << session->connection()->connection_id();
}
}
}
@@ -821,7 +831,7 @@ void QuicDispatcher::ProcessBufferedChlos(size_t max_connections_to_create) {
QuicConnectionId original_connection_id = server_connection_id;
server_connection_id = MaybeReplaceServerConnectionId(server_connection_id,
packet_list.version);
- QuicSession* session =
+ std::unique_ptr<QuicSession> session =
CreateQuicSession(server_connection_id, packets.front().peer_address,
packet_list.alpn, packet_list.version);
if (original_connection_id != server_connection_id) {
@@ -830,12 +840,12 @@ void QuicDispatcher::ProcessBufferedChlos(size_t max_connections_to_create) {
}
QUIC_DLOG(INFO) << "Created new session for " << server_connection_id;
- DCHECK(session_map_.find(server_connection_id) == session_map_.end())
- << "Tried to add session map existing entry " << server_connection_id;
-
- session_map_.insert(
- std::make_pair(server_connection_id, QuicWrapUnique(session)));
- DeliverPacketsToSession(packets, session);
+ auto insertion_result = session_map_.insert(
+ std::make_pair(server_connection_id, std::move(session)));
+ QUIC_BUG_IF(!insertion_result.second)
+ << "Tried to add a session to session_map with existing connection id: "
+ << server_connection_id;
+ DeliverPacketsToSession(packets, insertion_result.first->second.get());
}
}
@@ -887,22 +897,6 @@ void QuicDispatcher::BufferEarlyPacket(const ReceivedPacketInfo& packet_info) {
void QuicDispatcher::ProcessChlo(const std::string& alpn,
ReceivedPacketInfo* packet_info) {
- if (!accept_new_connections_) {
- // Don't any create new connection.
- QUIC_CODE_COUNT(quic_reject_stop_accepting_new_connections);
- StatelesslyTerminateConnection(
- packet_info->destination_connection_id, packet_info->form,
- /*version_flag=*/true, packet_info->use_length_prefix,
- packet_info->version, QUIC_HANDSHAKE_FAILED,
- "Stop accepting new connections",
- quic::QuicTimeWaitListManager::SEND_STATELESS_RESET);
- // Time wait list will reject the packet correspondingly.
- time_wait_list_manager()->ProcessPacket(
- packet_info->self_address, packet_info->peer_address,
- packet_info->destination_connection_id, packet_info->form,
- GetPerPacketContext());
- return;
- }
if (!buffered_packets_.HasBufferedPackets(
packet_info->destination_connection_id) &&
!ShouldCreateOrBufferPacketForConnection(*packet_info)) {
@@ -929,9 +923,10 @@ void QuicDispatcher::ProcessChlo(const std::string& alpn,
packet_info->destination_connection_id = MaybeReplaceServerConnectionId(
original_connection_id, packet_info->version);
// Creates a new session and process all buffered packets for this connection.
- QuicSession* session =
+ std::unique_ptr<QuicSession> session =
CreateQuicSession(packet_info->destination_connection_id,
packet_info->peer_address, alpn, packet_info->version);
+ DCHECK(session);
if (original_connection_id != packet_info->destination_connection_id) {
session->connection()->AddIncomingConnectionId(original_connection_id);
session->connection()->InstallInitialCrypters(original_connection_id);
@@ -939,23 +934,22 @@ void QuicDispatcher::ProcessChlo(const std::string& alpn,
QUIC_DLOG(INFO) << "Created new session for "
<< packet_info->destination_connection_id;
- DCHECK(session_map_.find(packet_info->destination_connection_id) ==
- session_map_.end())
- << "Tried to add session map existing entry "
+ auto insertion_result = session_map_.insert(std::make_pair(
+ packet_info->destination_connection_id, std::move(session)));
+ QUIC_BUG_IF(!insertion_result.second)
+ << "Tried to add a session to session_map with existing connection id: "
<< packet_info->destination_connection_id;
-
- session_map_.insert(std::make_pair(packet_info->destination_connection_id,
- QuicWrapUnique(session)));
+ QuicSession* session_ptr = insertion_result.first->second.get();
std::list<BufferedPacket> packets =
buffered_packets_.DeliverPackets(packet_info->destination_connection_id)
.buffered_packets;
// Process CHLO at first.
- session->ProcessUdpPacket(packet_info->self_address,
- packet_info->peer_address, packet_info->packet);
+ session_ptr->ProcessUdpPacket(packet_info->self_address,
+ packet_info->peer_address, packet_info->packet);
// Deliver queued-up packets in the same order as they arrived.
// Do this even when flag is off because there might be still some packets
// buffered in the store before flag is turned off.
- DeliverPacketsToSession(packets, session);
+ DeliverPacketsToSession(packets, session_ptr);
--new_sessions_allowed_per_event_loop_;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.h b/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.h
index 7dbdea65339..71cbb5771be 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.h
@@ -17,7 +17,7 @@
#include "net/third_party/quiche/src/quic/core/quic_blocked_writer_interface.h"
#include "net/third_party/quiche/src/quic/core/quic_buffered_packet_store.h"
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
-#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
+#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_process_packet_interface.h"
#include "net/third_party/quiche/src/quic/core/quic_session.h"
@@ -25,6 +25,7 @@
#include "net/third_party/quiche/src/quic/core/quic_version_manager.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
@@ -42,13 +43,14 @@ class QUIC_NO_EXPORT QuicDispatcher
// Ideally we'd have a linked_hash_set: the boolean is unused.
typedef QuicLinkedHashMap<QuicBlockedWriterInterface*, bool> WriteBlockedList;
- QuicDispatcher(const QuicConfig* config,
- const QuicCryptoServerConfig* crypto_config,
- QuicVersionManager* version_manager,
- std::unique_ptr<QuicConnectionHelperInterface> helper,
- std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
- std::unique_ptr<QuicAlarmFactory> alarm_factory,
- uint8_t expected_server_connection_id_length);
+ QuicDispatcher(
+ const QuicConfig* config,
+ const QuicCryptoServerConfig* crypto_config,
+ QuicVersionManager* version_manager,
+ std::unique_ptr<QuicConnectionHelperInterface> helper,
+ std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
+ std::unique_ptr<QuicAlarmFactory> alarm_factory,
+ uint8_t expected_server_connection_id_length);
QuicDispatcher(const QuicDispatcher&) = delete;
QuicDispatcher& operator=(const QuicDispatcher&) = delete;
@@ -137,11 +139,21 @@ class QUIC_NO_EXPORT QuicDispatcher
// Return true if there is CHLO buffered.
virtual bool HasChlosBuffered() const;
+ // Start accepting new ConnectionIds.
+ void StartAcceptingNewConnections();
+
+ // Stop accepting new ConnectionIds, either as a part of the lame
+ // duck process or because explicitly configured.
+ void StopAcceptingNewConnections();
+
+ bool accept_new_connections() const { return accept_new_connections_; }
+
protected:
- virtual QuicSession* CreateQuicSession(QuicConnectionId server_connection_id,
- const QuicSocketAddress& peer_address,
- QuicStringPiece alpn,
- const ParsedQuicVersion& version) = 0;
+ virtual std::unique_ptr<QuicSession> CreateQuicSession(
+ QuicConnectionId server_connection_id,
+ const QuicSocketAddress& peer_address,
+ quiche::QuicheStringPiece alpn,
+ const ParsedQuicVersion& version) = 0;
// Tries to validate and dispatch packet based on available information.
// Returns true if packet is dropped or successfully dispatched (e.g.,
@@ -208,7 +220,7 @@ class QUIC_NO_EXPORT QuicDispatcher
QuicConnectionHelperInterface* helper() { return helper_.get(); }
- QuicCryptoServerStream::Helper* session_helper() {
+ QuicCryptoServerStreamBase::Helper* session_helper() {
return session_helper_.get();
}
@@ -248,8 +260,6 @@ class QUIC_NO_EXPORT QuicDispatcher
QuicConnection* connection,
ConnectionCloseSource source);
- void StopAcceptingNewConnections();
-
// Called to terminate a connection statelessly. Depending on |format|, either
// 1) send connection close with |error_code| and |error_details| and add
// connection to time wait list or 2) directly add connection to time wait
@@ -285,6 +295,9 @@ class QUIC_NO_EXPORT QuicDispatcher
allow_short_initial_server_connection_ids;
}
+ // Called if a packet from an unseen connection is reset or rejected.
+ virtual void OnNewConnectionRejected() {}
+
private:
friend class test::QuicDispatcherPeer;
@@ -336,7 +349,7 @@ class QUIC_NO_EXPORT QuicDispatcher
std::unique_ptr<QuicConnectionHelperInterface> helper_;
// The helper used for all sessions.
- std::unique_ptr<QuicCryptoServerStream::Helper> session_helper_;
+ std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper_;
// Creates alarms.
std::unique_ptr<QuicAlarmFactory> alarm_factory_;
@@ -362,7 +375,8 @@ class QUIC_NO_EXPORT QuicDispatcher
// event loop. When reaches 0, it means can't create sessions for now.
int16_t new_sessions_allowed_per_event_loop_;
- // True if this dispatcher is not draining.
+ // True if this dispatcher is accepting new ConnectionIds (new client
+ // connections), false otherwise.
bool accept_new_connections_;
// If false, the dispatcher follows the IETF spec and rejects packets with
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher_test.cc
index 896438a2b73..7e54dd24cf0 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher_test.cc
@@ -20,11 +20,10 @@
#include "net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/fake_proof_source.h"
@@ -35,8 +34,13 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_time_wait_list_manager_peer.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_crypto_server_stream_helper.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/test_tools/quiche_test_utils.h"
using testing::_;
+using testing::ByMove;
+using testing::Eq;
using testing::InSequence;
using testing::Invoke;
using testing::NiceMock;
@@ -65,13 +69,14 @@ class TestQuicSpdyServerSession : public QuicServerSessionBase {
nullptr,
nullptr,
crypto_config,
- compressed_certs_cache),
- crypto_stream_(QuicServerSessionBase::GetMutableCryptoStream()) {}
+ compressed_certs_cache) {
+ Initialize();
+ }
TestQuicSpdyServerSession(const TestQuicSpdyServerSession&) = delete;
TestQuicSpdyServerSession& operator=(const TestQuicSpdyServerSession&) =
delete;
- ~TestQuicSpdyServerSession() override { delete connection(); }
+ ~TestQuicSpdyServerSession() override { DeleteConnection(); }
MOCK_METHOD2(OnConnectionClosed,
void(const QuicConnectionCloseFrame& frame,
@@ -81,31 +86,16 @@ class TestQuicSpdyServerSession : public QuicServerSessionBase {
MOCK_METHOD0(CreateOutgoingBidirectionalStream, QuicSpdyStream*());
MOCK_METHOD0(CreateOutgoingUnidirectionalStream, QuicSpdyStream*());
- QuicCryptoServerStreamBase* CreateQuicCryptoServerStream(
+ std::unique_ptr<QuicCryptoServerStreamBase> CreateQuicCryptoServerStream(
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache) override {
- return new QuicCryptoServerStream(crypto_config, compressed_certs_cache,
- this, stream_helper());
- }
-
- void SetCryptoStream(QuicCryptoServerStream* crypto_stream) {
- crypto_stream_ = crypto_stream;
- }
-
- QuicCryptoServerStreamBase* GetMutableCryptoStream() override {
- return crypto_stream_;
- }
-
- const QuicCryptoServerStreamBase* GetCryptoStream() const override {
- return crypto_stream_;
+ return CreateCryptoServerStream(crypto_config, compressed_certs_cache, this,
+ stream_helper());
}
- QuicCryptoServerStream::Helper* stream_helper() {
+ QuicCryptoServerStreamBase::Helper* stream_helper() {
return QuicServerSessionBase::stream_helper();
}
-
- private:
- QuicCryptoServerStreamBase* crypto_stream_;
};
class TestDispatcher : public QuicDispatcher {
@@ -118,17 +108,18 @@ class TestDispatcher : public QuicDispatcher {
crypto_config,
version_manager,
std::make_unique<MockQuicConnectionHelper>(),
- std::unique_ptr<QuicCryptoServerStream::Helper>(
+ std::unique_ptr<QuicCryptoServerStreamBase::Helper>(
new QuicSimpleCryptoServerStreamHelper()),
std::make_unique<MockAlarmFactory>(),
kQuicDefaultConnectionIdLength),
random_(random) {}
- MOCK_METHOD4(CreateQuicSession,
- QuicServerSessionBase*(QuicConnectionId connection_id,
- const QuicSocketAddress& peer_address,
- QuicStringPiece alpn,
- const quic::ParsedQuicVersion& version));
+ MOCK_METHOD4(
+ CreateQuicSession,
+ std::unique_ptr<QuicSession>(QuicConnectionId connection_id,
+ const QuicSocketAddress& peer_address,
+ quiche::QuicheStringPiece alpn,
+ const quic::ParsedQuicVersion& version));
MOCK_METHOD1(ShouldCreateOrBufferPacketForConnection,
bool(const ReceivedPacketInfo& packet_info));
@@ -185,13 +176,14 @@ class MockServerConnection : public MockQuicConnection {
QuicDispatcher* dispatcher_;
};
-class QuicDispatcherTest : public QuicTest {
+class QuicDispatcherTestBase : public QuicTestWithParam<ParsedQuicVersion> {
public:
- QuicDispatcherTest()
- : QuicDispatcherTest(crypto_test_utils::ProofSourceForTesting()) {}
+ QuicDispatcherTestBase()
+ : QuicDispatcherTestBase(crypto_test_utils::ProofSourceForTesting()) {}
- explicit QuicDispatcherTest(std::unique_ptr<ProofSource> proof_source)
- : version_manager_(AllSupportedVersions()),
+ explicit QuicDispatcherTestBase(std::unique_ptr<ProofSource> proof_source)
+ : version_(GetParam()),
+ version_manager_(AllSupportedVersions()),
crypto_config_(QuicCryptoServerConfig::TESTING,
QuicRandom::GetInstance(),
std::move(proof_source),
@@ -233,7 +225,7 @@ class QuicDispatcherTest : public QuicTest {
// Process a packet with an 8 byte connection id,
// 6 byte packet number, default path id, and packet number 1,
- // using the first supported version.
+ // using the version under test.
void ProcessPacket(QuicSocketAddress peer_address,
QuicConnectionId server_connection_id,
bool has_version_flag,
@@ -243,7 +235,7 @@ class QuicDispatcherTest : public QuicTest {
}
// Process a packet with a default path id, and packet number 1,
- // using the first supported version.
+ // using the version under test.
void ProcessPacket(QuicSocketAddress peer_address,
QuicConnectionId server_connection_id,
bool has_version_flag,
@@ -254,7 +246,7 @@ class QuicDispatcherTest : public QuicTest {
server_connection_id_included, packet_number_length, 1);
}
- // Process a packet using the first supported version.
+ // Process a packet using the version under test.
void ProcessPacket(QuicSocketAddress peer_address,
QuicConnectionId server_connection_id,
bool has_version_flag,
@@ -263,9 +255,8 @@ class QuicDispatcherTest : public QuicTest {
QuicPacketNumberLength packet_number_length,
uint64_t packet_number) {
ProcessPacket(peer_address, server_connection_id, has_version_flag,
- CurrentSupportedVersions().front(), data, true,
- server_connection_id_included, packet_number_length,
- packet_number);
+ version_, data, true, server_connection_id_included,
+ packet_number_length, packet_number);
}
// Processes a packet.
@@ -326,7 +317,7 @@ class QuicDispatcherTest : public QuicTest {
data_connection_map_[conn_id].pop_front();
}
- QuicServerSessionBase* CreateSession(
+ std::unique_ptr<QuicSession> CreateSession(
TestDispatcher* dispatcher,
const QuicConfig& config,
QuicConnectionId connection_id,
@@ -335,18 +326,19 @@ class QuicDispatcherTest : public QuicTest {
MockAlarmFactory* alarm_factory,
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache,
- TestQuicSpdyServerSession** session) {
+ TestQuicSpdyServerSession** session_ptr) {
MockServerConnection* connection = new MockServerConnection(
connection_id, helper, alarm_factory, dispatcher);
connection->SetQuicPacketWriter(dispatcher->writer(),
/*owns_writer=*/false);
- *session = new TestQuicSpdyServerSession(config, connection, crypto_config,
- compressed_certs_cache);
- connection->set_visitor(*session);
+ auto session = std::make_unique<TestQuicSpdyServerSession>(
+ config, connection, crypto_config, compressed_certs_cache);
+ *session_ptr = session.get();
+ connection->set_visitor(session.get());
ON_CALL(*connection, CloseConnection(_, _, _))
.WillByDefault(WithoutArgs(Invoke(
connection, &MockServerConnection::UnregisterOnConnectionClosed)));
- return *session;
+ return session;
}
void CreateTimeWaitListManager() {
@@ -365,17 +357,28 @@ class QuicDispatcherTest : public QuicTest {
return std::string(client_hello.GetSerialized().AsStringPiece());
}
+ std::string ExpectedAlpnForVersion(ParsedQuicVersion version) {
+ if (version.handshake_protocol == PROTOCOL_TLS1_3) {
+ // TODO(b/149597791) Remove this once we can parse ALPN with TLS.
+ return "";
+ }
+ return "hq";
+ }
+
+ std::string ExpectedAlpn() { return ExpectedAlpnForVersion(version_); }
+
void MarkSession1Deleted() { session1_ = nullptr; }
void VerifyVersionSupported(ParsedQuicVersion version) {
QuicConnectionId connection_id = TestConnectionId(++connection_id_);
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("hq"), _))
- .WillOnce(testing::Return(CreateSession(
+ EXPECT_CALL(*dispatcher_,
+ CreateQuicSession(connection_id, client_address,
+ Eq(ExpectedAlpnForVersion(version)), _))
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, connection_id, client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
ProcessUdpPacket(_, _, _))
.WillOnce(WithArg<2>(
@@ -392,13 +395,14 @@ class QuicDispatcherTest : public QuicTest {
void VerifyVersionNotSupported(ParsedQuicVersion version) {
QuicConnectionId connection_id = TestConnectionId(++connection_id_);
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("hq"), _))
+ EXPECT_CALL(*dispatcher_,
+ CreateQuicSession(connection_id, client_address, _, _))
.Times(0);
ProcessPacket(client_address, connection_id, true, version, SerializeCHLO(),
true, CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
}
+ ParsedQuicVersion version_;
MockQuicConnectionHelper mock_helper_;
MockAlarmFactory mock_alarm_factory_;
QuicConfig config_;
@@ -414,22 +418,32 @@ class QuicDispatcherTest : public QuicTest {
uint64_t connection_id_;
};
-TEST_F(QuicDispatcherTest, TlsClientHelloCreatesSession) {
- if (!QuicVersionUsesCryptoFrames(
- CurrentSupportedVersions().front().transport_version)) {
- // TLS is only supported in versions with crypto frames.
+class QuicDispatcherTestAllVersions : public QuicDispatcherTestBase {};
+class QuicDispatcherTestOneVersion : public QuicDispatcherTestBase {};
+
+INSTANTIATE_TEST_SUITE_P(QuicDispatcherTestsAllVersions,
+ QuicDispatcherTestAllVersions,
+ ::testing::ValuesIn(CurrentSupportedVersions()),
+ ::testing::PrintToStringParamName());
+
+INSTANTIATE_TEST_SUITE_P(QuicDispatcherTestsOneVersion,
+ QuicDispatcherTestOneVersion,
+ ::testing::Values(CurrentSupportedVersions().front()),
+ ::testing::PrintToStringParamName());
+
+TEST_P(QuicDispatcherTestAllVersions, TlsClientHelloCreatesSession) {
+ if (version_.handshake_protocol != PROTOCOL_TLS1_3) {
return;
}
- SetQuicReloadableFlag(quic_supports_tls_handshake, true);
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(1), client_address,
- QuicStringPiece(""), _))
- .WillOnce(testing::Return(CreateSession(
+ Eq(ExpectedAlpn()), _))
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(1), client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
ProcessUdpPacket(_, _, _))
.WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
@@ -438,24 +452,21 @@ TEST_F(QuicDispatcherTest, TlsClientHelloCreatesSession) {
EXPECT_CALL(*dispatcher_,
ShouldCreateOrBufferPacketForConnection(
ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
- ProcessPacket(
- client_address, TestConnectionId(1), true,
- ParsedQuicVersion(PROTOCOL_TLS1_3,
- CurrentSupportedVersions().front().transport_version),
- SerializeCHLO(), true, CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
- 1);
+ ProcessPacket(client_address, TestConnectionId(1), true, version_,
+ SerializeCHLO(), true, CONNECTION_ID_PRESENT,
+ PACKET_4BYTE_PACKET_NUMBER, 1);
}
-TEST_F(QuicDispatcherTest, ProcessPackets) {
+TEST_P(QuicDispatcherTestAllVersions, ProcessPackets) {
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(1), client_address,
- QuicStringPiece("hq"), _))
- .WillOnce(testing::Return(CreateSession(
+ Eq(ExpectedAlpn()), _))
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(1), client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
ProcessUdpPacket(_, _, _))
.WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
@@ -468,11 +479,11 @@ TEST_F(QuicDispatcherTest, ProcessPackets) {
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(2), client_address,
- QuicStringPiece("hq"), _))
- .WillOnce(testing::Return(CreateSession(
+ Eq(ExpectedAlpn()), _))
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(2), client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_)));
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_))));
EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()),
ProcessUdpPacket(_, _, _))
.WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
@@ -493,16 +504,16 @@ TEST_F(QuicDispatcherTest, ProcessPackets) {
}
// Regression test of b/93325907.
-TEST_F(QuicDispatcherTest, DispatcherDoesNotRejectPacketNumberZero) {
+TEST_P(QuicDispatcherTestAllVersions, DispatcherDoesNotRejectPacketNumberZero) {
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(1), client_address,
- QuicStringPiece("hq"), _))
- .WillOnce(testing::Return(CreateSession(
+ Eq(ExpectedAlpn()), _))
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(1), client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
// Verify both packets 1 and 2 are processed by connection 1.
EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
ProcessUdpPacket(_, _, _))
@@ -514,22 +525,16 @@ TEST_F(QuicDispatcherTest, DispatcherDoesNotRejectPacketNumberZero) {
EXPECT_CALL(*dispatcher_,
ShouldCreateOrBufferPacketForConnection(
ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
- ProcessPacket(
- client_address, TestConnectionId(1), true,
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO,
- CurrentSupportedVersions().front().transport_version),
- SerializeCHLO(), true, CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
- 1);
+ ProcessPacket(client_address, TestConnectionId(1), true, version_,
+ SerializeCHLO(), true, CONNECTION_ID_PRESENT,
+ PACKET_4BYTE_PACKET_NUMBER, 1);
// Packet number 256 with packet number length 1 would be considered as 0 in
// dispatcher.
- ProcessPacket(
- client_address, TestConnectionId(1), false,
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO,
- CurrentSupportedVersions().front().transport_version),
- "", true, CONNECTION_ID_PRESENT, PACKET_1BYTE_PACKET_NUMBER, 256);
+ ProcessPacket(client_address, TestConnectionId(1), false, version_, "", true,
+ CONNECTION_ID_PRESENT, PACKET_1BYTE_PACKET_NUMBER, 256);
}
-TEST_F(QuicDispatcherTest, StatelessVersionNegotiation) {
+TEST_P(QuicDispatcherTestOneVersion, StatelessVersionNegotiation) {
CreateTimeWaitListManager();
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
@@ -547,7 +552,27 @@ TEST_F(QuicDispatcherTest, StatelessVersionNegotiation) {
CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
}
-TEST_F(QuicDispatcherTest, StatelessVersionNegotiationWithClientConnectionId) {
+TEST_P(QuicDispatcherTestOneVersion,
+ StatelessVersionNegotiationWithVeryLongConnectionId) {
+ QuicConnectionId connection_id = QuicUtils::CreateRandomConnectionId(33);
+ CreateTimeWaitListManager();
+ QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
+
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
+ EXPECT_CALL(*time_wait_list_manager_,
+ SendVersionNegotiationPacket(connection_id, _, _, _, _, _, _, _))
+ .Times(1);
+ // Pad the CHLO message with enough data to make the packet large enough
+ // to trigger version negotiation.
+ std::string chlo = SerializeCHLO() + std::string(1200, 'a');
+ DCHECK_LE(1200u, chlo.length());
+ ProcessPacket(client_address, connection_id, true,
+ QuicVersionReservedForNegotiation(), chlo, true,
+ CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
+}
+
+TEST_P(QuicDispatcherTestOneVersion,
+ StatelessVersionNegotiationWithClientConnectionId) {
CreateTimeWaitListManager();
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
@@ -566,7 +591,7 @@ TEST_F(QuicDispatcherTest, StatelessVersionNegotiationWithClientConnectionId) {
PACKET_4BYTE_PACKET_NUMBER, 1);
}
-TEST_F(QuicDispatcherTest, NoVersionNegotiationWithSmallPacket) {
+TEST_P(QuicDispatcherTestOneVersion, NoVersionNegotiationWithSmallPacket) {
CreateTimeWaitListManager();
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
@@ -587,7 +612,8 @@ TEST_F(QuicDispatcherTest, NoVersionNegotiationWithSmallPacket) {
// Disabling CHLO size validation allows the dispatcher to send version
// negotiation packets in response to a CHLO that is otherwise too small.
-TEST_F(QuicDispatcherTest, VersionNegotiationWithoutChloSizeValidation) {
+TEST_P(QuicDispatcherTestOneVersion,
+ VersionNegotiationWithoutChloSizeValidation) {
crypto_config_.set_validate_chlo_size(false);
CreateTimeWaitListManager();
@@ -608,15 +634,15 @@ TEST_F(QuicDispatcherTest, VersionNegotiationWithoutChloSizeValidation) {
CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
}
-TEST_F(QuicDispatcherTest, Shutdown) {
+TEST_P(QuicDispatcherTestAllVersions, Shutdown) {
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
EXPECT_CALL(*dispatcher_,
- CreateQuicSession(_, client_address, QuicStringPiece("hq"), _))
- .WillOnce(testing::Return(CreateSession(
+ CreateQuicSession(_, client_address, Eq(ExpectedAlpn()), _))
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(1), client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
ProcessUdpPacket(_, _, _))
.WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
@@ -634,18 +660,18 @@ TEST_F(QuicDispatcherTest, Shutdown) {
dispatcher_->Shutdown();
}
-TEST_F(QuicDispatcherTest, TimeWaitListManager) {
+TEST_P(QuicDispatcherTestAllVersions, TimeWaitListManager) {
CreateTimeWaitListManager();
// Create a new session.
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
QuicConnectionId connection_id = TestConnectionId(1);
EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("hq"), _))
- .WillOnce(testing::Return(CreateSession(
+ Eq(ExpectedAlpn()), _))
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, connection_id, client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
ProcessUdpPacket(_, _, _))
.WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
@@ -675,15 +701,14 @@ TEST_F(QuicDispatcherTest, TimeWaitListManager) {
ProcessPacket(client_address, connection_id, true, "data");
}
-TEST_F(QuicDispatcherTest, NoVersionPacketToTimeWaitListManager) {
+TEST_P(QuicDispatcherTestAllVersions, NoVersionPacketToTimeWaitListManager) {
CreateTimeWaitListManager();
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
QuicConnectionId connection_id = TestConnectionId(1);
// Dispatcher forwards all packets for this connection_id to the time wait
// list manager.
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, QuicStringPiece("hq"), _))
- .Times(0);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
EXPECT_CALL(*time_wait_list_manager_,
ProcessPacket(_, _, connection_id, _, _))
.Times(0);
@@ -695,7 +720,7 @@ TEST_F(QuicDispatcherTest, NoVersionPacketToTimeWaitListManager) {
ProcessPacket(client_address, connection_id, false, SerializeCHLO());
}
-TEST_F(QuicDispatcherTest,
+TEST_P(QuicDispatcherTestAllVersions,
DonotTimeWaitPacketsWithUnknownConnectionIdAndNoVersion) {
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
CreateTimeWaitListManager();
@@ -719,9 +744,8 @@ TEST_F(QuicDispatcherTest,
}
// Makes sure nine-byte connection IDs are replaced by 8-byte ones.
-TEST_F(QuicDispatcherTest, LongConnectionIdLengthReplaced) {
- if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
- CurrentSupportedVersions()[0].transport_version)) {
+TEST_P(QuicDispatcherTestAllVersions, LongConnectionIdLengthReplaced) {
+ if (!version_.AllowsVariableLengthConnectionIds()) {
// When variable length connection IDs are not supported, the connection
// fails. See StrayPacketTruncatedConnectionId.
return;
@@ -734,11 +758,11 @@ TEST_F(QuicDispatcherTest, LongConnectionIdLengthReplaced) {
EXPECT_CALL(*dispatcher_,
CreateQuicSession(fixed_connection_id, client_address,
- QuicStringPiece("hq"), _))
- .WillOnce(testing::Return(CreateSession(
+ Eq(ExpectedAlpn()), _))
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, fixed_connection_id, client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
ProcessUdpPacket(_, _, _))
.WillOnce(WithArg<2>(
@@ -752,9 +776,8 @@ TEST_F(QuicDispatcherTest, LongConnectionIdLengthReplaced) {
}
// Makes sure zero-byte connection IDs are replaced by 8-byte ones.
-TEST_F(QuicDispatcherTest, InvalidShortConnectionIdLengthReplaced) {
- if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
- CurrentSupportedVersions()[0].transport_version)) {
+TEST_P(QuicDispatcherTestAllVersions, InvalidShortConnectionIdLengthReplaced) {
+ if (!version_.AllowsVariableLengthConnectionIds()) {
// When variable length connection IDs are not supported, the connection
// fails. See StrayPacketTruncatedConnectionId.
return;
@@ -772,11 +795,11 @@ TEST_F(QuicDispatcherTest, InvalidShortConnectionIdLengthReplaced) {
EXPECT_CALL(*dispatcher_,
CreateQuicSession(fixed_connection_id, client_address,
- QuicStringPiece("hq"), _))
- .WillOnce(testing::Return(CreateSession(
+ Eq(ExpectedAlpn()), _))
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, fixed_connection_id, client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
ProcessUdpPacket(_, _, _))
.WillOnce(WithArg<2>(
@@ -791,9 +814,8 @@ TEST_F(QuicDispatcherTest, InvalidShortConnectionIdLengthReplaced) {
// Makes sure TestConnectionId(1) creates a new connection and
// TestConnectionIdNineBytesLong(2) gets replaced.
-TEST_F(QuicDispatcherTest, MixGoodAndBadConnectionIdLengthPackets) {
- if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
- CurrentSupportedVersions()[0].transport_version)) {
+TEST_P(QuicDispatcherTestAllVersions, MixGoodAndBadConnectionIdLengthPackets) {
+ if (!version_.AllowsVariableLengthConnectionIds()) {
return;
}
@@ -804,11 +826,11 @@ TEST_F(QuicDispatcherTest, MixGoodAndBadConnectionIdLengthPackets) {
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(1), client_address,
- QuicStringPiece("hq"), _))
- .WillOnce(testing::Return(CreateSession(
+ Eq(ExpectedAlpn()), _))
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(1), client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
ProcessUdpPacket(_, _, _))
.WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
@@ -821,11 +843,11 @@ TEST_F(QuicDispatcherTest, MixGoodAndBadConnectionIdLengthPackets) {
EXPECT_CALL(*dispatcher_,
CreateQuicSession(fixed_connection_id, client_address,
- QuicStringPiece("hq"), _))
- .WillOnce(testing::Return(CreateSession(
+ Eq(ExpectedAlpn()), _))
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, fixed_connection_id, client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_)));
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_))));
EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()),
ProcessUdpPacket(_, _, _))
.WillOnce(WithArg<2>(
@@ -846,15 +868,14 @@ TEST_F(QuicDispatcherTest, MixGoodAndBadConnectionIdLengthPackets) {
ProcessPacket(client_address, TestConnectionId(1), false, "data");
}
-TEST_F(QuicDispatcherTest, ProcessPacketWithZeroPort) {
+TEST_P(QuicDispatcherTestAllVersions, ProcessPacketWithZeroPort) {
CreateTimeWaitListManager();
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 0);
// dispatcher_ should drop this packet.
EXPECT_CALL(*dispatcher_,
- CreateQuicSession(TestConnectionId(1), client_address,
- QuicStringPiece("hq"), _))
+ CreateQuicSession(TestConnectionId(1), client_address, _, _))
.Times(0);
EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0);
EXPECT_CALL(*time_wait_list_manager_,
@@ -863,16 +884,17 @@ TEST_F(QuicDispatcherTest, ProcessPacketWithZeroPort) {
ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
}
-TEST_F(QuicDispatcherTest, ProcessPacketWithInvalidShortInitialConnectionId) {
- // Enable a version that supports connection IDs of length different than 8.
- SetQuicReloadableFlag(quic_enable_version_50, true);
+TEST_P(QuicDispatcherTestAllVersions,
+ ProcessPacketWithInvalidShortInitialConnectionId) {
+ if (!version_.AllowsVariableLengthConnectionIds()) {
+ return;
+ }
CreateTimeWaitListManager();
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
// dispatcher_ should drop this packet.
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(_, client_address, QuicStringPiece("hq"), _))
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, client_address, _, _))
.Times(0);
EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0);
EXPECT_CALL(*time_wait_list_manager_,
@@ -881,17 +903,17 @@ TEST_F(QuicDispatcherTest, ProcessPacketWithInvalidShortInitialConnectionId) {
ProcessPacket(client_address, EmptyQuicConnectionId(), true, SerializeCHLO());
}
-TEST_F(QuicDispatcherTest, OKSeqNoPacketProcessed) {
+TEST_P(QuicDispatcherTestAllVersions, OKSeqNoPacketProcessed) {
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
QuicConnectionId connection_id = TestConnectionId(1);
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(1), client_address,
- QuicStringPiece("hq"), _))
- .WillOnce(testing::Return(CreateSession(
+ Eq(ExpectedAlpn()), _))
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(1), client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
ProcessUdpPacket(_, _, _))
.WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
@@ -908,31 +930,26 @@ TEST_F(QuicDispatcherTest, OKSeqNoPacketProcessed) {
QuicDispatcher::kMaxReasonableInitialPacketNumber);
}
-TEST_F(QuicDispatcherTest, SupportedTransportVersionsChangeInFlight) {
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
- "Supported versions out of sync");
- SetQuicReloadableFlag(quic_enable_version_50, true);
- SetQuicReloadableFlag(quic_enable_version_99, true);
-
+TEST_P(QuicDispatcherTestOneVersion, VersionsChangeInFlight) {
VerifyVersionNotSupported(QuicVersionReservedForNegotiation());
+ for (ParsedQuicVersion version : CurrentSupportedVersions()) {
+ VerifyVersionSupported(version);
+ }
- VerifyVersionSupported(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO,
- QuicVersionMin().transport_version));
- VerifyVersionSupported(QuicVersionMax());
-
- // Turn off version 50.
- SetQuicReloadableFlag(quic_enable_version_50, false);
+ // Turn off version Q050.
+ SetQuicReloadableFlag(quic_disable_version_q050, true);
VerifyVersionNotSupported(
ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50));
- // Turn on version 50.
- SetQuicReloadableFlag(quic_enable_version_50, true);
+ // Turn on version Q050.
+ SetQuicReloadableFlag(quic_disable_version_q050, false);
VerifyVersionSupported(
ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50));
}
-TEST_F(QuicDispatcherTest, RejectDeprecatedVersionsWithVersionNegotiation) {
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
+TEST_P(QuicDispatcherTestOneVersion,
+ RejectDeprecatedVersionsWithVersionNegotiation) {
+ static_assert(quic::SupportedVersions().size() == 8u,
"Please add deprecated versions to this test");
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
CreateTimeWaitListManager();
@@ -977,7 +994,7 @@ TEST_F(QuicDispatcherTest, RejectDeprecatedVersionsWithVersionNegotiation) {
}
}
-TEST_F(QuicDispatcherTest, VersionNegotiationProbeOld) {
+TEST_P(QuicDispatcherTestOneVersion, VersionNegotiationProbeOld) {
SetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids, false);
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
CreateTimeWaitListManager();
@@ -1006,7 +1023,7 @@ TEST_F(QuicDispatcherTest, VersionNegotiationProbeOld) {
dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
}
-TEST_F(QuicDispatcherTest, VersionNegotiationProbe) {
+TEST_P(QuicDispatcherTestOneVersion, VersionNegotiationProbe) {
SetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids, true);
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
CreateTimeWaitListManager();
@@ -1059,7 +1076,7 @@ class SavingWriter : public QuicPacketWriterWrapper {
std::vector<std::unique_ptr<QuicEncryptedPacket>> packets_;
};
-TEST_F(QuicDispatcherTest, VersionNegotiationProbeEndToEndOld) {
+TEST_P(QuicDispatcherTestOneVersion, VersionNegotiationProbeEndToEndOld) {
SetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids, false);
SavingWriter* saving_writer = new SavingWriter();
@@ -1098,12 +1115,12 @@ TEST_F(QuicDispatcherTest, VersionNegotiationProbeEndToEndOld) {
// The source connection ID of the probe response should match the
// destination connection ID of the probe request.
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"parsed probe", source_connection_id_bytes, source_connection_id_length,
destination_connection_id_bytes, sizeof(destination_connection_id_bytes));
}
-TEST_F(QuicDispatcherTest, VersionNegotiationProbeEndToEnd) {
+TEST_P(QuicDispatcherTestOneVersion, VersionNegotiationProbeEndToEnd) {
SetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids, true);
SavingWriter* saving_writer = new SavingWriter();
@@ -1142,12 +1159,12 @@ TEST_F(QuicDispatcherTest, VersionNegotiationProbeEndToEnd) {
// The source connection ID of the probe response should match the
// destination connection ID of the probe request.
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"parsed probe", source_connection_id_bytes, source_connection_id_length,
destination_connection_id_bytes, sizeof(destination_connection_id_bytes));
}
-TEST_F(QuicDispatcherTest, AndroidConformanceTestOld) {
+TEST_P(QuicDispatcherTestOneVersion, AndroidConformanceTestOld) {
// TODO(b/139691956) Remove this test once the workaround is removed.
SavingWriter* saving_writer = new SavingWriter();
// dispatcher_ takes ownership of saving_writer.
@@ -1187,13 +1204,13 @@ TEST_F(QuicDispatcherTest, AndroidConformanceTestOld) {
0x75, 0x76, 0x77, 0x78};
ASSERT_GE((*(saving_writer->packets()))[0]->length(),
1u + sizeof(connection_id_bytes));
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"response connection ID", &(*(saving_writer->packets()))[0]->data()[1],
sizeof(connection_id_bytes), connection_id_bytes,
sizeof(connection_id_bytes));
}
-TEST_F(QuicDispatcherTest, AndroidConformanceTest) {
+TEST_P(QuicDispatcherTestOneVersion, AndroidConformanceTest) {
// WARNING: do not remove or modify this test without making sure that we
// still have adequate coverage for the Android conformance test.
SavingWriter* saving_writer = new SavingWriter();
@@ -1235,25 +1252,31 @@ TEST_F(QuicDispatcherTest, AndroidConformanceTest) {
0x75, 0x76, 0x77, 0x78};
ASSERT_GE((*(saving_writer->packets()))[0]->length(),
1u + sizeof(connection_id_bytes));
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"response connection ID", &(*(saving_writer->packets()))[0]->data()[1],
sizeof(connection_id_bytes), connection_id_bytes,
sizeof(connection_id_bytes));
}
-TEST_F(QuicDispatcherTest, DoNotProcessSmallPacket) {
+TEST_P(QuicDispatcherTestAllVersions, DoNotProcessSmallPacket) {
+ if (!version_.HasIetfInvariantHeader()) {
+ // We only drop small packets when using IETF_QUIC_LONG_HEADER_PACKET.
+ return;
+ }
CreateTimeWaitListManager();
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
- EXPECT_CALL(*time_wait_list_manager_, SendPacket(_, _, _)).Times(1);
- ProcessPacket(client_address, TestConnectionId(1), true,
- CurrentSupportedVersions()[0], SerializeCHLO(), false,
+ EXPECT_CALL(*time_wait_list_manager_, SendPacket(_, _, _)).Times(0);
+ EXPECT_CALL(*time_wait_list_manager_,
+ AddConnectionIdToTimeWait(_, _, _, _, _))
+ .Times(0);
+ ProcessPacket(client_address, TestConnectionId(1), /*has_version_flag=*/true,
+ version_, SerializeCHLO(), /*full_padding=*/false,
CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
}
-TEST_F(QuicDispatcherTest, ProcessSmallCoalescedPacket) {
- SetQuicReloadableFlag(quic_enable_version_99, true);
+TEST_P(QuicDispatcherTestAllVersions, ProcessSmallCoalescedPacket) {
CreateTimeWaitListManager();
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
@@ -1301,36 +1324,95 @@ TEST_F(QuicDispatcherTest, ProcessSmallCoalescedPacket) {
dispatcher_->ProcessPacket(server_address_, client_address, packet);
}
+TEST_P(QuicDispatcherTestAllVersions, StopAcceptingNewConnections) {
+ QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
+
+ EXPECT_CALL(*dispatcher_,
+ CreateQuicSession(TestConnectionId(1), client_address,
+ Eq(ExpectedAlpn()), _))
+ .WillOnce(Return(ByMove(CreateSession(
+ dispatcher_.get(), config_, TestConnectionId(1), client_address,
+ &mock_helper_, &mock_alarm_factory_, &crypto_config_,
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
+ ProcessUdpPacket(_, _, _))
+ .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
+ ValidatePacket(TestConnectionId(1), packet);
+ })));
+ ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
+
+ dispatcher_->StopAcceptingNewConnections();
+ EXPECT_FALSE(dispatcher_->accept_new_connections());
+
+ // No more new connections afterwards.
+ EXPECT_CALL(*dispatcher_,
+ CreateQuicSession(TestConnectionId(2), client_address,
+ Eq(ExpectedAlpn()), _))
+ .Times(0u);
+ ProcessPacket(client_address, TestConnectionId(2), true, SerializeCHLO());
+
+ // Existing connections should be able to continue.
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
+ ProcessUdpPacket(_, _, _))
+ .Times(1u)
+ .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
+ ValidatePacket(TestConnectionId(1), packet);
+ })));
+ ProcessPacket(client_address, TestConnectionId(1), false, "data");
+}
+
+TEST_P(QuicDispatcherTestAllVersions, StartAcceptingNewConnections) {
+ dispatcher_->StopAcceptingNewConnections();
+ QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
+
+ // No more new connections afterwards.
+ EXPECT_CALL(*dispatcher_,
+ CreateQuicSession(TestConnectionId(2), client_address,
+ Eq(ExpectedAlpn()), _))
+ .Times(0u);
+ ProcessPacket(client_address, TestConnectionId(2), true, SerializeCHLO());
+
+ dispatcher_->StartAcceptingNewConnections();
+ EXPECT_TRUE(dispatcher_->accept_new_connections());
+
+ EXPECT_CALL(*dispatcher_,
+ CreateQuicSession(TestConnectionId(1), client_address,
+ Eq(ExpectedAlpn()), _))
+ .WillOnce(Return(ByMove(CreateSession(
+ dispatcher_.get(), config_, TestConnectionId(1), client_address,
+ &mock_helper_, &mock_alarm_factory_, &crypto_config_,
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
+ ProcessUdpPacket(_, _, _))
+ .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
+ ValidatePacket(TestConnectionId(1), packet);
+ })));
+ ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
+}
+
// Verify the stopgap test: Packets with truncated connection IDs should be
// dropped.
-class QuicDispatcherTestStrayPacketConnectionId : public QuicDispatcherTest {};
+class QuicDispatcherTestStrayPacketConnectionId
+ : public QuicDispatcherTestBase {};
+
+INSTANTIATE_TEST_SUITE_P(QuicDispatcherTestsStrayPacketConnectionId,
+ QuicDispatcherTestStrayPacketConnectionId,
+ ::testing::ValuesIn(CurrentSupportedVersions()),
+ ::testing::PrintToStringParamName());
// Packets with truncated connection IDs should be dropped.
-TEST_F(QuicDispatcherTestStrayPacketConnectionId,
+TEST_P(QuicDispatcherTestStrayPacketConnectionId,
StrayPacketTruncatedConnectionId) {
CreateTimeWaitListManager();
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
QuicConnectionId connection_id = TestConnectionId(1);
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, QuicStringPiece("hq"), _))
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
+ EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*time_wait_list_manager_,
+ AddConnectionIdToTimeWait(_, _, _, _, _))
.Times(0);
- if (VersionHasIetfInvariantHeader(
- CurrentSupportedVersions()[0].transport_version)) {
- // This IETF packet has invalid connection ID length.
- EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _))
- .Times(0);
- EXPECT_CALL(*time_wait_list_manager_,
- AddConnectionIdToTimeWait(_, _, _, _, _))
- .Times(0);
- } else {
- // This is a GQUIC packet considered as IETF QUIC packet with short header
- // with unacceptable packet number.
- EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _))
- .Times(1);
- EXPECT_CALL(*time_wait_list_manager_,
- AddConnectionIdToTimeWait(_, _, _, _, _))
- .Times(1);
- }
+
ProcessPacket(client_address, connection_id, true, "data",
CONNECTION_ID_ABSENT, PACKET_4BYTE_PACKET_NUMBER);
}
@@ -1357,21 +1439,21 @@ class BlockingWriter : public QuicPacketWriterWrapper {
bool write_blocked_;
};
-class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest {
+class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTestBase {
public:
void SetUp() override {
- QuicDispatcherTest::SetUp();
+ QuicDispatcherTestBase::SetUp();
writer_ = new BlockingWriter;
QuicDispatcherPeer::UseWriter(dispatcher_.get(), writer_);
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
EXPECT_CALL(*dispatcher_,
- CreateQuicSession(_, client_address, QuicStringPiece("hq"), _))
- .WillOnce(testing::Return(CreateSession(
+ CreateQuicSession(_, client_address, Eq(ExpectedAlpn()), _))
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(1), client_address,
&helper_, &alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
ProcessUdpPacket(_, _, _))
.WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
@@ -1383,11 +1465,11 @@ class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest {
ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
EXPECT_CALL(*dispatcher_,
- CreateQuicSession(_, client_address, QuicStringPiece("hq"), _))
- .WillOnce(testing::Return(CreateSession(
+ CreateQuicSession(_, client_address, Eq(ExpectedAlpn()), _))
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(2), client_address,
&helper_, &alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_)));
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_))));
EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()),
ProcessUdpPacket(_, _, _))
.WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
@@ -1446,7 +1528,12 @@ class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest {
QuicDispatcher::WriteBlockedList* blocked_list_;
};
-TEST_F(QuicDispatcherWriteBlockedListTest, BasicOnCanWrite) {
+INSTANTIATE_TEST_SUITE_P(QuicDispatcherWriteBlockedListTests,
+ QuicDispatcherWriteBlockedListTest,
+ ::testing::Values(CurrentSupportedVersions().front()),
+ ::testing::PrintToStringParamName());
+
+TEST_P(QuicDispatcherWriteBlockedListTest, BasicOnCanWrite) {
// No OnCanWrite calls because no connections are blocked.
dispatcher_->OnCanWrite();
@@ -1462,7 +1549,7 @@ TEST_F(QuicDispatcherWriteBlockedListTest, BasicOnCanWrite) {
EXPECT_FALSE(dispatcher_->HasPendingWrites());
}
-TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteOrder) {
+TEST_P(QuicDispatcherWriteBlockedListTest, OnCanWriteOrder) {
// Make sure we handle events in order.
InSequence s;
SetBlocked();
@@ -1481,7 +1568,7 @@ TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteOrder) {
dispatcher_->OnCanWrite();
}
-TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteRemove) {
+TEST_P(QuicDispatcherWriteBlockedListTest, OnCanWriteRemove) {
// Add and remove one connction.
SetBlocked();
dispatcher_->OnWriteBlocked(connection1());
@@ -1506,7 +1593,7 @@ TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteRemove) {
dispatcher_->OnCanWrite();
}
-TEST_F(QuicDispatcherWriteBlockedListTest, DoubleAdd) {
+TEST_P(QuicDispatcherWriteBlockedListTest, DoubleAdd) {
// Make sure a double add does not necessitate a double remove.
SetBlocked();
dispatcher_->OnWriteBlocked(connection1());
@@ -1523,7 +1610,7 @@ TEST_F(QuicDispatcherWriteBlockedListTest, DoubleAdd) {
dispatcher_->OnCanWrite();
}
-TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlockConnection1) {
+TEST_P(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlockConnection1) {
// If the 1st blocked writer gets blocked in OnCanWrite, it will be added back
// into the write blocked list.
InSequence s;
@@ -1546,7 +1633,7 @@ TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlockConnection1) {
EXPECT_FALSE(dispatcher_->HasPendingWrites());
}
-TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlockConnection2) {
+TEST_P(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlockConnection2) {
// If the 2nd blocked writer gets blocked in OnCanWrite, it will be added back
// into the write blocked list.
InSequence s;
@@ -1569,7 +1656,7 @@ TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlockConnection2) {
EXPECT_FALSE(dispatcher_->HasPendingWrites());
}
-TEST_F(QuicDispatcherWriteBlockedListTest,
+TEST_P(QuicDispatcherWriteBlockedListTest,
OnCanWriteHandleBlockBothConnections) {
// Both connections get blocked in OnCanWrite, and added back into the write
// blocked list.
@@ -1595,7 +1682,7 @@ TEST_F(QuicDispatcherWriteBlockedListTest,
EXPECT_FALSE(dispatcher_->HasPendingWrites());
}
-TEST_F(QuicDispatcherWriteBlockedListTest, PerConnectionWriterBlocked) {
+TEST_P(QuicDispatcherWriteBlockedListTest, PerConnectionWriterBlocked) {
// By default, all connections share the same packet writer with the
// dispatcher.
EXPECT_EQ(dispatcher_->writer(), connection1()->writer());
@@ -1615,7 +1702,7 @@ TEST_F(QuicDispatcherWriteBlockedListTest, PerConnectionWriterBlocked) {
EXPECT_FALSE(dispatcher_->HasPendingWrites());
}
-TEST_F(QuicDispatcherWriteBlockedListTest,
+TEST_P(QuicDispatcherWriteBlockedListTest,
RemoveConnectionFromWriteBlockedListWhenDeletingSessions) {
dispatcher_->OnConnectionClosed(connection1()->connection_id(),
QUIC_PACKET_WRITE_ERROR, "Closed by test.",
@@ -1633,27 +1720,29 @@ TEST_F(QuicDispatcherWriteBlockedListTest,
MarkSession1Deleted();
}
-class BufferedPacketStoreTest : public QuicDispatcherTest {
+class BufferedPacketStoreTest : public QuicDispatcherTestBase {
public:
BufferedPacketStoreTest()
- : QuicDispatcherTest(),
+ : QuicDispatcherTestBase(),
server_addr_(QuicSocketAddress(QuicIpAddress::Any4(), 5)),
client_addr_(QuicIpAddress::Loopback4(), 1234),
signed_config_(new QuicSignedServerConfig) {}
void SetUp() override {
- QuicDispatcherTest::SetUp();
+ QuicDispatcherTestBase::SetUp();
clock_ = QuicDispatcherPeer::GetHelper(dispatcher_.get())->GetClock();
- QuicTransportVersion version = AllSupportedTransportVersions().front();
+ ASSERT_EQ(PROTOCOL_QUIC_CRYPTO, version_.handshake_protocol);
+ ASSERT_NE(QUIC_VERSION_UNSUPPORTED, version_.transport_version);
+
CryptoHandshakeMessage chlo =
- crypto_test_utils::GenerateDefaultInchoateCHLO(clock_, version,
- &crypto_config_);
+ crypto_test_utils::GenerateDefaultInchoateCHLO(
+ clock_, version_.transport_version, &crypto_config_);
// Pass an inchoate CHLO.
crypto_test_utils::GenerateFullCHLO(
- chlo, &crypto_config_, server_addr_, client_addr_, version, clock_,
- signed_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
- &full_chlo_);
+ chlo, &crypto_config_, server_addr_, client_addr_,
+ version_.transport_version, clock_, signed_config_,
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &full_chlo_);
}
std::string SerializeFullCHLO() {
@@ -1668,7 +1757,24 @@ class BufferedPacketStoreTest : public QuicDispatcherTest {
CryptoHandshakeMessage full_chlo_;
};
-TEST_F(BufferedPacketStoreTest, ProcessNonChloPacketsUptoLimitAndProcessChlo) {
+ParsedQuicVersionVector BufferedPacketStoreTestParams() {
+ ParsedQuicVersionVector versions;
+ for (const ParsedQuicVersion& version : CurrentSupportedVersions()) {
+ if (version.handshake_protocol != PROTOCOL_QUIC_CRYPTO) {
+ // TODO(b/149597791) Remove this once we can parse ALPN with TLS.
+ break;
+ }
+ versions.push_back(version);
+ }
+ return versions;
+}
+
+INSTANTIATE_TEST_SUITE_P(BufferedPacketStoreTests,
+ BufferedPacketStoreTest,
+ ::testing::ValuesIn(BufferedPacketStoreTestParams()),
+ ::testing::PrintToStringParamName());
+
+TEST_P(BufferedPacketStoreTest, ProcessNonChloPacketsUptoLimitAndProcessChlo) {
InSequence s;
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
QuicConnectionId conn_id = TestConnectionId(1);
@@ -1678,8 +1784,9 @@ TEST_F(BufferedPacketStoreTest, ProcessNonChloPacketsUptoLimitAndProcessChlo) {
ReceivedPacketInfoConnectionIdEquals(conn_id)));
for (size_t i = 1; i <= kDefaultMaxUndecryptablePackets + 1; ++i) {
ProcessPacket(client_address, conn_id, true,
- QuicStrCat("data packet ", i + 1), CONNECTION_ID_PRESENT,
- PACKET_4BYTE_PACKET_NUMBER, /*packet_number=*/i + 1);
+ quiche::QuicheStrCat("data packet ", i + 1),
+ CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
+ /*packet_number=*/i + 1);
}
EXPECT_EQ(0u, dispatcher_->session_map().size())
<< "No session should be created before CHLO arrives.";
@@ -1688,12 +1795,12 @@ TEST_F(BufferedPacketStoreTest, ProcessNonChloPacketsUptoLimitAndProcessChlo) {
data_connection_map_[conn_id].pop_back();
// When CHLO arrives, a new session should be created, and all packets
// buffered should be delivered to the session.
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(conn_id, client_address, QuicStringPiece(), _))
- .WillOnce(testing::Return(CreateSession(
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address,
+ quiche::QuicheStringPiece(), _))
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
&mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
// Only |kDefaultMaxUndecryptablePackets| packets were buffered, and they
// should be delivered in arrival order.
@@ -1707,7 +1814,7 @@ TEST_F(BufferedPacketStoreTest, ProcessNonChloPacketsUptoLimitAndProcessChlo) {
ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
}
-TEST_F(BufferedPacketStoreTest,
+TEST_P(BufferedPacketStoreTest,
ProcessNonChloPacketsForDifferentConnectionsUptoLimit) {
InSequence s;
// A bunch of non-CHLO should be buffered upon arrival.
@@ -1719,7 +1826,7 @@ TEST_F(BufferedPacketStoreTest,
ShouldCreateOrBufferPacketForConnection(
ReceivedPacketInfoConnectionIdEquals(conn_id)));
ProcessPacket(client_address, conn_id, true,
- QuicStrCat("data packet on connection ", i),
+ quiche::QuicheStrCat("data packet on connection ", i),
CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
/*packet_number=*/2);
}
@@ -1742,11 +1849,11 @@ TEST_F(BufferedPacketStoreTest,
ReceivedPacketInfoConnectionIdEquals(conn_id)));
}
EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address,
- QuicStringPiece(), _))
- .WillOnce(testing::Return(CreateSession(
+ quiche::QuicheStringPiece(), _))
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
&mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
// First |kNumConnections| - 1 connections should have buffered
// a packet in store. The rest should have been dropped.
size_t num_packet_to_process = i <= kMaxConnectionsWithoutCHLO ? 2u : 1u;
@@ -1763,17 +1870,17 @@ TEST_F(BufferedPacketStoreTest,
}
// Tests that store delivers empty packet list if CHLO arrives firstly.
-TEST_F(BufferedPacketStoreTest, DeliverEmptyPackets) {
+TEST_P(BufferedPacketStoreTest, DeliverEmptyPackets) {
QuicConnectionId conn_id = TestConnectionId(1);
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(
ReceivedPacketInfoConnectionIdEquals(conn_id)));
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(conn_id, client_address, QuicStringPiece(), _))
- .WillOnce(testing::Return(CreateSession(
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address,
+ quiche::QuicheStringPiece(), _))
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
&mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
ProcessUdpPacket(_, client_address, _));
ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
@@ -1781,23 +1888,24 @@ TEST_F(BufferedPacketStoreTest, DeliverEmptyPackets) {
// Tests that a retransmitted CHLO arrives after a connection for the
// CHLO has been created.
-TEST_F(BufferedPacketStoreTest, ReceiveRetransmittedCHLO) {
+TEST_P(BufferedPacketStoreTest, ReceiveRetransmittedCHLO) {
InSequence s;
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
QuicConnectionId conn_id = TestConnectionId(1);
- ProcessPacket(client_address, conn_id, true, QuicStrCat("data packet ", 2),
- CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
+ ProcessPacket(client_address, conn_id, true,
+ quiche::QuicheStrCat("data packet ", 2), CONNECTION_ID_PRESENT,
+ PACKET_4BYTE_PACKET_NUMBER,
/*packet_number=*/2);
// When CHLO arrives, a new session should be created, and all packets
// buffered should be delivered to the session.
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(conn_id, client_address, QuicStringPiece(), _))
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address,
+ quiche::QuicheStringPiece(), _))
.Times(1) // Only triggered by 1st CHLO.
- .WillOnce(testing::Return(CreateSession(
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
&mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
ProcessUdpPacket(_, _, _))
.Times(3) // Triggered by 1 data packet and 2 CHLOs.
@@ -1811,7 +1919,7 @@ TEST_F(BufferedPacketStoreTest, ReceiveRetransmittedCHLO) {
}
// Tests that expiration of a connection add connection id to time wait list.
-TEST_F(BufferedPacketStoreTest, ReceiveCHLOAfterExpiration) {
+TEST_P(BufferedPacketStoreTest, ReceiveCHLOAfterExpiration) {
InSequence s;
CreateTimeWaitListManager();
QuicBufferedPacketStore* store =
@@ -1820,8 +1928,9 @@ TEST_F(BufferedPacketStoreTest, ReceiveCHLOAfterExpiration) {
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
QuicConnectionId conn_id = TestConnectionId(1);
- ProcessPacket(client_address, conn_id, true, QuicStrCat("data packet ", 2),
- CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
+ ProcessPacket(client_address, conn_id, true,
+ quiche::QuicheStrCat("data packet ", 2), CONNECTION_ID_PRESENT,
+ PACKET_4BYTE_PACKET_NUMBER,
/*packet_number=*/2);
mock_helper_.AdvanceTime(
@@ -1837,7 +1946,7 @@ TEST_F(BufferedPacketStoreTest, ReceiveCHLOAfterExpiration) {
ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
}
-TEST_F(BufferedPacketStoreTest, ProcessCHLOsUptoLimitAndBufferTheRest) {
+TEST_P(BufferedPacketStoreTest, ProcessCHLOsUptoLimitAndBufferTheRest) {
// Process more than (|kMaxNumSessionsToCreate| +
// |kDefaultMaxConnectionsInStore|) CHLOs,
// the first |kMaxNumSessionsToCreate| should create connections immediately,
@@ -1855,12 +1964,12 @@ TEST_F(BufferedPacketStoreTest, ProcessCHLOsUptoLimitAndBufferTheRest) {
if (conn_id <= kMaxNumSessionsToCreate) {
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(conn_id), client_addr_,
- QuicStringPiece(), _))
- .WillOnce(testing::Return(CreateSession(
+ quiche::QuicheStringPiece(), _))
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(conn_id),
client_addr_, &mock_helper_, &mock_alarm_factory_,
&crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
- &session1_)));
+ &session1_))));
EXPECT_CALL(
*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
ProcessUdpPacket(_, _, _))
@@ -1889,11 +1998,11 @@ TEST_F(BufferedPacketStoreTest, ProcessCHLOsUptoLimitAndBufferTheRest) {
++conn_id) {
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(conn_id), client_addr_,
- QuicStringPiece(), _))
- .WillOnce(testing::Return(CreateSession(
+ quiche::QuicheStringPiece(), _))
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(conn_id), client_addr_,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
ProcessUdpPacket(_, _, _))
.WillOnce(WithArg<2>(
@@ -1903,7 +2012,7 @@ TEST_F(BufferedPacketStoreTest, ProcessCHLOsUptoLimitAndBufferTheRest) {
}
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(kNumCHLOs), client_addr_,
- QuicStringPiece(), _))
+ quiche::QuicheStringPiece(), _))
.Times(0);
while (store->HasChlosBuffered()) {
@@ -1916,19 +2025,19 @@ TEST_F(BufferedPacketStoreTest, ProcessCHLOsUptoLimitAndBufferTheRest) {
}
// Duplicated CHLO shouldn't be buffered.
-TEST_F(BufferedPacketStoreTest, BufferDuplicatedCHLO) {
+TEST_P(BufferedPacketStoreTest, BufferDuplicatedCHLO) {
for (uint64_t conn_id = 1; conn_id <= kMaxNumSessionsToCreate + 1;
++conn_id) {
// Last CHLO will be buffered. Others will create connection right away.
if (conn_id <= kMaxNumSessionsToCreate) {
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(conn_id), client_addr_,
- QuicStringPiece(), _))
- .WillOnce(testing::Return(CreateSession(
+ quiche::QuicheStringPiece(), _))
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(conn_id),
client_addr_, &mock_helper_, &mock_alarm_factory_,
&crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
- &session1_)));
+ &session1_))));
EXPECT_CALL(
*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
ProcessUdpPacket(_, _, _))
@@ -1949,11 +2058,11 @@ TEST_F(BufferedPacketStoreTest, BufferDuplicatedCHLO) {
// Reset counter and process buffered CHLO.
EXPECT_CALL(*dispatcher_, CreateQuicSession(last_connection, client_addr_,
- QuicStringPiece(), _))
- .WillOnce(testing::Return(CreateSession(
+ quiche::QuicheStringPiece(), _))
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, last_connection, client_addr_,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
// Only one packet(CHLO) should be process.
EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
ProcessUdpPacket(_, _, _))
@@ -1965,7 +2074,7 @@ TEST_F(BufferedPacketStoreTest, BufferDuplicatedCHLO) {
dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
}
-TEST_F(BufferedPacketStoreTest, BufferNonChloPacketsUptoLimitWithChloBuffered) {
+TEST_P(BufferedPacketStoreTest, BufferNonChloPacketsUptoLimitWithChloBuffered) {
uint64_t last_conn_id = kMaxNumSessionsToCreate + 1;
QuicConnectionId last_connection_id = TestConnectionId(last_conn_id);
for (uint64_t conn_id = 1; conn_id <= last_conn_id; ++conn_id) {
@@ -1973,12 +2082,12 @@ TEST_F(BufferedPacketStoreTest, BufferNonChloPacketsUptoLimitWithChloBuffered) {
if (conn_id <= kMaxNumSessionsToCreate) {
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(conn_id), client_addr_,
- QuicStringPiece(), _))
- .WillOnce(testing::Return(CreateSession(
+ quiche::QuicheStringPiece(), _))
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(conn_id),
client_addr_, &mock_helper_, &mock_alarm_factory_,
&crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
- &session1_)));
+ &session1_))));
EXPECT_CALL(
*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
ProcessUdpPacket(_, _, _))
@@ -2000,11 +2109,11 @@ TEST_F(BufferedPacketStoreTest, BufferNonChloPacketsUptoLimitWithChloBuffered) {
// Reset counter and process buffered CHLO.
EXPECT_CALL(*dispatcher_, CreateQuicSession(last_connection_id, client_addr_,
- QuicStringPiece(), _))
- .WillOnce(testing::Return(CreateSession(
+ quiche::QuicheStringPiece(), _))
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, last_connection_id, client_addr_,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
// Only CHLO and following |kDefaultMaxUndecryptablePackets| data packets
// should be process.
EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
@@ -2019,7 +2128,7 @@ TEST_F(BufferedPacketStoreTest, BufferNonChloPacketsUptoLimitWithChloBuffered) {
// Tests that when dispatcher's packet buffer is full, a CHLO on connection
// which doesn't have buffered CHLO should be buffered.
-TEST_F(BufferedPacketStoreTest, ReceiveCHLOForBufferedConnection) {
+TEST_P(BufferedPacketStoreTest, ReceiveCHLOForBufferedConnection) {
QuicBufferedPacketStore* store =
QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
@@ -2036,12 +2145,12 @@ TEST_F(BufferedPacketStoreTest, ReceiveCHLOForBufferedConnection) {
if (conn_id <= kMaxNumSessionsToCreate + 1) {
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(conn_id), client_addr_,
- QuicStringPiece(), _))
- .WillOnce(testing::Return(CreateSession(
+ quiche::QuicheStringPiece(), _))
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(conn_id),
client_addr_, &mock_helper_, &mock_alarm_factory_,
&crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
- &session1_)));
+ &session1_))));
EXPECT_CALL(
*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
ProcessUdpPacket(_, _, _))
@@ -2064,10 +2173,9 @@ TEST_F(BufferedPacketStoreTest, ReceiveCHLOForBufferedConnection) {
}
// Regression test for b/117874922.
-TEST_F(BufferedPacketStoreTest, ProcessBufferedChloWithDifferentVersion) {
- // Turn off version 99, such that the preferred version is not supported by
- // the server.
- SetQuicReloadableFlag(quic_enable_version_99, false);
+TEST_P(BufferedPacketStoreTest, ProcessBufferedChloWithDifferentVersion) {
+ // Ensure the preferred version is not supported by the server.
+ SetQuicReloadableFlag(quic_enable_version_draft_27, false);
uint64_t last_connection_id = kMaxNumSessionsToCreate + 5;
ParsedQuicVersionVector supported_versions = CurrentSupportedVersions();
for (uint64_t conn_id = 1; conn_id <= last_connection_id; ++conn_id) {
@@ -2077,12 +2185,12 @@ TEST_F(BufferedPacketStoreTest, ProcessBufferedChloWithDifferentVersion) {
if (conn_id <= kMaxNumSessionsToCreate) {
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(conn_id), client_addr_,
- QuicStringPiece(), version))
- .WillOnce(testing::Return(CreateSession(
+ quiche::QuicheStringPiece(), version))
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(conn_id),
client_addr_, &mock_helper_, &mock_alarm_factory_,
&crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
- &session1_)));
+ &session1_))));
EXPECT_CALL(
*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
ProcessUdpPacket(_, _, _))
@@ -2103,11 +2211,11 @@ TEST_F(BufferedPacketStoreTest, ProcessBufferedChloWithDifferentVersion) {
supported_versions[(conn_id - 1) % supported_versions.size()];
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(conn_id), client_addr_,
- QuicStringPiece(), version))
- .WillOnce(testing::Return(CreateSession(
+ quiche::QuicheStringPiece(), version))
+ .WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(conn_id), client_addr_,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
ProcessUdpPacket(_, _, _))
.WillRepeatedly(WithArg<2>(
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.cc b/chromium/net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.cc
index 1f5fb87b9d3..3bfe7e68636 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.cc
@@ -8,7 +8,6 @@
#include <sys/socket.h>
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
-#include "net/quic/platform/impl/quic_socket_utils.h"
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.cc b/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.cc
index ae17f099a96..db97d32572d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.cc
@@ -165,6 +165,36 @@ const char* QuicErrorCodeToString(QuicErrorCode error) {
RETURN_STRING_LITERAL(QUIC_QPACK_DECODER_STREAM_ERROR);
RETURN_STRING_LITERAL(QUIC_STREAM_DATA_BEYOND_CLOSE_OFFSET);
RETURN_STRING_LITERAL(QUIC_STREAM_MULTIPLE_OFFSET);
+ RETURN_STRING_LITERAL(QUIC_HTTP_FRAME_TOO_LARGE);
+ RETURN_STRING_LITERAL(QUIC_HTTP_FRAME_ERROR);
+ RETURN_STRING_LITERAL(QUIC_HTTP_FRAME_UNEXPECTED_ON_SPDY_STREAM);
+ RETURN_STRING_LITERAL(QUIC_HTTP_FRAME_UNEXPECTED_ON_CONTROL_STREAM);
+ RETURN_STRING_LITERAL(QUIC_HTTP_INVALID_FRAME_SEQUENCE_ON_SPDY_STREAM);
+ RETURN_STRING_LITERAL(QUIC_HTTP_INVALID_FRAME_SEQUENCE_ON_CONTROL_STREAM);
+ RETURN_STRING_LITERAL(QUIC_HTTP_DUPLICATE_UNIDIRECTIONAL_STREAM);
+ RETURN_STRING_LITERAL(QUIC_HTTP_SERVER_INITIATED_BIDIRECTIONAL_STREAM);
+ RETURN_STRING_LITERAL(QUIC_HTTP_STREAM_WRONG_DIRECTION);
+ RETURN_STRING_LITERAL(QUIC_HTTP_CLOSED_CRITICAL_STREAM);
+ RETURN_STRING_LITERAL(QUIC_HTTP_MISSING_SETTINGS_FRAME);
+ RETURN_STRING_LITERAL(QUIC_HTTP_DUPLICATE_SETTING_IDENTIFIER);
+ RETURN_STRING_LITERAL(QUIC_HPACK_INDEX_VARINT_ERROR);
+ RETURN_STRING_LITERAL(QUIC_HPACK_NAME_LENGTH_VARINT_ERROR);
+ RETURN_STRING_LITERAL(QUIC_HPACK_VALUE_LENGTH_VARINT_ERROR);
+ RETURN_STRING_LITERAL(QUIC_HPACK_NAME_TOO_LONG);
+ RETURN_STRING_LITERAL(QUIC_HPACK_VALUE_TOO_LONG);
+ RETURN_STRING_LITERAL(QUIC_HPACK_NAME_HUFFMAN_ERROR);
+ RETURN_STRING_LITERAL(QUIC_HPACK_VALUE_HUFFMAN_ERROR);
+ RETURN_STRING_LITERAL(QUIC_HPACK_MISSING_DYNAMIC_TABLE_SIZE_UPDATE);
+ RETURN_STRING_LITERAL(QUIC_HPACK_INVALID_INDEX);
+ RETURN_STRING_LITERAL(QUIC_HPACK_INVALID_NAME_INDEX);
+ RETURN_STRING_LITERAL(QUIC_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_NOT_ALLOWED);
+ RETURN_STRING_LITERAL(
+ QUIC_HPACK_INITIAL_TABLE_SIZE_UPDATE_IS_ABOVE_LOW_WATER_MARK);
+ RETURN_STRING_LITERAL(
+ QUIC_HPACK_TABLE_SIZE_UPDATE_IS_ABOVE_ACKNOWLEDGED_SETTING);
+ RETURN_STRING_LITERAL(QUIC_HPACK_TRUNCATED_BLOCK);
+ RETURN_STRING_LITERAL(QUIC_HPACK_FRAGMENT_TOO_LONG);
+ RETURN_STRING_LITERAL(QUIC_HPACK_COMPRESSED_HEADER_SIZE_EXCEEDS_LIMIT);
RETURN_STRING_LITERAL(QUIC_LAST_ERROR);
// Intentionally have no default case, so we'll break the build
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.h b/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.h
index b6c2d50ca5f..0548e9b0fe0 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.h
@@ -353,8 +353,69 @@ enum QuicErrorCode {
// Received multiple close offset.
QUIC_STREAM_MULTIPLE_OFFSET = 130,
+ // Internal error codes for HTTP/3 errors.
+ QUIC_HTTP_FRAME_TOO_LARGE = 131,
+ QUIC_HTTP_FRAME_ERROR = 132,
+ // A frame that is never allowed on a request stream is received.
+ QUIC_HTTP_FRAME_UNEXPECTED_ON_SPDY_STREAM = 133,
+ // A frame that is never allowed on the control stream is received.
+ QUIC_HTTP_FRAME_UNEXPECTED_ON_CONTROL_STREAM = 134,
+ // An invalid sequence of frames normally allowed on a request stream is
+ // received.
+ QUIC_HTTP_INVALID_FRAME_SEQUENCE_ON_SPDY_STREAM = 151,
+ // A second SETTINGS frame is received on the control stream.
+ QUIC_HTTP_INVALID_FRAME_SEQUENCE_ON_CONTROL_STREAM = 152,
+ // A second instance of a unidirectional stream of a certain type is created.
+ QUIC_HTTP_DUPLICATE_UNIDIRECTIONAL_STREAM = 153,
+ // Client receives a server-initiated bidirectional stream.
+ QUIC_HTTP_SERVER_INITIATED_BIDIRECTIONAL_STREAM = 154,
+ // Server opens stream with stream ID corresponding to client-initiated
+ // stream or vice versa.
+ QUIC_HTTP_STREAM_WRONG_DIRECTION = 155,
+ // Peer closes one of the six critical unidirectional streams (control, QPACK
+ // encoder or decoder, in either direction).
+ QUIC_HTTP_CLOSED_CRITICAL_STREAM = 156,
+ // The first frame received on the control stream is not a SETTINGS frame.
+ QUIC_HTTP_MISSING_SETTINGS_FRAME = 157,
+ // The received SETTINGS frame contains duplicate setting identifiers.
+ QUIC_HTTP_DUPLICATE_SETTING_IDENTIFIER = 158,
+
+ // HPACK header block decoding errors.
+ // Index varint beyond implementation limit.
+ QUIC_HPACK_INDEX_VARINT_ERROR = 135,
+ // Name length varint beyond implementation limit.
+ QUIC_HPACK_NAME_LENGTH_VARINT_ERROR = 136,
+ // Value length varint beyond implementation limit.
+ QUIC_HPACK_VALUE_LENGTH_VARINT_ERROR = 137,
+ // Name length exceeds buffer limit.
+ QUIC_HPACK_NAME_TOO_LONG = 138,
+ // Value length exceeds buffer limit.
+ QUIC_HPACK_VALUE_TOO_LONG = 139,
+ // Name Huffman encoding error.
+ QUIC_HPACK_NAME_HUFFMAN_ERROR = 140,
+ // Value Huffman encoding error.
+ QUIC_HPACK_VALUE_HUFFMAN_ERROR = 141,
+ // Next instruction should have been a dynamic table size update.
+ QUIC_HPACK_MISSING_DYNAMIC_TABLE_SIZE_UPDATE = 142,
+ // Invalid index in indexed header field representation.
+ QUIC_HPACK_INVALID_INDEX = 143,
+ // Invalid index in literal header field with indexed name representation.
+ QUIC_HPACK_INVALID_NAME_INDEX = 144,
+ // Dynamic table size update not allowed.
+ QUIC_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_NOT_ALLOWED = 145,
+ // Initial dynamic table size update is above low water mark.
+ QUIC_HPACK_INITIAL_TABLE_SIZE_UPDATE_IS_ABOVE_LOW_WATER_MARK = 146,
+ // Dynamic table size update is above acknowledged setting.
+ QUIC_HPACK_TABLE_SIZE_UPDATE_IS_ABOVE_ACKNOWLEDGED_SETTING = 147,
+ // HPACK block ends in the middle of an instruction.
+ QUIC_HPACK_TRUNCATED_BLOCK = 148,
+ // Incoming data fragment exceeds buffer limit.
+ QUIC_HPACK_FRAGMENT_TOO_LONG = 149,
+ // Total compressed HPACK data size exceeds limit.
+ QUIC_HPACK_COMPRESSED_HEADER_SIZE_EXCEEDS_LIMIT = 150,
+
// No error. Used as bound while iterating.
- QUIC_LAST_ERROR = 131,
+ QUIC_LAST_ERROR = 159,
};
// QuicErrorCodes is encoded as four octets on-the-wire when doing Google QUIC,
// or a varint62 when doing IETF QUIC. Ensure that its value does not exceed
@@ -370,6 +431,27 @@ QUIC_EXPORT_PRIVATE const char* QuicRstStreamErrorCodeToString(
// Returns the name of the QuicErrorCode as a char*
QUIC_EXPORT_PRIVATE const char* QuicErrorCodeToString(QuicErrorCode error);
+// Wire values for HTTP/3 errors.
+// https://quicwg.org/base-drafts/draft-ietf-quic-http.html#http-error-codes
+enum class QuicHttp3ErrorCode {
+ IETF_QUIC_HTTP3_NO_ERROR = 0x100,
+ IETF_QUIC_HTTP3_GENERAL_PROTOCOL_ERROR = 0x101,
+ IETF_QUIC_HTTP3_INTERNAL_ERROR = 0x102,
+ IETF_QUIC_HTTP3_STREAM_CREATION_ERROR = 0x103,
+ IETF_QUIC_HTTP3_CLOSED_CRITICAL_STREAM = 0x104,
+ IETF_QUIC_HTTP3_FRAME_UNEXPECTED = 0x105,
+ IETF_QUIC_HTTP3_FRAME_ERROR = 0x106,
+ IETF_QUIC_HTTP3_EXCESSIVE_LOAD = 0x107,
+ IETF_QUIC_HTTP3_ID_ERROR = 0x108,
+ IETF_QUIC_HTTP3_SETTINGS_ERROR = 0x109,
+ IETF_QUIC_HTTP3_MISSING_SETTINGS = 0x10A,
+ IETF_QUIC_HTTP3_REQUEST_REJECTED = 0x10B,
+ IETF_QUIC_HTTP3_REQUEST_CANCELLED = 0x10C,
+ IETF_QUIC_HTTP3_REQUEST_INCOMPLETE = 0x10D,
+ IETF_QUIC_HTTP3_CONNECT_ERROR = 0x10F,
+ IETF_QUIC_HTTP3_VERSION_FALLBACK = 0x110,
+};
+
// Wire values for QPACK errors.
// https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#error-code-registration
enum QuicHttpQpackErrorCode {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_flow_controller.cc b/chromium/net/third_party/quiche/src/quic/core/quic_flow_controller.cc
index 40f18a33311..625cf46777b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_flow_controller.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_flow_controller.cc
@@ -14,7 +14,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
namespace quic {
@@ -25,7 +25,7 @@ std::string QuicFlowController::LogLabel() {
if (is_connection_flow_controller_) {
return "connection";
}
- return QuicStrCat("stream ", id_);
+ return quiche::QuicheStrCat("stream ", id_);
}
QuicFlowController::QuicFlowController(
@@ -99,8 +99,8 @@ void QuicFlowController::AddBytesSent(QuicByteCount bytes_sent) {
// This is an error on our side, close the connection as soon as possible.
connection_->CloseConnection(
QUIC_FLOW_CONTROL_SENT_TOO_MUCH_DATA,
- QuicStrCat(send_window_offset_ - (bytes_sent_ + bytes_sent),
- "bytes over send window offset"),
+ quiche::QuicheStrCat(send_window_offset_ - (bytes_sent_ + bytes_sent),
+ "bytes over send window offset"),
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return;
}
@@ -192,6 +192,9 @@ QuicByteCount QuicFlowController::WindowUpdateThreshold() {
}
void QuicFlowController::MaybeSendWindowUpdate() {
+ if (!session_->connection()->connected()) {
+ return;
+ }
// Send WindowUpdate to increase receive window if
// (receive window offset - consumed bytes) < (max window / 2).
// This is behaviour copied from SPDY.
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_flow_controller_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_flow_controller_test.cc
index e9854e9e3f9..8f4cdf7849e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_flow_controller_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_flow_controller_test.cc
@@ -8,12 +8,12 @@
#include <utility>
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_flow_controller_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
using testing::_;
using testing::Invoke;
@@ -91,9 +91,9 @@ TEST_F(QuicFlowControllerTest, SendingBytes) {
// Try to send more bytes, violating flow control.
EXPECT_CALL(*connection_,
CloseConnection(QUIC_FLOW_CONTROL_SENT_TOO_MUCH_DATA, _, _));
- EXPECT_QUIC_BUG(
- flow_controller_->AddBytesSent(send_window_ * 10),
- QuicStrCat("Trying to send an extra ", send_window_ * 10, " bytes"));
+ EXPECT_QUIC_BUG(flow_controller_->AddBytesSent(send_window_ * 10),
+ quiche::QuicheStrCat("Trying to send an extra ",
+ send_window_ * 10, " bytes"));
EXPECT_TRUE(flow_controller_->IsBlocked());
EXPECT_EQ(0u, flow_controller_->SendWindowSize());
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_framer.cc b/chromium/net/third_party/quiche/src/quic/core/quic_framer.cc
index c5708b94995..f90019176aa 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_framer.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_framer.cc
@@ -32,7 +32,6 @@
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_aligned.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_client_stats.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_fallthrough.h"
@@ -41,8 +40,10 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_stack_trace.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
@@ -165,7 +166,6 @@ QuicPacketNumberLength ReadSequenceNumberLength(uint8_t flags) {
}
QuicPacketNumberLength ReadAckPacketNumberLength(
- QuicTransportVersion /*version*/,
uint8_t flags) {
switch (flags & PACKET_FLAGS_8BYTE_PACKET) {
case PACKET_FLAGS_8BYTE_PACKET:
@@ -292,14 +292,14 @@ EncryptionLevel GetEncryptionLevel(const QuicPacketHeader& header) {
return NUM_ENCRYPTION_LEVELS;
}
-QuicStringPiece TruncateErrorString(QuicStringPiece error) {
+quiche::QuicheStringPiece TruncateErrorString(quiche::QuicheStringPiece error) {
if (error.length() <= kMaxErrorStringLength) {
return error;
}
- return QuicStringPiece(error.data(), kMaxErrorStringLength);
+ return quiche::QuicheStringPiece(error.data(), kMaxErrorStringLength);
}
-size_t TruncatedErrorStringSize(const QuicStringPiece& error) {
+size_t TruncatedErrorStringSize(const quiche::QuicheStringPiece& error) {
if (error.length() < kMaxErrorStringLength) {
return error.length();
}
@@ -320,8 +320,8 @@ bool IsValidPacketNumberLength(QuicPacketNumberLength packet_number_length) {
}
bool IsValidFullPacketNumber(uint64_t full_packet_number,
- QuicTransportVersion version) {
- return full_packet_number > 0 || version == QUIC_VERSION_99;
+ ParsedQuicVersion version) {
+ return full_packet_number > 0 || version.HasIetfQuicFrames();
}
bool AppendIetfConnectionIds(bool version_flag,
@@ -384,8 +384,9 @@ std::string GenerateErrorString(std::string initial_error_string,
// the error value in the string.
return initial_error_string;
}
- return QuicStrCat(std::to_string(static_cast<unsigned>(quic_error_code)), ":",
- initial_error_string);
+ return quiche::QuicheStrCat(
+ std::to_string(static_cast<unsigned>(quic_error_code)), ":",
+ initial_error_string);
}
} // namespace
@@ -422,6 +423,8 @@ QuicFramer::QuicFramer(const ParsedQuicVersionVector& supported_versions,
current_received_frame_type_(0) {
DCHECK(!supported_versions.empty());
version_ = supported_versions_[0];
+ DCHECK(version_.IsKnown())
+ << ParsedQuicVersionVectorToString(supported_versions_);
}
QuicFramer::~QuicFramer() {}
@@ -440,7 +443,7 @@ size_t QuicFramer::GetMinStreamFrameSize(QuicTransportVersion version,
(offset != 0 ? QuicDataWriter::GetVarInt62Len(offset) : 0);
}
return kQuicFrameTypeSize + GetStreamIdSize(stream_id) +
- GetStreamOffsetSize(version, offset) +
+ GetStreamOffsetSize(offset) +
(last_frame_in_packet ? 0 : kQuicStreamPayloadLengthSize);
}
@@ -465,12 +468,39 @@ size_t QuicFramer::GetMessageFrameSize(QuicTransportVersion version,
// static
size_t QuicFramer::GetMinAckFrameSize(
QuicTransportVersion version,
+ const QuicAckFrame& ack_frame,
+ uint32_t local_ack_delay_exponent,
QuicPacketNumberLength largest_observed_length) {
if (VersionHasIetfQuicFrames(version)) {
- // The minimal ack frame consists of the following four fields: Largest
- // Acknowledged, ACK Delay, ACK Block Count, and First ACK Block. Minimum
- // size of each is 1 byte.
- return kQuicFrameTypeSize + 4;
+ // The minimal ack frame consists of the following fields: Largest
+ // Acknowledged, ACK Delay, 0 ACK Block Count, First ACK Block and ECN
+ // counts.
+ // Type byte + largest acked.
+ size_t min_size =
+ kQuicFrameTypeSize +
+ QuicDataWriter::GetVarInt62Len(LargestAcked(ack_frame).ToUint64());
+ // Ack delay.
+ min_size += QuicDataWriter::GetVarInt62Len(
+ ack_frame.ack_delay_time.ToMicroseconds() >> local_ack_delay_exponent);
+ // 0 ack block count.
+ min_size += QuicDataWriter::GetVarInt62Len(0);
+ // First ack block.
+ min_size += QuicDataWriter::GetVarInt62Len(
+ ack_frame.packets.Empty() ? 0
+ : ack_frame.packets.rbegin()->Length() - 1);
+ // ECN counts.
+ if (ack_frame.ecn_counters_populated &&
+ (ack_frame.ect_0_count || ack_frame.ect_1_count ||
+ ack_frame.ecn_ce_count)) {
+ min_size += (QuicDataWriter::GetVarInt62Len(ack_frame.ect_0_count) +
+ QuicDataWriter::GetVarInt62Len(ack_frame.ect_1_count) +
+ QuicDataWriter::GetVarInt62Len(ack_frame.ecn_ce_count));
+ }
+ return min_size;
+ }
+ if (GetQuicReloadableFlag(quic_use_ack_frame_to_get_min_size)) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_use_ack_frame_to_get_min_size);
+ largest_observed_length = GetMinPacketNumberLength(LargestAcked(ack_frame));
}
size_t min_size = kQuicFrameTypeSize + largest_observed_length +
kQuicDeltaTimeLargestObservedSize;
@@ -479,7 +509,6 @@ size_t QuicFramer::GetMinAckFrameSize(
// static
size_t QuicFramer::GetStopWaitingFrameSize(
- QuicTransportVersion /*version*/,
QuicPacketNumberLength packet_number_length) {
size_t min_size = kQuicFrameTypeSize + packet_number_length;
return min_size;
@@ -652,6 +681,9 @@ size_t QuicFramer::GetRetransmittableControlFrameSize(
return GetPathChallengeFrameSize(*frame.path_challenge_frame);
case STOP_SENDING_FRAME:
return GetStopSendingFrameSize(*frame.stop_sending_frame);
+ case HANDSHAKE_DONE_FRAME:
+ // HANDSHAKE_DONE has no payload.
+ return kQuicFrameTypeSize;
case STREAM_FRAME:
case ACK_FRAME:
@@ -684,8 +716,7 @@ size_t QuicFramer::GetStreamIdSize(QuicStreamId stream_id) {
}
// static
-size_t QuicFramer::GetStreamOffsetSize(QuicTransportVersion /*version*/,
- QuicStreamOffset offset) {
+size_t QuicFramer::GetStreamOffsetSize(QuicStreamOffset offset) {
// 0 is a special case.
if (offset == 0) {
return 0;
@@ -788,8 +819,9 @@ size_t QuicFramer::GetSerializedFrameLength(
}
bool can_truncate =
frame.type == ACK_FRAME &&
- free_bytes >= GetMinAckFrameSize(version_.transport_version,
- PACKET_6BYTE_PACKET_NUMBER);
+ free_bytes >= GetMinAckFrameSize(
+ version_.transport_version, *frame.ack_frame,
+ local_ack_delay_exponent_, PACKET_6BYTE_PACKET_NUMBER);
if (can_truncate) {
// Truncate the frame so the packet will not exceed kMaxOutgoingPacketSize.
// Note that we may not use every byte of the writer in this case.
@@ -1156,6 +1188,9 @@ size_t QuicFramer::AppendIetfFrames(const QuicFrames& frames,
return 0;
}
break;
+ case HANDSHAKE_DONE_FRAME:
+ // HANDSHAKE_DONE has no payload.
+ break;
default:
set_detailed_error("Tried to append unknown frame type.");
RaiseError(QUIC_INVALID_FRAME_DATA);
@@ -1433,10 +1468,10 @@ bool QuicFramer::ProcessPacket(const QuicEncryptedPacket& packet) {
QUIC_CACHELINE_ALIGNED char buffer[kMaxIncomingPacketSize];
if (packet_has_ietf_packet_header) {
rv = ProcessIetfDataPacket(&reader, &header, packet, buffer,
- QUIC_ARRAYSIZE(buffer));
+ QUICHE_ARRAYSIZE(buffer));
} else {
rv = ProcessDataPacket(&reader, &header, packet, buffer,
- QUIC_ARRAYSIZE(buffer));
+ QUICHE_ARRAYSIZE(buffer));
}
} else {
std::unique_ptr<char[]> large_buffer(new char[packet.length()]);
@@ -1487,6 +1522,31 @@ bool QuicFramer::ProcessRetryPacket(QuicDataReader* reader,
const QuicPacketHeader& header) {
DCHECK_EQ(Perspective::IS_CLIENT, perspective_);
+ if (version_.HasRetryIntegrityTag()) {
+ DCHECK(version_.HasLengthPrefixedConnectionIds()) << version_;
+ const size_t bytes_remaining = reader->BytesRemaining();
+ if (bytes_remaining <= kRetryIntegrityTagLength) {
+ set_detailed_error("Retry packet too short to parse integrity tag.");
+ return false;
+ }
+ const size_t retry_token_length =
+ bytes_remaining - kRetryIntegrityTagLength;
+ DCHECK_GT(retry_token_length, 0u);
+ quiche::QuicheStringPiece retry_token;
+ if (!reader->ReadStringPiece(&retry_token, retry_token_length)) {
+ set_detailed_error("Failed to read retry token.");
+ return false;
+ }
+ quiche::QuicheStringPiece retry_without_tag =
+ reader->PreviouslyReadPayload();
+ quiche::QuicheStringPiece integrity_tag = reader->ReadRemainingPayload();
+ DCHECK_EQ(integrity_tag.length(), kRetryIntegrityTagLength);
+ visitor_->OnRetryPacket(EmptyQuicConnectionId(),
+ header.source_connection_id, retry_token,
+ integrity_tag, retry_without_tag);
+ return true;
+ }
+
QuicConnectionId original_destination_connection_id;
if (version_.HasLengthPrefixedConnectionIds()) {
// Parse Original Destination Connection ID.
@@ -1516,9 +1576,11 @@ bool QuicFramer::ProcessRetryPacket(QuicDataReader* reader,
return false;
}
- QuicStringPiece retry_token = reader->ReadRemainingPayload();
+ quiche::QuicheStringPiece retry_token = reader->ReadRemainingPayload();
visitor_->OnRetryPacket(original_destination_connection_id,
- header.source_connection_id, retry_token);
+ header.source_connection_id, retry_token,
+ /*retry_integrity_tag=*/quiche::QuicheStringPiece(),
+ /*retry_without_tag=*/quiche::QuicheStringPiece());
return true;
}
@@ -1534,7 +1596,8 @@ void QuicFramer::MaybeProcessCoalescedPacket(
return;
}
- QuicStringPiece remaining_data = encrypted_reader.PeekRemainingPayload();
+ quiche::QuicheStringPiece remaining_data =
+ encrypted_reader.PeekRemainingPayload();
DCHECK_EQ(remaining_data.length(), remaining_bytes_length);
const char* coalesced_data =
@@ -1545,22 +1608,39 @@ void QuicFramer::MaybeProcessCoalescedPacket(
QuicPacketHeader coalesced_header;
if (!ProcessIetfPacketHeader(&coalesced_reader, &coalesced_header)) {
- QUIC_PEER_BUG << ENDPOINT
- << "Failed to parse received coalesced header of length "
- << coalesced_data_length << ": "
- << QuicTextUtils::HexEncode(coalesced_data,
- coalesced_data_length)
- << " previous header was " << header;
+ // Some implementations pad their INITIAL packets by sending random invalid
+ // data after the INITIAL, and that is allowed by the specification. If we
+ // fail to parse a subsequent coalesced packet, simply ignore it.
+ QUIC_DLOG(INFO) << ENDPOINT
+ << "Failed to parse received coalesced header of length "
+ << coalesced_data_length
+ << " with error: " << detailed_error_ << ": "
+ << quiche::QuicheTextUtils::HexEncode(coalesced_data,
+ coalesced_data_length)
+ << " previous header was " << header;
return;
}
- if (coalesced_header.destination_connection_id !=
- header.destination_connection_id ||
- (coalesced_header.form != IETF_QUIC_SHORT_HEADER_PACKET &&
- coalesced_header.version != header.version)) {
- QUIC_PEER_BUG << ENDPOINT << "Received mismatched coalesced header "
- << coalesced_header << " previous header was " << header;
- return;
+ if (GetQuicReloadableFlag(quic_minimum_validation_of_coalesced_packets)) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_minimum_validation_of_coalesced_packets);
+ if (coalesced_header.destination_connection_id !=
+ header.destination_connection_id) {
+ // Drop coalesced packets with mismatched connection IDs.
+ QUIC_DLOG(INFO) << ENDPOINT << "Received mismatched coalesced header "
+ << coalesced_header << " previous header was " << header;
+ QUIC_CODE_COUNT(
+ quic_received_coalesced_packets_with_mismatched_connection_id);
+ return;
+ }
+ } else {
+ if (coalesced_header.destination_connection_id !=
+ header.destination_connection_id ||
+ (coalesced_header.form != IETF_QUIC_SHORT_HEADER_PACKET &&
+ coalesced_header.version != header.version)) {
+ QUIC_PEER_BUG << ENDPOINT << "Received mismatched coalesced header "
+ << coalesced_header << " previous header was " << header;
+ return;
+ }
}
QuicEncryptedPacket coalesced_packet(coalesced_data, coalesced_data_length,
@@ -1612,7 +1692,8 @@ bool QuicFramer::ProcessIetfDataPacket(QuicDataReader* encrypted_reader,
perspective_ == Perspective::IS_CLIENT) {
// Peek possible stateless reset token. Will only be used on decryption
// failure.
- QuicStringPiece remaining = encrypted_reader->PeekRemainingPayload();
+ quiche::QuicheStringPiece remaining =
+ encrypted_reader->PeekRemainingPayload();
if (remaining.length() >= sizeof(header->possible_stateless_reset_token)) {
header->has_possible_stateless_reset_token = true;
memcpy(&header->possible_stateless_reset_token,
@@ -1626,7 +1707,7 @@ bool QuicFramer::ProcessIetfDataPacket(QuicDataReader* encrypted_reader,
return false;
}
- QuicStringPiece associated_data;
+ quiche::QuicheStringPiece associated_data;
std::vector<char> ad_storage;
if (header->form == IETF_QUIC_SHORT_HEADER_PACKET ||
header->long_packet_type != VERSION_NEGOTIATION) {
@@ -1652,7 +1733,8 @@ bool QuicFramer::ProcessIetfDataPacket(QuicDataReader* encrypted_reader,
&full_packet_number, &ad_storage)) {
hp_removal_failed = true;
}
- associated_data = QuicStringPiece(ad_storage.data(), ad_storage.size());
+ associated_data =
+ quiche::QuicheStringPiece(ad_storage.data(), ad_storage.size());
} else if (!ProcessAndCalculatePacketNumber(
encrypted_reader, header->packet_number_length,
base_packet_number, &full_packet_number)) {
@@ -1662,7 +1744,7 @@ bool QuicFramer::ProcessIetfDataPacket(QuicDataReader* encrypted_reader,
}
if (hp_removal_failed ||
- !IsValidFullPacketNumber(full_packet_number, transport_version())) {
+ !IsValidFullPacketNumber(full_packet_number, version())) {
if (IsIetfStatelessResetPacket(*header)) {
// This is a stateless reset packet.
QuicIetfStatelessResetPacket packet(
@@ -1676,7 +1758,10 @@ bool QuicFramer::ProcessIetfDataPacket(QuicDataReader* encrypted_reader,
visitor_->OnUndecryptablePacket(
QuicEncryptedPacket(encrypted_reader->FullPayload()),
decryption_level, has_decryption_key);
- set_detailed_error("Unable to decrypt header protection.");
+ set_detailed_error(quiche::QuicheStrCat(
+ "Unable to decrypt ", EncryptionLevelToString(decryption_level),
+ " header protection", has_decryption_key ? "" : " (missing key)",
+ "."));
return RaiseError(QUIC_DECRYPTION_FAILURE);
}
RecordDroppedPacketReason(DroppedPacketReason::INVALID_PACKET_NUMBER);
@@ -1712,7 +1797,8 @@ bool QuicFramer::ProcessIetfDataPacket(QuicDataReader* encrypted_reader,
return false;
}
- QuicStringPiece encrypted = encrypted_reader->ReadRemainingPayload();
+ quiche::QuicheStringPiece encrypted =
+ encrypted_reader->ReadRemainingPayload();
if (!version_.HasHeaderProtection()) {
associated_data = GetAssociatedDataFromEncryptedPacket(
version_.transport_version, packet,
@@ -1740,7 +1826,13 @@ bool QuicFramer::ProcessIetfDataPacket(QuicDataReader* encrypted_reader,
visitor_->OnUndecryptablePacket(
QuicEncryptedPacket(encrypted_reader->FullPayload()), decryption_level,
has_decryption_key);
- set_detailed_error("Unable to decrypt payload.");
+ set_detailed_error(quiche::QuicheStrCat(
+ "Unable to decrypt ", EncryptionLevelToString(decryption_level),
+ " payload",
+ has_decryption_key || !version_.KnowsWhichDecrypterToUse()
+ ? ""
+ : " (missing key)",
+ "."));
RecordDroppedPacketReason(DroppedPacketReason::DECRYPTION_FAILURE);
return RaiseError(QUIC_DECRYPTION_FAILURE);
}
@@ -1808,14 +1900,16 @@ bool QuicFramer::ProcessDataPacket(QuicDataReader* encrypted_reader,
return false;
}
- QuicStringPiece encrypted = encrypted_reader->ReadRemainingPayload();
- QuicStringPiece associated_data = GetAssociatedDataFromEncryptedPacket(
- version_.transport_version, packet,
- GetIncludedDestinationConnectionIdLength(*header),
- GetIncludedSourceConnectionIdLength(*header), header->version_flag,
- header->nonce != nullptr, header->packet_number_length,
- header->retry_token_length_length, header->retry_token.length(),
- header->length_length);
+ quiche::QuicheStringPiece encrypted =
+ encrypted_reader->ReadRemainingPayload();
+ quiche::QuicheStringPiece associated_data =
+ GetAssociatedDataFromEncryptedPacket(
+ version_.transport_version, packet,
+ GetIncludedDestinationConnectionIdLength(*header),
+ GetIncludedSourceConnectionIdLength(*header), header->version_flag,
+ header->nonce != nullptr, header->packet_number_length,
+ header->retry_token_length_length, header->retry_token.length(),
+ header->length_length);
size_t decrypted_length = 0;
EncryptionLevel decrypted_level;
@@ -1829,7 +1923,9 @@ bool QuicFramer::ProcessDataPacket(QuicDataReader* encrypted_reader,
QuicEncryptedPacket(encrypted_reader->FullPayload()), decryption_level,
has_decryption_key);
RecordDroppedPacketReason(DroppedPacketReason::DECRYPTION_FAILURE);
- set_detailed_error("Unable to decrypt payload.");
+ set_detailed_error(quiche::QuicheStrCat(
+ "Unable to decrypt ", EncryptionLevelToString(decryption_level),
+ " payload."));
return RaiseError(QUIC_DECRYPTION_FAILURE);
}
@@ -1893,7 +1989,7 @@ bool QuicFramer::ProcessPublicResetPacket(QuicDataReader* reader,
}
// TODO(satyamshekhar): validate nonce to protect against DoS.
- QuicStringPiece address;
+ quiche::QuicheStringPiece address;
if (reset->GetStringPiece(kCADR, &address)) {
QuicSocketAddressCoder address_coder;
if (address_coder.Decode(address.data(), address.length())) {
@@ -1902,7 +1998,7 @@ bool QuicFramer::ProcessPublicResetPacket(QuicDataReader* reader,
}
}
- QuicStringPiece endpoint_id;
+ quiche::QuicheStringPiece endpoint_id;
if (perspective_ == Perspective::IS_CLIENT &&
reset->GetStringPiece(kEPID, &endpoint_id)) {
packet.endpoint_id = std::string(endpoint_id);
@@ -2269,7 +2365,6 @@ bool QuicFramer::ProcessPublicHeader(QuicDataReader* reader,
// static
QuicPacketNumberLength QuicFramer::GetMinPacketNumberLength(
- QuicTransportVersion /*version*/,
QuicPacketNumber packet_number) {
DCHECK(packet_number.IsInitialized());
if (packet_number < QuicPacketNumber(1 << (PACKET_1BYTE_PACKET_NUMBER * 8))) {
@@ -2357,7 +2452,7 @@ bool QuicFramer::ProcessUnauthenticatedHeader(QuicDataReader* encrypted_reader,
return RaiseError(QUIC_INVALID_PACKET_HEADER);
}
- if (!IsValidFullPacketNumber(full_packet_number, transport_version())) {
+ if (!IsValidFullPacketNumber(full_packet_number, version())) {
set_detailed_error("packet numbers cannot be 0.");
return RaiseError(QUIC_INVALID_PACKET_HEADER);
}
@@ -2468,7 +2563,7 @@ bool QuicFramer::ProcessIetfHeaderTypeByte(QuicDataReader* reader,
set_detailed_error("Fixed bit is 0 in short header.");
return false;
}
- if (!header->version.HasHeaderProtection()) {
+ if (!version_.HasHeaderProtection()) {
header->packet_number_length = GetShortHeaderPacketNumberLength(type);
}
QUIC_DVLOG(1) << "packet_number_length = " << header->packet_number_length;
@@ -2521,10 +2616,7 @@ bool QuicFramer::ProcessAndValidateIetfConnectionIdLength(
if (!should_update_expected_server_connection_id_length &&
(dcil != *destination_connection_id_length ||
scil != *source_connection_id_length) &&
- !QuicUtils::VariableLengthConnectionIdAllowedForVersion(
- version.transport_version)) {
- // TODO(dschinazi): use the framer's version once the
- // OnProtocolVersionMismatch call is moved to before this is run.
+ version.IsKnown() && !version.AllowsVariableLengthConnectionIds()) {
QUIC_DVLOG(1) << "dcil: " << static_cast<uint32_t>(dcil)
<< ", scil: " << static_cast<uint32_t>(scil);
*detailed_error = "Invalid ConnectionId length.";
@@ -2619,7 +2711,7 @@ bool QuicFramer::ProcessIetfPacketHeader(QuicDataReader* reader,
}
return true;
}
- if (!header->version.HasHeaderProtection()) {
+ if (header->version.IsKnown() && !header->version.HasHeaderProtection()) {
header->packet_number_length =
GetLongHeaderPacketNumberLength(header->type_byte);
}
@@ -2903,7 +2995,7 @@ bool QuicFramer::ProcessFrameData(QuicDataReader* reader,
return RaiseError(QUIC_INVALID_FRAME_DATA);
}
QuicCryptoFrame frame;
- if (!ProcessCryptoFrame(reader, &frame)) {
+ if (!ProcessCryptoFrame(reader, GetEncryptionLevel(header), &frame)) {
return RaiseError(QUIC_INVALID_FRAME_DATA);
}
QUIC_DVLOG(2) << ENDPOINT << "Processing crypto frame " << frame;
@@ -3024,8 +3116,6 @@ bool QuicFramer::ProcessIetfFrameData(QuicDataReader* reader,
if (!ProcessMaxDataFrame(reader, &frame)) {
return RaiseError(QUIC_INVALID_MAX_DATA_FRAME_DATA);
}
- // TODO(fkastenholz): Or should we create a new visitor function,
- // OnMaxDataFrame()?
QUIC_DVLOG(2) << ENDPOINT << "Processing IETF max data frame "
<< frame;
if (!visitor_->OnWindowUpdateFrame(frame)) {
@@ -3040,8 +3130,6 @@ bool QuicFramer::ProcessIetfFrameData(QuicDataReader* reader,
if (!ProcessMaxStreamDataFrame(reader, &frame)) {
return RaiseError(QUIC_INVALID_MAX_STREAM_DATA_FRAME_DATA);
}
- // TODO(fkastenholz): Or should we create a new visitor function,
- // OnMaxStreamDataFrame()?
QUIC_DVLOG(2) << ENDPOINT << "Processing IETF max stream data frame "
<< frame;
if (!visitor_->OnWindowUpdateFrame(frame)) {
@@ -3079,9 +3167,9 @@ bool QuicFramer::ProcessIetfFrameData(QuicDataReader* reader,
}
break;
}
- case IETF_BLOCKED: {
+ case IETF_DATA_BLOCKED: {
QuicBlockedFrame frame;
- if (!ProcessIetfBlockedFrame(reader, &frame)) {
+ if (!ProcessDataBlockedFrame(reader, &frame)) {
return RaiseError(QUIC_INVALID_BLOCKED_DATA);
}
QUIC_DVLOG(2) << ENDPOINT << "Processing IETF blocked frame "
@@ -3093,9 +3181,9 @@ bool QuicFramer::ProcessIetfFrameData(QuicDataReader* reader,
}
break;
}
- case IETF_STREAM_BLOCKED: {
+ case IETF_STREAM_DATA_BLOCKED: {
QuicBlockedFrame frame;
- if (!ProcessStreamBlockedFrame(reader, &frame)) {
+ if (!ProcessStreamDataBlockedFrame(reader, &frame)) {
return RaiseError(QUIC_INVALID_STREAM_BLOCKED_DATA);
}
QUIC_DVLOG(2) << ENDPOINT << "Processing IETF stream blocked frame "
@@ -3113,7 +3201,6 @@ bool QuicFramer::ProcessIetfFrameData(QuicDataReader* reader,
if (!ProcessStreamsBlockedFrame(reader, &frame, frame_type)) {
return RaiseError(QUIC_STREAMS_BLOCKED_DATA);
}
- QUIC_CODE_COUNT_N(quic_streams_blocked_received, 1, 2);
QUIC_DVLOG(2) << ENDPOINT << "Processing IETF streams blocked frame "
<< frame;
if (!visitor_->OnStreamsBlockedFrame(frame)) {
@@ -3238,7 +3325,7 @@ bool QuicFramer::ProcessIetfFrameData(QuicDataReader* reader,
}
case IETF_CRYPTO: {
QuicCryptoFrame frame;
- if (!ProcessCryptoFrame(reader, &frame)) {
+ if (!ProcessCryptoFrame(reader, GetEncryptionLevel(header), &frame)) {
return RaiseError(QUIC_INVALID_FRAME_DATA);
}
QUIC_DVLOG(2) << ENDPOINT << "Processing IETF crypto frame " << frame;
@@ -3249,6 +3336,19 @@ bool QuicFramer::ProcessIetfFrameData(QuicDataReader* reader,
}
break;
}
+ case IETF_HANDSHAKE_DONE: {
+ // HANDSHAKE_DONE has no payload.
+ QuicHandshakeDoneFrame handshake_done_frame;
+ if (!visitor_->OnHandshakeDoneFrame(handshake_done_frame)) {
+ QUIC_DVLOG(1) << ENDPOINT
+ << "Visitor asked to stop further processing.";
+ // Returning true since there was no parsing error.
+ return true;
+ }
+ QUIC_DVLOG(2) << ENDPOINT << "Processing handshake done frame "
+ << handshake_done_frame;
+ break;
+ }
default:
set_detailed_error("Illegal frame type.");
@@ -3329,8 +3429,8 @@ bool QuicFramer::ProcessStreamFrame(QuicDataReader* reader,
return false;
}
- // TODO(ianswett): Don't use QuicStringPiece as an intermediary.
- QuicStringPiece data;
+ // TODO(ianswett): Don't use quiche::QuicheStringPiece as an intermediary.
+ quiche::QuicheStringPiece data;
if (has_data_length) {
if (!reader->ReadStringPiece16(&data)) {
set_detailed_error("Unable to read frame data.");
@@ -3352,8 +3452,7 @@ bool QuicFramer::ProcessIetfStreamFrame(QuicDataReader* reader,
uint8_t frame_type,
QuicStreamFrame* frame) {
// Read stream id from the frame. It's always present.
- if (!reader->ReadVarIntU32(&frame->stream_id)) {
- set_detailed_error("Unable to read stream_id.");
+ if (!ReadUint32FromVarint62(reader, IETF_STREAM, &frame->stream_id)) {
return false;
}
@@ -3392,8 +3491,8 @@ bool QuicFramer::ProcessIetfStreamFrame(QuicDataReader* reader,
frame->fin = false;
}
- // TODO(ianswett): Don't use QuicStringPiece as an intermediary.
- QuicStringPiece data;
+ // TODO(ianswett): Don't use quiche::QuicheStringPiece as an intermediary.
+ quiche::QuicheStringPiece data;
if (!reader->ReadStringPiece(&data, frame->data_length)) {
set_detailed_error("Unable to read frame data.");
return false;
@@ -3405,7 +3504,9 @@ bool QuicFramer::ProcessIetfStreamFrame(QuicDataReader* reader,
}
bool QuicFramer::ProcessCryptoFrame(QuicDataReader* reader,
+ EncryptionLevel encryption_level,
QuicCryptoFrame* frame) {
+ frame->level = encryption_level;
if (!reader->ReadVarInt62(&frame->offset)) {
set_detailed_error("Unable to read crypto data offset.");
return false;
@@ -3418,8 +3519,8 @@ bool QuicFramer::ProcessCryptoFrame(QuicDataReader* reader,
}
frame->data_length = len;
- // TODO(ianswett): Don't use QuicStringPiece as an intermediary.
- QuicStringPiece data;
+ // TODO(ianswett): Don't use quiche::QuicheStringPiece as an intermediary.
+ quiche::QuicheStringPiece data;
if (!reader->ReadStringPiece(&data, frame->data_length)) {
set_detailed_error("Unable to read frame data.");
return false;
@@ -3437,11 +3538,9 @@ bool QuicFramer::ProcessAckFrame(QuicDataReader* reader, uint8_t frame_type) {
// Determine the two lengths from the frame type: largest acked length,
// ack block length.
const QuicPacketNumberLength ack_block_length = ReadAckPacketNumberLength(
- version_.transport_version,
ExtractBits(frame_type, kQuicSequenceNumberLengthNumBits,
kActBlockLengthOffset));
const QuicPacketNumberLength largest_acked_length = ReadAckPacketNumberLength(
- version_.transport_version,
ExtractBits(frame_type, kQuicSequenceNumberLengthNumBits,
kLargestAckedOffset));
@@ -3497,10 +3596,11 @@ bool QuicFramer::ProcessAckFrame(QuicDataReader* reader, uint8_t frame_type) {
first_ack_block_underflow = true;
}
if (first_ack_block_underflow) {
- set_detailed_error(QuicStrCat("Underflow with first ack block length ",
- first_block_length, " largest acked is ",
- largest_acked, ".")
- .c_str());
+ set_detailed_error(
+ quiche::QuicheStrCat("Underflow with first ack block length ",
+ first_block_length, " largest acked is ",
+ largest_acked, ".")
+ .c_str());
return false;
}
@@ -3533,8 +3633,9 @@ bool QuicFramer::ProcessAckFrame(QuicDataReader* reader, uint8_t frame_type) {
}
if (ack_block_underflow) {
set_detailed_error(
- QuicStrCat("Underflow with ack block length ", current_block_length,
- ", end of block is ", first_received - gap, ".")
+ quiche::QuicheStrCat("Underflow with ack block length ",
+ current_block_length, ", end of block is ",
+ first_received - gap, ".")
.c_str());
return false;
}
@@ -3566,7 +3667,13 @@ bool QuicFramer::ProcessAckFrame(QuicDataReader* reader, uint8_t frame_type) {
}
// Done processing the ACK frame.
- return visitor_->OnAckFrameEnd(QuicPacketNumber(first_received));
+ if (!visitor_->OnAckFrameEnd(QuicPacketNumber(first_received))) {
+ set_detailed_error(
+ "Error occurs when visitor finishes processing the ACK frame.");
+ return false;
+ }
+
+ return true;
}
bool QuicFramer::ProcessTimestampsInAckFrame(uint8_t num_received_packets,
@@ -3582,10 +3689,11 @@ bool QuicFramer::ProcessTimestampsInAckFrame(uint8_t num_received_packets,
}
if (largest_acked.ToUint64() <= delta_from_largest_observed) {
- set_detailed_error(QuicStrCat("delta_from_largest_observed too high: ",
- delta_from_largest_observed,
- ", largest_acked: ", largest_acked.ToUint64())
- .c_str());
+ set_detailed_error(
+ quiche::QuicheStrCat("delta_from_largest_observed too high: ",
+ delta_from_largest_observed,
+ ", largest_acked: ", largest_acked.ToUint64())
+ .c_str());
return false;
}
@@ -3610,9 +3718,9 @@ bool QuicFramer::ProcessTimestampsInAckFrame(uint8_t num_received_packets,
}
if (largest_acked.ToUint64() <= delta_from_largest_observed) {
set_detailed_error(
- QuicStrCat("delta_from_largest_observed too high: ",
- delta_from_largest_observed,
- ", largest_acked: ", largest_acked.ToUint64())
+ quiche::QuicheStrCat("delta_from_largest_observed too high: ",
+ delta_from_largest_observed,
+ ", largest_acked: ", largest_acked.ToUint64())
.c_str());
return false;
}
@@ -3663,26 +3771,6 @@ bool QuicFramer::ProcessIetfAckFrame(QuicDataReader* reader,
ack_frame->ack_delay_time =
QuicTime::Delta::FromMicroseconds(ack_delay_time_in_us);
}
- if (frame_type == IETF_ACK_ECN) {
- ack_frame->ecn_counters_populated = true;
- if (!reader->ReadVarInt62(&ack_frame->ect_0_count)) {
- set_detailed_error("Unable to read ack ect_0_count.");
- return false;
- }
- if (!reader->ReadVarInt62(&ack_frame->ect_1_count)) {
- set_detailed_error("Unable to read ack ect_1_count.");
- return false;
- }
- if (!reader->ReadVarInt62(&ack_frame->ecn_ce_count)) {
- set_detailed_error("Unable to read ack ecn_ce_count.");
- return false;
- }
- } else {
- ack_frame->ecn_counters_populated = false;
- ack_frame->ect_0_count = 0;
- ack_frame->ect_1_count = 0;
- ack_frame->ecn_ce_count = 0;
- }
if (!visitor_->OnAckFrameStart(QuicPacketNumber(largest_acked),
ack_frame->ack_delay_time)) {
// The visitor suppresses further processing of the packet. Although this is
@@ -3718,10 +3806,11 @@ bool QuicFramer::ProcessIetfAckFrame(QuicDataReader* reader,
// error if the value is wrong.
if (ack_block_value + first_sending_packet_number_.ToUint64() >
largest_acked) {
- set_detailed_error(QuicStrCat("Underflow with first ack block length ",
- ack_block_value + 1, " largest acked is ",
- largest_acked, ".")
- .c_str());
+ set_detailed_error(
+ quiche::QuicheStrCat("Underflow with first ack block length ",
+ ack_block_value + 1, " largest acked is ",
+ largest_acked, ".")
+ .c_str());
return false;
}
@@ -3751,8 +3840,9 @@ bool QuicFramer::ProcessIetfAckFrame(QuicDataReader* reader,
// The test is written this way to detect wrap-arounds.
if ((gap_block_value + 2) > block_low) {
set_detailed_error(
- QuicStrCat("Underflow with gap block length ", gap_block_value + 1,
- " previous ack block start is ", block_low, ".")
+ quiche::QuicheStrCat("Underflow with gap block length ",
+ gap_block_value + 1,
+ " previous ack block start is ", block_low, ".")
.c_str());
return false;
}
@@ -3772,8 +3862,9 @@ bool QuicFramer::ProcessIetfAckFrame(QuicDataReader* reader,
if (ack_block_value + first_sending_packet_number_.ToUint64() >
(block_high - 1)) {
set_detailed_error(
- QuicStrCat("Underflow with ack block length ", ack_block_value + 1,
- " latest ack block end is ", block_high - 1, ".")
+ quiche::QuicheStrCat("Underflow with ack block length ",
+ ack_block_value + 1, " latest ack block end is ",
+ block_high - 1, ".")
.c_str());
return false;
}
@@ -3793,7 +3884,34 @@ bool QuicFramer::ProcessIetfAckFrame(QuicDataReader* reader,
ack_block_count--;
}
- return visitor_->OnAckFrameEnd(QuicPacketNumber(block_low));
+ if (frame_type == IETF_ACK_ECN) {
+ ack_frame->ecn_counters_populated = true;
+ if (!reader->ReadVarInt62(&ack_frame->ect_0_count)) {
+ set_detailed_error("Unable to read ack ect_0_count.");
+ return false;
+ }
+ if (!reader->ReadVarInt62(&ack_frame->ect_1_count)) {
+ set_detailed_error("Unable to read ack ect_1_count.");
+ return false;
+ }
+ if (!reader->ReadVarInt62(&ack_frame->ecn_ce_count)) {
+ set_detailed_error("Unable to read ack ecn_ce_count.");
+ return false;
+ }
+ } else {
+ ack_frame->ecn_counters_populated = false;
+ ack_frame->ect_0_count = 0;
+ ack_frame->ect_1_count = 0;
+ ack_frame->ecn_ce_count = 0;
+ }
+ // TODO(fayang): Report ECN counts to visitor when they are actually used.
+ if (!visitor_->OnAckFrameEnd(QuicPacketNumber(block_low))) {
+ set_detailed_error(
+ "Error occurs when visitor finishes processing the ACK frame.");
+ return false;
+ }
+
+ return true;
}
bool QuicFramer::ProcessStopWaitingFrame(QuicDataReader* reader,
@@ -3864,7 +3982,7 @@ bool QuicFramer::ProcessConnectionCloseFrame(QuicDataReader* reader,
// available in extracted_error_code.
frame->extracted_error_code = frame->quic_error_code;
- QuicStringPiece error_details;
+ quiche::QuicheStringPiece error_details;
if (!reader->ReadStringPiece16(&error_details)) {
set_detailed_error("Unable to read connection close error details.");
return false;
@@ -3895,7 +4013,7 @@ bool QuicFramer::ProcessGoAwayFrame(QuicDataReader* reader,
}
frame->last_good_stream_id = static_cast<QuicStreamId>(stream_id);
- QuicStringPiece reason_phrase;
+ quiche::QuicheStringPiece reason_phrase;
if (!reader->ReadStringPiece16(&reason_phrase)) {
set_detailed_error("Unable to read goaway reason.");
return false;
@@ -3949,7 +4067,7 @@ bool QuicFramer::ProcessMessageFrame(QuicDataReader* reader,
bool no_message_length,
QuicMessageFrame* frame) {
if (no_message_length) {
- QuicStringPiece remaining(reader->ReadRemainingPayload());
+ quiche::QuicheStringPiece remaining(reader->ReadRemainingPayload());
frame->data = remaining.data();
frame->message_length = remaining.length();
return true;
@@ -3961,7 +4079,7 @@ bool QuicFramer::ProcessMessageFrame(QuicDataReader* reader,
return false;
}
- QuicStringPiece message_piece;
+ quiche::QuicheStringPiece message_piece;
if (!reader->ReadStringPiece(&message_piece, message_length)) {
set_detailed_error("Unable to read message data");
return false;
@@ -3974,7 +4092,7 @@ bool QuicFramer::ProcessMessageFrame(QuicDataReader* reader,
}
// static
-QuicStringPiece QuicFramer::GetAssociatedDataFromEncryptedPacket(
+quiche::QuicheStringPiece QuicFramer::GetAssociatedDataFromEncryptedPacket(
QuicTransportVersion version,
const QuicEncryptedPacket& encrypted,
QuicConnectionIdLength destination_connection_id_length,
@@ -3986,7 +4104,7 @@ QuicStringPiece QuicFramer::GetAssociatedDataFromEncryptedPacket(
uint64_t retry_token_length,
QuicVariableLengthIntegerLength length_length) {
// TODO(ianswett): This is identical to QuicData::AssociatedData.
- return QuicStringPiece(
+ return quiche::QuicheStringPiece(
encrypted.data(),
GetStartOfEncryptedData(version, destination_connection_id_length,
source_connection_id_length, includes_version,
@@ -4065,6 +4183,12 @@ void QuicFramer::SetEncrypter(EncryptionLevel level,
encrypter_[level] = std::move(encrypter);
}
+void QuicFramer::RemoveEncrypter(EncryptionLevel level) {
+ QUIC_DVLOG(1) << ENDPOINT << "Removing encrypter of "
+ << EncryptionLevelToString(level);
+ encrypter_[level] = nullptr;
+}
+
void QuicFramer::SetInitialObfuscators(QuicConnectionId connection_id) {
CrypterPair crypters;
CryptoUtils::CreateInitialObfuscators(perspective_, version_, connection_id,
@@ -4091,9 +4215,10 @@ size_t QuicFramer::EncryptInPlace(EncryptionLevel level,
size_t output_length = 0;
if (!encrypter_[level]->EncryptPacket(
packet_number.ToUint64(),
- QuicStringPiece(buffer, ad_len), // Associated data
- QuicStringPiece(buffer + ad_len, total_len - ad_len), // Plaintext
- buffer + ad_len, // Destination buffer
+ quiche::QuicheStringPiece(buffer, ad_len), // Associated data
+ quiche::QuicheStringPiece(buffer + ad_len,
+ total_len - ad_len), // Plaintext
+ buffer + ad_len, // Destination buffer
&output_length, buffer_len - ad_len)) {
RaiseError(QUIC_ENCRYPTION_FAILURE);
return 0;
@@ -4132,7 +4257,7 @@ bool QuicFramer::ApplyHeaderProtection(EncryptionLevel level,
// Sample the ciphertext and generate the mask to use for header protection.
size_t sample_offset = pn_offset + 4;
QuicDataReader sample_reader(buffer, buffer_len);
- QuicStringPiece sample;
+ quiche::QuicheStringPiece sample;
if (!sample_reader.Seek(sample_offset) ||
!sample_reader.ReadStringPiece(&sample, kHPSampleLen)) {
QUIC_BUG << "Not enough bytes to sample: sample_offset " << sample_offset
@@ -4141,6 +4266,14 @@ bool QuicFramer::ApplyHeaderProtection(EncryptionLevel level,
return false;
}
+ if (encrypter_[level] == nullptr) {
+ QUIC_BUG
+ << ENDPOINT
+ << "Attempted to apply header protection without encrypter at level "
+ << EncryptionLevelToString(level) << " using " << version_;
+ return false;
+ }
+
std::string mask = encrypter_[level]->GenerateHeaderProtectionMask(sample);
if (mask.empty()) {
QUIC_BUG << "Unable to generate header protection mask.";
@@ -4219,11 +4352,11 @@ bool QuicFramer::RemoveHeaderProtection(QuicDataReader* reader,
// Read a sample from the ciphertext and compute the mask to use for header
// protection.
- QuicStringPiece remaining_packet = reader->PeekRemainingPayload();
+ quiche::QuicheStringPiece remaining_packet = reader->PeekRemainingPayload();
QuicDataReader sample_reader(remaining_packet);
// The sample starts 4 bytes after the start of the packet number.
- QuicStringPiece pn;
+ quiche::QuicheStringPiece pn;
if (!sample_reader.ReadStringPiece(&pn, 4)) {
QUIC_DVLOG(1) << "Not enough data to sample";
return false;
@@ -4260,7 +4393,7 @@ bool QuicFramer::RemoveHeaderProtection(QuicDataReader* reader,
static_cast<QuicPacketNumberLength>((header->type_byte & 0x03) + 1);
char pn_buffer[IETF_MAX_PACKET_NUMBER_LENGTH] = {};
- QuicDataWriter pn_writer(QUIC_ARRAYSIZE(pn_buffer), pn_buffer);
+ QuicDataWriter pn_writer(QUICHE_ARRAYSIZE(pn_buffer), pn_buffer);
// Read the (protected) packet number from the reader and unmask the packet
// number.
@@ -4291,7 +4424,7 @@ bool QuicFramer::RemoveHeaderProtection(QuicDataReader* reader,
}
// Get the associated data, and apply the same unmasking operations to it.
- QuicStringPiece ad = GetAssociatedDataFromEncryptedPacket(
+ quiche::QuicheStringPiece ad = GetAssociatedDataFromEncryptedPacket(
version_.transport_version, packet,
GetIncludedDestinationConnectionIdLength(*header),
GetIncludedSourceConnectionIdLength(*header), header->version_flag,
@@ -4333,7 +4466,7 @@ size_t QuicFramer::EncryptPayload(EncryptionLevel level,
return 0;
}
- QuicStringPiece associated_data =
+ quiche::QuicheStringPiece associated_data =
packet.AssociatedData(version_.transport_version);
// Copy in the header, because the encrypter only populates the encrypted
// plaintext content.
@@ -4360,6 +4493,12 @@ size_t QuicFramer::EncryptPayload(EncryptionLevel level,
size_t QuicFramer::GetCiphertextSize(EncryptionLevel level,
size_t plaintext_size) const {
+ if (encrypter_[level] == nullptr) {
+ QUIC_BUG << ENDPOINT
+ << "Attempted to get ciphertext size without encrypter at level "
+ << EncryptionLevelToString(level) << " using " << version_;
+ return plaintext_size;
+ }
return encrypter_[level]->GetCiphertextSize(plaintext_size);
}
@@ -4380,8 +4519,8 @@ size_t QuicFramer::GetMaxPlaintextSize(size_t ciphertext_size) {
return min_plaintext_size;
}
-bool QuicFramer::DecryptPayload(QuicStringPiece encrypted,
- QuicStringPiece associated_data,
+bool QuicFramer::DecryptPayload(quiche::QuicheStringPiece encrypted,
+ quiche::QuicheStringPiece associated_data,
const QuicPacketHeader& header,
char* decrypted_buffer,
size_t buffer_length,
@@ -4495,8 +4634,32 @@ size_t QuicFramer::GetIetfAckFrameSize(const QuicAckFrame& frame) {
ack_delay_time_us = ack_delay_time_us >> local_ack_delay_exponent_;
ack_frame_size += QuicDataWriter::GetVarInt62Len(ack_delay_time_us);
- // If |ecn_counters_populated| is true and any of the ecn counters is non-0
- // then the ecn counters are included...
+ if (frame.packets.Empty() || frame.packets.Max() != largest_acked) {
+ QUIC_BUG << "Malformed ack frame";
+ // ACK frame serialization will fail and connection will be closed.
+ return ack_frame_size;
+ }
+
+ // Ack block count.
+ ack_frame_size +=
+ QuicDataWriter::GetVarInt62Len(frame.packets.NumIntervals() - 1);
+
+ // First Ack range.
+ auto iter = frame.packets.rbegin();
+ ack_frame_size += QuicDataWriter::GetVarInt62Len(iter->Length() - 1);
+ QuicPacketNumber previous_smallest = iter->min();
+ ++iter;
+
+ // Ack blocks.
+ for (; iter != frame.packets.rend(); ++iter) {
+ const uint64_t gap = previous_smallest - iter->max() - 1;
+ const uint64_t ack_range = iter->Length() - 1;
+ ack_frame_size += (QuicDataWriter::GetVarInt62Len(gap) +
+ QuicDataWriter::GetVarInt62Len(ack_range));
+ previous_smallest = iter->min();
+ }
+
+ // ECN counts.
if (frame.ecn_counters_populated &&
(frame.ect_0_count || frame.ect_1_count || frame.ecn_ce_count)) {
ack_frame_size += QuicDataWriter::GetVarInt62Len(frame.ect_0_count);
@@ -4504,72 +4667,6 @@ size_t QuicFramer::GetIetfAckFrameSize(const QuicAckFrame& frame) {
ack_frame_size += QuicDataWriter::GetVarInt62Len(frame.ecn_ce_count);
}
- // The rest (ack_block_count, first_ack_block, and additional ack
- // blocks, if any) depends:
- uint64_t ack_block_count = frame.packets.NumIntervals();
- if (ack_block_count == 0) {
- // If the QuicAckFrame has no Intervals, then it is interpreted
- // as an ack of a single packet at QuicAckFrame.largest_acked.
- // The resulting ack will consist of only the frame's
- // largest_ack & first_ack_block fields. The first ack block will be 0
- // (indicating a single packet) and the ack block_count will be 0.
- // Each 0 takes 1 byte when VarInt62 encoded.
- ack_frame_size += 2;
- return ack_frame_size;
- }
-
- auto itr = frame.packets.rbegin();
- QuicPacketNumber ack_block_largest = largest_acked;
- QuicPacketNumber ack_block_smallest;
- if ((itr->max() - 1) == largest_acked) {
- // If largest_acked + 1 is equal to the Max() of the first Interval
- // in the QuicAckFrame then the first Interval is the first ack block of the
- // frame; remaining Intervals are additional ack blocks. The QuicAckFrame's
- // first Interval is encoded in the frame's largest_acked/first_ack_block,
- // the remaining Intervals are encoded in additional ack blocks in the
- // frame, and the packet's ack_block_count is the number of QuicAckFrame
- // Intervals - 1.
- ack_block_smallest = itr->min();
- itr++;
- ack_block_count--;
- } else {
- // If QuicAckFrame.largest_acked is NOT equal to the Max() of
- // the first Interval then it is interpreted as acking a single
- // packet at QuicAckFrame.largest_acked, with additional
- // Intervals indicating additional ack blocks. The encoding is
- // a) The packet's largest_acked is the QuicAckFrame's largest
- // acked,
- // b) the first ack block size is 0,
- // c) The packet's ack_block_count is the number of QuicAckFrame
- // Intervals, and
- // d) The QuicAckFrame Intervals are encoded in additional ack
- // blocks in the packet.
- ack_block_smallest = largest_acked;
- }
- size_t ack_block_count_size = QuicDataWriter::GetVarInt62Len(ack_block_count);
- ack_frame_size += ack_block_count_size;
-
- uint64_t first_ack_block = ack_block_largest - ack_block_smallest;
- size_t first_ack_block_size = QuicDataWriter::GetVarInt62Len(first_ack_block);
- ack_frame_size += first_ack_block_size;
-
- // Account for the remaining Intervals, if any.
- while (ack_block_count != 0) {
- uint64_t gap_size = ack_block_smallest - itr->max();
- // Decrement per the protocol specification
- size_t size_of_gap_size = QuicDataWriter::GetVarInt62Len(gap_size - 1);
- ack_frame_size += size_of_gap_size;
-
- uint64_t block_size = itr->max() - itr->min();
- // Decrement per the protocol specification
- size_t size_of_block_size = QuicDataWriter::GetVarInt62Len(block_size - 1);
- ack_frame_size += size_of_block_size;
-
- ack_block_smallest = itr->min();
- itr++;
- ack_block_count--;
- }
-
return ack_frame_size;
}
@@ -4584,12 +4681,13 @@ size_t QuicFramer::GetAckFrameSize(
}
AckFrameInfo ack_info = GetAckFrameInfo(ack);
QuicPacketNumberLength largest_acked_length =
- GetMinPacketNumberLength(version_.transport_version, LargestAcked(ack));
- QuicPacketNumberLength ack_block_length = GetMinPacketNumberLength(
- version_.transport_version, QuicPacketNumber(ack_info.max_block_length));
+ GetMinPacketNumberLength(LargestAcked(ack));
+ QuicPacketNumberLength ack_block_length =
+ GetMinPacketNumberLength(QuicPacketNumber(ack_info.max_block_length));
ack_size =
- GetMinAckFrameSize(version_.transport_version, largest_acked_length);
+ GetMinAckFrameSize(version_.transport_version, ack,
+ local_ack_delay_exponent_, largest_acked_length);
// First ack block length.
ack_size += ack_block_length;
if (ack_info.num_ack_blocks != 0) {
@@ -4635,8 +4733,7 @@ size_t QuicFramer::ComputeFrameLength(
return GetAckFrameSize(*frame.ack_frame, packet_number_length);
}
case STOP_WAITING_FRAME:
- return GetStopWaitingFrameSize(version_.transport_version,
- packet_number_length);
+ return GetStopWaitingFrameSize(packet_number_length);
case MTU_DISCOVERY_FRAME:
// MTU discovery frames are serialized as ping frames.
return kQuicFrameTypeSize;
@@ -4754,9 +4851,9 @@ bool QuicFramer::AppendIetfTypeByte(const QuicFrame& frame,
case BLOCKED_FRAME:
if (frame.blocked_frame->stream_id ==
QuicUtils::GetInvalidStreamId(transport_version())) {
- type_byte = IETF_BLOCKED;
+ type_byte = IETF_DATA_BLOCKED;
} else {
- type_byte = IETF_STREAM_BLOCKED;
+ type_byte = IETF_STREAM_DATA_BLOCKED;
}
break;
case STOP_WAITING_FRAME:
@@ -4815,6 +4912,9 @@ bool QuicFramer::AppendIetfTypeByte(const QuicFrame& frame,
case CRYPTO_FRAME:
type_byte = IETF_CRYPTO;
break;
+ case HANDSHAKE_DONE_FRAME:
+ type_byte = IETF_HANDSHAKE_DONE;
+ break;
default:
QUIC_BUG << "Attempt to generate a frame type for an unsupported value: "
<< frame.type;
@@ -4887,9 +4987,8 @@ bool QuicFramer::AppendStreamFrame(const QuicStreamFrame& frame,
QUIC_BUG << "Writing stream id size failed.";
return false;
}
- if (!AppendStreamOffset(
- GetStreamOffsetSize(version_.transport_version, frame.offset),
- frame.offset, writer)) {
+ if (!AppendStreamOffset(GetStreamOffsetSize(frame.offset), frame.offset,
+ writer)) {
QUIC_BUG << "Writing offset size failed.";
return false;
}
@@ -4951,8 +5050,8 @@ bool QuicFramer::ProcessNewTokenFrame(QuicDataReader* reader,
return false;
}
- // TODO(ianswett): Don't use QuicStringPiece as an intermediary.
- QuicStringPiece data;
+ // TODO(ianswett): Don't use quiche::QuicheStringPiece as an intermediary.
+ quiche::QuicheStringPiece data;
if (!reader->ReadStringPiece(&data, length)) {
set_detailed_error("Unable to read new token data.");
return false;
@@ -5047,20 +5146,17 @@ bool QuicFramer::AppendAckFrameAndTypeByte(const QuicAckFrame& frame,
const AckFrameInfo new_ack_info = GetAckFrameInfo(frame);
QuicPacketNumber largest_acked = LargestAcked(frame);
QuicPacketNumberLength largest_acked_length =
- GetMinPacketNumberLength(version_.transport_version, largest_acked);
+ GetMinPacketNumberLength(largest_acked);
QuicPacketNumberLength ack_block_length =
- GetMinPacketNumberLength(version_.transport_version,
- QuicPacketNumber(new_ack_info.max_block_length));
+ GetMinPacketNumberLength(QuicPacketNumber(new_ack_info.max_block_length));
// Calculate available bytes for timestamps and ack blocks.
int32_t available_timestamp_and_ack_block_bytes =
writer->capacity() - writer->length() - ack_block_length -
- GetMinAckFrameSize(version_.transport_version, largest_acked_length) -
+ GetMinAckFrameSize(version_.transport_version, frame,
+ local_ack_delay_exponent_, largest_acked_length) -
(new_ack_info.num_ack_blocks != 0 ? kNumberOfAckBlocksSize : 0);
DCHECK_LE(0, available_timestamp_and_ack_block_bytes);
- // Write out the type byte by setting the low order bits and doing shifts
- // to make room for the next bit flags to be set.
- // Whether there are multiple ack blocks.
uint8_t type_byte = 0;
SetBit(&type_byte, new_ack_info.num_ack_blocks != 0,
kQuicHasMultipleAckBlocksOffset);
@@ -5254,8 +5350,8 @@ bool QuicFramer::AppendStopWaitingFrame(const QuicPacketHeader& header,
const QuicStopWaitingFrame& frame,
QuicDataWriter* writer) {
DCHECK(!VersionHasIetfInvariantHeader(version_.transport_version));
- DCHECK(frame.least_unacked.IsInitialized() &&
- header.packet_number >= frame.least_unacked);
+ DCHECK(frame.least_unacked.IsInitialized());
+ DCHECK_GE(header.packet_number, frame.least_unacked);
const uint64_t least_unacked_delta =
header.packet_number - frame.least_unacked;
const uint64_t length_shift = header.packet_number_length * 8;
@@ -5281,57 +5377,17 @@ bool QuicFramer::AppendStopWaitingFrame(const QuicPacketHeader& header,
return true;
}
-int QuicFramer::CalculateIetfAckBlockCount(const QuicAckFrame& frame,
- QuicDataWriter* /*writer*/,
- size_t available_space) {
- // Number of blocks requested in the frame
- uint64_t ack_block_count = frame.packets.NumIntervals();
-
- auto itr = frame.packets.rbegin();
-
- int actual_block_count = 1;
- uint64_t block_length = itr->max() - itr->min();
- size_t encoded_size = QuicDataWriter::GetVarInt62Len(block_length);
- if (encoded_size > available_space) {
- return 0;
- }
- available_space -= encoded_size;
- QuicPacketNumber previous_ack_end = itr->min();
- ack_block_count--;
-
- while (ack_block_count) {
- // Each block is a gap followed by another ACK. Calculate each value,
- // determine the encoded lengths, and check against the available space.
- itr++;
- size_t gap = previous_ack_end - itr->max() - 1;
- encoded_size = QuicDataWriter::GetVarInt62Len(gap);
-
- // Add the ACK block.
- block_length = itr->max() - itr->min();
- encoded_size += QuicDataWriter::GetVarInt62Len(block_length);
-
- if (encoded_size > available_space) {
- // No room for this block, so what we've
- // done up to now is all that can be done.
- return actual_block_count;
- }
- available_space -= encoded_size;
- actual_block_count++;
- previous_ack_end = itr->min();
- ack_block_count--;
- }
- // Ran through the whole thing! We can do all blocks.
- return actual_block_count;
-}
-
bool QuicFramer::AppendIetfAckFrameAndTypeByte(const QuicAckFrame& frame,
QuicDataWriter* writer) {
- // Assume frame is an IETF_ACK frame. If |ecn_counters_populated| is true and
- // any of the ECN counters is non-0 then turn it into an IETF_ACK+ECN frame.
uint8_t type = IETF_ACK;
+ uint64_t ecn_size = 0;
if (frame.ecn_counters_populated &&
(frame.ect_0_count || frame.ect_1_count || frame.ecn_ce_count)) {
+ // Change frame type to ACK_ECN if any ECN count is available.
type = IETF_ACK_ECN;
+ ecn_size = (QuicDataWriter::GetVarInt62Len(frame.ect_0_count) +
+ QuicDataWriter::GetVarInt62Len(frame.ect_1_count) +
+ QuicDataWriter::GetVarInt62Len(frame.ecn_ce_count));
}
if (!writer->WriteUInt8(type)) {
@@ -5356,100 +5412,81 @@ bool QuicFramer::AppendIetfAckFrameAndTypeByte(const QuicAckFrame& frame,
set_detailed_error("No room for ack-delay in ack frame");
return false;
}
- if (type == IETF_ACK_ECN) {
- // Encode the ACK ECN fields
- if (!writer->WriteVarInt62(frame.ect_0_count)) {
- set_detailed_error("No room for ect_0_count in ack frame");
- return false;
- }
- if (!writer->WriteVarInt62(frame.ect_1_count)) {
- set_detailed_error("No room for ect_1_count in ack frame");
- return false;
- }
- if (!writer->WriteVarInt62(frame.ecn_ce_count)) {
- set_detailed_error("No room for ecn_ce_count in ack frame");
- return false;
- }
- }
-
- uint64_t ack_block_count = frame.packets.NumIntervals();
- if (ack_block_count == 0) {
- // If the QuicAckFrame has no Intervals, then it is interpreted
- // as an ack of a single packet at QuicAckFrame.largest_acked.
- // The resulting ack will consist of only the frame's
- // largest_ack & first_ack_block fields. The first ack block will be 0
- // (indicating a single packet) and the ack block_count will be 0.
- if (!writer->WriteVarInt62(0)) {
- set_detailed_error("No room for ack block count in ack frame");
- return false;
- }
- // size of the first block is 1 packet
- if (!writer->WriteVarInt62(0)) {
- set_detailed_error("No room for first ack block in ack frame");
- return false;
- }
- return true;
- }
- // Case 2 or 3
- auto itr = frame.packets.rbegin();
- QuicPacketNumber ack_block_largest(largest_acked);
- QuicPacketNumber ack_block_smallest;
- if ((itr->max() - 1) == QuicPacketNumber(largest_acked)) {
- // If largest_acked + 1 is equal to the Max() of the first Interval
- // in the QuicAckFrame then the first Interval is the first ack block of the
- // frame; remaining Intervals are additional ack blocks. The QuicAckFrame's
- // first Interval is encoded in the frame's largest_acked/first_ack_block,
- // the remaining Intervals are encoded in additional ack blocks in the
- // frame, and the packet's ack_block_count is the number of QuicAckFrame
- // Intervals - 1.
- ack_block_smallest = itr->min();
- itr++;
- ack_block_count--;
- } else {
- // If QuicAckFrame.largest_acked is NOT equal to the Max() of
- // the first Interval then it is interpreted as acking a single
- // packet at QuicAckFrame.largest_acked, with additional
- // Intervals indicating additional ack blocks. The encoding is
- // a) The packet's largest_acked is the QuicAckFrame's largest
- // acked,
- // b) the first ack block size is 0,
- // c) The packet's ack_block_count is the number of QuicAckFrame
- // Intervals, and
- // d) The QuicAckFrame Intervals are encoded in additional ack
- // blocks in the packet.
- ack_block_smallest = largest_acked;
+ if (frame.packets.Empty() || frame.packets.Max() != largest_acked) {
+ QUIC_BUG << "Malformed ack frame: " << frame;
+ set_detailed_error("Malformed ack frame");
+ return false;
}
+ // Latch ack_block_count for potential truncation.
+ const uint64_t ack_block_count = frame.packets.NumIntervals() - 1;
+ QuicDataWriter count_writer(QuicDataWriter::GetVarInt62Len(ack_block_count),
+ writer->data() + writer->length());
if (!writer->WriteVarInt62(ack_block_count)) {
set_detailed_error("No room for ack block count in ack frame");
return false;
}
-
- uint64_t first_ack_block = ack_block_largest - ack_block_smallest;
- if (!writer->WriteVarInt62(first_ack_block)) {
+ auto iter = frame.packets.rbegin();
+ if (!writer->WriteVarInt62(iter->Length() - 1)) {
set_detailed_error("No room for first ack block in ack frame");
return false;
}
+ QuicPacketNumber previous_smallest = iter->min();
+ ++iter;
+ // Append remaining ACK blocks.
+ uint64_t appended_ack_blocks = 0;
+ for (; iter != frame.packets.rend(); ++iter) {
+ const uint64_t gap = previous_smallest - iter->max() - 1;
+ const uint64_t ack_range = iter->Length() - 1;
- // For the remaining QuicAckFrame Intervals, if any
- while (ack_block_count != 0) {
- uint64_t gap_size = ack_block_smallest - itr->max();
- if (!writer->WriteVarInt62(gap_size - 1)) {
- set_detailed_error("No room for gap block in ack frame");
+ if (writer->remaining() < ecn_size ||
+ writer->remaining() - ecn_size <
+ QuicDataWriter::GetVarInt62Len(gap) +
+ QuicDataWriter::GetVarInt62Len(ack_range)) {
+ // ACK range does not fit, truncate it.
+ break;
+ }
+ const bool success =
+ writer->WriteVarInt62(gap) && writer->WriteVarInt62(ack_range);
+ DCHECK(success);
+ previous_smallest = iter->min();
+ ++appended_ack_blocks;
+ }
+
+ if (appended_ack_blocks < ack_block_count) {
+ // Truncation is needed, rewrite the ack block count.
+ if (QuicDataWriter::GetVarInt62Len(appended_ack_blocks) !=
+ QuicDataWriter::GetVarInt62Len(ack_block_count) ||
+ !count_writer.WriteVarInt62(appended_ack_blocks)) {
+ // This should never happen as ack_block_count is limited by
+ // max_ack_ranges_.
+ QUIC_BUG << "Ack frame truncation fails. ack_block_count: "
+ << ack_block_count
+ << ", appended count: " << appended_ack_blocks;
+ set_detailed_error("ACK frame truncation fails");
return false;
}
+ QUIC_DLOG(INFO) << ENDPOINT << "ACK ranges get truncated from "
+ << ack_block_count << " to " << appended_ack_blocks;
+ }
- uint64_t block_size = itr->max() - itr->min();
- if (!writer->WriteVarInt62(block_size - 1)) {
- set_detailed_error("No room for nth ack block in ack frame");
+ if (type == IETF_ACK_ECN) {
+ // Encode the ECN counts.
+ if (!writer->WriteVarInt62(frame.ect_0_count)) {
+ set_detailed_error("No room for ect_0_count in ack frame");
+ return false;
+ }
+ if (!writer->WriteVarInt62(frame.ect_1_count)) {
+ set_detailed_error("No room for ect_1_count in ack frame");
+ return false;
+ }
+ if (!writer->WriteVarInt62(frame.ecn_ce_count)) {
+ set_detailed_error("No room for ecn_ce_count in ack frame");
return false;
}
-
- ack_block_smallest = itr->min();
- itr++;
- ack_block_count--;
}
+
return true;
}
@@ -5522,9 +5559,9 @@ bool QuicFramer::AppendBlockedFrame(const QuicBlockedFrame& frame,
QuicDataWriter* writer) {
if (VersionHasIetfQuicFrames(version_.transport_version)) {
if (frame.stream_id == QuicUtils::GetInvalidStreamId(transport_version())) {
- return AppendIetfBlockedFrame(frame, writer);
+ return AppendDataBlockedFrame(frame, writer);
}
- return AppendStreamBlockedFrame(frame, writer);
+ return AppendStreamDataBlockedFrame(frame, writer);
}
uint32_t stream_id = static_cast<uint32_t>(frame.stream_id);
if (!writer->WriteUInt32(stream_id)) {
@@ -5669,7 +5706,7 @@ bool QuicFramer::ProcessIetfConnectionCloseFrame(
return false;
}
- QuicStringPiece phrase;
+ quiche::QuicheStringPiece phrase;
if (!reader->ReadStringPiece(&phrase, static_cast<size_t>(phrase_length))) {
set_detailed_error("Unable to read connection close error details.");
return false;
@@ -5749,8 +5786,7 @@ bool QuicFramer::ProcessIetfResetStreamFrame(QuicDataReader* reader,
// Get Stream ID from frame. ReadVarIntStreamID returns false
// if either A) there is a read error or B) the resulting value of
// the Stream ID is larger than the maximum allowed value.
- if (!reader->ReadVarIntU32(&frame->stream_id)) {
- set_detailed_error("Unable to read rst stream stream id.");
+ if (!ReadUint32FromVarint62(reader, IETF_RST_STREAM, &frame->stream_id)) {
return false;
}
@@ -5777,8 +5813,8 @@ bool QuicFramer::ProcessIetfResetStreamFrame(QuicDataReader* reader,
bool QuicFramer::ProcessStopSendingFrame(
QuicDataReader* reader,
QuicStopSendingFrame* stop_sending_frame) {
- if (!reader->ReadVarIntU32(&stop_sending_frame->stream_id)) {
- set_detailed_error("Unable to read stop sending stream id.");
+ if (!ReadUint32FromVarint62(reader, IETF_STOP_SENDING,
+ &stop_sending_frame->stream_id)) {
return false;
}
@@ -5850,8 +5886,8 @@ bool QuicFramer::AppendMaxStreamDataFrame(const QuicWindowUpdateFrame& frame,
bool QuicFramer::ProcessMaxStreamDataFrame(QuicDataReader* reader,
QuicWindowUpdateFrame* frame) {
- if (!reader->ReadVarIntU32(&frame->stream_id)) {
- set_detailed_error("Can not read MAX_STREAM_DATA stream id");
+ if (!ReadUint32FromVarint62(reader, IETF_MAX_STREAM_DATA,
+ &frame->stream_id)) {
return false;
}
if (!reader->ReadVarInt62(&frame->max_data)) {
@@ -5873,15 +5909,16 @@ bool QuicFramer::AppendMaxStreamsFrame(const QuicMaxStreamsFrame& frame,
bool QuicFramer::ProcessMaxStreamsFrame(QuicDataReader* reader,
QuicMaxStreamsFrame* frame,
uint64_t frame_type) {
- if (!reader->ReadVarIntU32(&frame->stream_count)) {
- set_detailed_error("Can not read MAX_STREAMS stream count.");
+ if (!ReadUint32FromVarint62(reader,
+ static_cast<QuicIetfFrameType>(frame_type),
+ &frame->stream_count)) {
return false;
}
frame->unidirectional = (frame_type == IETF_MAX_STREAMS_UNIDIRECTIONAL);
return true;
}
-bool QuicFramer::AppendIetfBlockedFrame(const QuicBlockedFrame& frame,
+bool QuicFramer::AppendDataBlockedFrame(const QuicBlockedFrame& frame,
QuicDataWriter* writer) {
if (!writer->WriteVarInt62(frame.offset)) {
set_detailed_error("Can not write blocked offset.");
@@ -5890,7 +5927,7 @@ bool QuicFramer::AppendIetfBlockedFrame(const QuicBlockedFrame& frame,
return true;
}
-bool QuicFramer::ProcessIetfBlockedFrame(QuicDataReader* reader,
+bool QuicFramer::ProcessDataBlockedFrame(QuicDataReader* reader,
QuicBlockedFrame* frame) {
// Indicates that it is a BLOCKED frame (as opposed to STREAM_BLOCKED).
frame->stream_id = QuicUtils::GetInvalidStreamId(transport_version());
@@ -5901,8 +5938,8 @@ bool QuicFramer::ProcessIetfBlockedFrame(QuicDataReader* reader,
return true;
}
-bool QuicFramer::AppendStreamBlockedFrame(const QuicBlockedFrame& frame,
- QuicDataWriter* writer) {
+bool QuicFramer::AppendStreamDataBlockedFrame(const QuicBlockedFrame& frame,
+ QuicDataWriter* writer) {
if (!writer->WriteVarInt62(frame.stream_id)) {
set_detailed_error("Can not write stream blocked stream id.");
return false;
@@ -5914,10 +5951,10 @@ bool QuicFramer::AppendStreamBlockedFrame(const QuicBlockedFrame& frame,
return true;
}
-bool QuicFramer::ProcessStreamBlockedFrame(QuicDataReader* reader,
- QuicBlockedFrame* frame) {
- if (!reader->ReadVarIntU32(&frame->stream_id)) {
- set_detailed_error("Can not read stream blocked stream id.");
+bool QuicFramer::ProcessStreamDataBlockedFrame(QuicDataReader* reader,
+ QuicBlockedFrame* frame) {
+ if (!ReadUint32FromVarint62(reader, IETF_STREAM_DATA_BLOCKED,
+ &frame->stream_id)) {
return false;
}
if (!reader->ReadVarInt62(&frame->offset)) {
@@ -5939,26 +5976,19 @@ bool QuicFramer::AppendStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame,
bool QuicFramer::ProcessStreamsBlockedFrame(QuicDataReader* reader,
QuicStreamsBlockedFrame* frame,
uint64_t frame_type) {
- if (!reader->ReadVarIntU32(&frame->stream_count)) {
- set_detailed_error("Can not read STREAMS_BLOCKED stream count.");
+ if (!ReadUint32FromVarint62(reader,
+ static_cast<QuicIetfFrameType>(frame_type),
+ &frame->stream_count)) {
return false;
}
- frame->unidirectional = (frame_type == IETF_STREAMS_BLOCKED_UNIDIRECTIONAL);
-
- // TODO(fkastenholz): handle properly when the STREAMS_BLOCKED
- // frame is implemented and passed up to the stream ID manager.
- if (frame->stream_count >
- QuicUtils::GetMaxStreamCount(
- (frame_type == IETF_STREAMS_BLOCKED_UNIDIRECTIONAL),
- ((perspective_ == Perspective::IS_CLIENT)
- ? Perspective::IS_SERVER
- : Perspective::IS_CLIENT))) {
+ if (frame->stream_count > QuicUtils::GetMaxStreamCount()) {
// If stream count is such that the resulting stream ID would exceed our
// implementation limit, generate an error.
set_detailed_error(
"STREAMS_BLOCKED stream count exceeds implementation limit.");
return false;
}
+ frame->unidirectional = (frame_type == IETF_STREAMS_BLOCKED_UNIDIRECTIONAL);
return true;
}
@@ -6045,6 +6075,24 @@ bool QuicFramer::ProcessRetireConnectionIdFrame(
return true;
}
+bool QuicFramer::ReadUint32FromVarint62(QuicDataReader* reader,
+ QuicIetfFrameType type,
+ QuicStreamId* id) {
+ uint64_t temp_uint64;
+ if (!reader->ReadVarInt62(&temp_uint64)) {
+ set_detailed_error("Unable to read " + QuicIetfFrameTypeString(type) +
+ " frame stream id/count.");
+ return false;
+ }
+ if (temp_uint64 > kMaxQuicStreamId) {
+ set_detailed_error("Stream id/count of " + QuicIetfFrameTypeString(type) +
+ "frame is too large.");
+ return false;
+ }
+ *id = static_cast<uint32_t>(temp_uint64);
+ return true;
+}
+
uint8_t QuicFramer::GetStreamFrameTypeByte(const QuicStreamFrame& frame,
bool last_frame_in_packet) const {
if (VersionHasIetfQuicFrames(version_.transport_version)) {
@@ -6060,8 +6108,7 @@ uint8_t QuicFramer::GetStreamFrameTypeByte(const QuicStreamFrame& frame,
// Offset 3 bits.
type_byte <<= kQuicStreamShift;
- const size_t offset_len =
- GetStreamOffsetSize(version_.transport_version, frame.offset);
+ const size_t offset_len = GetStreamOffsetSize(frame.offset);
if (offset_len > 0) {
type_byte |= offset_len - 1;
}
@@ -6094,8 +6141,8 @@ uint8_t QuicFramer::GetIetfStreamFrameTypeByte(
void QuicFramer::InferPacketHeaderTypeFromVersion() {
// This function should only be called when server connection negotiates the
// version.
- DCHECK(perspective_ == Perspective::IS_SERVER &&
- !infer_packet_header_type_from_version_);
+ DCHECK_EQ(perspective_, Perspective::IS_SERVER);
+ DCHECK(!infer_packet_header_type_from_version_);
infer_packet_header_type_from_version_ = true;
}
@@ -6126,7 +6173,7 @@ QuicErrorCode QuicFramer::ParsePublicHeaderDispatcher(
QuicConnectionId* destination_connection_id,
QuicConnectionId* source_connection_id,
bool* retry_token_present,
- QuicStringPiece* retry_token,
+ quiche::QuicheStringPiece* retry_token,
std::string* detailed_error) {
QuicDataReader reader(packet.data(), packet.length());
if (reader.IsDoneReading()) {
@@ -6296,7 +6343,7 @@ QuicErrorCode QuicFramer::ParsePublicHeader(
QuicConnectionId* source_connection_id,
QuicLongHeaderType* long_packet_type,
QuicVariableLengthIntegerLength* retry_token_length_length,
- QuicStringPiece* retry_token,
+ quiche::QuicheStringPiece* retry_token,
std::string* detailed_error) {
*version_present = false;
*has_length_prefix = false;
@@ -6305,7 +6352,7 @@ QuicErrorCode QuicFramer::ParsePublicHeader(
*source_connection_id = EmptyQuicConnectionId();
*long_packet_type = INVALID_PACKET_TYPE;
*retry_token_length_length = VARIABLE_LENGTH_INTEGER_LENGTH_0;
- *retry_token = QuicStringPiece();
+ *retry_token = quiche::QuicheStringPiece();
*detailed_error = "";
if (!reader->ReadUInt8(first_byte)) {
@@ -6573,11 +6620,11 @@ bool QuicFramer::ParseServerVersionNegotiationProbeResponse(
// the string is not found, or is not properly formed, it returns
// ErrorCode::QUIC_IETF_GQUIC_ERROR_MISSING
void MaybeExtractQuicErrorCode(QuicConnectionCloseFrame* frame) {
- std::vector<QuicStringPiece> ed =
- QuicTextUtils::Split(frame->error_details, ':');
+ std::vector<quiche::QuicheStringPiece> ed =
+ quiche::QuicheTextUtils::Split(frame->error_details, ':');
uint64_t extracted_error_code;
- if (ed.size() < 2 || !QuicTextUtils::IsAllDigits(ed[0]) ||
- !QuicTextUtils::StringToUint64(ed[0], &extracted_error_code)) {
+ if (ed.size() < 2 || !quiche::QuicheTextUtils::IsAllDigits(ed[0]) ||
+ !quiche::QuicheTextUtils::StringToUint64(ed[0], &extracted_error_code)) {
if (frame->close_type == IETF_QUIC_TRANSPORT_CONNECTION_CLOSE &&
frame->transport_error_code == NO_IETF_QUIC_ERROR) {
frame->extracted_error_code = QUIC_NO_ERROR;
@@ -6591,7 +6638,7 @@ void MaybeExtractQuicErrorCode(QuicConnectionCloseFrame* frame) {
// including, the split character, so the length of ed[0] is just the number
// of digits in the error number. In removing the prefix, 1 is added to the
// length to account for the :
- QuicStringPiece x = QuicStringPiece(frame->error_details);
+ quiche::QuicheStringPiece x = quiche::QuicheStringPiece(frame->error_details);
x.remove_prefix(ed[0].length() + 1);
frame->error_details = std::string(x);
frame->extracted_error_code =
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_framer.h b/chromium/net/third_party/quiche/src/quic/core/quic_framer.h
index cd2e2c7c438..746e6a1dacc 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_framer.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_framer.h
@@ -17,7 +17,7 @@
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -94,10 +94,21 @@ class QUIC_EXPORT_PRIVATE QuicFramerVisitorInterface {
const QuicVersionNegotiationPacket& packet) = 0;
// Called only when |perspective_| is IS_CLIENT and a retry packet has been
- // parsed.
+ // parsed. |new_connection_id| contains the value of the Source Connection
+ // ID field, and |retry_token| contains the value of the Retry Token field.
+ // On versions where HasRetryIntegrityTag() is false,
+ // |original_connection_id| contains the value of the Original Destination
+ // Connection ID field, and both |retry_integrity_tag| and
+ // |retry_without_tag| are empty.
+ // On versions where HasRetryIntegrityTag() is true,
+ // |original_connection_id| is empty, |retry_integrity_tag| contains the
+ // value of the Retry Integrity Tag field, and |retry_without_tag| contains
+ // the entire RETRY packet except the Retry Integrity Tag field.
virtual void OnRetryPacket(QuicConnectionId original_connection_id,
QuicConnectionId new_connection_id,
- QuicStringPiece retry_token) = 0;
+ quiche::QuicheStringPiece retry_token,
+ quiche::QuicheStringPiece retry_integrity_tag,
+ quiche::QuicheStringPiece retry_without_tag) = 0;
// Called when all fields except packet number has been parsed, but has not
// been authenticated. If it returns false, framing for this packet will
@@ -204,6 +215,9 @@ class QUIC_EXPORT_PRIVATE QuicFramerVisitorInterface {
// Called when a message frame has been parsed.
virtual bool OnMessageFrame(const QuicMessageFrame& frame) = 0;
+ // Called when a handshake done frame has been parsed.
+ virtual bool OnHandshakeDoneFrame(const QuicHandshakeDoneFrame& frame) = 0;
+
// Called when a packet has been completely processed.
virtual void OnPacketComplete() = 0;
@@ -298,12 +312,15 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
QuicByteCount length);
// Size in bytes of all ack frame fields without the missing packets or ack
// blocks.
+ // TODO(fayang): Remove |largest_observed_length| when deprecating
+ // quic_use_ack_frame_to_get_min_size.
static size_t GetMinAckFrameSize(
QuicTransportVersion version,
+ const QuicAckFrame& ack_frame,
+ uint32_t local_ack_delay_exponent,
QuicPacketNumberLength largest_observed_length);
// Size in bytes of a stop waiting frame.
static size_t GetStopWaitingFrameSize(
- QuicTransportVersion version,
QuicPacketNumberLength packet_number_length);
// Size in bytes of all reset stream frame fields.
static size_t GetRstStreamFrameSize(QuicTransportVersion version,
@@ -337,8 +354,7 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
// Size in bytes required to serialize the stream id.
static size_t GetStreamIdSize(QuicStreamId stream_id);
// Size in bytes required to serialize the stream offset.
- static size_t GetStreamOffsetSize(QuicTransportVersion version,
- QuicStreamOffset offset);
+ static size_t GetStreamOffsetSize(QuicStreamOffset offset);
// Size in bytes for a serialized new connection id frame
static size_t GetNewConnectionIdFrameSize(
const QuicNewConnectionIdFrame& frame);
@@ -368,7 +384,7 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
// Returns the associated data from the encrypted packet |encrypted| as a
// stringpiece.
- static QuicStringPiece GetAssociatedDataFromEncryptedPacket(
+ static quiche::QuicheStringPiece GetAssociatedDataFromEncryptedPacket(
QuicTransportVersion version,
const QuicEncryptedPacket& encrypted,
QuicConnectionIdLength destination_connection_id_length,
@@ -397,7 +413,7 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
QuicConnectionId* source_connection_id,
QuicLongHeaderType* long_packet_type,
QuicVariableLengthIntegerLength* retry_token_length_length,
- QuicStringPiece* retry_token,
+ quiche::QuicheStringPiece* retry_token,
std::string* detailed_error);
// Parses the unencryoted fields in |packet| and stores them in the other
@@ -415,7 +431,7 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
QuicConnectionId* destination_connection_id,
QuicConnectionId* source_connection_id,
bool* retry_token_present,
- QuicStringPiece* retry_token,
+ quiche::QuicheStringPiece* retry_token,
std::string* detailed_error);
// Serializes a packet containing |frames| into |buffer|.
@@ -508,6 +524,9 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
void SetEncrypter(EncryptionLevel level,
std::unique_ptr<QuicEncrypter> encrypter);
+ // Called to remove encrypter of encryption |level|.
+ void RemoveEncrypter(EncryptionLevel level);
+
// Sets the encrypter and decrypter for the ENCRYPTION_INITIAL level.
void SetInitialObfuscators(QuicConnectionId connection_id);
@@ -541,7 +560,6 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
// The minimum packet number length required to represent |packet_number|.
static QuicPacketNumberLength GetMinPacketNumberLength(
- QuicTransportVersion version,
QuicPacketNumber packet_number);
void SetSupportedVersions(const ParsedQuicVersionVector& versions) {
@@ -780,8 +798,8 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
bool no_message_length,
QuicMessageFrame* frame);
- bool DecryptPayload(QuicStringPiece encrypted,
- QuicStringPiece associated_data,
+ bool DecryptPayload(quiche::QuicheStringPiece encrypted,
+ quiche::QuicheStringPiece associated_data,
const QuicPacketHeader& header,
char* decrypted_buffer,
size_t buffer_length,
@@ -865,11 +883,6 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
bool AppendIetfAckFrameAndTypeByte(const QuicAckFrame& frame,
QuicDataWriter* writer);
- // Used by AppendIetfAckFrameAndTypeByte to figure out how many ack
- // blocks can be included.
- int CalculateIetfAckBlockCount(const QuicAckFrame& frame,
- QuicDataWriter* writer,
- size_t available_space);
bool AppendStopWaitingFrame(const QuicPacketHeader& header,
const QuicStopWaitingFrame& frame,
QuicDataWriter* builder);
@@ -903,7 +916,9 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
QuicRstStreamFrame* frame);
bool ProcessStopSendingFrame(QuicDataReader* reader,
QuicStopSendingFrame* stop_sending_frame);
- bool ProcessCryptoFrame(QuicDataReader* reader, QuicCryptoFrame* frame);
+ bool ProcessCryptoFrame(QuicDataReader* reader,
+ EncryptionLevel encryption_level,
+ QuicCryptoFrame* frame);
// IETF frame appending methods. All methods append the type byte as well.
bool AppendIetfStreamFrame(const QuicStreamFrame& frame,
@@ -936,14 +951,14 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
QuicMaxStreamsFrame* frame,
uint64_t frame_type);
- bool AppendIetfBlockedFrame(const QuicBlockedFrame& frame,
+ bool AppendDataBlockedFrame(const QuicBlockedFrame& frame,
QuicDataWriter* writer);
- bool ProcessIetfBlockedFrame(QuicDataReader* reader, QuicBlockedFrame* frame);
+ bool ProcessDataBlockedFrame(QuicDataReader* reader, QuicBlockedFrame* frame);
- bool AppendStreamBlockedFrame(const QuicBlockedFrame& frame,
- QuicDataWriter* writer);
- bool ProcessStreamBlockedFrame(QuicDataReader* reader,
- QuicBlockedFrame* frame);
+ bool AppendStreamDataBlockedFrame(const QuicBlockedFrame& frame,
+ QuicDataWriter* writer);
+ bool ProcessStreamDataBlockedFrame(QuicDataReader* reader,
+ QuicBlockedFrame* frame);
bool AppendStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame,
QuicDataWriter* writer);
@@ -981,6 +996,11 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
void set_detailed_error(const char* error) { detailed_error_ = error; }
void set_detailed_error(std::string error) { detailed_error_ = error; }
+ // Returns false if the reading fails.
+ bool ReadUint32FromVarint62(QuicDataReader* reader,
+ QuicIetfFrameType type,
+ QuicStreamId* id);
+
std::string detailed_error_;
QuicFramerVisitorInterface* visitor_;
QuicErrorCode error_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_framer_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_framer_test.cc
index ff9653d3827..813d4f6c270 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_framer_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_framer_test.cc
@@ -22,20 +22,21 @@
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_framer_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/simple_data_producer.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
+#include "net/third_party/quiche/src/common/test_tools/quiche_test_utils.h"
using testing::_;
using testing::Return;
-using testing::Truly;
namespace quic {
namespace test {
@@ -91,15 +92,17 @@ const uint8_t kVarInt62EightBytes = 0xc0;
class TestEncrypter : public QuicEncrypter {
public:
~TestEncrypter() override {}
- bool SetKey(QuicStringPiece /*key*/) override { return true; }
- bool SetNoncePrefix(QuicStringPiece /*nonce_prefix*/) override {
+ bool SetKey(quiche::QuicheStringPiece /*key*/) override { return true; }
+ bool SetNoncePrefix(quiche::QuicheStringPiece /*nonce_prefix*/) override {
+ return true;
+ }
+ bool SetIV(quiche::QuicheStringPiece /*iv*/) override { return true; }
+ bool SetHeaderProtectionKey(quiche::QuicheStringPiece /*key*/) override {
return true;
}
- bool SetIV(QuicStringPiece /*iv*/) override { return true; }
- bool SetHeaderProtectionKey(QuicStringPiece /*key*/) override { return true; }
bool EncryptPacket(uint64_t packet_number,
- QuicStringPiece associated_data,
- QuicStringPiece plaintext,
+ quiche::QuicheStringPiece associated_data,
+ quiche::QuicheStringPiece plaintext,
char* output,
size_t* output_length,
size_t /*max_output_length*/) override {
@@ -111,7 +114,7 @@ class TestEncrypter : public QuicEncrypter {
return true;
}
std::string GenerateHeaderProtectionMask(
- QuicStringPiece /*sample*/) override {
+ quiche::QuicheStringPiece /*sample*/) override {
return std::string(5, 0);
}
size_t GetKeySize() const override { return 0; }
@@ -123,8 +126,12 @@ class TestEncrypter : public QuicEncrypter {
size_t GetCiphertextSize(size_t plaintext_size) const override {
return plaintext_size;
}
- QuicStringPiece GetKey() const override { return QuicStringPiece(); }
- QuicStringPiece GetNoncePrefix() const override { return QuicStringPiece(); }
+ quiche::QuicheStringPiece GetKey() const override {
+ return quiche::QuicheStringPiece();
+ }
+ quiche::QuicheStringPiece GetNoncePrefix() const override {
+ return quiche::QuicheStringPiece();
+ }
QuicPacketNumber packet_number_;
std::string associated_data_;
@@ -134,13 +141,15 @@ class TestEncrypter : public QuicEncrypter {
class TestDecrypter : public QuicDecrypter {
public:
~TestDecrypter() override {}
- bool SetKey(QuicStringPiece /*key*/) override { return true; }
- bool SetNoncePrefix(QuicStringPiece /*nonce_prefix*/) override {
+ bool SetKey(quiche::QuicheStringPiece /*key*/) override { return true; }
+ bool SetNoncePrefix(quiche::QuicheStringPiece /*nonce_prefix*/) override {
return true;
}
- bool SetIV(QuicStringPiece /*iv*/) override { return true; }
- bool SetHeaderProtectionKey(QuicStringPiece /*key*/) override { return true; }
- bool SetPreliminaryKey(QuicStringPiece /*key*/) override {
+ bool SetIV(quiche::QuicheStringPiece /*iv*/) override { return true; }
+ bool SetHeaderProtectionKey(quiche::QuicheStringPiece /*key*/) override {
+ return true;
+ }
+ bool SetPreliminaryKey(quiche::QuicheStringPiece /*key*/) override {
QUIC_BUG << "should not be called";
return false;
}
@@ -148,8 +157,8 @@ class TestDecrypter : public QuicDecrypter {
return true;
}
bool DecryptPacket(uint64_t packet_number,
- QuicStringPiece associated_data,
- QuicStringPiece ciphertext,
+ quiche::QuicheStringPiece associated_data,
+ quiche::QuicheStringPiece ciphertext,
char* output,
size_t* output_length,
size_t /*max_output_length*/) override {
@@ -167,8 +176,12 @@ class TestDecrypter : public QuicDecrypter {
size_t GetKeySize() const override { return 0; }
size_t GetNoncePrefixSize() const override { return 0; }
size_t GetIVSize() const override { return 0; }
- QuicStringPiece GetKey() const override { return QuicStringPiece(); }
- QuicStringPiece GetNoncePrefix() const override { return QuicStringPiece(); }
+ quiche::QuicheStringPiece GetKey() const override {
+ return quiche::QuicheStringPiece();
+ }
+ quiche::QuicheStringPiece GetNoncePrefix() const override {
+ return quiche::QuicheStringPiece();
+ }
// Use a distinct value starting with 0xFFFFFF, which is never used by TLS.
uint32_t cipher_id() const override { return 0xFFFFFFF2; }
QuicPacketNumber packet_number_;
@@ -211,12 +224,19 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
void OnRetryPacket(QuicConnectionId original_connection_id,
QuicConnectionId new_connection_id,
- QuicStringPiece retry_token) override {
+ quiche::QuicheStringPiece retry_token,
+ quiche::QuicheStringPiece retry_integrity_tag,
+ quiche::QuicheStringPiece retry_without_tag) override {
+ on_retry_packet_called_ = true;
retry_original_connection_id_ =
std::make_unique<QuicConnectionId>(original_connection_id);
retry_new_connection_id_ =
std::make_unique<QuicConnectionId>(new_connection_id);
retry_token_ = std::make_unique<std::string>(std::string(retry_token));
+ retry_token_integrity_tag_ =
+ std::make_unique<std::string>(std::string(retry_integrity_tag));
+ retry_without_tag_ =
+ std::make_unique<std::string>(std::string(retry_without_tag));
EXPECT_EQ(0u, framer_->current_received_frame_type());
}
@@ -286,7 +306,7 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
new std::string(frame.data_buffer, frame.data_length);
crypto_data_.push_back(QuicWrapUnique(string_data));
crypto_frames_.push_back(std::make_unique<QuicCryptoFrame>(
- ENCRYPTION_INITIAL, frame.offset, *string_data));
+ frame.level, frame.offset, *string_data));
if (VersionHasIetfQuicFrames(transport_version_)) {
EXPECT_EQ(IETF_CRYPTO, framer_->current_received_frame_type());
} else {
@@ -303,7 +323,8 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
ack_frame.ack_delay_time = ack_delay_time;
ack_frames_.push_back(std::make_unique<QuicAckFrame>(ack_frame));
if (VersionHasIetfQuicFrames(transport_version_)) {
- EXPECT_EQ(IETF_ACK, framer_->current_received_frame_type());
+ EXPECT_TRUE(IETF_ACK == framer_->current_received_frame_type() ||
+ IETF_ACK_ECN == framer_->current_received_frame_type());
} else {
EXPECT_EQ(0u, framer_->current_received_frame_type());
}
@@ -314,7 +335,8 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
DCHECK(!ack_frames_.empty());
ack_frames_[ack_frames_.size() - 1]->packets.AddRange(start, end);
if (VersionHasIetfQuicFrames(transport_version_)) {
- EXPECT_EQ(IETF_ACK, framer_->current_received_frame_type());
+ EXPECT_TRUE(IETF_ACK == framer_->current_received_frame_type() ||
+ IETF_ACK_ECN == framer_->current_received_frame_type());
} else {
EXPECT_EQ(0u, framer_->current_received_frame_type());
}
@@ -375,6 +397,15 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
return true;
}
+ bool OnHandshakeDoneFrame(const QuicHandshakeDoneFrame& frame) override {
+ ++frame_count_;
+ handshake_done_frames_.push_back(
+ std::make_unique<QuicHandshakeDoneFrame>(frame));
+ DCHECK(VersionHasIetfQuicFrames(transport_version_));
+ EXPECT_EQ(IETF_HANDSHAKE_DONE, framer_->current_received_frame_type());
+ return true;
+ }
+
void OnPacketComplete() override { ++complete_packets_; }
bool OnRstStreamFrame(const QuicRstStreamFrame& frame) override {
@@ -467,8 +498,8 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
bool OnBlockedFrame(const QuicBlockedFrame& frame) override {
blocked_frame_ = frame;
if (VersionHasIetfQuicFrames(transport_version_)) {
- EXPECT_TRUE(IETF_BLOCKED == framer_->current_received_frame_type() ||
- IETF_STREAM_BLOCKED ==
+ EXPECT_TRUE(IETF_DATA_BLOCKED == framer_->current_received_frame_type() ||
+ IETF_STREAM_DATA_BLOCKED ==
framer_->current_received_frame_type());
} else {
EXPECT_EQ(0u, framer_->current_received_frame_type());
@@ -532,6 +563,9 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
std::unique_ptr<QuicConnectionId> retry_original_connection_id_;
std::unique_ptr<QuicConnectionId> retry_new_connection_id_;
std::unique_ptr<std::string> retry_token_;
+ std::unique_ptr<std::string> retry_token_integrity_tag_;
+ std::unique_ptr<std::string> retry_without_tag_;
+ bool on_retry_packet_called_ = false;
std::vector<std::unique_ptr<QuicStreamFrame>> stream_frames_;
std::vector<std::unique_ptr<QuicCryptoFrame>> crypto_frames_;
std::vector<std::unique_ptr<QuicAckFrame>> ack_frames_;
@@ -539,6 +573,7 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
std::vector<std::unique_ptr<QuicPaddingFrame>> padding_frames_;
std::vector<std::unique_ptr<QuicPingFrame>> ping_frames_;
std::vector<std::unique_ptr<QuicMessageFrame>> message_frames_;
+ std::vector<std::unique_ptr<QuicHandshakeDoneFrame>> handshake_done_frames_;
std::vector<std::unique_ptr<QuicEncryptedPacket>> coalesced_packets_;
std::vector<std::unique_ptr<QuicEncryptedPacket>> undecryptable_packets_;
std::vector<EncryptionLevel> undecryptable_decryption_levels_;
@@ -582,7 +617,6 @@ class QuicFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
start_,
Perspective::IS_SERVER,
kQuicDefaultConnectionIdLength) {
- SetQuicReloadableFlag(quic_supports_tls_handshake, true);
framer_.set_version(version_);
if (framer_.version().KnowsWhichDecrypterToUse()) {
framer_.InstallDecrypter(ENCRYPTION_INITIAL,
@@ -663,7 +697,7 @@ class QuicFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
<< " actual: " << decrypter_->packet_number_;
return false;
}
- QuicStringPiece associated_data =
+ quiche::QuicheStringPiece associated_data =
QuicFramer::GetAssociatedDataFromEncryptedPacket(
framer_.transport_version(), encrypted,
destination_connection_id_length, source_connection_id_length,
@@ -672,12 +706,13 @@ class QuicFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
retry_token_length, length_length);
if (associated_data != decrypter_->associated_data_) {
QUIC_LOG(ERROR) << "Decrypted incorrect associated data. expected "
- << QuicTextUtils::HexEncode(associated_data)
+ << quiche::QuicheTextUtils::HexEncode(associated_data)
<< " actual: "
- << QuicTextUtils::HexEncode(decrypter_->associated_data_);
+ << quiche::QuicheTextUtils::HexEncode(
+ decrypter_->associated_data_);
return false;
}
- QuicStringPiece ciphertext(
+ quiche::QuicheStringPiece ciphertext(
encrypted.AsStringPiece().substr(GetStartOfEncryptedData(
framer_.transport_version(), destination_connection_id_length,
source_connection_id_length, includes_version,
@@ -685,10 +720,12 @@ class QuicFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
retry_token_length_length, retry_token_length, length_length)));
if (ciphertext != decrypter_->ciphertext_) {
QUIC_LOG(ERROR) << "Decrypted incorrect ciphertext data. expected "
- << QuicTextUtils::HexEncode(ciphertext) << " actual: "
- << QuicTextUtils::HexEncode(decrypter_->ciphertext_)
+ << quiche::QuicheTextUtils::HexEncode(ciphertext)
+ << " actual: "
+ << quiche::QuicheTextUtils::HexEncode(
+ decrypter_->ciphertext_)
<< " associated data: "
- << QuicTextUtils::HexEncode(associated_data);
+ << quiche::QuicheTextUtils::HexEncode(associated_data);
return false;
}
return true;
@@ -955,10 +992,10 @@ TEST_P(QuicFramerTest, LargePacket) {
};
// clang-format on
unsigned char* p = packet;
- size_t p_size = QUIC_ARRAYSIZE(packet);
+ size_t p_size = QUICHE_ARRAYSIZE(packet);
if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet46;
- p_size = QUIC_ARRAYSIZE(packet46);
+ p_size = QUICHE_ARRAYSIZE(packet46);
}
const size_t header_size = GetPacketHeaderSize(
@@ -1023,7 +1060,7 @@ TEST_P(QuicFramerTest, PacketHeader) {
QuicVersionLabel version_label;
std::string detailed_error;
bool retry_token_present, use_length_prefix;
- QuicStringPiece retry_token;
+ quiche::QuicheStringPiece retry_token;
ParsedQuicVersion parsed_version = UnsupportedQuicVersion();
const QuicErrorCode error_code = QuicFramer::ParsePublicHeaderDispatcher(
*encrypted, kQuicDefaultConnectionIdLength, &format, &long_packet_type,
@@ -1088,7 +1125,7 @@ TEST_P(QuicFramerTest, LongPacketHeader) {
QuicVersionLabel version_label;
std::string detailed_error;
bool retry_token_present, use_length_prefix;
- QuicStringPiece retry_token;
+ quiche::QuicheStringPiece retry_token;
ParsedQuicVersion parsed_version = UnsupportedQuicVersion();
const QuicErrorCode error_code = QuicFramer::ParsePublicHeaderDispatcher(
*encrypted, kQuicDefaultConnectionIdLength, &format, &long_packet_type,
@@ -1154,10 +1191,10 @@ TEST_P(QuicFramerTest, LongPacketHeaderWithBothConnectionIds) {
// clang-format on
unsigned char* p = packet;
- size_t p_length = QUIC_ARRAYSIZE(packet);
+ size_t p_length = QUICHE_ARRAYSIZE(packet);
if (framer_.transport_version() >= QUIC_VERSION_49) {
p = packet49;
- p_length = QUIC_ARRAYSIZE(packet49);
+ p_length = QUICHE_ARRAYSIZE(packet49);
}
QuicEncryptedPacket encrypted(AsChars(p), p_length, false);
@@ -1168,7 +1205,7 @@ TEST_P(QuicFramerTest, LongPacketHeaderWithBothConnectionIds) {
QuicVersionLabel version_label = 0;
std::string detailed_error = "";
bool retry_token_present, use_length_prefix;
- QuicStringPiece retry_token;
+ quiche::QuicheStringPiece retry_token;
ParsedQuicVersion parsed_version = UnsupportedQuicVersion();
const QuicErrorCode error_code = QuicFramer::ParsePublicHeaderDispatcher(
encrypted, kQuicDefaultConnectionIdLength, &format, &long_packet_type,
@@ -1239,13 +1276,13 @@ TEST_P(QuicFramerTest, ParsePublicHeader) {
};
// clang-format on
unsigned char* p = packet;
- size_t p_length = QUIC_ARRAYSIZE(packet);
+ size_t p_length = QUICHE_ARRAYSIZE(packet);
if (framer_.transport_version() >= QUIC_VERSION_49) {
p = packet49;
- p_length = QUIC_ARRAYSIZE(packet49);
+ p_length = QUICHE_ARRAYSIZE(packet49);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
- p_length = QUIC_ARRAYSIZE(packet46);
+ p_length = QUICHE_ARRAYSIZE(packet46);
}
uint8_t first_byte = 0x33;
@@ -1258,7 +1295,7 @@ TEST_P(QuicFramerTest, ParsePublicHeader) {
QuicLongHeaderType long_packet_type = INVALID_PACKET_TYPE;
QuicVariableLengthIntegerLength retry_token_length_length =
VARIABLE_LENGTH_INTEGER_LENGTH_4;
- QuicStringPiece retry_token;
+ quiche::QuicheStringPiece retry_token;
std::string detailed_error = "foobar";
QuicDataReader reader(AsChars(p), p_length);
@@ -1281,7 +1318,7 @@ TEST_P(QuicFramerTest, ParsePublicHeader) {
EXPECT_EQ(FramerTestConnectionId(), destination_connection_id);
EXPECT_EQ(EmptyQuicConnectionId(), source_connection_id);
EXPECT_EQ(VARIABLE_LENGTH_INTEGER_LENGTH_0, retry_token_length_length);
- EXPECT_EQ(QuicStringPiece(), retry_token);
+ EXPECT_EQ(quiche::QuicheStringPiece(), retry_token);
if (VersionHasIetfInvariantHeader(framer_.transport_version())) {
EXPECT_EQ(IETF_QUIC_LONG_HEADER_PACKET, format);
EXPECT_EQ(HANDSHAKE, long_packet_type);
@@ -1316,7 +1353,7 @@ TEST_P(QuicFramerTest, ParsePublicHeaderProxBadSourceConnectionIdLength) {
};
// clang-format on
unsigned char* p = packet;
- size_t p_length = QUIC_ARRAYSIZE(packet);
+ size_t p_length = QUICHE_ARRAYSIZE(packet);
uint8_t first_byte = 0x33;
PacketHeaderFormat format = GOOGLE_QUIC_PACKET;
@@ -1328,7 +1365,7 @@ TEST_P(QuicFramerTest, ParsePublicHeaderProxBadSourceConnectionIdLength) {
QuicLongHeaderType long_packet_type = INVALID_PACKET_TYPE;
QuicVariableLengthIntegerLength retry_token_length_length =
VARIABLE_LENGTH_INTEGER_LENGTH_4;
- QuicStringPiece retry_token;
+ quiche::QuicheStringPiece retry_token;
std::string detailed_error = "foobar";
QuicDataReader reader(AsChars(p), p_length);
@@ -1348,7 +1385,7 @@ TEST_P(QuicFramerTest, ParsePublicHeaderProxBadSourceConnectionIdLength) {
EXPECT_EQ(FramerTestConnectionId(), destination_connection_id);
EXPECT_EQ(EmptyQuicConnectionId(), source_connection_id);
EXPECT_EQ(VARIABLE_LENGTH_INTEGER_LENGTH_0, retry_token_length_length);
- EXPECT_EQ(QuicStringPiece(), retry_token);
+ EXPECT_EQ(quiche::QuicheStringPiece(), retry_token);
EXPECT_EQ(IETF_QUIC_LONG_HEADER_PACKET, format);
}
@@ -1373,7 +1410,8 @@ TEST_P(QuicFramerTest, ClientConnectionIdFromShortHeaderToClient) {
0x00,
};
// clang-format on
- QuicEncryptedPacket encrypted(AsChars(packet), QUIC_ARRAYSIZE(packet), false);
+ QuicEncryptedPacket encrypted(AsChars(packet), QUICHE_ARRAYSIZE(packet),
+ false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_THAT(framer_.error(), IsQuicNoError());
EXPECT_EQ("", framer_.detailed_error());
@@ -1407,7 +1445,8 @@ TEST_P(QuicFramerTest, ClientConnectionIdFromShortHeaderToServer) {
0x00,
};
// clang-format on
- QuicEncryptedPacket encrypted(AsChars(packet), QUIC_ARRAYSIZE(packet), false);
+ QuicEncryptedPacket encrypted(AsChars(packet), QUICHE_ARRAYSIZE(packet),
+ false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_THAT(framer_.error(), IsQuicNoError());
EXPECT_EQ("", framer_.detailed_error());
@@ -1900,13 +1939,13 @@ TEST_P(QuicFramerTest, PacketWithDiversificationNonce) {
}
unsigned char* p = packet;
- size_t p_size = QUIC_ARRAYSIZE(packet);
+ size_t p_size = QUICHE_ARRAYSIZE(packet);
if (framer_.transport_version() >= QUIC_VERSION_49) {
p = packet49;
- p_size = QUIC_ARRAYSIZE(packet49);
+ p_size = QUICHE_ARRAYSIZE(packet49);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
- p_size = QUIC_ARRAYSIZE(packet46);
+ p_size = QUICHE_ARRAYSIZE(packet46);
}
QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
@@ -1975,13 +2014,13 @@ TEST_P(QuicFramerTest, LargePublicFlagWithMismatchedVersions) {
// clang-format on
unsigned char* p = packet;
- size_t p_size = QUIC_ARRAYSIZE(packet);
+ size_t p_size = QUICHE_ARRAYSIZE(packet);
if (framer_.transport_version() >= QUIC_VERSION_49) {
p = packet49;
- p_size = QUIC_ARRAYSIZE(packet49);
+ p_size = QUICHE_ARRAYSIZE(packet49);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
- p_size = QUIC_ARRAYSIZE(packet46);
+ p_size = QUICHE_ARRAYSIZE(packet46);
}
QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
@@ -2078,13 +2117,13 @@ TEST_P(QuicFramerTest, PaddingFrame) {
// clang-format on
unsigned char* p = packet;
- size_t p_size = QUIC_ARRAYSIZE(packet);
+ size_t p_size = QUICHE_ARRAYSIZE(packet);
if (VersionHasIetfQuicFrames(framer_.transport_version())) {
p = packet99;
- p_size = QUIC_ARRAYSIZE(packet99);
+ p_size = QUICHE_ARRAYSIZE(packet99);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
- p_size = QUIC_ARRAYSIZE(packet46);
+ p_size = QUICHE_ARRAYSIZE(packet46);
}
QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
@@ -2183,7 +2222,7 @@ TEST_P(QuicFramerTest, StreamFrame) {
{"",
{ 0x08 | 0x01 | 0x02 | 0x04 }},
// stream id
- {"Unable to read stream_id.",
+ {"Unable to read IETF_STREAM frame stream id/count.",
{kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04}},
// offset
{"Unable to read stream data offset.",
@@ -2248,7 +2287,7 @@ TEST_P(QuicFramerTest, EmptyStreamFrame) {
{"",
{ 0x08 | 0x01 | 0x02 | 0x04 }},
// stream id
- {"Unable to read stream_id.",
+ {"Unable to read IETF_STREAM frame stream id/count.",
{kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04}},
// offset
{"Unable to read stream data offset.",
@@ -2348,19 +2387,20 @@ TEST_P(QuicFramerTest, MissingDiversificationNonce) {
// clang-format on
unsigned char* p = packet;
- size_t p_length = QUIC_ARRAYSIZE(packet);
+ size_t p_length = QUICHE_ARRAYSIZE(packet);
if (framer_.transport_version() >= QUIC_VERSION_49) {
p = packet49;
- p_length = QUIC_ARRAYSIZE(packet49);
+ p_length = QUICHE_ARRAYSIZE(packet49);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
- p_length = QUIC_ARRAYSIZE(packet46);
+ p_length = QUICHE_ARRAYSIZE(packet46);
}
QuicEncryptedPacket encrypted(AsChars(p), p_length, false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
if (framer_.version().HasHeaderProtection()) {
EXPECT_THAT(framer_.error(), IsError(QUIC_DECRYPTION_FAILURE));
- EXPECT_EQ("Unable to decrypt header protection.", framer_.detailed_error());
+ EXPECT_EQ("Unable to decrypt ENCRYPTION_ZERO_RTT header protection.",
+ framer_.detailed_error());
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
// Cannot read diversification nonce.
EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_PACKET_HEADER));
@@ -2506,7 +2546,7 @@ TEST_P(QuicFramerTest, StreamFrame2ByteStreamId) {
{"",
{0x08 | 0x01 | 0x02 | 0x04}},
// stream id
- {"Unable to read stream_id.",
+ {"Unable to read IETF_STREAM frame stream id/count.",
{kVarInt62TwoBytes + 0x03, 0x04}},
// offset
{"Unable to read stream data offset.",
@@ -2626,7 +2666,7 @@ TEST_P(QuicFramerTest, StreamFrame1ByteStreamId) {
{"",
{0x08 | 0x01 | 0x02 | 0x04}},
// stream id
- {"Unable to read stream_id.",
+ {"Unable to read IETF_STREAM frame stream id/count.",
{kVarInt62OneByte + 0x04}},
// offset
{"Unable to read stream data offset.",
@@ -2933,8 +2973,8 @@ TEST_P(QuicFramerTest, RejectPacket) {
}
QuicEncryptedPacket encrypted(AsChars(p),
framer_.transport_version() > QUIC_VERSION_43
- ? QUIC_ARRAYSIZE(packet46)
- : QUIC_ARRAYSIZE(packet),
+ ? QUICHE_ARRAYSIZE(packet46)
+ : QUICHE_ARRAYSIZE(packet),
false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
@@ -2969,12 +3009,13 @@ TEST_P(QuicFramerTest, RejectPublicHeader) {
};
// clang-format on
- QuicEncryptedPacket encrypted(
- framer_.transport_version() >= QUIC_VERSION_46 ? AsChars(packet46)
- : AsChars(packet),
- framer_.transport_version() >= QUIC_VERSION_46 ? QUIC_ARRAYSIZE(packet46)
- : QUIC_ARRAYSIZE(packet),
- false);
+ QuicEncryptedPacket encrypted(framer_.transport_version() >= QUIC_VERSION_46
+ ? AsChars(packet46)
+ : AsChars(packet),
+ framer_.transport_version() >= QUIC_VERSION_46
+ ? QUICHE_ARRAYSIZE(packet46)
+ : QUICHE_ARRAYSIZE(packet),
+ false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_THAT(framer_.error(), IsQuicNoError());
@@ -3993,9 +4034,9 @@ TEST_P(QuicFramerTest, AckFrameTimeStampDeltaTooHigh) {
QuicEncryptedPacket encrypted(
AsChars(framer_.transport_version() >= QUIC_VERSION_46 ? packet46
: packet),
- QUIC_ARRAYSIZE(packet), false);
+ QUICHE_ARRAYSIZE(packet), false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
- EXPECT_TRUE(QuicTextUtils::StartsWith(
+ EXPECT_TRUE(quiche::QuicheTextUtils::StartsWith(
framer_.detailed_error(), "delta_from_largest_observed too high"));
}
@@ -4067,9 +4108,9 @@ TEST_P(QuicFramerTest, AckFrameTimeStampSecondDeltaTooHigh) {
QuicEncryptedPacket encrypted(
AsChars(framer_.transport_version() >= QUIC_VERSION_46 ? packet46
: packet),
- QUIC_ARRAYSIZE(packet), false);
+ QUICHE_ARRAYSIZE(packet), false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
- EXPECT_TRUE(QuicTextUtils::StartsWith(
+ EXPECT_TRUE(quiche::QuicheTextUtils::StartsWith(
framer_.detailed_error(), "delta_from_largest_observed too high"));
}
@@ -4187,8 +4228,8 @@ TEST_P(QuicFramerTest, InvalidNewStopWaitingFrame) {
QuicEncryptedPacket encrypted(
AsChars(framer_.transport_version() >= QUIC_VERSION_46 ? packet46
: packet),
- framer_.transport_version() > QUIC_VERSION_43 ? QUIC_ARRAYSIZE(packet46)
- : QUIC_ARRAYSIZE(packet),
+ framer_.transport_version() > QUIC_VERSION_43 ? QUICHE_ARRAYSIZE(packet46)
+ : QUICHE_ARRAYSIZE(packet),
false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_STOP_WAITING_DATA));
@@ -4262,7 +4303,7 @@ TEST_P(QuicFramerTest, RstStreamFrame) {
{"",
{0x04}},
// stream id
- {"Unable to read rst stream stream id.",
+ {"Unable to read IETF_RST_STREAM frame stream id/count.",
{kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04}},
// application error code
{"Unable to read rst stream error code.",
@@ -4906,7 +4947,7 @@ TEST_P(QuicFramerTest, MaxStreamDataFrame) {
{"",
{0x11}},
// stream id
- {"Can not read MAX_STREAM_DATA stream id",
+ {"Unable to read IETF_MAX_STREAM_DATA frame stream id/count.",
{kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04}},
// byte offset
{"Can not read MAX_STREAM_DATA byte-count",
@@ -4984,7 +5025,7 @@ TEST_P(QuicFramerTest, BlockedFrame) {
{"",
{0x15}},
// stream id
- {"Can not read stream blocked stream id.",
+ {"Unable to read IETF_STREAM_DATA_BLOCKED frame stream id/count.",
{kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04}},
// Offset
{"Can not read stream blocked offset.",
@@ -5067,10 +5108,10 @@ TEST_P(QuicFramerTest, PingFrame) {
: (framer_.transport_version() >= QUIC_VERSION_46 ? packet46
: packet)),
VersionHasIetfQuicFrames(framer_.transport_version())
- ? QUIC_ARRAYSIZE(packet99)
+ ? QUICHE_ARRAYSIZE(packet99)
: (framer_.transport_version() >= QUIC_VERSION_46
- ? QUIC_ARRAYSIZE(packet46)
- : QUIC_ARRAYSIZE(packet)),
+ ? QUICHE_ARRAYSIZE(packet46)
+ : QUICHE_ARRAYSIZE(packet)),
false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
@@ -5085,6 +5126,39 @@ TEST_P(QuicFramerTest, PingFrame) {
// No need to check the PING frame boundaries because it has no payload.
}
+TEST_P(QuicFramerTest, HandshakeDoneFrame) {
+ SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
+ // clang-format off
+ unsigned char packet[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (Handshake done frame)
+ 0x1e,
+ };
+ // clang-format on
+
+ if (!VersionHasIetfQuicFrames(framer_.transport_version())) {
+ return;
+ }
+
+ QuicEncryptedPacket encrypted(AsChars(packet), QUICHE_ARRAYSIZE(packet),
+ false);
+ EXPECT_TRUE(framer_.ProcessPacket(encrypted));
+
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
+ ASSERT_TRUE(visitor_.header_.get());
+ EXPECT_TRUE(CheckDecryption(
+ encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
+ PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
+
+ EXPECT_EQ(1u, visitor_.handshake_done_frames_.size());
+}
+
TEST_P(QuicFramerTest, MessageFrame) {
if (!VersionSupportsMessageFrames(framer_.transport_version())) {
return;
@@ -5310,7 +5384,8 @@ TEST_P(QuicFramerTest, PublicResetPacketWithTrailingJunk) {
return;
}
- QuicEncryptedPacket encrypted(AsChars(packet), QUIC_ARRAYSIZE(packet), false);
+ QuicEncryptedPacket encrypted(AsChars(packet), QUICHE_ARRAYSIZE(packet),
+ false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
ASSERT_THAT(framer_.error(), IsError(QUIC_INVALID_PUBLIC_RST_PACKET));
EXPECT_EQ("Unable to read reset message.", framer_.detailed_error());
@@ -5411,7 +5486,8 @@ TEST_P(QuicFramerTest, IetfStatelessResetPacket) {
ENCRYPTION_ZERO_RTT, std::unique_ptr<QuicDecrypter>(decrypter_), false);
}
// This packet cannot be decrypted because diversification nonce is missing.
- QuicEncryptedPacket encrypted(AsChars(packet), QUIC_ARRAYSIZE(packet), false);
+ QuicEncryptedPacket encrypted(AsChars(packet), QUICHE_ARRAYSIZE(packet),
+ false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
ASSERT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.stateless_reset_packet_.get());
@@ -5454,7 +5530,8 @@ TEST_P(QuicFramerTest, IetfStatelessResetPacketInvalidStatelessResetToken) {
ENCRYPTION_ZERO_RTT, std::unique_ptr<QuicDecrypter>(decrypter_), false);
}
// This packet cannot be decrypted because diversification nonce is missing.
- QuicEncryptedPacket encrypted(AsChars(packet), QUIC_ARRAYSIZE(packet), false);
+ QuicEncryptedPacket encrypted(AsChars(packet), QUICHE_ARRAYSIZE(packet),
+ false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
EXPECT_THAT(framer_.error(), IsError(QUIC_DECRYPTION_FAILURE));
ASSERT_FALSE(visitor_.stateless_reset_packet_);
@@ -5574,10 +5651,10 @@ TEST_P(QuicFramerTest, VersionNegotiationPacketServer) {
};
// clang-format on
unsigned char* p = packet;
- size_t p_length = QUIC_ARRAYSIZE(packet);
+ size_t p_length = QUICHE_ARRAYSIZE(packet);
if (framer_.version().HasLengthPrefixedConnectionIds()) {
p = packet2;
- p_length = QUIC_ARRAYSIZE(packet2);
+ p_length = QUICHE_ARRAYSIZE(packet2);
}
QuicEncryptedPacket encrypted(AsChars(p), p_length, false);
@@ -5669,13 +5746,34 @@ TEST_P(QuicFramerTest, ParseIetfRetryPacket) {
'H', 'e', 'l', 'l', 'o', ' ', 't', 'h', 'i', 's',
' ', 'i', 's', ' ', 'R', 'E', 'T', 'R', 'Y', '!',
};
+ unsigned char packet_with_tag[] = {
+ // public flags (long header with packet type RETRY)
+ 0xF0,
+ // version
+ QUIC_VERSION_BYTES,
+ // destination connection ID length
+ 0x00,
+ // source connection ID length
+ 0x08,
+ // source connection ID
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x11,
+ // retry token
+ 'H', 'e', 'l', 'l', 'o', ' ', 't', 'h', 'i', 's',
+ ' ', 'i', 's', ' ', 'R', 'E', 'T', 'R', 'Y', '!',
+ // retry token integrity tag
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ };
// clang-format on
unsigned char* p = packet;
- size_t p_length = QUIC_ARRAYSIZE(packet);
- if (framer_.transport_version() >= QUIC_VERSION_49) {
+ size_t p_length = QUICHE_ARRAYSIZE(packet);
+ if (framer_.version().HasRetryIntegrityTag()) {
+ p = packet_with_tag;
+ p_length = QUICHE_ARRAYSIZE(packet_with_tag);
+ } else if (framer_.transport_version() >= QUIC_VERSION_49) {
p = packet49;
- p_length = QUIC_ARRAYSIZE(packet49);
+ p_length = QUICHE_ARRAYSIZE(packet49);
}
QuicEncryptedPacket encrypted(AsChars(p), p_length, false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
@@ -5683,46 +5781,57 @@ TEST_P(QuicFramerTest, ParseIetfRetryPacket) {
EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
- ASSERT_TRUE(visitor_.retry_original_connection_id_.get());
+ ASSERT_TRUE(visitor_.on_retry_packet_called_);
ASSERT_TRUE(visitor_.retry_new_connection_id_.get());
ASSERT_TRUE(visitor_.retry_token_.get());
- EXPECT_EQ(FramerTestConnectionId(),
- *visitor_.retry_original_connection_id_.get());
+ if (framer_.version().HasRetryIntegrityTag()) {
+ ASSERT_TRUE(visitor_.retry_token_integrity_tag_.get());
+ static const unsigned char expected_integrity_tag[16] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ };
+ quiche::test::CompareCharArraysWithHexError(
+ "retry integrity tag", visitor_.retry_token_integrity_tag_->data(),
+ visitor_.retry_token_integrity_tag_->length(),
+ reinterpret_cast<const char*>(expected_integrity_tag),
+ QUICHE_ARRAYSIZE(expected_integrity_tag));
+ ASSERT_TRUE(visitor_.retry_without_tag_.get());
+ quiche::test::CompareCharArraysWithHexError(
+ "retry without tag", visitor_.retry_without_tag_->data(),
+ visitor_.retry_without_tag_->length(),
+ reinterpret_cast<const char*>(packet_with_tag), 35);
+ } else {
+ ASSERT_TRUE(visitor_.retry_original_connection_id_.get());
+ EXPECT_EQ(FramerTestConnectionId(),
+ *visitor_.retry_original_connection_id_.get());
+ }
+
EXPECT_EQ(FramerTestConnectionIdPlusOne(),
*visitor_.retry_new_connection_id_.get());
EXPECT_EQ("Hello this is RETRY!", *visitor_.retry_token_.get());
-}
-TEST_P(QuicFramerTest, RejectIetfRetryPacketAsServer) {
- if (!framer_.version().SupportsRetry()) {
- return;
- }
- // IETF RETRY is only sent from client to server.
+ // IETF RETRY is only sent from client to server, the rest of this test
+ // ensures that the server correctly drops them without acting on them.
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER);
- // clang-format off
- unsigned char packet[] = {
- // public flags (long header with packet type RETRY and ODCIL=8)
- 0xF5,
- // version
- QUIC_VERSION_BYTES,
- // connection ID lengths
- 0x00, 0x08,
- // source connection ID
- 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x11,
- // original destination connection ID
- 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
- // retry token
- 'H', 'e', 'l', 'l', 'o', ' ', 't', 'h', 'i', 's',
- ' ', 'i', 's', ' ', 'R', 'E', 'T', 'R', 'Y', '!',
- };
- // clang-format on
+ // Reset our visitor state to default settings.
+ visitor_.retry_original_connection_id_.reset();
+ visitor_.retry_new_connection_id_.reset();
+ visitor_.retry_token_.reset();
+ visitor_.retry_token_integrity_tag_.reset();
+ visitor_.retry_without_tag_.reset();
+ visitor_.on_retry_packet_called_ = false;
- QuicEncryptedPacket encrypted(AsChars(packet), QUIC_ARRAYSIZE(packet), false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_PACKET_HEADER));
EXPECT_EQ("Client-initiated RETRY is invalid.", framer_.detailed_error());
+
+ EXPECT_FALSE(visitor_.on_retry_packet_called_);
+ EXPECT_FALSE(visitor_.retry_new_connection_id_.get());
+ EXPECT_FALSE(visitor_.retry_token_.get());
+ EXPECT_FALSE(visitor_.retry_token_integrity_tag_.get());
+ EXPECT_FALSE(visitor_.retry_without_tag_.get());
}
TEST_P(QuicFramerTest, BuildPaddingFramePacket) {
@@ -5793,10 +5902,10 @@ TEST_P(QuicFramerTest, BuildPaddingFramePacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"constructed packet", data->data(), data->length(), AsChars(p),
- framer_.transport_version() > QUIC_VERSION_43 ? QUIC_ARRAYSIZE(packet46)
- : QUIC_ARRAYSIZE(packet));
+ framer_.transport_version() > QUIC_VERSION_43 ? QUICHE_ARRAYSIZE(packet46)
+ : QUICHE_ARRAYSIZE(packet));
}
TEST_P(QuicFramerTest, BuildStreamFramePacketWithNewPaddingFrame) {
@@ -5807,7 +5916,7 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketWithNewPaddingFrame) {
header.version_flag = false;
header.packet_number = kPacketNumber;
QuicStreamFrame stream_frame(kStreamId, true, kStreamOffset,
- QuicStringPiece("hello world!"));
+ quiche::QuicheStringPiece("hello world!"));
QuicPaddingFrame padding_frame(2);
QuicFrames frames = {QuicFrame(padding_frame), QuicFrame(stream_frame),
QuicFrame(padding_frame)};
@@ -5899,18 +6008,18 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketWithNewPaddingFrame) {
ASSERT_TRUE(data != nullptr);
unsigned char* p = packet;
- size_t p_size = QUIC_ARRAYSIZE(packet);
+ size_t p_size = QUICHE_ARRAYSIZE(packet);
if (VersionHasIetfQuicFrames(framer_.transport_version())) {
p = packet99;
- p_size = QUIC_ARRAYSIZE(packet99);
+ p_size = QUICHE_ARRAYSIZE(packet99);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
- p_size = QUIC_ARRAYSIZE(packet46);
+ p_size = QUICHE_ARRAYSIZE(packet46);
}
QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(p), p_size);
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(p), p_size);
}
TEST_P(QuicFramerTest, Build4ByteSequenceNumberPaddingFramePacket) {
@@ -5982,10 +6091,10 @@ TEST_P(QuicFramerTest, Build4ByteSequenceNumberPaddingFramePacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"constructed packet", data->data(), data->length(), AsChars(p),
- framer_.transport_version() > QUIC_VERSION_43 ? QUIC_ARRAYSIZE(packet46)
- : QUIC_ARRAYSIZE(packet));
+ framer_.transport_version() > QUIC_VERSION_43 ? QUICHE_ARRAYSIZE(packet46)
+ : QUICHE_ARRAYSIZE(packet));
}
TEST_P(QuicFramerTest, Build2ByteSequenceNumberPaddingFramePacket) {
@@ -6057,10 +6166,10 @@ TEST_P(QuicFramerTest, Build2ByteSequenceNumberPaddingFramePacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"constructed packet", data->data(), data->length(), AsChars(p),
- framer_.transport_version() > QUIC_VERSION_43 ? QUIC_ARRAYSIZE(packet46)
- : QUIC_ARRAYSIZE(packet));
+ framer_.transport_version() > QUIC_VERSION_43 ? QUICHE_ARRAYSIZE(packet46)
+ : QUICHE_ARRAYSIZE(packet));
}
TEST_P(QuicFramerTest, Build1ByteSequenceNumberPaddingFramePacket) {
@@ -6132,10 +6241,10 @@ TEST_P(QuicFramerTest, Build1ByteSequenceNumberPaddingFramePacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"constructed packet", data->data(), data->length(), AsChars(p),
- framer_.transport_version() > QUIC_VERSION_43 ? QUIC_ARRAYSIZE(packet46)
- : QUIC_ARRAYSIZE(packet));
+ framer_.transport_version() > QUIC_VERSION_43 ? QUICHE_ARRAYSIZE(packet46)
+ : QUICHE_ARRAYSIZE(packet));
}
TEST_P(QuicFramerTest, BuildStreamFramePacket) {
@@ -6150,7 +6259,7 @@ TEST_P(QuicFramerTest, BuildStreamFramePacket) {
}
QuicStreamFrame stream_frame(kStreamId, true, kStreamOffset,
- QuicStringPiece("hello world!"));
+ quiche::QuicheStringPiece("hello world!"));
QuicFrames frames = {QuicFrame(stream_frame)};
@@ -6223,16 +6332,16 @@ TEST_P(QuicFramerTest, BuildStreamFramePacket) {
ASSERT_TRUE(data != nullptr);
unsigned char* p = packet;
- size_t p_size = QUIC_ARRAYSIZE(packet);
+ size_t p_size = QUICHE_ARRAYSIZE(packet);
if (VersionHasIetfQuicFrames(framer_.transport_version())) {
p = packet99;
- p_size = QUIC_ARRAYSIZE(packet99);
+ p_size = QUICHE_ARRAYSIZE(packet99);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
- p_size = QUIC_ARRAYSIZE(packet46);
+ p_size = QUICHE_ARRAYSIZE(packet46);
}
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(p), p_size);
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(p), p_size);
}
TEST_P(QuicFramerTest, BuildStreamFramePacketWithVersionFlag) {
@@ -6249,7 +6358,7 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketWithVersionFlag) {
}
QuicStreamFrame stream_frame(kStreamId, true, kStreamOffset,
- QuicStringPiece("hello world!"));
+ quiche::QuicheStringPiece("hello world!"));
QuicFrames frames = {QuicFrame(stream_frame)};
// clang-format off
@@ -6353,19 +6462,19 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketWithVersionFlag) {
ASSERT_TRUE(data != nullptr);
unsigned char* p = packet;
- size_t p_size = QUIC_ARRAYSIZE(packet);
+ size_t p_size = QUICHE_ARRAYSIZE(packet);
if (VersionHasIetfQuicFrames(framer_.transport_version())) {
p = packet99;
- p_size = QUIC_ARRAYSIZE(packet99);
+ p_size = QUICHE_ARRAYSIZE(packet99);
} else if (framer_.transport_version() >= QUIC_VERSION_49) {
p = packet49;
- p_size = QUIC_ARRAYSIZE(packet49);
+ p_size = QUICHE_ARRAYSIZE(packet49);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
- p_size = QUIC_ARRAYSIZE(packet46);
+ p_size = QUICHE_ARRAYSIZE(packet46);
}
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(p), p_size);
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(p), p_size);
}
TEST_P(QuicFramerTest, BuildCryptoFramePacket) {
@@ -6382,7 +6491,7 @@ TEST_P(QuicFramerTest, BuildCryptoFramePacket) {
SimpleDataProducer data_producer;
framer_.set_data_producer(&data_producer);
- QuicStringPiece crypto_frame_contents("hello world!");
+ quiche::QuicheStringPiece crypto_frame_contents("hello world!");
QuicCryptoFrame crypto_frame(ENCRYPTION_INITIAL, kStreamOffset,
crypto_frame_contents.length());
data_producer.SaveCryptoData(ENCRYPTION_INITIAL, kStreamOffset,
@@ -6435,21 +6544,21 @@ TEST_P(QuicFramerTest, BuildCryptoFramePacket) {
// clang-format on
unsigned char* packet = packet48;
- size_t packet_size = QUIC_ARRAYSIZE(packet48);
- if (framer_.transport_version() == QUIC_VERSION_99) {
+ size_t packet_size = QUICHE_ARRAYSIZE(packet48);
+ if (framer_.version().HasIetfQuicFrames()) {
packet = packet99;
- packet_size = QUIC_ARRAYSIZE(packet99);
+ packet_size = QUICHE_ARRAYSIZE(packet99);
}
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet),
- packet_size);
+ quiche::test::CompareCharArraysWithHexError("constructed packet",
+ data->data(), data->length(),
+ AsChars(packet), packet_size);
}
TEST_P(QuicFramerTest, CryptoFrame) {
- if (framer_.transport_version() < QUIC_VERSION_48) {
+ if (!QuicVersionUsesCryptoFrames(framer_.transport_version())) {
// CRYPTO frames aren't supported prior to v48.
return;
}
@@ -6512,7 +6621,7 @@ TEST_P(QuicFramerTest, CryptoFrame) {
// clang-format on
PacketFragments& fragments =
- framer_.transport_version() == QUIC_VERSION_99 ? packet99 : packet48;
+ framer_.version().HasIetfQuicFrames() ? packet99 : packet48;
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -6524,6 +6633,7 @@ TEST_P(QuicFramerTest, CryptoFrame) {
PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
ASSERT_EQ(1u, visitor_.crypto_frames_.size());
QuicCryptoFrame* frame = visitor_.crypto_frames_[0].get();
+ EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, frame->level);
EXPECT_EQ(kStreamOffset, frame->offset);
EXPECT_EQ("hello world!",
std::string(frame->data_buffer, frame->data_length));
@@ -6573,13 +6683,13 @@ TEST_P(QuicFramerTest, BuildVersionNegotiationPacket) {
};
// clang-format on
unsigned char* p = packet;
- size_t p_size = QUIC_ARRAYSIZE(packet);
+ size_t p_size = QUICHE_ARRAYSIZE(packet);
if (framer_.transport_version() >= QUIC_VERSION_49) {
p = packet49;
- p_size = QUIC_ARRAYSIZE(packet49);
+ p_size = QUICHE_ARRAYSIZE(packet49);
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet46;
- p_size = QUIC_ARRAYSIZE(packet46);
+ p_size = QUICHE_ARRAYSIZE(packet46);
}
QuicConnectionId connection_id = FramerTestConnectionId();
@@ -6589,8 +6699,8 @@ TEST_P(QuicFramerTest, BuildVersionNegotiationPacket) {
framer_.transport_version() > QUIC_VERSION_43,
framer_.version().HasLengthPrefixedConnectionIds(),
SupportedVersions(GetParam())));
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(p), p_size);
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(p), p_size);
}
TEST_P(QuicFramerTest, BuildVersionNegotiationPacketWithClientConnectionId) {
@@ -6624,9 +6734,9 @@ TEST_P(QuicFramerTest, BuildVersionNegotiationPacketWithClientConnectionId) {
QuicFramer::BuildVersionNegotiationPacket(
server_connection_id, client_connection_id, true, true,
SupportedVersions(GetParam())));
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet),
- QUIC_ARRAYSIZE(packet));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(packet),
+ QUICHE_ARRAYSIZE(packet));
}
TEST_P(QuicFramerTest, BuildAckFramePacketOneAckBlock) {
@@ -6707,19 +6817,19 @@ TEST_P(QuicFramerTest, BuildAckFramePacketOneAckBlock) {
};
// clang-format on
unsigned char* p = packet;
- size_t p_size = QUIC_ARRAYSIZE(packet);
+ size_t p_size = QUICHE_ARRAYSIZE(packet);
if (VersionHasIetfQuicFrames(framer_.transport_version())) {
p = packet99;
- p_size = QUIC_ARRAYSIZE(packet99);
+ p_size = QUICHE_ARRAYSIZE(packet99);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
- p_size = QUIC_ARRAYSIZE(packet46);
+ p_size = QUICHE_ARRAYSIZE(packet46);
}
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(p), p_size);
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(p), p_size);
}
TEST_P(QuicFramerTest, BuildAckFramePacketOneAckBlockMaxLength) {
@@ -6800,19 +6910,19 @@ TEST_P(QuicFramerTest, BuildAckFramePacketOneAckBlockMaxLength) {
};
// clang-format on
unsigned char* p = packet;
- size_t p_size = QUIC_ARRAYSIZE(packet);
+ size_t p_size = QUICHE_ARRAYSIZE(packet);
if (VersionHasIetfQuicFrames(framer_.transport_version())) {
p = packet99;
- p_size = QUIC_ARRAYSIZE(packet99);
+ p_size = QUICHE_ARRAYSIZE(packet99);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
- p_size = QUIC_ARRAYSIZE(packet46);
+ p_size = QUICHE_ARRAYSIZE(packet46);
}
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(p), p_size);
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(p), p_size);
}
TEST_P(QuicFramerTest, BuildAckFramePacketMultipleAckBlocks) {
@@ -6948,20 +7058,20 @@ TEST_P(QuicFramerTest, BuildAckFramePacketMultipleAckBlocks) {
};
// clang-format on
unsigned char* p = packet;
- size_t p_size = QUIC_ARRAYSIZE(packet);
+ size_t p_size = QUICHE_ARRAYSIZE(packet);
if (VersionHasIetfQuicFrames(framer_.transport_version())) {
p = packet99;
- p_size = QUIC_ARRAYSIZE(packet99);
+ p_size = QUICHE_ARRAYSIZE(packet99);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
- p_size = QUIC_ARRAYSIZE(packet46);
+ p_size = QUICHE_ARRAYSIZE(packet46);
}
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(p), p_size);
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(p), p_size);
}
TEST_P(QuicFramerTest, BuildAckFramePacketMaxAckBlocks) {
@@ -7257,20 +7367,20 @@ TEST_P(QuicFramerTest, BuildAckFramePacketMaxAckBlocks) {
};
// clang-format on
unsigned char* p = packet;
- size_t p_size = QUIC_ARRAYSIZE(packet);
+ size_t p_size = QUICHE_ARRAYSIZE(packet);
if (VersionHasIetfQuicFrames(framer_.transport_version())) {
p = packet99;
- p_size = QUIC_ARRAYSIZE(packet99);
+ p_size = QUICHE_ARRAYSIZE(packet99);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
- p_size = QUIC_ARRAYSIZE(packet46);
+ p_size = QUICHE_ARRAYSIZE(packet46);
}
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(p), p_size);
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(p), p_size);
}
TEST_P(QuicFramerTest, BuildNewStopWaitingPacket) {
@@ -7309,9 +7419,9 @@ TEST_P(QuicFramerTest, BuildNewStopWaitingPacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet),
- QUIC_ARRAYSIZE(packet));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(packet),
+ QUICHE_ARRAYSIZE(packet));
}
TEST_P(QuicFramerTest, BuildRstFramePacketQuic) {
@@ -7395,18 +7505,18 @@ TEST_P(QuicFramerTest, BuildRstFramePacketQuic) {
ASSERT_TRUE(data != nullptr);
unsigned char* p = packet;
- size_t p_size = QUIC_ARRAYSIZE(packet);
+ size_t p_size = QUICHE_ARRAYSIZE(packet);
if (VersionHasIetfQuicFrames(framer_.transport_version())) {
p = packet99;
- p_size = QUIC_ARRAYSIZE(packet99);
+ p_size = QUICHE_ARRAYSIZE(packet99);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
- p_size = QUIC_ARRAYSIZE(packet46);
+ p_size = QUICHE_ARRAYSIZE(packet46);
}
QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(p), p_size);
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(p), p_size);
}
TEST_P(QuicFramerTest, BuildCloseFramePacket) {
@@ -7494,20 +7604,20 @@ TEST_P(QuicFramerTest, BuildCloseFramePacket) {
// clang-format on
unsigned char* p = packet;
- size_t p_size = QUIC_ARRAYSIZE(packet);
+ size_t p_size = QUICHE_ARRAYSIZE(packet);
if (VersionHasIetfQuicFrames(framer_.transport_version())) {
p = packet99;
- p_size = QUIC_ARRAYSIZE(packet99);
+ p_size = QUICHE_ARRAYSIZE(packet99);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
- p_size = QUIC_ARRAYSIZE(packet46);
+ p_size = QUICHE_ARRAYSIZE(packet46);
}
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(p), p_size);
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(p), p_size);
}
TEST_P(QuicFramerTest, BuildCloseFramePacketExtendedInfo) {
@@ -7599,20 +7709,20 @@ TEST_P(QuicFramerTest, BuildCloseFramePacketExtendedInfo) {
// clang-format on
unsigned char* p = packet;
- size_t p_size = QUIC_ARRAYSIZE(packet);
+ size_t p_size = QUICHE_ARRAYSIZE(packet);
if (VersionHasIetfQuicFrames(framer_.transport_version())) {
p = packet99;
- p_size = QUIC_ARRAYSIZE(packet99);
+ p_size = QUICHE_ARRAYSIZE(packet99);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
- p_size = QUIC_ARRAYSIZE(packet46);
+ p_size = QUICHE_ARRAYSIZE(packet46);
}
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(p), p_size);
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(p), p_size);
}
TEST_P(QuicFramerTest, BuildTruncatedCloseFramePacket) {
@@ -7784,20 +7894,20 @@ TEST_P(QuicFramerTest, BuildTruncatedCloseFramePacket) {
// clang-format on
unsigned char* p = packet;
- size_t p_size = QUIC_ARRAYSIZE(packet);
+ size_t p_size = QUICHE_ARRAYSIZE(packet);
if (VersionHasIetfQuicFrames(framer_.transport_version())) {
p = packet99;
- p_size = QUIC_ARRAYSIZE(packet99);
+ p_size = QUICHE_ARRAYSIZE(packet99);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
- p_size = QUIC_ARRAYSIZE(packet46);
+ p_size = QUICHE_ARRAYSIZE(packet46);
}
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(p), p_size);
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(p), p_size);
}
TEST_P(QuicFramerTest, BuildApplicationCloseFramePacket) {
@@ -7847,9 +7957,9 @@ TEST_P(QuicFramerTest, BuildApplicationCloseFramePacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet99),
- QUIC_ARRAYSIZE(packet99));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(packet99),
+ QUICHE_ARRAYSIZE(packet99));
}
TEST_P(QuicFramerTest, BuildTruncatedApplicationCloseFramePacket) {
@@ -7929,9 +8039,9 @@ TEST_P(QuicFramerTest, BuildTruncatedApplicationCloseFramePacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet99),
- QUIC_ARRAYSIZE(packet99));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(packet99),
+ QUICHE_ARRAYSIZE(packet99));
}
TEST_P(QuicFramerTest, BuildGoAwayPacket) {
@@ -8003,17 +8113,17 @@ TEST_P(QuicFramerTest, BuildGoAwayPacket) {
// clang-format on
unsigned char* p = packet;
- size_t p_size = QUIC_ARRAYSIZE(packet);
+ size_t p_size = QUICHE_ARRAYSIZE(packet);
if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet46;
- p_size = QUIC_ARRAYSIZE(packet46);
+ p_size = QUICHE_ARRAYSIZE(packet46);
}
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(p), p_size);
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(p), p_size);
}
TEST_P(QuicFramerTest, BuildTruncatedGoAwayPacket) {
@@ -8140,17 +8250,17 @@ TEST_P(QuicFramerTest, BuildTruncatedGoAwayPacket) {
// clang-format on
unsigned char* p = packet;
- size_t p_size = QUIC_ARRAYSIZE(packet);
+ size_t p_size = QUICHE_ARRAYSIZE(packet);
if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet46;
- p_size = QUIC_ARRAYSIZE(packet46);
+ p_size = QUICHE_ARRAYSIZE(packet46);
}
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(p), p_size);
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(p), p_size);
}
TEST_P(QuicFramerTest, BuildWindowUpdatePacket) {
@@ -8224,17 +8334,17 @@ TEST_P(QuicFramerTest, BuildWindowUpdatePacket) {
ASSERT_TRUE(data != nullptr);
unsigned char* p = packet;
- size_t p_size = QUIC_ARRAYSIZE(packet);
+ size_t p_size = QUICHE_ARRAYSIZE(packet);
if (VersionHasIetfQuicFrames(framer_.transport_version())) {
p = packet99;
- p_size = QUIC_ARRAYSIZE(packet99);
+ p_size = QUICHE_ARRAYSIZE(packet99);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
- p_size = QUIC_ARRAYSIZE(packet46);
+ p_size = QUICHE_ARRAYSIZE(packet46);
}
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(p), p_size);
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(p), p_size);
}
TEST_P(QuicFramerTest, BuildMaxStreamDataPacket) {
@@ -8277,9 +8387,9 @@ TEST_P(QuicFramerTest, BuildMaxStreamDataPacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet99),
- QUIC_ARRAYSIZE(packet99));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(packet99),
+ QUICHE_ARRAYSIZE(packet99));
}
TEST_P(QuicFramerTest, BuildMaxDataPacket) {
@@ -8321,9 +8431,9 @@ TEST_P(QuicFramerTest, BuildMaxDataPacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet99),
- QUIC_ARRAYSIZE(packet99));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(packet99),
+ QUICHE_ARRAYSIZE(packet99));
}
TEST_P(QuicFramerTest, BuildBlockedPacket) {
@@ -8385,7 +8495,7 @@ TEST_P(QuicFramerTest, BuildBlockedPacket) {
// packet number
0x12, 0x34, 0x56, 0x78,
- // frame type (IETF_BLOCKED frame)
+ // frame type (IETF_DATA_BLOCKED frame)
0x14,
// Offset
kVarInt62EightBytes + 0x3a, 0x98, 0xFE, 0xDC, 0x32, 0x10, 0x76, 0x54
@@ -8396,17 +8506,17 @@ TEST_P(QuicFramerTest, BuildBlockedPacket) {
ASSERT_TRUE(data != nullptr);
unsigned char* p = packet;
- size_t p_size = QUIC_ARRAYSIZE(packet);
+ size_t p_size = QUICHE_ARRAYSIZE(packet);
if (VersionHasIetfQuicFrames(framer_.transport_version())) {
p = packet99;
- p_size = QUIC_ARRAYSIZE(packet99);
+ p_size = QUICHE_ARRAYSIZE(packet99);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
- p_size = QUIC_ARRAYSIZE(packet46);
+ p_size = QUICHE_ARRAYSIZE(packet46);
}
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(p), p_size);
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(p), p_size);
}
TEST_P(QuicFramerTest, BuildPingPacket) {
@@ -8467,10 +8577,44 @@ TEST_P(QuicFramerTest, BuildPingPacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"constructed packet", data->data(), data->length(), AsChars(p),
- framer_.transport_version() > QUIC_VERSION_43 ? QUIC_ARRAYSIZE(packet46)
- : QUIC_ARRAYSIZE(packet));
+ framer_.transport_version() > QUIC_VERSION_43 ? QUICHE_ARRAYSIZE(packet46)
+ : QUICHE_ARRAYSIZE(packet));
+}
+
+TEST_P(QuicFramerTest, BuildHandshakeDonePacket) {
+ QuicPacketHeader header;
+ header.destination_connection_id = FramerTestConnectionId();
+ header.reset_flag = false;
+ header.version_flag = false;
+ header.packet_number = kPacketNumber;
+
+ QuicFrames frames = {QuicFrame(QuicHandshakeDoneFrame())};
+
+ // clang-format off
+ unsigned char packet[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (Handshake done frame)
+ 0x1e,
+ };
+ // clang-format on
+ if (!VersionHasIetfQuicFrames(framer_.transport_version())) {
+ return;
+ }
+
+ std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
+ ASSERT_TRUE(data != nullptr);
+
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(packet),
+ QUICHE_ARRAYSIZE(packet));
}
TEST_P(QuicFramerTest, BuildMessagePacket) {
@@ -8539,12 +8683,11 @@ TEST_P(QuicFramerTest, BuildMessagePacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(p),
- QUIC_ARRAYSIZE(packet46));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(p),
+ QUICHE_ARRAYSIZE(packet46));
}
-
// Test that the MTU discovery packet is serialized correctly as a PING packet.
TEST_P(QuicFramerTest, BuildMtuDiscoveryPacket) {
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
@@ -8604,10 +8747,10 @@ TEST_P(QuicFramerTest, BuildMtuDiscoveryPacket) {
p = packet46;
}
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"constructed packet", data->data(), data->length(), AsChars(p),
- framer_.transport_version() > QUIC_VERSION_43 ? QUIC_ARRAYSIZE(packet46)
- : QUIC_ARRAYSIZE(packet));
+ framer_.transport_version() > QUIC_VERSION_43 ? QUICHE_ARRAYSIZE(packet46)
+ : QUICHE_ARRAYSIZE(packet));
}
TEST_P(QuicFramerTest, BuildPublicResetPacket) {
@@ -8642,9 +8785,9 @@ TEST_P(QuicFramerTest, BuildPublicResetPacket) {
std::unique_ptr<QuicEncryptedPacket> data(
framer_.BuildPublicResetPacket(reset_packet));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet),
- QUIC_ARRAYSIZE(packet));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(packet),
+ QUICHE_ARRAYSIZE(packet));
}
TEST_P(QuicFramerTest, BuildPublicResetPacketWithClientAddress) {
@@ -8691,9 +8834,9 @@ TEST_P(QuicFramerTest, BuildPublicResetPacketWithClientAddress) {
framer_.BuildPublicResetPacket(reset_packet));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet),
- QUIC_ARRAYSIZE(packet));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(packet),
+ QUICHE_ARRAYSIZE(packet));
}
TEST_P(QuicFramerTest, BuildPublicResetPacketWithEndpointId) {
@@ -8765,13 +8908,13 @@ TEST_P(QuicFramerTest, BuildPublicResetPacketWithEndpointId) {
// Variant 1 ends with char 'd'. Variant 1 ends with char 0xAB.
if ('d' == data->data()[data->length() - 1]) {
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"constructed packet", data->data(), data->length(),
- AsChars(packet_variant1), QUIC_ARRAYSIZE(packet_variant1));
+ AsChars(packet_variant1), QUICHE_ARRAYSIZE(packet_variant1));
} else {
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"constructed packet", data->data(), data->length(),
- AsChars(packet_variant2), QUIC_ARRAYSIZE(packet_variant2));
+ AsChars(packet_variant2), QUICHE_ARRAYSIZE(packet_variant2));
}
}
@@ -8793,17 +8936,17 @@ TEST_P(QuicFramerTest, BuildIetfStatelessResetPacket) {
kTestStatelessResetToken));
ASSERT_TRUE(data != nullptr);
// Skip packet number byte which is random in stateless reset packet.
- test::CompareCharArraysWithHexError("constructed packet", data->data(), 1,
- AsChars(packet), 1);
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), 1, AsChars(packet), 1);
const size_t random_bytes_length =
data->length() - kPacketHeaderTypeSize - sizeof(kTestStatelessResetToken);
EXPECT_EQ(kMinRandomBytesLengthInStatelessReset, random_bytes_length);
// Verify stateless reset token is correct.
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"constructed packet",
data->data() + data->length() - sizeof(kTestStatelessResetToken),
sizeof(kTestStatelessResetToken),
- AsChars(packet) + QUIC_ARRAYSIZE(packet) -
+ AsChars(packet) + QUICHE_ARRAYSIZE(packet) -
sizeof(kTestStatelessResetToken),
sizeof(kTestStatelessResetToken));
}
@@ -8859,10 +9002,10 @@ TEST_P(QuicFramerTest, EncryptPacket) {
// clang-format on
unsigned char* p = packet;
- size_t p_size = QUIC_ARRAYSIZE(packet);
+ size_t p_size = QUICHE_ARRAYSIZE(packet);
if (framer_.transport_version() >= QUIC_VERSION_50) {
p = packet50;
- p_size = QUIC_ARRAYSIZE(packet50);
+ p_size = QUICHE_ARRAYSIZE(packet50);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
}
@@ -8944,14 +9087,14 @@ TEST_P(QuicFramerTest, EncryptPacketWithVersionFlag) {
// clang-format on
unsigned char* p = packet;
- size_t p_size = QUIC_ARRAYSIZE(packet);
+ size_t p_size = QUICHE_ARRAYSIZE(packet);
// TODO(ianswett): see todo in previous test.
if (framer_.transport_version() >= QUIC_VERSION_50) {
p = packet50;
- p_size = QUIC_ARRAYSIZE(packet50);
+ p_size = QUICHE_ARRAYSIZE(packet50);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
- p_size = QUIC_ARRAYSIZE(packet46);
+ p_size = QUICHE_ARRAYSIZE(packet46);
}
std::unique_ptr<QuicPacket> raw(new QuicPacket(
@@ -9007,6 +9150,56 @@ TEST_P(QuicFramerTest, AckTruncationLargePacket) {
EXPECT_EQ(QuicPacketNumber(600u), processed_ack_frame.packets.Max());
}
+// Regression test for b/150386368.
+TEST_P(QuicFramerTest, IetfAckFrameTruncation) {
+ if (!VersionHasIetfQuicFrames(framer_.transport_version())) {
+ return;
+ }
+ SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
+
+ QuicPacketHeader header;
+ header.destination_connection_id = FramerTestConnectionId();
+ header.reset_flag = false;
+ header.version_flag = false;
+ header.packet_number = kPacketNumber;
+
+ QuicAckFrame ack_frame;
+ // Create a packet with just the ack.
+ ack_frame = MakeAckFrameWithGaps(/*gap_size=*/0xffffffff,
+ /*max_num_gaps=*/200,
+ /*largest_acked=*/kMaxIetfVarInt);
+ ack_frame.ecn_counters_populated = true;
+ ack_frame.ect_0_count = 100;
+ ack_frame.ect_1_count = 10000;
+ ack_frame.ecn_ce_count = 1000000;
+ QuicFrames frames = {QuicFrame(&ack_frame)};
+ // Build an ACK packet.
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
+ std::unique_ptr<QuicPacket> raw_ack_packet(BuildDataPacket(header, frames));
+ ASSERT_TRUE(raw_ack_packet != nullptr);
+ char buffer[kMaxOutgoingPacketSize];
+ size_t encrypted_length =
+ framer_.EncryptPayload(ENCRYPTION_INITIAL, header.packet_number,
+ *raw_ack_packet, buffer, kMaxOutgoingPacketSize);
+ ASSERT_NE(0u, encrypted_length);
+ // Now make sure we can turn our ack packet back into an ack frame.
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER);
+ ASSERT_TRUE(framer_.ProcessPacket(
+ QuicEncryptedPacket(buffer, encrypted_length, false)));
+ ASSERT_EQ(1u, visitor_.ack_frames_.size());
+ QuicAckFrame& processed_ack_frame = *visitor_.ack_frames_[0];
+ EXPECT_EQ(QuicPacketNumber(kMaxIetfVarInt),
+ LargestAcked(processed_ack_frame));
+ // Verify ACK frame gets truncated.
+ ASSERT_LT(processed_ack_frame.packets.NumPacketsSlow(),
+ ack_frame.packets.NumIntervals());
+ EXPECT_EQ(157u, processed_ack_frame.packets.NumPacketsSlow());
+ EXPECT_LT(processed_ack_frame.packets.NumIntervals(),
+ ack_frame.packets.NumIntervals());
+ EXPECT_EQ(QuicPacketNumber(kMaxIetfVarInt),
+ processed_ack_frame.packets.Max());
+}
+
TEST_P(QuicFramerTest, AckTruncationSmallPacket) {
if (VersionHasIetfQuicFrames(framer_.transport_version())) {
// This test is not applicable to this version; the range count is
@@ -9227,13 +9420,13 @@ TEST_P(QuicFramerTest, StopPacketProcessing) {
EXPECT_CALL(visitor, OnDecryptedPacket(_));
unsigned char* p = packet;
- size_t p_size = QUIC_ARRAYSIZE(packet);
+ size_t p_size = QUICHE_ARRAYSIZE(packet);
if (VersionHasIetfQuicFrames(framer_.transport_version())) {
p = packet99;
- p_size = QUIC_ARRAYSIZE(packet99);
+ p_size = QUICHE_ARRAYSIZE(packet99);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
- p_size = QUIC_ARRAYSIZE(packet46);
+ p_size = QUICHE_ARRAYSIZE(packet46);
}
QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
@@ -9242,11 +9435,13 @@ TEST_P(QuicFramerTest, StopPacketProcessing) {
static char kTestString[] = "At least 20 characters.";
static QuicStreamId kTestQuicStreamId = 1;
-static bool ExpectedStreamFrame(const QuicStreamFrame& frame) {
- return (frame.stream_id == kTestQuicStreamId ||
- QuicUtils::IsCryptoStreamId(QUIC_VERSION_99, frame.stream_id)) &&
- !frame.fin && frame.offset == 0 &&
- std::string(frame.data_buffer, frame.data_length) == kTestString;
+
+MATCHER_P(ExpectedStreamFrame, version, "") {
+ return (arg.stream_id == kTestQuicStreamId ||
+ QuicUtils::IsCryptoStreamId(version.transport_version,
+ arg.stream_id)) &&
+ !arg.fin && arg.offset == 0 &&
+ std::string(arg.data_buffer, arg.data_length) == kTestString;
// FIN is hard-coded false in ConstructEncryptedPacket.
// Offset 0 is hard-coded in ConstructEncryptedPacket.
}
@@ -9285,7 +9480,8 @@ TEST_P(QuicFramerTest, ConstructEncryptedPacket) {
EXPECT_CALL(visitor, OnError(_)).Times(0);
EXPECT_CALL(visitor, OnStreamFrame(_)).Times(0);
if (!QuicVersionUsesCryptoFrames(framer_.version().transport_version)) {
- EXPECT_CALL(visitor, OnStreamFrame(Truly(ExpectedStreamFrame))).Times(1);
+ EXPECT_CALL(visitor, OnStreamFrame(ExpectedStreamFrame(framer_.version())))
+ .Times(1);
} else {
EXPECT_CALL(visitor, OnCryptoFrame(_)).Times(1);
}
@@ -9353,7 +9549,7 @@ TEST_P(QuicFramerTest, IetfBlockedFrame) {
// packet number
{"",
{0x12, 0x34, 0x9A, 0xBC}},
- // frame type (IETF_BLOCKED)
+ // frame type (IETF_DATA_BLOCKED)
{"",
{0x14}},
// blocked offset
@@ -9403,7 +9599,7 @@ TEST_P(QuicFramerTest, BuildIetfBlockedPacket) {
// packet number
0x12, 0x34, 0x56, 0x78,
- // frame type (IETF_BLOCKED)
+ // frame type (IETF_DATA_BLOCKED)
0x14,
// Offset
kVarInt62EightBytes + 0x3a, 0x98, 0xFE, 0xDC, 0x32, 0x10, 0x76, 0x54
@@ -9413,9 +9609,9 @@ TEST_P(QuicFramerTest, BuildIetfBlockedPacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet99),
- QUIC_ARRAYSIZE(packet99));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(packet99),
+ QUICHE_ARRAYSIZE(packet99));
}
TEST_P(QuicFramerTest, IetfStreamBlockedFrame) {
@@ -9436,11 +9632,11 @@ TEST_P(QuicFramerTest, IetfStreamBlockedFrame) {
// packet number
{"",
{0x12, 0x34, 0x9A, 0xBC}},
- // frame type (IETF_STREAM_BLOCKED)
+ // frame type (IETF_STREAM_DATA_BLOCKED)
{"",
{0x15}},
// blocked offset
- {"Can not read stream blocked stream id.",
+ {"Unable to read IETF_STREAM_DATA_BLOCKED frame stream id/count.",
{kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04}},
{"Can not read stream blocked offset.",
{kVarInt62EightBytes + 0x3a, 0x98, 0xFE, 0xDC, 0x32, 0x10, 0x76, 0x54}},
@@ -9489,7 +9685,7 @@ TEST_P(QuicFramerTest, BuildIetfStreamBlockedPacket) {
// packet number
0x12, 0x34, 0x56, 0x78,
- // frame type (IETF_STREAM_BLOCKED)
+ // frame type (IETF_STREAM_DATA_BLOCKED)
0x15,
// Stream ID
kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04,
@@ -9501,9 +9697,9 @@ TEST_P(QuicFramerTest, BuildIetfStreamBlockedPacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet99),
- QUIC_ARRAYSIZE(packet99));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(packet99),
+ QUICHE_ARRAYSIZE(packet99));
}
TEST_P(QuicFramerTest, BiDiMaxStreamsFrame) {
@@ -9528,7 +9724,7 @@ TEST_P(QuicFramerTest, BiDiMaxStreamsFrame) {
{"",
{0x12}},
// max. streams
- {"Can not read MAX_STREAMS stream count.",
+ {"Unable to read IETF_MAX_STREAMS_BIDIRECTIONAL frame stream id/count.",
{kVarInt62OneByte + 0x03}},
};
// clang-format on
@@ -9568,7 +9764,7 @@ TEST_P(QuicFramerTest, UniDiMaxStreamsFrame) {
{"",
{0x13}},
// max. streams
- {"Can not read MAX_STREAMS stream count.",
+ {"Unable to read IETF_MAX_STREAMS_UNIDIRECTIONAL frame stream id/count.",
{kVarInt62OneByte + 0x03}},
};
// clang-format on
@@ -9611,7 +9807,7 @@ TEST_P(QuicFramerTest, ServerUniDiMaxStreamsFrame) {
{"",
{0x13}},
// max. streams
- {"Can not read MAX_STREAMS stream count.",
+ {"Unable to read IETF_MAX_STREAMS_UNIDIRECTIONAL frame stream id/count.",
{kVarInt62OneByte + 0x03}},
};
// clang-format on
@@ -9651,7 +9847,7 @@ TEST_P(QuicFramerTest, ClientUniDiMaxStreamsFrame) {
{"",
{0x13}},
// max. streams
- {"Can not read MAX_STREAMS stream count.",
+ {"Unable to read IETF_MAX_STREAMS_UNIDIRECTIONAL frame stream id/count.",
{kVarInt62OneByte + 0x03}},
};
// clang-format on
@@ -9703,7 +9899,7 @@ TEST_P(QuicFramerTest, BiDiMaxStreamsFrameTooBig) {
};
// clang-format on
- QuicEncryptedPacket encrypted(AsChars(packet99), QUIC_ARRAYSIZE(packet99),
+ QuicEncryptedPacket encrypted(AsChars(packet99), QUICHE_ARRAYSIZE(packet99),
false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_THAT(framer_.error(), IsQuicNoError());
@@ -9740,7 +9936,7 @@ TEST_P(QuicFramerTest, ClientBiDiMaxStreamsFrameTooBig) {
};
// clang-format on
- QuicEncryptedPacket encrypted(AsChars(packet99), QUIC_ARRAYSIZE(packet99),
+ QuicEncryptedPacket encrypted(AsChars(packet99), QUICHE_ARRAYSIZE(packet99),
false);
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
@@ -9780,7 +9976,7 @@ TEST_P(QuicFramerTest, ServerUniDiMaxStreamsFrameTooBig) {
};
// clang-format on
- QuicEncryptedPacket encrypted(AsChars(packet99), QUIC_ARRAYSIZE(packet99),
+ QuicEncryptedPacket encrypted(AsChars(packet99), QUICHE_ARRAYSIZE(packet99),
false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
@@ -9818,7 +10014,7 @@ TEST_P(QuicFramerTest, ClientUniDiMaxStreamsFrameTooBig) {
};
// clang-format on
- QuicEncryptedPacket encrypted(AsChars(packet99), QUIC_ARRAYSIZE(packet99),
+ QuicEncryptedPacket encrypted(AsChars(packet99), QUICHE_ARRAYSIZE(packet99),
false);
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
@@ -9856,7 +10052,7 @@ TEST_P(QuicFramerTest, MaxStreamsFrameZeroCount) {
};
// clang-format on
- QuicEncryptedPacket encrypted(AsChars(packet99), QUIC_ARRAYSIZE(packet99),
+ QuicEncryptedPacket encrypted(AsChars(packet99), QUICHE_ARRAYSIZE(packet99),
false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
}
@@ -9883,7 +10079,7 @@ TEST_P(QuicFramerTest, ServerBiDiStreamsBlockedFrame) {
{"",
{0x13}},
// stream count
- {"Can not read MAX_STREAMS stream count.",
+ {"Unable to read IETF_MAX_STREAMS_UNIDIRECTIONAL frame stream id/count.",
{kVarInt62OneByte + 0x00}},
};
// clang-format on
@@ -9926,7 +10122,8 @@ TEST_P(QuicFramerTest, BiDiStreamsBlockedFrame) {
{"",
{0x16}},
// stream id
- {"Can not read STREAMS_BLOCKED stream count.",
+ {"Unable to read IETF_STREAMS_BLOCKED_BIDIRECTIONAL "
+ "frame stream id/count.",
{kVarInt62OneByte + 0x03}},
};
// clang-format on
@@ -9969,7 +10166,8 @@ TEST_P(QuicFramerTest, UniDiStreamsBlockedFrame) {
{"",
{0x17}},
// stream id
- {"Can not read STREAMS_BLOCKED stream count.",
+ {"Unable to read IETF_STREAMS_BLOCKED_UNIDIRECTIONAL "
+ "frame stream id/count.",
{kVarInt62OneByte + 0x03}},
};
// clang-format on
@@ -10009,7 +10207,8 @@ TEST_P(QuicFramerTest, ClientUniDiStreamsBlockedFrame) {
{"",
{0x17}},
// stream id
- {"Can not read STREAMS_BLOCKED stream count.",
+ {"Unable to read IETF_STREAMS_BLOCKED_UNIDIRECTIONAL "
+ "frame stream id/count.",
{kVarInt62OneByte + 0x03}},
};
// clang-format on
@@ -10058,7 +10257,7 @@ TEST_P(QuicFramerTest, StreamsBlockedFrameTooBig) {
};
// clang-format on
- QuicEncryptedPacket encrypted(AsChars(packet99), QUIC_ARRAYSIZE(packet99),
+ QuicEncryptedPacket encrypted(AsChars(packet99), QUICHE_ARRAYSIZE(packet99),
false);
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
@@ -10092,7 +10291,8 @@ TEST_P(QuicFramerTest, StreamsBlockedFrameZeroCount) {
{"",
{0x17}},
// stream id
- {"Can not read STREAMS_BLOCKED stream count.",
+ {"Unable to read IETF_STREAMS_BLOCKED_UNIDIRECTIONAL "
+ "frame stream id/count.",
{kVarInt62OneByte + 0x00}},
};
// clang-format on
@@ -10150,9 +10350,9 @@ TEST_P(QuicFramerTest, BuildBiDiStreamsBlockedPacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet99),
- QUIC_ARRAYSIZE(packet99));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(packet99),
+ QUICHE_ARRAYSIZE(packet99));
}
TEST_P(QuicFramerTest, BuildUniStreamsBlockedPacket) {
@@ -10192,9 +10392,9 @@ TEST_P(QuicFramerTest, BuildUniStreamsBlockedPacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet99),
- QUIC_ARRAYSIZE(packet99));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(packet99),
+ QUICHE_ARRAYSIZE(packet99));
}
TEST_P(QuicFramerTest, BuildBiDiMaxStreamsPacket) {
@@ -10234,9 +10434,9 @@ TEST_P(QuicFramerTest, BuildBiDiMaxStreamsPacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet99),
- QUIC_ARRAYSIZE(packet99));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(packet99),
+ QUICHE_ARRAYSIZE(packet99));
}
TEST_P(QuicFramerTest, BuildUniDiMaxStreamsPacket) {
@@ -10279,9 +10479,9 @@ TEST_P(QuicFramerTest, BuildUniDiMaxStreamsPacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet99),
- QUIC_ARRAYSIZE(packet99));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(packet99),
+ QUICHE_ARRAYSIZE(packet99));
}
TEST_P(QuicFramerTest, NewConnectionIdFrame) {
@@ -10450,7 +10650,7 @@ TEST_P(QuicFramerTest, InvalidLongNewConnectionIdFrame) {
AssemblePacketFromFragments(packet99));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_NEW_CONNECTION_ID_DATA));
- EXPECT_EQ("Unable to read new connection ID frame connection id.",
+ EXPECT_EQ("Invalid new connection ID length for version.",
framer_.detailed_error());
}
@@ -10548,9 +10748,9 @@ TEST_P(QuicFramerTest, BuildNewConnectionIdFramePacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet99),
- QUIC_ARRAYSIZE(packet99));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(packet99),
+ QUICHE_ARRAYSIZE(packet99));
}
TEST_P(QuicFramerTest, NewTokenFrame) {
@@ -10642,9 +10842,9 @@ TEST_P(QuicFramerTest, BuildNewTokenFramePacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet),
- QUIC_ARRAYSIZE(packet));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(packet),
+ QUICHE_ARRAYSIZE(packet));
}
TEST_P(QuicFramerTest, IetfStopSendingFrame) {
@@ -10669,7 +10869,7 @@ TEST_P(QuicFramerTest, IetfStopSendingFrame) {
{"",
{0x05}},
// stream id
- {"Unable to read stop sending stream id.",
+ {"Unable to read IETF_STOP_SENDING frame stream id/count.",
{kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04}},
{"Unable to read stop sending application error code.",
{kVarInt62FourBytes + 0x00, 0x00, 0x76, 0x54}},
@@ -10730,9 +10930,9 @@ TEST_P(QuicFramerTest, BuildIetfStopSendingPacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet99),
- QUIC_ARRAYSIZE(packet99));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(packet99),
+ QUICHE_ARRAYSIZE(packet99));
}
TEST_P(QuicFramerTest, IetfPathChallengeFrame) {
@@ -10813,9 +11013,9 @@ TEST_P(QuicFramerTest, BuildIetfPathChallengePacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet99),
- QUIC_ARRAYSIZE(packet99));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(packet99),
+ QUICHE_ARRAYSIZE(packet99));
}
TEST_P(QuicFramerTest, IetfPathResponseFrame) {
@@ -10896,9 +11096,9 @@ TEST_P(QuicFramerTest, BuildIetfPathResponsePacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet99),
- QUIC_ARRAYSIZE(packet99));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(packet99),
+ QUICHE_ARRAYSIZE(packet99));
}
TEST_P(QuicFramerTest, GetRetransmittableControlFrameSize) {
@@ -11701,9 +11901,9 @@ TEST_P(QuicFramerTest, BuildRetireConnectionIdFramePacket) {
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet99),
- QUIC_ARRAYSIZE(packet99));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(), AsChars(packet99),
+ QUICHE_ARRAYSIZE(packet99));
}
TEST_P(QuicFramerTest, AckFrameWithInvalidLargestObserved) {
@@ -11771,10 +11971,10 @@ TEST_P(QuicFramerTest, AckFrameWithInvalidLargestObserved) {
// clang-format on
unsigned char* p = packet;
- size_t p_size = QUIC_ARRAYSIZE(packet);
+ size_t p_size = QUICHE_ARRAYSIZE(packet);
if (VersionHasIetfQuicFrames(framer_.transport_version())) {
p = packet99;
- p_size = QUIC_ARRAYSIZE(packet99);
+ p_size = QUICHE_ARRAYSIZE(packet99);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
}
@@ -11849,13 +12049,13 @@ TEST_P(QuicFramerTest, FirstAckBlockJustUnderFlow) {
// clang-format on
unsigned char* p = packet;
- size_t p_size = QUIC_ARRAYSIZE(packet);
+ size_t p_size = QUICHE_ARRAYSIZE(packet);
if (VersionHasIetfQuicFrames(framer_.transport_version())) {
p = packet99;
- p_size = QUIC_ARRAYSIZE(packet99);
+ p_size = QUICHE_ARRAYSIZE(packet99);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
- p_size = QUIC_ARRAYSIZE(packet46);
+ p_size = QUICHE_ARRAYSIZE(packet46);
}
QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
@@ -11957,13 +12157,13 @@ TEST_P(QuicFramerTest, ThirdAckBlockJustUnderflow) {
// clang-format on
unsigned char* p = packet;
- size_t p_size = QUIC_ARRAYSIZE(packet);
+ size_t p_size = QUICHE_ARRAYSIZE(packet);
if (VersionHasIetfQuicFrames(framer_.transport_version())) {
p = packet99;
- p_size = QUIC_ARRAYSIZE(packet99);
+ p_size = QUICHE_ARRAYSIZE(packet99);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
- p_size = QUIC_ARRAYSIZE(packet46);
+ p_size = QUICHE_ARRAYSIZE(packet46);
}
QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
@@ -12104,10 +12304,10 @@ TEST_P(QuicFramerTest, CoalescedPacket) {
// clang-format on
unsigned char* p = packet;
- size_t p_length = QUIC_ARRAYSIZE(packet);
- if (framer_.transport_version() == QUIC_VERSION_99) {
+ size_t p_length = QUICHE_ARRAYSIZE(packet);
+ if (framer_.version().HasIetfQuicFrames()) {
p = packet99;
- p_length = QUIC_ARRAYSIZE(packet99);
+ p_length = QUICHE_ARRAYSIZE(packet99);
}
QuicEncryptedPacket encrypted(AsChars(p), p_length, false);
@@ -12141,6 +12341,272 @@ TEST_P(QuicFramerTest, CoalescedPacket) {
CheckStreamFrameData("HELLO_WORLD?", visitor_.stream_frames_[1].get());
}
+TEST_P(QuicFramerTest, CoalescedPacketWithUdpPadding) {
+ if (!framer_.version().HasLongHeaderLengths()) {
+ return;
+ }
+ SetDecrypterLevel(ENCRYPTION_ZERO_RTT);
+ // clang-format off
+ unsigned char packet[] = {
+ // first coalesced packet
+ // public flags (long header with packet type ZERO_RTT_PROTECTED and
+ // 4-byte packet number)
+ 0xD3,
+ // version
+ QUIC_VERSION_BYTES,
+ // destination connection ID length
+ 0x08,
+ // destination connection ID
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // source connection ID length
+ 0x00,
+ // long header packet length
+ 0x1E,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+ // frame type (stream frame with fin)
+ 0xFE,
+ // stream id
+ 0x02, 0x03, 0x04,
+ // offset
+ 0x3A, 0x98, 0xFE, 0xDC, 0x32, 0x10, 0x76, 0x54,
+ // data length
+ 0x00, 0x0c,
+ // data
+ 'h', 'e', 'l', 'l',
+ 'o', ' ', 'w', 'o',
+ 'r', 'l', 'd', '!',
+ // padding
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ };
+ unsigned char packet99[] = {
+ // first coalesced packet
+ // public flags (long header with packet type ZERO_RTT_PROTECTED and
+ // 4-byte packet number)
+ 0xD3,
+ // version
+ QUIC_VERSION_BYTES,
+ // destination connection ID length
+ 0x08,
+ // destination connection ID
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // source connection ID length
+ 0x00,
+ // long header packet length
+ 0x1E,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+ // frame type (IETF_STREAM frame with FIN, LEN, and OFFSET bits set)
+ 0x08 | 0x01 | 0x02 | 0x04,
+ // stream id
+ kVarInt62FourBytes + 0x00, 0x02, 0x03, 0x04,
+ // offset
+ kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC,
+ 0x32, 0x10, 0x76, 0x54,
+ // data length
+ kVarInt62OneByte + 0x0c,
+ // data
+ 'h', 'e', 'l', 'l',
+ 'o', ' ', 'w', 'o',
+ 'r', 'l', 'd', '!',
+ // padding
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ };
+ // clang-format on
+
+ unsigned char* p = packet;
+ size_t p_length = QUICHE_ARRAYSIZE(packet);
+ if (framer_.version().HasIetfQuicFrames()) {
+ p = packet99;
+ p_length = QUICHE_ARRAYSIZE(packet99);
+ }
+
+ QuicEncryptedPacket encrypted(AsChars(p), p_length, false);
+ EXPECT_TRUE(framer_.ProcessPacket(encrypted));
+
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
+ ASSERT_TRUE(visitor_.header_.get());
+
+ ASSERT_EQ(1u, visitor_.stream_frames_.size());
+ EXPECT_EQ(0u, visitor_.ack_frames_.size());
+
+ // Stream ID should be the last 3 bytes of kStreamId.
+ EXPECT_EQ(0x00FFFFFF & kStreamId, visitor_.stream_frames_[0]->stream_id);
+ EXPECT_TRUE(visitor_.stream_frames_[0]->fin);
+ EXPECT_EQ(kStreamOffset, visitor_.stream_frames_[0]->offset);
+ CheckStreamFrameData("hello world!", visitor_.stream_frames_[0].get());
+
+ EXPECT_EQ(visitor_.coalesced_packets_.size(), 0u);
+}
+
+TEST_P(QuicFramerTest, CoalescedPacketWithDifferentVersion) {
+ if (!QuicVersionHasLongHeaderLengths(framer_.transport_version())) {
+ return;
+ }
+ SetQuicReloadableFlag(quic_minimum_validation_of_coalesced_packets, true);
+ SetDecrypterLevel(ENCRYPTION_ZERO_RTT);
+ // clang-format off
+ unsigned char packet[] = {
+ // first coalesced packet
+ // public flags (long header with packet type ZERO_RTT_PROTECTED and
+ // 4-byte packet number)
+ 0xD3,
+ // version
+ QUIC_VERSION_BYTES,
+ // destination connection ID length
+ 0x08,
+ // destination connection ID
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // source connection ID length
+ 0x00,
+ // long header packet length
+ 0x1E,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+ // frame type (stream frame with fin)
+ 0xFE,
+ // stream id
+ 0x02, 0x03, 0x04,
+ // offset
+ 0x3A, 0x98, 0xFE, 0xDC, 0x32, 0x10, 0x76, 0x54,
+ // data length
+ 0x00, 0x0c,
+ // data
+ 'h', 'e', 'l', 'l',
+ 'o', ' ', 'w', 'o',
+ 'r', 'l', 'd', '!',
+ // second coalesced packet
+ // public flags (long header with packet type ZERO_RTT_PROTECTED and
+ // 4-byte packet number)
+ 0xD3,
+ // garbage version
+ 'G', 'A', 'B', 'G',
+ // destination connection ID length
+ 0x08,
+ // destination connection ID
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // source connection ID length
+ 0x00,
+ // long header packet length
+ 0x1E,
+ // packet number
+ 0x12, 0x34, 0x56, 0x79,
+ // frame type (stream frame with fin)
+ 0xFE,
+ // stream id
+ 0x02, 0x03, 0x04,
+ // offset
+ 0x3A, 0x98, 0xFE, 0xDC, 0x32, 0x10, 0x76, 0x54,
+ // data length
+ 0x00, 0x0c,
+ // data
+ 'H', 'E', 'L', 'L',
+ 'O', '_', 'W', 'O',
+ 'R', 'L', 'D', '?',
+ };
+ unsigned char packet99[] = {
+ // first coalesced packet
+ // public flags (long header with packet type ZERO_RTT_PROTECTED and
+ // 4-byte packet number)
+ 0xD3,
+ // version
+ QUIC_VERSION_BYTES,
+ // destination connection ID length
+ 0x08,
+ // destination connection ID
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // source connection ID length
+ 0x00,
+ // long header packet length
+ 0x1E,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+ // frame type (IETF_STREAM frame with FIN, LEN, and OFFSET bits set)
+ 0x08 | 0x01 | 0x02 | 0x04,
+ // stream id
+ kVarInt62FourBytes + 0x00, 0x02, 0x03, 0x04,
+ // offset
+ kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC,
+ 0x32, 0x10, 0x76, 0x54,
+ // data length
+ kVarInt62OneByte + 0x0c,
+ // data
+ 'h', 'e', 'l', 'l',
+ 'o', ' ', 'w', 'o',
+ 'r', 'l', 'd', '!',
+ // second coalesced packet
+ // public flags (long header with packet type ZERO_RTT_PROTECTED and
+ // 4-byte packet number)
+ 0xD3,
+ // garbage version
+ 'G', 'A', 'B', 'G',
+ // destination connection ID length
+ 0x08,
+ // destination connection ID
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // source connection ID length
+ 0x00,
+ // long header packet length
+ 0x1E,
+ // packet number
+ 0x12, 0x34, 0x56, 0x79,
+ // frame type (IETF_STREAM frame with FIN, LEN, and OFFSET bits set)
+ 0x08 | 0x01 | 0x02 | 0x04,
+ // stream id
+ kVarInt62FourBytes + 0x00, 0x02, 0x03, 0x04,
+ // offset
+ kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC,
+ 0x32, 0x10, 0x76, 0x54,
+ // data length
+ kVarInt62OneByte + 0x0c,
+ // data
+ 'H', 'E', 'L', 'L',
+ 'O', '_', 'W', 'O',
+ 'R', 'L', 'D', '?',
+ };
+ // clang-format on
+
+ unsigned char* p = packet;
+ size_t p_length = QUICHE_ARRAYSIZE(packet);
+ if (framer_.version().HasIetfQuicFrames()) {
+ p = packet99;
+ p_length = QUICHE_ARRAYSIZE(packet99);
+ }
+
+ QuicEncryptedPacket encrypted(AsChars(p), p_length, false);
+ EXPECT_TRUE(framer_.ProcessPacket(encrypted));
+
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
+ ASSERT_TRUE(visitor_.header_.get());
+
+ ASSERT_EQ(1u, visitor_.stream_frames_.size());
+ EXPECT_EQ(0u, visitor_.ack_frames_.size());
+
+ // Stream ID should be the last 3 bytes of kStreamId.
+ EXPECT_EQ(0x00FFFFFF & kStreamId, visitor_.stream_frames_[0]->stream_id);
+ EXPECT_TRUE(visitor_.stream_frames_[0]->fin);
+ EXPECT_EQ(kStreamOffset, visitor_.stream_frames_[0]->offset);
+ CheckStreamFrameData("hello world!", visitor_.stream_frames_[0].get());
+
+ ASSERT_EQ(visitor_.coalesced_packets_.size(), 1u);
+ EXPECT_TRUE(framer_.ProcessPacket(*visitor_.coalesced_packets_[0].get()));
+
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
+ ASSERT_TRUE(visitor_.header_.get());
+
+ ASSERT_EQ(1u, visitor_.stream_frames_.size());
+ // Verify version mismatch gets reported.
+ EXPECT_EQ(1, visitor_.version_mismatch_);
+}
+
TEST_P(QuicFramerTest, UndecryptablePacketWithoutDecrypter) {
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
@@ -12216,13 +12682,13 @@ TEST_P(QuicFramerTest, UndecryptablePacketWithoutDecrypter) {
};
// clang-format on
unsigned char* p = packet;
- size_t p_length = QUIC_ARRAYSIZE(packet);
+ size_t p_length = QUICHE_ARRAYSIZE(packet);
if (framer_.transport_version() >= QUIC_VERSION_49) {
p = packet49;
- p_length = QUIC_ARRAYSIZE(packet49);
+ p_length = QUICHE_ARRAYSIZE(packet49);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
- p_length = QUIC_ARRAYSIZE(packet46);
+ p_length = QUICHE_ARRAYSIZE(packet46);
}
// First attempt decryption without the handshake crypter.
EXPECT_FALSE(
@@ -12231,7 +12697,7 @@ TEST_P(QuicFramerTest, UndecryptablePacketWithoutDecrypter) {
ASSERT_EQ(1u, visitor_.undecryptable_packets_.size());
ASSERT_EQ(1u, visitor_.undecryptable_decryption_levels_.size());
ASSERT_EQ(1u, visitor_.undecryptable_has_decryption_keys_.size());
- CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"undecryptable packet", visitor_.undecryptable_packets_[0]->data(),
visitor_.undecryptable_packets_[0]->length(), AsChars(p), p_length);
if (framer_.version().KnowsWhichDecrypterToUse()) {
@@ -12318,13 +12784,13 @@ TEST_P(QuicFramerTest, UndecryptablePacketWithDecrypter) {
};
// clang-format on
unsigned char* p = packet;
- size_t p_length = QUIC_ARRAYSIZE(packet);
+ size_t p_length = QUICHE_ARRAYSIZE(packet);
if (framer_.transport_version() >= QUIC_VERSION_49) {
p = packet49;
- p_length = QUIC_ARRAYSIZE(packet49);
+ p_length = QUICHE_ARRAYSIZE(packet49);
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
- p_length = QUIC_ARRAYSIZE(packet46);
+ p_length = QUICHE_ARRAYSIZE(packet46);
}
EXPECT_FALSE(
@@ -12333,7 +12799,7 @@ TEST_P(QuicFramerTest, UndecryptablePacketWithDecrypter) {
ASSERT_EQ(1u, visitor_.undecryptable_packets_.size());
ASSERT_EQ(1u, visitor_.undecryptable_decryption_levels_.size());
ASSERT_EQ(1u, visitor_.undecryptable_has_decryption_keys_.size());
- CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"undecryptable packet", visitor_.undecryptable_packets_[0]->data(),
visitor_.undecryptable_packets_[0]->length(), AsChars(p), p_length);
if (framer_.version().KnowsWhichDecrypterToUse()) {
@@ -12482,10 +12948,10 @@ TEST_P(QuicFramerTest, UndecryptableCoalescedPacket) {
const size_t length_of_first_coalesced_packet = 46;
unsigned char* p = packet;
- size_t p_length = QUIC_ARRAYSIZE(packet);
- if (framer_.transport_version() == QUIC_VERSION_99) {
+ size_t p_length = QUICHE_ARRAYSIZE(packet);
+ if (framer_.version().HasIetfQuicFrames()) {
p = packet99;
- p_length = QUIC_ARRAYSIZE(packet99);
+ p_length = QUICHE_ARRAYSIZE(packet99);
}
QuicEncryptedPacket encrypted(AsChars(p), p_length, false);
@@ -12499,10 +12965,10 @@ TEST_P(QuicFramerTest, UndecryptableCoalescedPacket) {
ASSERT_EQ(1u, visitor_.undecryptable_has_decryption_keys_.size());
// Make sure we only receive the first undecryptable packet and not the
// full packet including the second coalesced packet.
- CompareCharArraysWithHexError("undecryptable packet",
- visitor_.undecryptable_packets_[0]->data(),
- visitor_.undecryptable_packets_[0]->length(),
- AsChars(p), length_of_first_coalesced_packet);
+ quiche::test::CompareCharArraysWithHexError(
+ "undecryptable packet", visitor_.undecryptable_packets_[0]->data(),
+ visitor_.undecryptable_packets_[0]->length(), AsChars(p),
+ length_of_first_coalesced_packet);
EXPECT_EQ(ENCRYPTION_HANDSHAKE, visitor_.undecryptable_decryption_levels_[0]);
EXPECT_TRUE(visitor_.undecryptable_has_decryption_keys_[0]);
@@ -12649,16 +13115,20 @@ TEST_P(QuicFramerTest, MismatchedCoalescedPacket) {
// clang-format on
unsigned char* p = packet;
- size_t p_length = QUIC_ARRAYSIZE(packet);
- if (framer_.transport_version() == QUIC_VERSION_99) {
+ size_t p_length = QUICHE_ARRAYSIZE(packet);
+ if (framer_.version().HasIetfQuicFrames()) {
p = packet99;
- p_length = QUIC_ARRAYSIZE(packet99);
+ p_length = QUICHE_ARRAYSIZE(packet99);
}
QuicEncryptedPacket encrypted(AsChars(p), p_length, false);
- EXPECT_QUIC_PEER_BUG(EXPECT_TRUE(framer_.ProcessPacket(encrypted)),
- "Server: Received mismatched coalesced header.*");
+ if (GetQuicReloadableFlag(quic_minimum_validation_of_coalesced_packets)) {
+ EXPECT_TRUE(framer_.ProcessPacket(encrypted));
+ } else {
+ EXPECT_QUIC_PEER_BUG(EXPECT_TRUE(framer_.ProcessPacket(encrypted)),
+ "Server: Received mismatched coalesced header.*");
+ }
EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
@@ -12755,16 +13225,15 @@ TEST_P(QuicFramerTest, InvalidCoalescedPacket) {
// clang-format on
unsigned char* p = packet;
- size_t p_length = QUIC_ARRAYSIZE(packet);
- if (framer_.transport_version() == QUIC_VERSION_99) {
+ size_t p_length = QUICHE_ARRAYSIZE(packet);
+ if (framer_.version().HasIetfQuicFrames()) {
p = packet99;
- p_length = QUIC_ARRAYSIZE(packet99);
+ p_length = QUICHE_ARRAYSIZE(packet99);
}
QuicEncryptedPacket encrypted(AsChars(p), p_length, false);
- EXPECT_QUIC_PEER_BUG(EXPECT_TRUE(framer_.ProcessPacket(encrypted)),
- "Server: Failed to parse received coalesced header.*");
+ EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
@@ -12818,7 +13287,7 @@ TEST_P(QuicFramerTest, CoalescedPacketWithZeroesRoundTrip) {
unsigned char packet[kMaxOutgoingPacketSize] = {};
size_t encrypted_length =
framer_.EncryptPayload(ENCRYPTION_INITIAL, header.packet_number, *data,
- AsChars(packet), QUIC_ARRAYSIZE(packet));
+ AsChars(packet), QUICHE_ARRAYSIZE(packet));
ASSERT_NE(0u, encrypted_length);
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER);
@@ -12830,12 +13299,12 @@ TEST_P(QuicFramerTest, CoalescedPacketWithZeroesRoundTrip) {
std::move(server_crypters.decrypter));
// Make sure the first long header initial packet parses correctly.
- QuicEncryptedPacket encrypted(AsChars(packet), QUIC_ARRAYSIZE(packet), false);
+ QuicEncryptedPacket encrypted(AsChars(packet), QUICHE_ARRAYSIZE(packet),
+ false);
// Make sure we discard the subsequent zeroes.
- EXPECT_QUIC_PEER_BUG(EXPECT_TRUE(framer_.ProcessPacket(encrypted)),
- "Server: (Failed to parse received|Received mismatched) "
- "coalesced header.*");
+ EXPECT_TRUE(framer_.ProcessPacket(encrypted));
+ EXPECT_TRUE(visitor_.coalesced_packets_.empty());
}
TEST_P(QuicFramerTest, ClientReceivesInvalidVersion) {
@@ -12861,7 +13330,8 @@ TEST_P(QuicFramerTest, ClientReceivesInvalidVersion) {
};
// clang-format on
- QuicEncryptedPacket encrypted(AsChars(packet), QUIC_ARRAYSIZE(packet), false);
+ QuicEncryptedPacket encrypted(AsChars(packet), QUICHE_ARRAYSIZE(packet),
+ false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_VERSION));
@@ -12869,8 +13339,7 @@ TEST_P(QuicFramerTest, ClientReceivesInvalidVersion) {
}
TEST_P(QuicFramerTest, PacketHeaderWithVariableLengthConnectionId) {
- if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
- framer_.transport_version())) {
+ if (!framer_.version().AllowsVariableLengthConnectionIds()) {
return;
}
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
@@ -12985,11 +13454,11 @@ TEST_P(QuicFramerTest, MultiplePacketNumberSpaces) {
if (!QuicVersionHasLongHeaderLengths(framer_.transport_version())) {
EXPECT_TRUE(framer_.ProcessPacket(
QuicEncryptedPacket(AsChars(long_header_packet),
- QUIC_ARRAYSIZE(long_header_packet), false)));
+ QUICHE_ARRAYSIZE(long_header_packet), false)));
} else {
EXPECT_TRUE(framer_.ProcessPacket(
QuicEncryptedPacket(AsChars(long_header_packet99),
- QUIC_ARRAYSIZE(long_header_packet99), false)));
+ QUICHE_ARRAYSIZE(long_header_packet99), false)));
}
EXPECT_THAT(framer_.error(), IsQuicNoError());
@@ -13016,7 +13485,8 @@ TEST_P(QuicFramerTest, MultiplePacketNumberSpaces) {
// clang-format on
QuicEncryptedPacket short_header_encrypted(
- AsChars(short_header_packet), QUIC_ARRAYSIZE(short_header_packet), false);
+ AsChars(short_header_packet), QUICHE_ARRAYSIZE(short_header_packet),
+ false);
if (framer_.version().KnowsWhichDecrypterToUse()) {
framer_.InstallDecrypter(ENCRYPTION_FORWARD_SECURE,
std::make_unique<TestDecrypter>());
@@ -13223,9 +13693,9 @@ TEST_P(QuicFramerTest, WriteClientVersionNegotiationProbePacketOld) {
EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
packet, sizeof(packet), destination_connection_id_bytes,
sizeof(destination_connection_id_bytes)));
- test::CompareCharArraysWithHexError("constructed packet", packet,
- sizeof(packet), expected_packet,
- sizeof(expected_packet));
+ quiche::test::CompareCharArraysWithHexError("constructed packet", packet,
+ sizeof(packet), expected_packet,
+ sizeof(expected_packet));
QuicEncryptedPacket encrypted(reinterpret_cast<const char*>(packet),
sizeof(packet), false);
// Make sure we fail to parse this packet for the version under test.
@@ -13250,7 +13720,7 @@ TEST_P(QuicFramerTest, WriteClientVersionNegotiationProbePacketOld) {
QuicConnectionId destination_connection_id = TestConnectionId(0x33);
QuicConnectionId source_connection_id = TestConnectionId(0x34);
bool retry_token_present = true;
- QuicStringPiece retry_token;
+ quiche::QuicheStringPiece retry_token;
std::string detailed_error = "foobar";
QuicErrorCode parse_result = QuicFramer::ParsePublicHeaderDispatcher(
@@ -13267,7 +13737,7 @@ TEST_P(QuicFramerTest, WriteClientVersionNegotiationProbePacketOld) {
EXPECT_EQ(probe_payload_connection_id, destination_connection_id);
EXPECT_EQ(EmptyQuicConnectionId(), source_connection_id);
EXPECT_FALSE(retry_token_present);
- EXPECT_EQ(QuicStringPiece(), retry_token);
+ EXPECT_EQ(quiche::QuicheStringPiece(), retry_token);
EXPECT_EQ("", detailed_error);
}
@@ -13323,9 +13793,9 @@ TEST_P(QuicFramerTest, WriteClientVersionNegotiationProbePacket) {
EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
packet, sizeof(packet), destination_connection_id_bytes,
sizeof(destination_connection_id_bytes)));
- test::CompareCharArraysWithHexError("constructed packet", packet,
- sizeof(packet), expected_packet,
- sizeof(expected_packet));
+ quiche::test::CompareCharArraysWithHexError("constructed packet", packet,
+ sizeof(packet), expected_packet,
+ sizeof(expected_packet));
QuicEncryptedPacket encrypted(reinterpret_cast<const char*>(packet),
sizeof(packet), false);
if (!framer_.version().HasLengthPrefixedConnectionIds()) {
@@ -13402,7 +13872,7 @@ TEST_P(QuicFramerTest, DispatcherParseOldClientVersionNegotiationProbePacket) {
QuicConnectionId destination_connection_id = TestConnectionId(1);
QuicConnectionId source_connection_id = TestConnectionId(2);
bool retry_token_present = true;
- QuicStringPiece retry_token;
+ quiche::QuicheStringPiece retry_token;
std::string detailed_error = "foobar";
QuicErrorCode header_parse_result = QuicFramer::ParsePublicHeaderDispatcher(
encrypted, kQuicDefaultConnectionIdLength, &format, &long_packet_type,
@@ -13481,7 +13951,7 @@ TEST_P(QuicFramerTest, DispatcherParseClientVersionNegotiationProbePacket) {
QuicConnectionId destination_connection_id = TestConnectionId(1);
QuicConnectionId source_connection_id = TestConnectionId(2);
bool retry_token_present = true;
- QuicStringPiece retry_token;
+ quiche::QuicheStringPiece retry_token;
std::string detailed_error = "foobar";
QuicErrorCode header_parse_result = QuicFramer::ParsePublicHeaderDispatcher(
encrypted, kQuicDefaultConnectionIdLength, &format, &long_packet_type,
@@ -13524,7 +13994,7 @@ TEST_P(QuicFramerTest, ParseServerVersionNegotiationProbeResponseOld) {
reinterpret_cast<char*>(parsed_probe_payload_bytes),
&parsed_probe_payload_length, &parse_detailed_error));
EXPECT_EQ("", parse_detailed_error);
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"parsed probe", parsed_probe_payload_bytes, parsed_probe_payload_length,
probe_payload_bytes, sizeof(probe_payload_bytes));
}
@@ -13555,7 +14025,7 @@ TEST_P(QuicFramerTest, ParseServerVersionNegotiationProbeResponse) {
reinterpret_cast<char*>(parsed_probe_payload_bytes),
&parsed_probe_payload_length, &parse_detailed_error));
EXPECT_EQ("", parse_detailed_error);
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"parsed probe", parsed_probe_payload_bytes, parsed_probe_payload_length,
probe_payload_bytes, sizeof(probe_payload_bytes));
}
@@ -13606,15 +14076,14 @@ TEST_P(QuicFramerTest, ClientConnectionIdFromLongHeaderToClient) {
};
// clang-format on
unsigned char* p = packet;
- size_t p_length = QUIC_ARRAYSIZE(packet);
+ size_t p_length = QUICHE_ARRAYSIZE(packet);
if (framer_.transport_version() >= QUIC_VERSION_49) {
p = packet49;
- p_length = QUIC_ARRAYSIZE(packet49);
+ p_length = QUICHE_ARRAYSIZE(packet49);
}
const bool parse_success =
framer_.ProcessPacket(QuicEncryptedPacket(AsChars(p), p_length, false));
- if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
- framer_.transport_version())) {
+ if (!framer_.version().AllowsVariableLengthConnectionIds()) {
EXPECT_FALSE(parse_success);
EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_PACKET_HEADER));
EXPECT_EQ("Invalid ConnectionId length.", framer_.detailed_error());
@@ -13672,15 +14141,14 @@ TEST_P(QuicFramerTest, ClientConnectionIdFromLongHeaderToServer) {
};
// clang-format on
unsigned char* p = packet;
- size_t p_length = QUIC_ARRAYSIZE(packet);
+ size_t p_length = QUICHE_ARRAYSIZE(packet);
if (framer_.transport_version() >= QUIC_VERSION_49) {
p = packet49;
- p_length = QUIC_ARRAYSIZE(packet49);
+ p_length = QUICHE_ARRAYSIZE(packet49);
}
const bool parse_success =
framer_.ProcessPacket(QuicEncryptedPacket(AsChars(p), p_length, false));
- if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
- framer_.transport_version())) {
+ if (!framer_.version().AllowsVariableLengthConnectionIds()) {
EXPECT_FALSE(parse_success);
EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_PACKET_HEADER));
EXPECT_EQ("Invalid ConnectionId length.", framer_.detailed_error());
@@ -13895,8 +14363,8 @@ TEST_P(QuicFramerTest, OverlyLargeAckDelay) {
};
// clang-format on
- framer_.ProcessPacket(
- QuicEncryptedPacket(AsChars(packet99), QUIC_ARRAYSIZE(packet99), false));
+ framer_.ProcessPacket(QuicEncryptedPacket(AsChars(packet99),
+ QUICHE_ARRAYSIZE(packet99), false));
ASSERT_EQ(1u, visitor_.ack_frames_.size());
// Verify ack_delay_time is set correctly.
EXPECT_EQ(QuicTime::Delta::Infinite(),
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector.cc b/chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector.cc
new file mode 100644
index 00000000000..8d76fd2aba3
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector.cc
@@ -0,0 +1,109 @@
+// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/quic_idle_network_detector.h"
+
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
+
+namespace quic {
+
+namespace {
+
+class AlarmDelegate : public QuicAlarm::Delegate {
+ public:
+ explicit AlarmDelegate(QuicIdleNetworkDetector* detector)
+ : detector_(detector) {}
+ AlarmDelegate(const AlarmDelegate&) = delete;
+ AlarmDelegate& operator=(const AlarmDelegate&) = delete;
+
+ void OnAlarm() override { detector_->OnAlarm(); }
+
+ private:
+ QuicIdleNetworkDetector* detector_;
+};
+
+} // namespace
+
+QuicIdleNetworkDetector::QuicIdleNetworkDetector(
+ Delegate* delegate,
+ QuicTime now,
+ QuicConnectionArena* arena,
+ QuicAlarmFactory* alarm_factory)
+ : delegate_(delegate),
+ start_time_(now),
+ handshake_timeout_(QuicTime::Delta::Infinite()),
+ time_of_last_received_packet_(now),
+ time_of_first_packet_sent_after_receiving_(QuicTime::Zero()),
+ idle_network_timeout_(QuicTime::Delta::Infinite()),
+ alarm_(
+ alarm_factory->CreateAlarm(arena->New<AlarmDelegate>(this), arena)) {}
+
+void QuicIdleNetworkDetector::OnAlarm() {
+ if (handshake_timeout_.IsInfinite()) {
+ delegate_->OnIdleNetworkDetected();
+ return;
+ }
+ if (idle_network_timeout_.IsInfinite()) {
+ delegate_->OnHandshakeTimeout();
+ return;
+ }
+ if (last_network_activity_time() + idle_network_timeout_ >
+ start_time_ + handshake_timeout_) {
+ delegate_->OnHandshakeTimeout();
+ return;
+ }
+ delegate_->OnIdleNetworkDetected();
+}
+
+void QuicIdleNetworkDetector::SetTimeouts(
+ QuicTime::Delta handshake_timeout,
+ QuicTime::Delta idle_network_timeout) {
+ handshake_timeout_ = handshake_timeout;
+ idle_network_timeout_ = idle_network_timeout;
+
+ SetAlarm();
+}
+
+void QuicIdleNetworkDetector::StopDetection() {
+ alarm_->Cancel();
+ handshake_timeout_ = QuicTime::Delta::Infinite();
+ idle_network_timeout_ = QuicTime::Delta::Infinite();
+}
+
+void QuicIdleNetworkDetector::OnPacketSent(QuicTime now) {
+ if (time_of_first_packet_sent_after_receiving_ >
+ time_of_last_received_packet_) {
+ return;
+ }
+ time_of_first_packet_sent_after_receiving_ =
+ std::max(time_of_first_packet_sent_after_receiving_, now);
+
+ SetAlarm();
+}
+
+void QuicIdleNetworkDetector::OnPacketReceived(QuicTime now) {
+ time_of_last_received_packet_ = std::max(time_of_last_received_packet_, now);
+
+ SetAlarm();
+}
+
+void QuicIdleNetworkDetector::SetAlarm() {
+ // Set alarm to the nearer deadline.
+ QuicTime new_deadline = QuicTime::Zero();
+ if (!handshake_timeout_.IsInfinite()) {
+ new_deadline = start_time_ + handshake_timeout_;
+ }
+ if (!idle_network_timeout_.IsInfinite()) {
+ const QuicTime idle_network_deadline =
+ last_network_activity_time() + idle_network_timeout_;
+ if (new_deadline.IsInitialized()) {
+ new_deadline = std::min(new_deadline, idle_network_deadline);
+ } else {
+ new_deadline = idle_network_deadline;
+ }
+ }
+ alarm_->Update(new_deadline, kAlarmGranularity);
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector.h b/chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector.h
new file mode 100644
index 00000000000..83beb29694a
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector.h
@@ -0,0 +1,103 @@
+// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_CORE_QUIC_IDLE_NETWORK_DETECTOR_H_
+#define QUICHE_QUIC_CORE_QUIC_IDLE_NETWORK_DETECTOR_H_
+
+#include "net/third_party/quiche/src/quic/core/quic_alarm.h"
+#include "net/third_party/quiche/src/quic/core/quic_alarm_factory.h"
+#include "net/third_party/quiche/src/quic/core/quic_one_block_arena.h"
+#include "net/third_party/quiche/src/quic/core/quic_time.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+
+namespace quic {
+
+namespace test {
+class QuicConnectionPeer;
+class QuicIdleNetworkDetectorTestPeer;
+} // namespace test
+
+// QuicIdleNetworkDetector detects handshake timeout and idle network timeout.
+// Handshake timeout detection is disabled after handshake completes. Idle
+// network deadline is extended by network activity (e.g., sending or receiving
+// packets).
+class QUIC_EXPORT_PRIVATE QuicIdleNetworkDetector {
+ public:
+ class QUIC_EXPORT_PRIVATE Delegate {
+ public:
+ virtual ~Delegate() {}
+
+ // Called when handshake times out.
+ virtual void OnHandshakeTimeout() = 0;
+
+ // Called when idle network has been detected.
+ virtual void OnIdleNetworkDetected() = 0;
+ };
+
+ QuicIdleNetworkDetector(Delegate* delegate,
+ QuicTime now,
+ QuicConnectionArena* arena,
+ QuicAlarmFactory* alarm_factory);
+
+ void OnAlarm();
+
+ // Called to set handshake_timeout_ and idle_network_timeout_.
+ void SetTimeouts(QuicTime::Delta handshake_timeout,
+ QuicTime::Delta idle_network_timeout);
+
+ void StopDetection();
+
+ // Called when a packet gets sent.
+ void OnPacketSent(QuicTime now);
+
+ // Called when a packet gets received.
+ void OnPacketReceived(QuicTime now);
+
+ QuicTime::Delta handshake_timeout() const { return handshake_timeout_; }
+
+ QuicTime time_of_last_received_packet() const {
+ return time_of_last_received_packet_;
+ }
+
+ QuicTime last_network_activity_time() const {
+ return std::max(time_of_last_received_packet_,
+ time_of_first_packet_sent_after_receiving_);
+ }
+
+ QuicTime::Delta idle_network_timeout() const { return idle_network_timeout_; }
+
+ private:
+ friend class test::QuicConnectionPeer;
+ friend class test::QuicIdleNetworkDetectorTestPeer;
+
+ void SetAlarm();
+
+ Delegate* delegate_; // Not owned.
+
+ // Start time of the detector, handshake deadline = start_time_ +
+ // handshake_timeout_.
+ const QuicTime start_time_;
+
+ // Handshake timeout. Infinit means handshake has completed.
+ QuicTime::Delta handshake_timeout_;
+
+ // Time that last packet is received for this connection. Initialized to
+ // start_time_.
+ QuicTime time_of_last_received_packet_;
+
+ // Time that the first packet gets sent after the received packet. idle
+ // network deadline = std::max(time_of_last_received_packet_,
+ // time_of_first_packet_sent_after_receiving_) + idle_network_timeout_.
+ // Initialized to 0.
+ QuicTime time_of_first_packet_sent_after_receiving_;
+
+ // Idle network timeout. Infinit means no idle network timeout.
+ QuicTime::Delta idle_network_timeout_;
+
+ QuicArenaScopedPtr<QuicAlarm> alarm_;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_QUIC_IDLE_NETWORK_DETECTOR_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector_test.cc
new file mode 100644
index 00000000000..16941ef7a82
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector_test.cc
@@ -0,0 +1,148 @@
+// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/quic_idle_network_detector.h"
+
+#include "net/third_party/quiche/src/quic/core/quic_one_block_arena.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+
+namespace quic {
+namespace test {
+
+class QuicIdleNetworkDetectorTestPeer {
+ public:
+ static QuicAlarm* GetAlarm(QuicIdleNetworkDetector* detector) {
+ return detector->alarm_.get();
+ }
+};
+
+namespace {
+
+class MockDelegate : public QuicIdleNetworkDetector::Delegate {
+ public:
+ MOCK_METHOD0(OnHandshakeTimeout, void());
+ MOCK_METHOD0(OnIdleNetworkDetected, void());
+};
+
+class QuicIdleNetworkDetectorTest : public QuicTest {
+ public:
+ QuicIdleNetworkDetectorTest() {
+ clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
+ detector_ = std::make_unique<QuicIdleNetworkDetector>(
+ &delegate_, clock_.Now(), &arena_, &alarm_factory_);
+ alarm_ = static_cast<MockAlarmFactory::TestAlarm*>(
+ QuicIdleNetworkDetectorTestPeer::GetAlarm(detector_.get()));
+ }
+
+ protected:
+ testing::StrictMock<MockDelegate> delegate_;
+ QuicConnectionArena arena_;
+ MockAlarmFactory alarm_factory_;
+
+ std::unique_ptr<QuicIdleNetworkDetector> detector_;
+
+ MockAlarmFactory::TestAlarm* alarm_;
+ MockClock clock_;
+};
+
+TEST_F(QuicIdleNetworkDetectorTest,
+ IdleNetworkDetectedBeforeHandshakeCompletes) {
+ EXPECT_FALSE(alarm_->IsSet());
+ detector_->SetTimeouts(
+ /*handshake_timeout=*/QuicTime::Delta::FromSeconds(30),
+ /*idle_network_timeout=*/QuicTime::Delta::FromSeconds(20));
+ EXPECT_TRUE(alarm_->IsSet());
+ EXPECT_EQ(clock_.Now() + QuicTime::Delta::FromSeconds(20),
+ alarm_->deadline());
+
+ // No network activity for 20s.
+ clock_.AdvanceTime(QuicTime::Delta::FromSeconds(20));
+ EXPECT_CALL(delegate_, OnIdleNetworkDetected());
+ alarm_->Fire();
+}
+
+TEST_F(QuicIdleNetworkDetectorTest, HandshakeTimeout) {
+ EXPECT_FALSE(alarm_->IsSet());
+ detector_->SetTimeouts(
+ /*handshake_timeout=*/QuicTime::Delta::FromSeconds(30),
+ /*idle_network_timeout=*/QuicTime::Delta::FromSeconds(20));
+ EXPECT_TRUE(alarm_->IsSet());
+
+ // Has network activity after 15s.
+ clock_.AdvanceTime(QuicTime::Delta::FromSeconds(15));
+ detector_->OnPacketReceived(clock_.Now());
+ EXPECT_EQ(clock_.Now() + QuicTime::Delta::FromSeconds(15),
+ alarm_->deadline());
+ // Handshake does not complete for another 15s.
+ clock_.AdvanceTime(QuicTime::Delta::FromSeconds(15));
+ EXPECT_CALL(delegate_, OnHandshakeTimeout());
+ alarm_->Fire();
+}
+
+TEST_F(QuicIdleNetworkDetectorTest,
+ IdleNetworkDetectedAfterHandshakeCompletes) {
+ EXPECT_FALSE(alarm_->IsSet());
+ detector_->SetTimeouts(
+ /*handshake_timeout=*/QuicTime::Delta::FromSeconds(30),
+ /*idle_network_timeout=*/QuicTime::Delta::FromSeconds(20));
+ EXPECT_TRUE(alarm_->IsSet());
+
+ // Handshake completes in 200ms.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(200));
+ detector_->OnPacketReceived(clock_.Now());
+ detector_->SetTimeouts(
+ /*handshake_timeout=*/QuicTime::Delta::Infinite(),
+ /*idle_network_timeout=*/QuicTime::Delta::FromSeconds(600));
+ EXPECT_EQ(clock_.Now() + QuicTime::Delta::FromSeconds(600),
+ alarm_->deadline());
+
+ // No network activity for 600s.
+ clock_.AdvanceTime(QuicTime::Delta::FromSeconds(600));
+ EXPECT_CALL(delegate_, OnIdleNetworkDetected());
+ alarm_->Fire();
+}
+
+TEST_F(QuicIdleNetworkDetectorTest,
+ DoNotExtendIdleDeadlineOnConsecutiveSentPackets) {
+ EXPECT_FALSE(alarm_->IsSet());
+ detector_->SetTimeouts(
+ /*handshake_timeout=*/QuicTime::Delta::FromSeconds(30),
+ /*idle_network_timeout=*/QuicTime::Delta::FromSeconds(20));
+ EXPECT_TRUE(alarm_->IsSet());
+
+ // Handshake completes in 200ms.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(200));
+ detector_->OnPacketReceived(clock_.Now());
+ detector_->SetTimeouts(
+ /*handshake_timeout=*/QuicTime::Delta::Infinite(),
+ /*idle_network_timeout=*/QuicTime::Delta::FromSeconds(600));
+ EXPECT_EQ(clock_.Now() + QuicTime::Delta::FromSeconds(600),
+ alarm_->deadline());
+
+ // Sent packets after 200ms.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(200));
+ detector_->OnPacketSent(clock_.Now());
+ const QuicTime packet_sent_time = clock_.Now();
+ EXPECT_EQ(packet_sent_time + QuicTime::Delta::FromSeconds(600),
+ alarm_->deadline());
+
+ // Sent another packet after 200ms
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(200));
+ detector_->OnPacketSent(clock_.Now());
+ // Verify idle network deadline does not extend.
+ EXPECT_EQ(packet_sent_time + QuicTime::Delta::FromSeconds(600),
+ alarm_->deadline());
+
+ // No network activity for 600s.
+ clock_.AdvanceTime(QuicTime::Delta::FromSeconds(600) -
+ QuicTime::Delta::FromMilliseconds(200));
+ EXPECT_CALL(delegate_, OnIdleNetworkDetected());
+ alarm_->Fire();
+}
+
+} // namespace
+
+} // namespace test
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_ietf_framer_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_ietf_framer_test.cc
deleted file mode 100644
index e4feb471131..00000000000
--- a/chromium/net/third_party/quiche/src/quic/core/quic_ietf_framer_test.cc
+++ /dev/null
@@ -1,1501 +0,0 @@
-// Copyright (c) 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// gunit tests for the IETF-format framer --- generally does a simple test
-// for each framer; we generate the template object (eg
-// QuicIetfStreamFrame) with the correct stuff in it, ask that a frame
-// be serialized (call AppendIetf<mumble>) then deserialized (call
-// ProcessIetf<mumble>) and then check that the gazintas and gazoutas
-// are the same.
-//
-// We do minimal checking of the serialized frame
-//
-// We do look at various different values (resulting in different
-// length varints, etc)
-
-#include "net/third_party/quiche/src/quic/core/quic_framer.h"
-
-#include <algorithm>
-#include <cstdint>
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "net/third_party/quiche/src/quic/core/crypto/null_decrypter.h"
-#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h"
-#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
-#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
-#include "net/third_party/quiche/src/quic/core/quic_data_reader.h"
-#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
-#include "net/third_party/quiche/src/quic/core/quic_packets.h"
-#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/test_tools/quic_framer_peer.h"
-#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
-#include "net/third_party/quiche/src/quic/test_tools/simple_data_producer.h"
-
-namespace quic {
-namespace test {
-namespace {
-
-const size_t kNormalPacketBufferSize = 1400;
-// Several different stream ids, should be encoded
-// in 8, 4, 2, and 1 byte, respectively. Last one
-// checks that value==0 works.
-// All stream IDs end in 0x0, so the client/server- initiated
-// and Uni/Bi-directional bits are available to alter, as any
-// given test may wish.
-const QuicIetfStreamId kStreamId8 = UINT64_C(0x3EDCBA9876543210);
-const QuicIetfStreamId kStreamId4 = UINT64_C(0x36543210);
-const QuicIetfStreamId kStreamId2 = UINT64_C(0x3210);
-const QuicIetfStreamId kStreamId1 = UINT64_C(0x10);
-const QuicIetfStreamId kStreamId0 = UINT64_C(0x00);
-
-// Ditto for the offsets.
-const QuicIetfStreamOffset kOffset8 = UINT64_C(0x3210BA9876543210);
-const QuicIetfStreamOffset kOffset4 = UINT64_C(0x32109876);
-const QuicIetfStreamOffset kOffset2 = UINT64_C(0x3456);
-const QuicIetfStreamOffset kOffset1 = UINT64_C(0x3f);
-const QuicIetfStreamOffset kOffset0 = UINT64_C(0x00);
-
-// Structures used to create various ack frames.
-
-// Defines an ack frame to feed through the framer/deframer.
-struct ack_frame {
- uint64_t delay_time;
- bool is_ack_ecn;
- QuicPacketCount ect_0_count;
- QuicPacketCount ect_1_count;
- QuicPacketCount ecn_ce_count;
- const std::vector<QuicAckBlock>& ranges;
- uint64_t expected_frame_type;
-};
-
-class TestQuicVisitor : public QuicFramerVisitorInterface {
- public:
- TestQuicVisitor() {}
-
- ~TestQuicVisitor() override {}
-
- void OnError(QuicFramer* f) override {
- QUIC_DLOG(INFO) << "QuicIetfFramer Error: "
- << QuicErrorCodeToString(f->error()) << " (" << f->error()
- << ")";
- }
-
- void OnPacket() override {}
-
- void OnPublicResetPacket(const QuicPublicResetPacket& /*packet*/) override {}
-
- void OnVersionNegotiationPacket(
- const QuicVersionNegotiationPacket& /*packet*/) override {}
-
- void OnRetryPacket(QuicConnectionId /*original_connection_id*/,
- QuicConnectionId /*new_connection_id*/,
- QuicStringPiece /*retry_token*/) override {}
-
- bool OnProtocolVersionMismatch(
- ParsedQuicVersion /*received_version*/) override {
- return false;
- }
-
- bool OnUnauthenticatedPublicHeader(
- const QuicPacketHeader& /*header*/) override {
- return true;
- }
-
- bool OnUnauthenticatedHeader(const QuicPacketHeader& /*header*/) override {
- return true;
- }
-
- void OnDecryptedPacket(EncryptionLevel /*level*/) override {}
-
- bool OnPacketHeader(const QuicPacketHeader& /*header*/) override {
- return true;
- }
-
- void OnCoalescedPacket(const QuicEncryptedPacket& /*packet*/) override {}
-
- void OnUndecryptablePacket(const QuicEncryptedPacket& /*packet*/,
- EncryptionLevel /*decryption_level*/,
- bool /*has_decryption_key*/) override {}
-
- bool OnStreamFrame(const QuicStreamFrame& /*frame*/) override { return true; }
-
- bool OnCryptoFrame(const QuicCryptoFrame& /*frame*/) override { return true; }
-
- bool OnAckFrameStart(QuicPacketNumber /*largest_acked*/,
- QuicTime::Delta /*ack_delay_time*/) override {
- return true;
- }
-
- bool OnAckRange(QuicPacketNumber /*start*/,
- QuicPacketNumber /*end*/) override {
- return true;
- }
-
- bool OnAckTimestamp(QuicPacketNumber /*packet_number*/,
- QuicTime /*timestamp*/) override {
- return true;
- }
-
- bool OnAckFrameEnd(QuicPacketNumber /*start*/) override { return true; }
-
- bool OnStopWaitingFrame(const QuicStopWaitingFrame& /*frame*/) override {
- return true;
- }
-
- bool OnPaddingFrame(const QuicPaddingFrame& /*frame*/) override {
- return true;
- }
-
- bool OnPingFrame(const QuicPingFrame& /*frame*/) override { return true; }
-
- bool OnMessageFrame(const QuicMessageFrame& /*frame*/) override {
- return true;
- }
-
- void OnPacketComplete() override {}
-
- bool OnRstStreamFrame(const QuicRstStreamFrame& /*frame*/) override {
- return true;
- }
-
- bool OnConnectionCloseFrame(
- const QuicConnectionCloseFrame& /*frame*/) override {
- return true;
- }
-
- bool OnStopSendingFrame(const QuicStopSendingFrame& /*frame*/) override {
- return true;
- }
-
- bool OnPathChallengeFrame(const QuicPathChallengeFrame& /*frame*/) override {
- return true;
- }
- bool OnPathResponseFrame(const QuicPathResponseFrame& /*frame*/) override {
- return true;
- }
-
- bool OnGoAwayFrame(const QuicGoAwayFrame& /*frame*/) override { return true; }
-
- bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& /*frame*/) override {
- return true;
- }
-
- bool OnBlockedFrame(const QuicBlockedFrame& /*frame*/) override {
- return true;
- }
-
- bool OnNewConnectionIdFrame(
- const QuicNewConnectionIdFrame& /*frame*/) override {
- return true;
- }
-
- bool OnRetireConnectionIdFrame(
- const QuicRetireConnectionIdFrame& /*frame*/) override {
- return true;
- }
-
- bool OnNewTokenFrame(const QuicNewTokenFrame& /*frame*/) override {
- return true;
- }
-
- bool IsValidStatelessResetToken(QuicUint128 /*token*/) const override {
- return true;
- }
-
- void OnAuthenticatedIetfStatelessResetPacket(
- const QuicIetfStatelessResetPacket& /*packet*/) override {}
-
- bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& /*frame*/) override {
- return true;
- }
-
- bool OnStreamsBlockedFrame(
- const QuicStreamsBlockedFrame& /*frame*/) override {
- return true;
- }
-};
-
-class QuicIetfFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
- public:
- QuicIetfFramerTest()
- : start_(QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(0x10)),
- framer_(AllSupportedVersions(),
- start_,
- Perspective::IS_SERVER,
- kQuicDefaultConnectionIdLength) {
- framer_.set_visitor(&visitor_);
- }
-
- // Utility functions to do actual framing/deframing.
- void TryStreamFrame(char* packet_buffer,
- size_t packet_buffer_size,
- const char* xmit_packet_data,
- size_t xmit_packet_data_size,
- QuicIetfStreamId stream_id,
- QuicIetfStreamOffset offset,
- bool fin_bit,
- bool last_frame_bit,
- QuicIetfFrameType frame_type) {
- // initialize a writer so that the serialized packet is placed in
- // packet_buffer.
- QuicDataWriter writer(packet_buffer_size, packet_buffer,
- quiche::NETWORK_BYTE_ORDER); // do not really care
- // about endianness.
- // set up to define the source frame we wish to send.
- QuicStreamFrame source_stream_frame(
- stream_id, fin_bit, offset, xmit_packet_data, xmit_packet_data_size);
-
- // Write the frame to the packet buffer.
- EXPECT_TRUE(QuicFramerPeer::AppendIetfStreamFrame(
- &framer_, source_stream_frame, last_frame_bit, &writer));
- // Better have something in the packet buffer.
- EXPECT_NE(0u, writer.length());
- // Now set up a reader to read in the frame.
- QuicDataReader reader(packet_buffer, writer.length(),
- quiche::NETWORK_BYTE_ORDER);
-
- // A StreamFrame to hold the results... we know the frame type,
- // put it into the QuicIetfStreamFrame
- QuicStreamFrame sink_stream_frame;
- if (xmit_packet_data_size) {
- EXPECT_EQ(sink_stream_frame.data_buffer, nullptr);
- EXPECT_EQ(sink_stream_frame.data_length, 0u);
- }
-
- EXPECT_TRUE(QuicFramerPeer::ProcessIetfStreamFrame(
- &framer_, &reader, frame_type, &sink_stream_frame));
-
- // Now check that the streamid, fin-bit, offset, and
- // data len all match the input.
- EXPECT_EQ(sink_stream_frame.stream_id, source_stream_frame.stream_id);
- EXPECT_EQ(sink_stream_frame.fin, source_stream_frame.fin);
- EXPECT_EQ(sink_stream_frame.data_length, source_stream_frame.data_length);
- if (frame_type & IETF_STREAM_FRAME_OFF_BIT) {
- // There was an offset in the frame, see if xmit and rcv vales equal.
- EXPECT_EQ(sink_stream_frame.offset, source_stream_frame.offset);
- } else {
- // Offset not in frame, so it better come out 0.
- EXPECT_EQ(sink_stream_frame.offset, 0u);
- }
- if (xmit_packet_data_size) {
- ASSERT_NE(sink_stream_frame.data_buffer, nullptr);
- ASSERT_NE(source_stream_frame.data_buffer, nullptr);
- EXPECT_EQ(strcmp(sink_stream_frame.data_buffer,
- source_stream_frame.data_buffer),
- 0);
- } else {
- // No data in the frame.
- EXPECT_EQ(source_stream_frame.data_length, 0u);
- EXPECT_EQ(sink_stream_frame.data_length, 0u);
- }
- }
-
- // Overall ack frame encode/decode/compare function
- // Encodes an ack frame as specified at |*frame|
- // Then decodes the frame,
- // Then compares the two
- // Does some basic checking:
- // - did the writer write something?
- // - did the reader read the entire packet?
- // - did the things the reader read match what the writer wrote?
- // Returns true if it all worked false if not.
- bool TryAckFrame(char* packet_buffer,
- size_t /*packet_buffer_size*/,
- struct ack_frame* frame) {
- QuicAckFrame transmit_frame = InitAckFrame(frame->ranges);
- if (frame->is_ack_ecn) {
- transmit_frame.ecn_counters_populated = true;
- transmit_frame.ect_0_count = frame->ect_0_count;
- transmit_frame.ect_1_count = frame->ect_1_count;
- transmit_frame.ecn_ce_count = frame->ecn_ce_count;
- }
- transmit_frame.ack_delay_time =
- QuicTime::Delta::FromMicroseconds(frame->delay_time);
- size_t expected_size =
- QuicFramerPeer::GetIetfAckFrameSize(&framer_, transmit_frame);
-
- // Make a writer so that the serialized packet is placed in
- // packet_buffer.
- QuicDataWriter writer(expected_size, packet_buffer,
- quiche::NETWORK_BYTE_ORDER);
-
- // Write the frame to the packet buffer.
- EXPECT_TRUE(QuicFramerPeer::AppendIetfAckFrameAndTypeByte(
- &framer_, transmit_frame, &writer));
-
- size_t expected_frame_length = QuicFramerPeer::ComputeFrameLength(
- &framer_, QuicFrame(&transmit_frame), false,
- static_cast<QuicPacketNumberLength>(123456u));
-
- // Encoded length should match what ComputeFrameLength returns
- EXPECT_EQ(expected_frame_length, writer.length());
- // and what is in the buffer should be the expected size.
- EXPECT_EQ(expected_size, writer.length()) << "Frame is " << transmit_frame;
- // Now set up a reader to read in the frame.
- QuicDataReader reader(packet_buffer, writer.length(),
- quiche::NETWORK_BYTE_ORDER);
-
- // read in the frame type
- uint8_t received_frame_type;
- EXPECT_TRUE(reader.ReadUInt8(&received_frame_type));
- EXPECT_EQ(frame->expected_frame_type, received_frame_type);
-
- // an AckFrame to hold the results
- QuicAckFrame receive_frame;
-
- EXPECT_TRUE(QuicFramerPeer::ProcessIetfAckFrame(
- &framer_, &reader, received_frame_type, &receive_frame));
-
- if (frame->is_ack_ecn &&
- (frame->ect_0_count || frame->ect_1_count || frame->ecn_ce_count)) {
- EXPECT_TRUE(receive_frame.ecn_counters_populated);
- EXPECT_EQ(receive_frame.ect_0_count, frame->ect_0_count);
- EXPECT_EQ(receive_frame.ect_1_count, frame->ect_1_count);
- EXPECT_EQ(receive_frame.ecn_ce_count, frame->ecn_ce_count);
- } else {
- EXPECT_FALSE(receive_frame.ecn_counters_populated);
- EXPECT_EQ(receive_frame.ect_0_count, 0u);
- EXPECT_EQ(receive_frame.ect_1_count, 0u);
- EXPECT_EQ(receive_frame.ecn_ce_count, 0u);
- }
-
- // Now check that the received frame matches the sent frame.
- EXPECT_EQ(transmit_frame.largest_acked, receive_frame.largest_acked);
- // The ~0x7 needs some explaining. The ack frame format down shifts the
- // delay time by 3 (divide by 8) to allow for greater ranges in delay time.
- // Therefore, if we give the framer a delay time that is not an
- // even multiple of 8, the value that the deframer produces will
- // not be the same as what the framer got. The downshift on
- // framing and upshift on deframing results in clearing the 3
- // low-order bits ... The masking basically does the same thing,
- // so the compare works properly.
- return true;
- }
-
- // encode, decode, and check a Path Challenge frame.
- bool TryPathChallengeFrame(char* packet_buffer,
- size_t packet_buffer_size,
- const QuicPathFrameBuffer& data) {
- // Make a writer so that the serialized packet is placed in
- // packet_buffer.
- QuicDataWriter writer(packet_buffer_size, packet_buffer,
- quiche::NETWORK_BYTE_ORDER);
-
- QuicPathChallengeFrame transmit_frame(0, data);
-
- // write the frame to the packet buffer.
- EXPECT_TRUE(QuicFramerPeer::AppendPathChallengeFrame(
- &framer_, transmit_frame, &writer));
-
- // Check for correct length in the packet buffer.
- EXPECT_EQ(kQuicPathChallengeFrameSize, writer.length());
-
- // now set up a reader to read in the frame.
- QuicDataReader reader(packet_buffer, writer.length(),
- quiche::NETWORK_BYTE_ORDER);
-
- QuicPathChallengeFrame receive_frame;
-
- EXPECT_TRUE(QuicFramerPeer::ProcessPathChallengeFrame(&framer_, &reader,
- &receive_frame));
-
- // Now check that the received frame matches the sent frame.
- EXPECT_EQ(
- 0, memcmp(transmit_frame.data_buffer.data(),
- receive_frame.data_buffer.data(), kQuicPathFrameBufferSize));
- return true;
- }
-
- // encode, decode, and check a Path Response frame.
- bool TryPathResponseFrame(char* packet_buffer,
- size_t packet_buffer_size,
- const QuicPathFrameBuffer& data) {
- // Make a writer so that the serialized packet is placed in
- // packet_buffer.
- QuicDataWriter writer(packet_buffer_size, packet_buffer,
- quiche::NETWORK_BYTE_ORDER);
-
- QuicPathResponseFrame transmit_frame(0, data);
-
- // Write the frame to the packet buffer.
- EXPECT_TRUE(QuicFramerPeer::AppendPathResponseFrame(
- &framer_, transmit_frame, &writer));
-
- // Check for correct length in the packet buffer.
- EXPECT_EQ(kQuicPathResponseFrameSize, writer.length());
-
- // Set up a reader to read in the frame.
- QuicDataReader reader(packet_buffer, writer.length(),
- quiche::NETWORK_BYTE_ORDER);
-
- QuicPathResponseFrame receive_frame;
-
- EXPECT_TRUE(QuicFramerPeer::ProcessPathResponseFrame(&framer_, &reader,
- &receive_frame));
-
- // Now check that the received frame matches the sent frame.
- EXPECT_EQ(
- 0, memcmp(transmit_frame.data_buffer.data(),
- receive_frame.data_buffer.data(), kQuicPathFrameBufferSize));
- return true;
- }
-
- // Test the Serialization/deserialization of a Reset Stream Frame.
- void TryResetFrame(char* packet_buffer,
- size_t packet_buffer_size,
- QuicStreamId stream_id,
- uint16_t error_code,
- QuicStreamOffset final_offset) {
- // Initialize a writer so that the serialized packet is placed in
- // packet_buffer.
- QuicDataWriter writer(packet_buffer_size, packet_buffer,
- quiche::NETWORK_BYTE_ORDER);
-
- QuicRstStreamFrame transmit_frame(static_cast<QuicControlFrameId>(1),
- stream_id, error_code, final_offset);
-
- // Write the frame to the packet buffer.
- EXPECT_TRUE(QuicFramerPeer::AppendIetfResetStreamFrame(
- &framer_, transmit_frame, &writer));
- // Check that the size of the serialzed frame is in the allowed range (3 to
- // 24 bytes, inclusive).
- EXPECT_LT(2u, writer.length());
- EXPECT_GT(25u, writer.length());
- // Now set up a reader to read in the thing in.
- QuicDataReader reader(packet_buffer, writer.length(),
- quiche::NETWORK_BYTE_ORDER);
-
- // A QuicRstStreamFrame to hold the results
- QuicRstStreamFrame receive_frame;
- EXPECT_TRUE(QuicFramerPeer::ProcessIetfResetStreamFrame(&framer_, &reader,
- &receive_frame));
-
- // Now check that the received values match the input.
- EXPECT_EQ(receive_frame.stream_id, transmit_frame.stream_id);
- EXPECT_EQ(receive_frame.ietf_error_code, transmit_frame.ietf_error_code);
- EXPECT_EQ(receive_frame.byte_offset, transmit_frame.byte_offset);
- }
-
- void TryMaxStreamsFrame(QuicStreamCount stream_count,
- bool unidirectional,
- bool stream_id_server_initiated) {
- char packet_buffer[kNormalPacketBufferSize];
- memset(packet_buffer, 0, sizeof(packet_buffer));
-
- Perspective old_perspective = framer_.perspective();
- // Set up the writer and transmit QuicMaxStreamsFrame
- QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
- quiche::NETWORK_BYTE_ORDER);
-
- // Set the perspective of the sender. If the stream id is supposed to
- // be server-initiated, then the sender of the MAX_STREAMS should be
- // a client, and vice versa. Do this prior to constructing the frame or
- // generating the packet, so that any internal dependencies are satisfied.
- QuicFramerPeer::SetPerspective(&framer_, (stream_id_server_initiated)
- ? Perspective::IS_CLIENT
- : Perspective::IS_SERVER);
- QuicMaxStreamsFrame transmit_frame(0, stream_count, unidirectional);
-
- // Add the frame.
- EXPECT_TRUE(QuicFramerPeer::AppendMaxStreamsFrame(&framer_, transmit_frame,
- &writer));
-
- // Check that buffer length is in the expected range
- EXPECT_LE(1u, writer.length());
- EXPECT_GE(8u, writer.length());
-
- // Set the perspective for the receiver.
- QuicFramerPeer::SetPerspective(&framer_, (stream_id_server_initiated)
- ? Perspective::IS_SERVER
- : Perspective::IS_CLIENT);
-
- // Set up reader and empty receive QuicPaddingFrame.
- QuicDataReader reader(packet_buffer, writer.length(),
- quiche::NETWORK_BYTE_ORDER);
- QuicMaxStreamsFrame receive_frame;
-
- // Deframe it
- EXPECT_TRUE(QuicFramerPeer::ProcessMaxStreamsFrame(
- &framer_, &reader, &receive_frame,
- (unidirectional) ? IETF_MAX_STREAMS_UNIDIRECTIONAL
- : IETF_MAX_STREAMS_BIDIRECTIONAL))
- << " Error: " << framer_.detailed_error();
-
- // Now check that received and sent data are equivalent
- EXPECT_EQ(stream_count, receive_frame.stream_count);
- EXPECT_EQ(transmit_frame.stream_count, receive_frame.stream_count);
- QuicFramerPeer::SetPerspective(&framer_, old_perspective);
- }
-
- void TryStreamsBlockedFrame(QuicStreamCount stream_count,
- bool unidirectional,
- bool stream_id_server_initiated) {
- char packet_buffer[kNormalPacketBufferSize];
- memset(packet_buffer, 0, sizeof(packet_buffer));
-
- Perspective old_perspective = framer_.perspective();
- // Set up the writer and transmit QuicStreamsBlockedFrame
- QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
- quiche::NETWORK_BYTE_ORDER);
-
- // Set the perspective of the sender. If the stream id is supposed to
- // be server-initiated, then the sender of the STREAMS_BLOCKED should be
- // a client, and vice versa. Do this prior to constructing the frame or
- // generating the packet, so that any internal dependencies are satisfied.
- QuicFramerPeer::SetPerspective(&framer_, (stream_id_server_initiated)
- ? Perspective::IS_SERVER
- : Perspective::IS_CLIENT);
- QuicStreamsBlockedFrame transmit_frame(0, stream_count, unidirectional);
-
- // Add the frame.
- EXPECT_TRUE(QuicFramerPeer::AppendStreamsBlockedFrame(
- &framer_, transmit_frame, &writer));
-
- // Check that buffer length is in the expected range
- EXPECT_LE(1u, writer.length());
- EXPECT_GE(8u, writer.length());
-
- // Set the perspective for the receiver.
- QuicFramerPeer::SetPerspective(&framer_, (stream_id_server_initiated)
- ? Perspective::IS_CLIENT
- : Perspective::IS_SERVER);
-
- // Set up reader and empty receive QuicPaddingFrame.
- QuicDataReader reader(packet_buffer, writer.length(),
- quiche::NETWORK_BYTE_ORDER);
- QuicStreamsBlockedFrame receive_frame;
-
- // Deframe it
- EXPECT_TRUE(QuicFramerPeer::ProcessStreamsBlockedFrame(
- &framer_, &reader, &receive_frame,
- (unidirectional) ? IETF_STREAMS_BLOCKED_UNIDIRECTIONAL
- : IETF_STREAMS_BLOCKED_BIDIRECTIONAL));
-
- // Now check that received and sent data are equivalent
- EXPECT_EQ(stream_count, receive_frame.stream_count);
- EXPECT_EQ(transmit_frame.stream_count, receive_frame.stream_count);
- QuicFramerPeer::SetPerspective(&framer_, old_perspective);
- }
-
- QuicTime start_;
- QuicFramer framer_;
- test::TestQuicVisitor visitor_;
-};
-
-struct stream_frame_variant {
- QuicIetfStreamId stream_id;
- QuicIetfStreamOffset offset;
- bool fin_bit;
- bool last_frame_bit;
- uint8_t frame_type;
-} stream_frame_to_test[] = {
-#define IETF_STREAM0 (((uint8_t)IETF_STREAM))
-
-#define IETF_STREAM1 (((uint8_t)IETF_STREAM) | IETF_STREAM_FRAME_FIN_BIT)
-
-#define IETF_STREAM2 (((uint8_t)IETF_STREAM) | IETF_STREAM_FRAME_LEN_BIT)
-
-#define IETF_STREAM3 \
- (((uint8_t)IETF_STREAM) | IETF_STREAM_FRAME_LEN_BIT | \
- IETF_STREAM_FRAME_FIN_BIT)
-
-#define IETF_STREAM4 (((uint8_t)IETF_STREAM) | IETF_STREAM_FRAME_OFF_BIT)
-
-#define IETF_STREAM5 \
- (((uint8_t)IETF_STREAM) | IETF_STREAM_FRAME_OFF_BIT | \
- IETF_STREAM_FRAME_FIN_BIT)
-
-#define IETF_STREAM6 \
- (((uint8_t)IETF_STREAM) | IETF_STREAM_FRAME_OFF_BIT | \
- IETF_STREAM_FRAME_LEN_BIT)
-
-#define IETF_STREAM7 \
- (((uint8_t)IETF_STREAM) | IETF_STREAM_FRAME_OFF_BIT | \
- IETF_STREAM_FRAME_LEN_BIT | IETF_STREAM_FRAME_FIN_BIT)
-
- {kStreamId8, kOffset8, true, false, IETF_STREAM7},
- {kStreamId8, kOffset8, false, false, IETF_STREAM6},
- {kStreamId8, kOffset4, true, false, IETF_STREAM7},
- {kStreamId8, kOffset4, false, false, IETF_STREAM6},
- {kStreamId8, kOffset2, true, false, IETF_STREAM7},
- {kStreamId8, kOffset2, false, false, IETF_STREAM6},
- {kStreamId8, kOffset1, true, false, IETF_STREAM7},
- {kStreamId8, kOffset1, false, false, IETF_STREAM6},
- {kStreamId8, kOffset0, true, false, IETF_STREAM3},
- {kStreamId8, kOffset0, false, false, IETF_STREAM2},
- {kStreamId4, kOffset8, true, false, IETF_STREAM7},
- {kStreamId4, kOffset8, false, false, IETF_STREAM6},
- {kStreamId4, kOffset4, true, false, IETF_STREAM7},
- {kStreamId4, kOffset4, false, false, IETF_STREAM6},
- {kStreamId4, kOffset2, true, false, IETF_STREAM7},
- {kStreamId4, kOffset2, false, false, IETF_STREAM6},
- {kStreamId4, kOffset1, true, false, IETF_STREAM7},
- {kStreamId4, kOffset1, false, false, IETF_STREAM6},
- {kStreamId4, kOffset0, true, false, IETF_STREAM3},
- {kStreamId4, kOffset0, false, false, IETF_STREAM2},
- {kStreamId2, kOffset8, true, false, IETF_STREAM7},
- {kStreamId2, kOffset8, false, false, IETF_STREAM6},
- {kStreamId2, kOffset4, true, false, IETF_STREAM7},
- {kStreamId2, kOffset4, false, false, IETF_STREAM6},
- {kStreamId2, kOffset2, true, false, IETF_STREAM7},
- {kStreamId2, kOffset2, false, false, IETF_STREAM6},
- {kStreamId2, kOffset1, true, false, IETF_STREAM7},
- {kStreamId2, kOffset1, false, false, IETF_STREAM6},
- {kStreamId2, kOffset0, true, false, IETF_STREAM3},
- {kStreamId2, kOffset0, false, false, IETF_STREAM2},
- {kStreamId1, kOffset8, true, false, IETF_STREAM7},
- {kStreamId1, kOffset8, false, false, IETF_STREAM6},
- {kStreamId1, kOffset4, true, false, IETF_STREAM7},
- {kStreamId1, kOffset4, false, false, IETF_STREAM6},
- {kStreamId1, kOffset2, true, false, IETF_STREAM7},
- {kStreamId1, kOffset2, false, false, IETF_STREAM6},
- {kStreamId1, kOffset1, true, false, IETF_STREAM7},
- {kStreamId1, kOffset1, false, false, IETF_STREAM6},
- {kStreamId1, kOffset0, true, false, IETF_STREAM3},
- {kStreamId1, kOffset0, false, false, IETF_STREAM2},
- {kStreamId0, kOffset8, true, false, IETF_STREAM7},
- {kStreamId0, kOffset8, false, false, IETF_STREAM6},
- {kStreamId0, kOffset4, true, false, IETF_STREAM7},
- {kStreamId0, kOffset4, false, false, IETF_STREAM6},
- {kStreamId0, kOffset2, true, false, IETF_STREAM7},
- {kStreamId0, kOffset2, false, false, IETF_STREAM6},
- {kStreamId0, kOffset1, true, false, IETF_STREAM7},
- {kStreamId0, kOffset1, false, false, IETF_STREAM6},
- {kStreamId0, kOffset0, true, false, IETF_STREAM3},
- {kStreamId0, kOffset0, false, false, IETF_STREAM2},
-
- {kStreamId8, kOffset8, true, true, IETF_STREAM5},
- {kStreamId8, kOffset8, false, true, IETF_STREAM4},
- {kStreamId8, kOffset4, true, true, IETF_STREAM5},
- {kStreamId8, kOffset4, false, true, IETF_STREAM4},
- {kStreamId8, kOffset2, true, true, IETF_STREAM5},
- {kStreamId8, kOffset2, false, true, IETF_STREAM4},
- {kStreamId8, kOffset1, true, true, IETF_STREAM5},
- {kStreamId8, kOffset1, false, true, IETF_STREAM4},
- {kStreamId8, kOffset0, true, true, IETF_STREAM1},
- {kStreamId8, kOffset0, false, true, IETF_STREAM0},
- {kStreamId4, kOffset8, true, true, IETF_STREAM5},
- {kStreamId4, kOffset8, false, true, IETF_STREAM4},
- {kStreamId4, kOffset4, true, true, IETF_STREAM5},
- {kStreamId4, kOffset4, false, true, IETF_STREAM4},
- {kStreamId4, kOffset2, true, true, IETF_STREAM5},
- {kStreamId4, kOffset2, false, true, IETF_STREAM4},
- {kStreamId4, kOffset1, true, true, IETF_STREAM5},
- {kStreamId4, kOffset1, false, true, IETF_STREAM4},
- {kStreamId4, kOffset0, true, true, IETF_STREAM1},
- {kStreamId4, kOffset0, false, true, IETF_STREAM0},
- {kStreamId2, kOffset8, true, true, IETF_STREAM5},
- {kStreamId2, kOffset8, false, true, IETF_STREAM4},
- {kStreamId2, kOffset4, true, true, IETF_STREAM5},
- {kStreamId2, kOffset4, false, true, IETF_STREAM4},
- {kStreamId2, kOffset2, true, true, IETF_STREAM5},
- {kStreamId2, kOffset2, false, true, IETF_STREAM4},
- {kStreamId2, kOffset1, true, true, IETF_STREAM5},
- {kStreamId2, kOffset1, false, true, IETF_STREAM4},
- {kStreamId2, kOffset0, true, true, IETF_STREAM1},
- {kStreamId2, kOffset0, false, true, IETF_STREAM0},
- {kStreamId1, kOffset8, true, true, IETF_STREAM5},
- {kStreamId1, kOffset8, false, true, IETF_STREAM4},
- {kStreamId1, kOffset4, true, true, IETF_STREAM5},
- {kStreamId1, kOffset4, false, true, IETF_STREAM4},
- {kStreamId1, kOffset2, true, true, IETF_STREAM5},
- {kStreamId1, kOffset2, false, true, IETF_STREAM4},
- {kStreamId1, kOffset1, true, true, IETF_STREAM5},
- {kStreamId1, kOffset1, false, true, IETF_STREAM4},
- {kStreamId1, kOffset0, true, true, IETF_STREAM1},
- {kStreamId1, kOffset0, false, true, IETF_STREAM0},
- {kStreamId0, kOffset8, true, true, IETF_STREAM5},
- {kStreamId0, kOffset8, false, true, IETF_STREAM4},
- {kStreamId0, kOffset4, true, true, IETF_STREAM5},
- {kStreamId0, kOffset4, false, true, IETF_STREAM4},
- {kStreamId0, kOffset2, true, true, IETF_STREAM5},
- {kStreamId0, kOffset2, false, true, IETF_STREAM4},
- {kStreamId0, kOffset1, true, true, IETF_STREAM5},
- {kStreamId0, kOffset1, false, true, IETF_STREAM4},
- {kStreamId0, kOffset0, true, true, IETF_STREAM1},
- {kStreamId0, kOffset0, false, true, IETF_STREAM0},
-};
-
-TEST_F(QuicIetfFramerTest, StreamFrame) {
- char packet_buffer[kNormalPacketBufferSize];
- const char* transmit_packet_data =
- "this is a test of some packet data, "
- "can do a simple strcmp to see if the "
- "input and output are the same!";
-
- size_t transmit_packet_data_len = strlen(transmit_packet_data) + 1;
- for (size_t i = 0; i < QUIC_ARRAYSIZE(stream_frame_to_test); ++i) {
- SCOPED_TRACE(i);
- struct stream_frame_variant* variant = &stream_frame_to_test[i];
- TryStreamFrame(packet_buffer, sizeof(packet_buffer), transmit_packet_data,
- transmit_packet_data_len, variant->stream_id,
- variant->offset, variant->fin_bit, variant->last_frame_bit,
- static_cast<QuicIetfFrameType>(variant->frame_type));
- }
-}
-// As the previous test, but with no data.
-TEST_F(QuicIetfFramerTest, ZeroLengthStreamFrame) {
- char packet_buffer[kNormalPacketBufferSize];
-
- for (size_t i = 0; i < QUIC_ARRAYSIZE(stream_frame_to_test); ++i) {
- SCOPED_TRACE(i);
- struct stream_frame_variant* variant = &stream_frame_to_test[i];
- TryStreamFrame(packet_buffer, sizeof(packet_buffer),
- /* xmit_packet_data = */ NULL,
- /* xmit_packet_data_size = */ 0, variant->stream_id,
- variant->offset, variant->fin_bit, variant->last_frame_bit,
- static_cast<QuicIetfFrameType>(variant->frame_type));
- }
-}
-
-TEST_F(QuicIetfFramerTest, CryptoFrame) {
- SimpleDataProducer data_producer;
- framer_.set_data_producer(&data_producer);
- char packet_buffer[kNormalPacketBufferSize];
-
- QuicStringPiece frame_data("This is a CRYPTO frame.");
-
- QuicStreamOffset offsets[] = {kOffset8, kOffset4, kOffset2, kOffset1,
- kOffset0};
- for (QuicStreamOffset offset : offsets) {
- QuicCryptoFrame frame(ENCRYPTION_INITIAL, offset, frame_data.length());
- data_producer.SaveCryptoData(ENCRYPTION_INITIAL, offset, frame_data);
-
- QuicDataWriter writer(QUIC_ARRAYSIZE(packet_buffer), packet_buffer,
- quiche::NETWORK_BYTE_ORDER);
-
- // Write the frame.
- EXPECT_TRUE(QuicFramerPeer::AppendCryptoFrame(&framer_, frame, &writer));
- EXPECT_NE(0u, writer.length());
- // Read it back.
- QuicDataReader reader(packet_buffer, writer.length(),
- quiche::NETWORK_BYTE_ORDER);
- QuicCryptoFrame read_frame;
- EXPECT_TRUE(
- QuicFramerPeer::ProcessCryptoFrame(&framer_, &reader, &read_frame));
-
- // Check that the frames match:
- QuicStringPiece read_data(read_frame.data_buffer, read_frame.data_length);
- EXPECT_EQ(read_frame.data_length, frame.data_length);
- EXPECT_EQ(read_frame.offset, frame.offset);
- EXPECT_EQ(read_data, frame_data);
- }
-}
-
-TEST_F(QuicIetfFramerTest, ConnectionClose) {
- char packet_buffer[kNormalPacketBufferSize];
-
- // initialize a writer so that the serialized packet is placed in
- // packet_buffer.
- QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
- quiche::NETWORK_BYTE_ORDER);
-
- std::string test_string = "Ich Bin Ein Jelly Donut?";
- QuicConnectionCloseFrame sent_frame(QUIC_VERSION_99, QUIC_NO_ERROR,
- test_string,
- /*transport_close_frame_type=*/123);
-
- // write the frame to the packet buffer.
- EXPECT_TRUE(QuicFramerPeer::AppendIetfConnectionCloseFrame(
- &framer_, sent_frame, &writer));
-
- // better have something in the packet buffer.
- EXPECT_NE(0u, writer.length());
-
- // now set up a reader to read in the frame.
- QuicDataReader reader(packet_buffer, writer.length(),
- quiche::NETWORK_BYTE_ORDER);
-
- // a QuicConnectionCloseFrame to hold the results.
- QuicConnectionCloseFrame sink_frame;
-
- EXPECT_TRUE(QuicFramerPeer::ProcessIetfConnectionCloseFrame(
- &framer_, &reader, IETF_QUIC_TRANSPORT_CONNECTION_CLOSE, &sink_frame));
-
- // Now check that received == sent
- EXPECT_EQ(sent_frame.quic_error_code, sink_frame.quic_error_code);
- EXPECT_THAT(sink_frame.quic_error_code, IsQuicNoError());
- EXPECT_EQ(sink_frame.error_details, test_string);
- EXPECT_EQ(sink_frame.close_type, sent_frame.close_type);
- EXPECT_EQ(sent_frame.close_type, IETF_QUIC_TRANSPORT_CONNECTION_CLOSE);
-}
-
-TEST_F(QuicIetfFramerTest, ApplicationClose) {
- char packet_buffer[kNormalPacketBufferSize];
-
- // initialize a writer so that the serialized packet is placed in
- // packet_buffer.
- QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
- quiche::NETWORK_BYTE_ORDER);
-
- std::string test_string = "Ich Bin Ein Jelly Donut?";
- QuicConnectionCloseFrame sent_frame(QUIC_VERSION_99, QUIC_LAST_ERROR,
- test_string,
- /*transport_close_frame_type=*/0);
-
- // write the frame to the packet buffer.
- EXPECT_TRUE(QuicFramerPeer::AppendIetfConnectionCloseFrame(
- &framer_, sent_frame, &writer));
-
- // better have something in the packet buffer.
- EXPECT_NE(0u, writer.length());
-
- // now set up a reader to read in the frame.
- QuicDataReader reader(packet_buffer, writer.length(),
- quiche::NETWORK_BYTE_ORDER);
-
- // a QuicConnectionCloseFrame to hold the results.
- QuicConnectionCloseFrame sink_frame;
-
- EXPECT_TRUE(QuicFramerPeer::ProcessIetfConnectionCloseFrame(
- &framer_, &reader, IETF_QUIC_APPLICATION_CONNECTION_CLOSE, &sink_frame));
-
- // Now check that received == sent
- EXPECT_EQ(sink_frame.quic_error_code, QUIC_LAST_ERROR);
- EXPECT_EQ(sent_frame.quic_error_code, sink_frame.quic_error_code);
- EXPECT_EQ(sink_frame.error_details, test_string);
- EXPECT_EQ(sent_frame.close_type, IETF_QUIC_APPLICATION_CONNECTION_CLOSE);
- EXPECT_EQ(sent_frame.close_type, sink_frame.close_type);
-}
-
-// Testing for the IETF ACK framer.
-// clang-format off
-struct ack_frame ack_frame_variants[] = {
- {90000,
- false,
- 0,
- 0,
- 0,
- {{QuicPacketNumber(1000), QuicPacketNumber(2001)}},
- IETF_ACK},
- {0,
- false,
- 0,
- 0,
- 0,
- {{QuicPacketNumber(1000), QuicPacketNumber(2001)}},
- IETF_ACK},
- {1,
- false,
- 0,
- 0,
- 0,
- {{QuicPacketNumber(1), QuicPacketNumber(2)},
- {QuicPacketNumber(5), QuicPacketNumber(6)}},
- IETF_ACK},
- {63,
- false,
- 0,
- 0,
- 0,
- {{QuicPacketNumber(1), QuicPacketNumber(2)},
- {QuicPacketNumber(5), QuicPacketNumber(6)}},
- IETF_ACK},
- {64,
- false,
- 0,
- 0,
- 0,
- {{QuicPacketNumber(1), QuicPacketNumber(2)},
- {QuicPacketNumber(3), QuicPacketNumber(4)},
- {QuicPacketNumber(5), QuicPacketNumber(6)},
- {QuicPacketNumber(7), QuicPacketNumber(8)},
- {QuicPacketNumber(9), QuicPacketNumber(10)},
- {QuicPacketNumber(11), QuicPacketNumber(12)}},
- IETF_ACK},
- {10000,
- false,
- 0,
- 0,
- 0,
- {{QuicPacketNumber(1), QuicPacketNumber(2)},
- {QuicPacketNumber(3), QuicPacketNumber(4)},
- {QuicPacketNumber(5), QuicPacketNumber(6)},
- {QuicPacketNumber(7), QuicPacketNumber(8)},
- {QuicPacketNumber(9), QuicPacketNumber(10)},
- {QuicPacketNumber(11), QuicPacketNumber(12)}},
- IETF_ACK},
- {100000000,
- false,
- 0,
- 0,
- 0,
- {{QuicPacketNumber(1), QuicPacketNumber(2)},
- {QuicPacketNumber(3), QuicPacketNumber(4)},
- {QuicPacketNumber(5), QuicPacketNumber(6)},
- {QuicPacketNumber(7), QuicPacketNumber(8)},
- {QuicPacketNumber(9), QuicPacketNumber(10)},
- {QuicPacketNumber(11), QuicPacketNumber(12)}},
- IETF_ACK},
- {0,
- false,
- 0,
- 0,
- 0,
- {{QuicPacketNumber(1), QuicPacketNumber(65)}},
- IETF_ACK},
- {9223372036854775807,
- false,
- 0,
- 0,
- 0,
- {{QuicPacketNumber(1), QuicPacketNumber(11)},
- {QuicPacketNumber(74), QuicPacketNumber(138)}},
- IETF_ACK},
- // This ack is for packets 60 & 125. There are 64 packets in the gap.
- // The encoded value is gap_size - 1, or 63. Crosses a VarInt62 encoding
- // boundary...
- {1,
- false,
- 0,
- 0,
- 0,
- {{QuicPacketNumber(60), QuicPacketNumber(61)},
- {QuicPacketNumber(125), QuicPacketNumber(126)}},
- IETF_ACK},
- {2,
- false,
- 0,
- 0,
- 0,
- {{QuicPacketNumber(1), QuicPacketNumber(65)},
- {QuicPacketNumber(129), QuicPacketNumber(130)}},
- IETF_ACK},
- {3,
- false,
- 0,
- 0,
- 0,
- {{QuicPacketNumber(1), QuicPacketNumber(65)},
- {QuicPacketNumber(129), QuicPacketNumber(195)}},
- IETF_ACK},
- {4,
- false,
- 0,
- 0,
- 0,
- {{QuicPacketNumber(1), QuicPacketNumber(65)},
- {QuicPacketNumber(129), QuicPacketNumber(194)}},
- IETF_ACK},
- {5,
- false,
- 0,
- 0,
- 0,
- {{QuicPacketNumber(1), QuicPacketNumber(65)},
- {QuicPacketNumber(129), QuicPacketNumber(193)}},
- IETF_ACK},
- {6,
- false,
- 0,
- 0,
- 0,
- {{QuicPacketNumber(1), QuicPacketNumber(65)},
- {QuicPacketNumber(129), QuicPacketNumber(192)}},
- IETF_ACK},
- // declare some ack_ecn frames to try.
- {6,
- false,
- 100,
- 200,
- 300,
- {{QuicPacketNumber(1), QuicPacketNumber(65)},
- {QuicPacketNumber(129), QuicPacketNumber(192)}},
- IETF_ACK},
- {6,
- true,
- 100,
- 200,
- 300,
- {{QuicPacketNumber(1), QuicPacketNumber(65)},
- {QuicPacketNumber(129), QuicPacketNumber(192)}},
- IETF_ACK_ECN},
- {6,
- true,
- 100,
- 0,
- 0,
- {{QuicPacketNumber(1), QuicPacketNumber(65)},
- {QuicPacketNumber(129), QuicPacketNumber(192)}},
- IETF_ACK_ECN},
- {6,
- true,
- 0,
- 200,
- 0,
- {{QuicPacketNumber(1), QuicPacketNumber(65)},
- {QuicPacketNumber(129), QuicPacketNumber(192)}},
- IETF_ACK_ECN},
- {6,
- true,
- 0,
- 0,
- 300,
- {{QuicPacketNumber(1), QuicPacketNumber(65)},
- {QuicPacketNumber(129), QuicPacketNumber(192)}},
- IETF_ACK_ECN},
- {6,
- true,
- 0,
- 0,
- 0,
- {{QuicPacketNumber(1), QuicPacketNumber(65)},
- {QuicPacketNumber(129), QuicPacketNumber(192)}},
- IETF_ACK},
-};
-// clang-format on
-
-TEST_F(QuicIetfFramerTest, AckFrame) {
- char packet_buffer[kNormalPacketBufferSize];
- for (auto ack_frame_variant : ack_frame_variants) {
- EXPECT_TRUE(
- TryAckFrame(packet_buffer, sizeof(packet_buffer), &ack_frame_variant));
- }
-}
-
-// Test the case of having a QuicAckFrame with no ranges in it. By
-// examination of the Google Quic Ack code and tests, this case should
-// be handled as an ack with no "ranges after the first"; the
-// AckBlockCount should be 0 and the FirstAckBlock should be
-// |LargestAcked| - 1 (number of packets preceding the LargestAcked.
-TEST_F(QuicIetfFramerTest, AckFrameNoRanges) {
- char packet_buffer[kNormalPacketBufferSize];
-
- // Make a writer so that the serialized packet is placed in
- // packet_buffer.
- QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
- quiche::NETWORK_BYTE_ORDER);
-
- QuicAckFrame transmit_frame;
- transmit_frame.largest_acked = QuicPacketNumber(1);
- transmit_frame.ack_delay_time = QuicTime::Delta::FromMicroseconds(0);
-
- size_t expected_size =
- QuicFramerPeer::GetIetfAckFrameSize(&framer_, transmit_frame);
- // Write the frame to the packet buffer.
- EXPECT_TRUE(QuicFramerPeer::AppendIetfAckFrameAndTypeByte(
- &framer_, transmit_frame, &writer));
-
- uint8_t packet[] = {
- 0x02, // type, IETF_ACK
- 0x01, // largest_acked,
- 0x00, // delay
- 0x00, // count of additional ack blocks
- 0x00, // size of first ack block (packets preceding largest_acked)
- };
- EXPECT_EQ(expected_size, sizeof(packet));
- EXPECT_EQ(sizeof(packet), writer.length());
- EXPECT_EQ(0, memcmp(packet, packet_buffer, writer.length()));
-
- // Now set up a reader to read in the frame.
- QuicDataReader reader(packet_buffer, writer.length(),
- quiche::NETWORK_BYTE_ORDER);
-
- // an AckFrame to hold the results
- QuicAckFrame receive_frame;
-
- // read in the frame type
- uint8_t received_frame_type;
- EXPECT_TRUE(reader.ReadUInt8(&received_frame_type));
- EXPECT_EQ(received_frame_type, IETF_ACK);
-
- EXPECT_TRUE(QuicFramerPeer::ProcessIetfAckFrame(&framer_, &reader, IETF_ACK,
- &receive_frame));
-
- // Now check that the received frame matches the sent frame.
- EXPECT_EQ(transmit_frame.largest_acked, receive_frame.largest_acked);
-}
-
-TEST_F(QuicIetfFramerTest, PathChallengeFrame) {
- // Double-braces needed on some platforms due to
- // https://bugs.llvm.org/show_bug.cgi?id=21629
- QuicPathFrameBuffer buffer0 = {{0, 0, 0, 0, 0, 0, 0, 0}};
- QuicPathFrameBuffer buffer1 = {
- {0x80, 0x91, 0xa2, 0xb3, 0xc4, 0xd5, 0xe5, 0xf7}};
- char packet_buffer[kNormalPacketBufferSize];
- EXPECT_TRUE(
- TryPathChallengeFrame(packet_buffer, sizeof(packet_buffer), buffer0));
- EXPECT_TRUE(
- TryPathChallengeFrame(packet_buffer, sizeof(packet_buffer), buffer1));
-}
-
-TEST_F(QuicIetfFramerTest, PathResponseFrame) {
- // Double-braces needed on some platforms due to
- // https://bugs.llvm.org/show_bug.cgi?id=21629
- QuicPathFrameBuffer buffer0 = {{0, 0, 0, 0, 0, 0, 0, 0}};
- QuicPathFrameBuffer buffer1 = {
- {0x80, 0x91, 0xa2, 0xb3, 0xc4, 0xd5, 0xe5, 0xf7}};
- char packet_buffer[kNormalPacketBufferSize];
- EXPECT_TRUE(
- TryPathResponseFrame(packet_buffer, sizeof(packet_buffer), buffer0));
- EXPECT_TRUE(
- TryPathResponseFrame(packet_buffer, sizeof(packet_buffer), buffer1));
-}
-
-TEST_F(QuicIetfFramerTest, ResetStreamFrame) {
- char packet_buffer[kNormalPacketBufferSize];
- struct resets {
- QuicStreamId stream_id;
- uint16_t error_code;
- QuicStreamOffset final_offset;
- } reset_frames[] = {
- {0, 55, 0},
- {0x10, 73, 0x300},
- };
- for (auto reset : reset_frames) {
- TryResetFrame(packet_buffer, sizeof(packet_buffer), reset.stream_id,
- reset.error_code, reset.final_offset);
- }
-}
-
-TEST_F(QuicIetfFramerTest, StopSendingFrame) {
- char packet_buffer[kNormalPacketBufferSize];
-
- // Make a writer so that the serialized packet is placed in
- // packet_buffer.
- QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
- quiche::NETWORK_BYTE_ORDER);
-
- QuicStopSendingFrame transmit_frame;
- transmit_frame.stream_id = 12345;
- transmit_frame.application_error_code = 543;
-
- // Write the frame to the packet buffer.
- EXPECT_TRUE(QuicFramerPeer::AppendStopSendingFrame(&framer_, transmit_frame,
- &writer));
- // Check that the number of bytes in the buffer is in the
- // allowed range.
- EXPECT_LE(3u, writer.length());
- EXPECT_GE(10u, writer.length());
-
- QuicDataReader reader(packet_buffer, writer.length(),
- quiche::NETWORK_BYTE_ORDER);
-
- // A frame to hold the results
- QuicStopSendingFrame receive_frame;
-
- EXPECT_TRUE(QuicFramerPeer::ProcessStopSendingFrame(&framer_, &reader,
- &receive_frame));
-
- // Verify that the transmitted and received values are the same.
- EXPECT_EQ(receive_frame.stream_id, 12345u);
- EXPECT_EQ(receive_frame.application_error_code, 543u);
- EXPECT_EQ(receive_frame.stream_id, transmit_frame.stream_id);
- EXPECT_EQ(receive_frame.application_error_code,
- transmit_frame.application_error_code);
-}
-
-TEST_F(QuicIetfFramerTest, MaxDataFrame) {
- char packet_buffer[kNormalPacketBufferSize];
- QuicStreamOffset window_sizes[] = {0, 1, 2, 5, 10,
- 20, 50, 100, 200, 500,
- 1000000, kOffset8, kOffset4, kOffset2};
- for (QuicStreamOffset window_size : window_sizes) {
- memset(packet_buffer, 0, sizeof(packet_buffer));
-
- // Set up the writer and transmit QuicWindowUpdateFrame
- QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
- quiche::NETWORK_BYTE_ORDER);
- QuicWindowUpdateFrame transmit_frame(0, 99, window_size);
-
- // Add the frame.
- EXPECT_TRUE(
- QuicFramerPeer::AppendMaxDataFrame(&framer_, transmit_frame, &writer));
-
- // Check that the number of bytes in the buffer is in the expected range.
- EXPECT_LE(1u, writer.length());
- EXPECT_GE(8u, writer.length());
-
- // Set up reader and an empty QuicWindowUpdateFrame
- QuicDataReader reader(packet_buffer, writer.length(),
- quiche::NETWORK_BYTE_ORDER);
- QuicWindowUpdateFrame receive_frame;
-
- // Deframe it
- EXPECT_TRUE(
- QuicFramerPeer::ProcessMaxDataFrame(&framer_, &reader, &receive_frame));
-
- // Now check that the received data equals the sent data.
- EXPECT_EQ(transmit_frame.max_data, window_size);
- EXPECT_EQ(transmit_frame.max_data, receive_frame.max_data);
- EXPECT_EQ(QuicUtils::GetInvalidStreamId(framer_.transport_version()),
- receive_frame.stream_id);
- }
-}
-
-TEST_F(QuicIetfFramerTest, MaxStreamDataFrame) {
- char packet_buffer[kNormalPacketBufferSize];
- QuicStreamOffset window_sizes[] = {0, 1, 2, 5, 10,
- 20, 50, 100, 200, 500,
- 1000000, kOffset8, kOffset4, kOffset2};
- QuicIetfStreamId stream_ids[] = {kStreamId4, kStreamId2, kStreamId1,
- kStreamId0};
-
- for (QuicIetfStreamId stream_id : stream_ids) {
- for (QuicStreamOffset window_size : window_sizes) {
- memset(packet_buffer, 0, sizeof(packet_buffer));
-
- // Set up the writer and transmit QuicWindowUpdateFrame
- QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
- quiche::NETWORK_BYTE_ORDER);
- QuicWindowUpdateFrame transmit_frame(0, stream_id, window_size);
-
- // Add the frame.
- EXPECT_TRUE(QuicFramerPeer::AppendMaxStreamDataFrame(
- &framer_, transmit_frame, &writer));
-
- // Check that number of bytes in the buffer is in the expected range.
- EXPECT_LE(2u, writer.length());
- EXPECT_GE(16u, writer.length());
-
- // Set up reader and empty receive QuicPaddingFrame.
- QuicDataReader reader(packet_buffer, writer.length(),
- quiche::NETWORK_BYTE_ORDER);
- QuicWindowUpdateFrame receive_frame;
-
- // Deframe it
- EXPECT_TRUE(QuicFramerPeer::ProcessMaxStreamDataFrame(&framer_, &reader,
- &receive_frame));
-
- // Now check that received data and sent data are equal.
- EXPECT_EQ(transmit_frame.max_data, window_size);
- EXPECT_EQ(transmit_frame.max_data, receive_frame.max_data);
- EXPECT_EQ(stream_id, receive_frame.stream_id);
- EXPECT_EQ(transmit_frame.stream_id, receive_frame.stream_id);
- }
- }
-}
-
-TEST_F(QuicIetfFramerTest, MaxStreamsFrame) {
- QuicStreamCount stream_counts[] = {0x3fffffff, 0x3fff, 0x3f, 0x1};
-
- for (QuicStreamCount stream_count : stream_counts) {
- // Cover all four combinations of uni/bi-directional and
- // server-/client- initiation.
- TryMaxStreamsFrame(stream_count, /*unidirectional=*/true,
- /*stream_id_server_initiated=*/true);
- TryMaxStreamsFrame(stream_count, /*unidirectional=*/true,
- /*stream_id_server_initiated=*/false);
- TryMaxStreamsFrame(stream_count, /*unidirectional=*/false,
- /*stream_id_server_initiated=*/true);
- TryMaxStreamsFrame(stream_count, /*unidirectional=*/false,
- /*stream_id_server_initiated=*/false);
- }
-}
-
-TEST_F(QuicIetfFramerTest, BlockedFrame) {
- char packet_buffer[kNormalPacketBufferSize];
- QuicStreamOffset offsets[] = {kOffset8, kOffset4, kOffset2, kOffset1,
- kOffset0};
-
- for (QuicStreamOffset offset : offsets) {
- memset(packet_buffer, 0, sizeof(packet_buffer));
-
- // Set up the writer and transmit QuicBlockedFrame
- QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
- quiche::NETWORK_BYTE_ORDER);
- QuicBlockedFrame transmit_frame(
- 0, QuicUtils::GetInvalidStreamId(framer_.transport_version()), offset);
-
- // Add the frame.
- EXPECT_TRUE(QuicFramerPeer::AppendIetfBlockedFrame(&framer_, transmit_frame,
- &writer));
-
- // Check that buffer length is in the expected range
- EXPECT_LE(1u, writer.length());
- EXPECT_GE(8u, writer.length());
-
- // Set up reader and empty receive QuicFrame.
- QuicDataReader reader(packet_buffer, writer.length(),
- quiche::NETWORK_BYTE_ORDER);
- QuicBlockedFrame receive_frame;
-
- // Deframe it
- EXPECT_TRUE(QuicFramerPeer::ProcessIetfBlockedFrame(&framer_, &reader,
- &receive_frame));
-
- // Check that received and sent data are equivalent
- EXPECT_EQ(QuicUtils::GetInvalidStreamId(framer_.transport_version()),
- receive_frame.stream_id);
- EXPECT_EQ(offset, receive_frame.offset);
- EXPECT_EQ(transmit_frame.offset, receive_frame.offset);
- }
-}
-
-TEST_F(QuicIetfFramerTest, StreamBlockedFrame) {
- char packet_buffer[kNormalPacketBufferSize];
- QuicStreamOffset offsets[] = {0, 1, 2, 5, 10,
- 20, 50, 100, 200, 500,
- 1000000, kOffset8, kOffset4, kOffset2};
- QuicIetfStreamId stream_ids[] = {kStreamId4, kStreamId2, kStreamId1,
- kStreamId0};
-
- for (QuicIetfStreamId stream_id : stream_ids) {
- for (QuicStreamOffset offset : offsets) {
- memset(packet_buffer, 0, sizeof(packet_buffer));
-
- // Set up the writer and transmit QuicWindowUpdateFrame
- QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
- quiche::NETWORK_BYTE_ORDER);
- QuicBlockedFrame transmit_frame(0, stream_id, offset);
-
- // Add the frame.
- EXPECT_TRUE(QuicFramerPeer::AppendStreamBlockedFrame(
- &framer_, transmit_frame, &writer));
-
- // Check that number of bytes in the buffer is in the expected range.
- EXPECT_LE(2u, writer.length());
- EXPECT_GE(16u, writer.length());
-
- // Set up reader and empty receive QuicPaddingFrame.
- QuicDataReader reader(packet_buffer, writer.length(),
- quiche::NETWORK_BYTE_ORDER);
- QuicBlockedFrame receive_frame;
-
- // Deframe it
- EXPECT_TRUE(QuicFramerPeer::ProcessStreamBlockedFrame(&framer_, &reader,
- &receive_frame));
-
- // Now check that received == sent
- EXPECT_EQ(transmit_frame.offset, offset);
- EXPECT_EQ(transmit_frame.offset, receive_frame.offset);
- EXPECT_EQ(stream_id, receive_frame.stream_id);
- EXPECT_EQ(transmit_frame.stream_id, receive_frame.stream_id);
- }
- }
-}
-
-TEST_F(QuicIetfFramerTest, StreamsBlockedFrame) {
- QuicStreamCount stream_counts[] = {0x3fffffff, 0x3fff, 0x3f, 0x1};
-
- for (QuicStreamCount stream_count : stream_counts) {
- TryStreamsBlockedFrame(stream_count,
- /*unidirectional=*/false,
- /*stream_id_server_initiated=*/false);
- TryStreamsBlockedFrame(stream_count,
- /*unidirectional=*/false,
- /*stream_id_server_initiated=*/true);
- TryStreamsBlockedFrame(stream_count,
- /*unidirectional=*/true,
- /*stream_id_server_initiated=*/false);
- TryStreamsBlockedFrame(stream_count,
- /*unidirectional=*/true,
- /*stream_id_server_initiated=*/true);
- }
-}
-
-TEST_F(QuicIetfFramerTest, NewConnectionIdFrame) {
- char packet_buffer[kNormalPacketBufferSize];
-
- QuicNewConnectionIdFrame transmit_frame;
- transmit_frame.connection_id = TestConnectionId(UINT64_C(0x0edcba9876543201));
- transmit_frame.sequence_number = 0x01020304;
- transmit_frame.retire_prior_to = 0x00020304;
- // The token is defined as a uint128 -- a 16-byte integer.
- // The value is set in this manner because we want each
- // byte to have a specific value so that the binary
- // packet check (below) is good. If we used integer
- // operations (eg. "token = 0x12345...") then the bytes
- // would be set in host order.
- unsigned char token_bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
- 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
- 0x0c, 0x0d, 0x0e, 0x0f};
- memcpy(&transmit_frame.stateless_reset_token, token_bytes,
- sizeof(transmit_frame.stateless_reset_token));
-
- memset(packet_buffer, 0, sizeof(packet_buffer));
-
- // Set up the writer and transmit a QuicNewConnectionIdFrame
- QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
- quiche::NETWORK_BYTE_ORDER);
-
- // Add the frame.
- EXPECT_TRUE(QuicFramerPeer::AppendNewConnectionIdFrame(
- &framer_, transmit_frame, &writer));
- // clang-format off
- uint8_t packet[] = {
- // sequence number, 0x80 for varint62 encoding
- 0x80 + 0x01, 0x02, 0x03, 0x04,
- // retire_prior_to, 0x80 for varint62 encoding
- 0x80 + 0x00, 0x02, 0x03, 0x04,
- // new connection id length, is not varint62 encoded.
- 0x08,
- // new connection id, is not varint62 encoded.
- 0x0E, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x01,
- // the reset token:
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
- };
- // clang-format on
-
- // Check that buffer length is correct
- EXPECT_EQ(sizeof(packet), writer.length());
- EXPECT_EQ(0, memcmp(packet_buffer, packet, sizeof(packet)));
-
- // Set up reader and empty receive QuicPaddingFrame.
- QuicDataReader reader(packet_buffer, writer.length(),
- quiche::NETWORK_BYTE_ORDER);
- QuicNewConnectionIdFrame receive_frame;
-
- // Deframe it
- EXPECT_TRUE(QuicFramerPeer::ProcessNewConnectionIdFrame(&framer_, &reader,
- &receive_frame));
-
- // Now check that received == sent
- EXPECT_EQ(transmit_frame.connection_id, receive_frame.connection_id);
- EXPECT_EQ(transmit_frame.sequence_number, receive_frame.sequence_number);
- EXPECT_EQ(transmit_frame.retire_prior_to, receive_frame.retire_prior_to);
- EXPECT_EQ(transmit_frame.stateless_reset_token,
- receive_frame.stateless_reset_token);
-}
-
-TEST_F(QuicIetfFramerTest, RetireConnectionIdFrame) {
- char packet_buffer[kNormalPacketBufferSize];
-
- QuicRetireConnectionIdFrame transmit_frame;
- transmit_frame.sequence_number = 0x01020304;
-
- memset(packet_buffer, 0, sizeof(packet_buffer));
-
- // Set up the writer and transmit QuicRetireConnectionIdFrame
- QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
- quiche::NETWORK_BYTE_ORDER);
-
- // Add the frame.
- EXPECT_TRUE(QuicFramerPeer::AppendRetireConnectionIdFrame(
- &framer_, transmit_frame, &writer));
- // Check that buffer length is correct
- EXPECT_EQ(4u, writer.length());
- // clang-format off
- uint8_t packet[] = {
- // sequence number, 0x80 for varint62 encoding
- 0x80 + 0x01, 0x02, 0x03, 0x04,
- };
-
- // clang-format on
- EXPECT_EQ(0, memcmp(packet_buffer, packet, sizeof(packet)));
-
- // Set up reader and empty receive QuicPaddingFrame.
- QuicDataReader reader(packet_buffer, writer.length(),
- quiche::NETWORK_BYTE_ORDER);
- QuicRetireConnectionIdFrame receive_frame;
-
- // Deframe it
- EXPECT_TRUE(QuicFramerPeer::ProcessRetireConnectionIdFrame(&framer_, &reader,
- &receive_frame));
-
- // Now check that received == sent
- EXPECT_EQ(transmit_frame.sequence_number, receive_frame.sequence_number);
-}
-
-} // namespace
-} // namespace test
-} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_interval_deque.h b/chromium/net/third_party/quiche/src/quic/core/quic_interval_deque.h
new file mode 100644
index 00000000000..2a3a758b385
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_interval_deque.h
@@ -0,0 +1,391 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_CORE_QUIC_SEEKER_H_
+#define QUICHE_QUIC_CORE_QUIC_SEEKER_H_
+
+#include <algorithm>
+
+#include "net/third_party/quiche/src/quic/core/quic_circular_deque.h"
+#include "net/third_party/quiche/src/quic/core/quic_interval.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_optional.h"
+
+namespace quic {
+
+namespace test {
+class QuicIntervalDequePeer;
+} // namespace test
+
+// QuicIntervalDeque<T, C> is a templated wrapper container, wrapping random
+// access data structures. The wrapper allows items to be added to the
+// underlying container with intervals associated with each item. The intervals
+// _should_ be added already sorted and represent searchable indices. The search
+// is optimized for sequential usage.
+//
+// As the intervals are to be searched sequentially the search for the next
+// interval can be achieved in O(1), by simply remembering the last interval
+// consumed. The structure also checks for an "off-by-one" use case wherein the
+// |cached_index_| is off by one index as the caller didn't call operator |++|
+// to increment the index. Other intervals can be found in O(log(n)) as they are
+// binary searchable. A use case for this structure is packet buffering: Packets
+// are sent sequentially but can sometimes needed for retransmission. The
+// packets and their payloads are added with associated intervals representing
+// data ranges they carry. When a user asks for a particular interval it's very
+// likely they are requesting the next sequential interval, receiving it in O(1)
+// time. Updating the sequential index is done automatically through the
+// |DataAt| method and its iterator operator |++|.
+//
+// The intervals are represented using the usual C++ STL convention, namely as
+// the half-open QuicInterval [min, max). A point p is considered to be
+// contained in the QuicInterval iff p >= min && p < max. One consequence of
+// this definition is that for any non-empty QuicInterval, min is contained in
+// the QuicInterval but max is not. There is no canonical representation for the
+// empty QuicInterval; and empty intervals are forbidden from being added to
+// this container as they would be unsearchable.
+//
+// The type T is required to be copy-constructable or move-constructable. The
+// type T is also expected to have an |interval()| method returning a
+// QuicInterval<std::size> for the particular value. The type C is required to
+// be a random access container supporting the methods |pop_front|, |push_back|,
+// |operator[]|, |size|, and iterator support for |std::lower_bound| eg. a
+// |deque| or |vector|.
+//
+// The QuicIntervalDeque<T, C>, like other C++ STL random access containers,
+// doesn't have any explicit support for any equality operators.
+//
+//
+// Examples with internal state:
+//
+// // An example class to be stored inside the Interval Deque.
+// struct IntervalVal {
+// const int32_t val;
+// const size_t interval_begin, interval_end;
+// QuicInterval<size_t> interval();
+// };
+// typedef IntervalVal IV;
+// QuicIntervialDeque<IntervalValue> deque;
+//
+// // State:
+// // cached_index -> None
+// // container -> {}
+//
+// // Add interval items
+// deque.PushBack(IV(val: 0, interval_begin: 0, interval_end: 10));
+// deque.PushBack(IV(val: 1, interval_begin: 20, interval_end: 25));
+// deque.PushBack(IV(val: 2, interval_begin: 25, interval_end: 30));
+//
+// // State:
+// // cached_index -> 0
+// // container -> {{0, [0, 10)}, {1, [20, 25)}, {2, [25, 30)}}
+//
+// // Look for 0 and return [0, 10). Time: O(1)
+// auto it = deque.DataAt(0);
+// assert(it->val == 0);
+// it++; // Increment and move the |cached_index_| over [0, 10) to [20, 25).
+// assert(it->val == 1);
+//
+// // State:
+// // cached_index -> 1
+// // container -> {{0, [0, 10)}, {1, [20, 25)}, {2, [25, 30)}}
+//
+// // Look for 20 and return [20, 25). Time: O(1)
+// auto it = deque.DataAt(20); // |cached_index_| remains unchanged.
+// assert(it->val == 1);
+//
+// // State:
+// // cached_index -> 1
+// // container -> {{0, [0, 10)}, {1, [20, 25)}, {2, [25, 30)}}
+//
+// // Look for 15 and return deque.DataEnd(). Time: O(log(n))
+// auto it = deque.DataAt(15); // |cached_index_| remains unchanged.
+// assert(it == deque.DataEnd());
+//
+// // Look for 25 and return [25, 30). Time: O(1) with off-by-one.
+// auto it = deque.DataAt(25); // |cached_index_| is updated to 2.
+// assert(it->val == 2);
+// it++; // |cached_index_| is set to |None| as all data has been iterated.
+//
+//
+// // State:
+// // cached_index -> None
+// // container -> {{0, [0, 10)}, {1, [20, 25)}, {2, [25, 30)}}
+//
+// // Look again for 0 and return [0, 10). Time: O(log(n))
+// auto it = deque.DataAt(0);
+//
+//
+// deque.PopFront(); // Pop -> {0, [0, 10)}
+//
+// // State:
+// // cached_index -> None
+// // container -> {{1, [20, 25)}, {2, [25, 30)}}
+//
+// deque.PopFront(); // Pop -> {1, [20, 25)}
+//
+// // State:
+// // cached_index -> None
+// // container -> {{2, [25, 30)}}
+//
+// deque.PushBack(IV(val: 3, interval_begin: 35, interval_end: 50));
+//
+// // State:
+// // cached_index -> 1
+// // container -> {{2, [25, 30)}, {3, [35, 50)}}
+
+template <class T, class C = QUIC_NO_EXPORT QuicCircularDeque<T>>
+class QUIC_NO_EXPORT QuicIntervalDeque {
+ public:
+ class QUIC_NO_EXPORT Iterator {
+ public:
+ // Used by |std::lower_bound|
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = T;
+ using difference_type = std::ptrdiff_t;
+ using pointer = T*;
+ using reference = T&;
+
+ // Every increment of the iterator will increment the |cached_index_| if
+ // |index_| is larger than the current |cached_index_|. |index_| is bounded
+ // at |deque_.size()| and any attempt to increment above that will be
+ // ignored. Once an iterator has iterated all elements the |cached_index_|
+ // will be reset.
+ Iterator(std::size_t index, QuicIntervalDeque* deque)
+ : index_(index), deque_(deque) {}
+ // Only the ++ operator attempts to update the cached index. Other operators
+ // are used by |lower_bound| to binary search and are thus private.
+ Iterator& operator++() {
+ // Don't increment when we are at the end.
+ const std::size_t container_size = deque_->container_.size();
+ if (index_ >= container_size) {
+ QUIC_BUG << "Iterator out of bounds.";
+ return *this;
+ }
+ index_++;
+ if (deque_->cached_index_.has_value()) {
+ const std::size_t cached_index = deque_->cached_index_.value();
+ // If all items are iterated then reset the |cached_index_|
+ if (index_ == container_size) {
+ deque_->cached_index_.reset();
+ } else {
+ // Otherwise the new |cached_index_| is the max of itself and |index_|
+ if (cached_index < index_) {
+ deque_->cached_index_ = index_;
+ }
+ }
+ }
+ return *this;
+ }
+ Iterator operator++(int) {
+ Iterator copy = *this;
+ ++(*this);
+ return copy;
+ }
+ reference operator*() { return deque_->container_[index_]; }
+ pointer operator->() { return &deque_->container_[index_]; }
+ bool operator==(const Iterator& rhs) const {
+ return index_ == rhs.index_ && deque_ == rhs.deque_;
+ }
+ bool operator!=(const Iterator& rhs) const { return !(*this == rhs); }
+
+ private:
+ // A set of private operators for |std::lower_bound|
+ Iterator operator+(difference_type amount) const {
+ Iterator copy = *this;
+ copy.index_ += amount;
+ DCHECK(copy.index_ < copy.deque_->size());
+ return copy;
+ }
+ Iterator& operator+=(difference_type amount) {
+ index_ += amount;
+ DCHECK(index_ < deque_->size());
+ return *this;
+ }
+ difference_type operator-(const Iterator& rhs) const {
+ return static_cast<difference_type>(index_) -
+ static_cast<difference_type>(rhs.index_);
+ }
+
+ // |index_| is the index of the item in |*deque_|.
+ std::size_t index_;
+ // |deque_| is a pointer to the container the iterator came from.
+ QuicIntervalDeque* deque_;
+
+ friend class QuicIntervalDeque;
+ };
+
+ QuicIntervalDeque();
+
+ // Adds an item to the underlying container. The |item|'s interval _should_ be
+ // strictly greater than the last interval added.
+ void PushBack(T&& item);
+ void PushBack(const T& item);
+ // Removes the front/top of the underlying container and the associated
+ // interval.
+ void PopFront();
+ // Returns an iterator to the beginning of the data. The iterator will move
+ // the |cached_index_| as the iterator moves.
+ Iterator DataBegin();
+ // Returns an iterator to the end of the data.
+ Iterator DataEnd();
+ // Returns an iterator pointing to the item in |interval_begin|. The iterator
+ // will move the |cached_index_| as the iterator moves.
+ Iterator DataAt(const std::size_t interval_begin);
+
+ // Returns the number of items contained inside the structure.
+ std::size_t Size() const;
+ // Returns whether the structure is empty.
+ bool Empty() const;
+
+ private:
+ struct QUIC_NO_EXPORT IntervalCompare {
+ bool operator()(const T& item, std::size_t interval_begin) const {
+ return item.interval().max() <= interval_begin;
+ }
+ };
+
+ template <class U>
+ void PushBackUniversal(U&& item);
+
+ Iterator Search(const std::size_t interval_begin,
+ const std::size_t begin_index,
+ const std::size_t end_index);
+
+ // For accessing the |cached_index_|
+ friend class test::QuicIntervalDequePeer;
+
+ C container_;
+ quiche::QuicheOptional<std::size_t> cached_index_;
+};
+
+template <class T, class C>
+QuicIntervalDeque<T, C>::QuicIntervalDeque() {}
+
+template <class T, class C>
+void QuicIntervalDeque<T, C>::PushBack(T&& item) {
+ PushBackUniversal(std::move(item));
+}
+
+template <class T, class C>
+void QuicIntervalDeque<T, C>::PushBack(const T& item) {
+ PushBackUniversal(item);
+}
+
+template <class T, class C>
+void QuicIntervalDeque<T, C>::PopFront() {
+ if (container_.size() == 0) {
+ QUIC_BUG << "Trying to pop from an empty container.";
+ return;
+ }
+ container_.pop_front();
+ if (container_.size() == 0) {
+ cached_index_.reset();
+ }
+ if (cached_index_.value_or(0) > 0) {
+ cached_index_ = cached_index_.value() - 1;
+ }
+}
+
+template <class T, class C>
+typename QuicIntervalDeque<T, C>::Iterator
+QuicIntervalDeque<T, C>::DataBegin() {
+ return Iterator(0, this);
+}
+
+template <class T, class C>
+typename QuicIntervalDeque<T, C>::Iterator QuicIntervalDeque<T, C>::DataEnd() {
+ return Iterator(container_.size(), this);
+}
+
+template <class T, class C>
+typename QuicIntervalDeque<T, C>::Iterator QuicIntervalDeque<T, C>::DataAt(
+ const std::size_t interval_begin) {
+ // No |cached_index_| value means all items can be searched.
+ if (!cached_index_.has_value()) {
+ return Search(interval_begin, 0, container_.size());
+ }
+
+ const std::size_t cached_index = cached_index_.value();
+ DCHECK(cached_index < container_.size());
+
+ const QuicInterval<size_t> cached_interval =
+ container_[cached_index].interval();
+ // Does our cached index point directly to what we want?
+ if (cached_interval.Contains(interval_begin)) {
+ return Iterator(cached_index, this);
+ }
+
+ // Are we off-by-one?
+ const std::size_t next_index = cached_index + 1;
+ if (next_index < container_.size()) {
+ if (container_[next_index].interval().Contains(interval_begin)) {
+ cached_index_ = next_index;
+ return Iterator(next_index, this);
+ }
+ }
+
+ // Small optimization:
+ // Determine if we should binary search above or below the cached interval.
+ const std::size_t cached_begin = cached_interval.min();
+ bool looking_below = interval_begin < cached_begin;
+ const std::size_t lower = looking_below ? 0 : cached_index + 1;
+ const std::size_t upper = looking_below ? cached_index : container_.size();
+ Iterator ret = Search(interval_begin, lower, upper);
+ if (ret == DataEnd()) {
+ return ret;
+ }
+ // Update the |cached_index_| to point to the higher index.
+ if (!looking_below) {
+ cached_index_ = ret.index_;
+ }
+ return ret;
+}
+
+template <class T, class C>
+std::size_t QuicIntervalDeque<T, C>::Size() const {
+ return container_.size();
+}
+
+template <class T, class C>
+bool QuicIntervalDeque<T, C>::Empty() const {
+ return container_.size() == 0;
+}
+
+template <class T, class C>
+template <class U>
+void QuicIntervalDeque<T, C>::PushBackUniversal(U&& item) {
+ QuicInterval<std::size_t> interval = item.interval();
+ // Adding an empty interval is a bug.
+ if (interval.Empty()) {
+ QUIC_BUG << "Trying to save empty interval to QuicCircularDeque.";
+ return;
+ }
+ container_.push_back(std::forward<U>(item));
+ if (!cached_index_.has_value()) {
+ cached_index_ = container_.size() - 1;
+ }
+}
+
+template <class T, class C>
+typename QuicIntervalDeque<T, C>::Iterator QuicIntervalDeque<T, C>::Search(
+ const std::size_t interval_begin,
+ const std::size_t begin_index,
+ const std::size_t end_index) {
+ auto begin = container_.begin() + begin_index;
+ auto end = container_.begin() + end_index;
+ auto res = std::lower_bound(begin, end, interval_begin, IntervalCompare());
+ // Just because we run |lower_bound| and it didn't return |container_.end()|
+ // doesn't mean we found our desired interval.
+ if (res != end && res->interval().Contains(interval_begin)) {
+ return Iterator(std::distance(begin, res) + begin_index, this);
+ }
+ return DataEnd();
+}
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_QUIC_SEEKER_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_interval_deque_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_interval_deque_test.cc
new file mode 100644
index 00000000000..f7a84414434
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_interval_deque_test.cc
@@ -0,0 +1,360 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/quic_interval_deque.h"
+#include <cstdint>
+#include <ostream>
+#include "net/third_party/quiche/src/quic/core/quic_interval.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_interval_deque_peer.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+
+namespace quic {
+namespace test {
+namespace {
+
+const int32_t kSize = 100;
+const std::size_t kIntervalStep = 10;
+
+} // namespace
+
+struct TestIntervalItem {
+ int32_t val;
+ std::size_t interval_start, interval_end;
+ QuicInterval<std::size_t> interval() const {
+ return QuicInterval<std::size_t>(interval_start, interval_end);
+ }
+ TestIntervalItem(int32_t val,
+ std::size_t interval_start,
+ std::size_t interval_end)
+ : val(val), interval_start(interval_start), interval_end(interval_end) {}
+};
+
+typedef QuicIntervalDeque<TestIntervalItem> QID;
+
+class QuicIntervalDequeTest : public QuicTest {
+ public:
+ QuicIntervalDequeTest() {
+ // Add items with intervals of |kIntervalStep| size.
+ for (int32_t i = 0; i < kSize; ++i) {
+ const std::size_t interval_begin = kIntervalStep * i;
+ const std::size_t interval_end = interval_begin + kIntervalStep;
+ qid_.PushBack(TestIntervalItem(i, interval_begin, interval_end));
+ }
+ }
+
+ QID qid_;
+};
+
+// The goal of this test is to show insertion/push_back, iteration, and and
+// deletion/pop_front from the container.
+TEST_F(QuicIntervalDequeTest, InsertRemoveSize) {
+ QID qid;
+
+ EXPECT_EQ(qid.Size(), std::size_t(0));
+ qid.PushBack(TestIntervalItem(0, 0, 10));
+ EXPECT_EQ(qid.Size(), std::size_t(1));
+ qid.PushBack(TestIntervalItem(1, 10, 20));
+ EXPECT_EQ(qid.Size(), std::size_t(2));
+ qid.PushBack(TestIntervalItem(2, 20, 30));
+ EXPECT_EQ(qid.Size(), std::size_t(3));
+ qid.PushBack(TestIntervalItem(3, 30, 40));
+ EXPECT_EQ(qid.Size(), std::size_t(4));
+
+ // Advance the index all the way...
+ int32_t i = 0;
+ for (auto it = qid.DataAt(0); it != qid.DataEnd(); ++it, ++i) {
+ const int32_t index = QuicIntervalDequePeer::GetCachedIndex(&qid);
+ EXPECT_EQ(index, i);
+ EXPECT_EQ(it->val, i);
+ }
+ const int32_t index = QuicIntervalDequePeer::GetCachedIndex(&qid);
+ EXPECT_EQ(index, -1);
+
+ qid.PopFront();
+ EXPECT_EQ(qid.Size(), std::size_t(3));
+ qid.PopFront();
+ EXPECT_EQ(qid.Size(), std::size_t(2));
+ qid.PopFront();
+ EXPECT_EQ(qid.Size(), std::size_t(1));
+ qid.PopFront();
+ EXPECT_EQ(qid.Size(), std::size_t(0));
+
+ EXPECT_QUIC_BUG(qid.PopFront(), "Trying to pop from an empty container.");
+}
+
+// The goal of this test is to push data into the container at specific
+// intervals and show how the |DataAt| method can move the |cached_index| as the
+// iterator moves through the data.
+TEST_F(QuicIntervalDequeTest, InsertIterateWhole) {
+ // The write index should point to the beginning of the container.
+ const int32_t cached_index = QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ EXPECT_EQ(cached_index, 0);
+
+ auto it = qid_.DataBegin();
+ auto end = qid_.DataEnd();
+ for (int32_t i = 0; i < kSize; ++i, ++it) {
+ EXPECT_EQ(it->val, i);
+ const std::size_t current_iteraval_begin = i * kIntervalStep;
+ // The |DataAt| method should find the correct interval.
+ auto lookup = qid_.DataAt(current_iteraval_begin);
+ EXPECT_EQ(i, lookup->val);
+ // Make sure the index hasn't changed just from using |DataAt|
+ const int32_t index_before = QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ EXPECT_EQ(index_before, i);
+ // This increment should move the index forward.
+ lookup++;
+ // Check that the index has changed.
+ const int32_t index_after = QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ const int32_t after_i = (i + 1) == kSize ? -1 : (i + 1);
+ EXPECT_EQ(index_after, after_i);
+ EXPECT_NE(it, end);
+ }
+}
+
+// The goal of this test is to push data into the container at specific
+// intervals and show how the |DataAt| method can move the |cached_index| using
+// the off-by-one logic.
+TEST_F(QuicIntervalDequeTest, OffByOne) {
+ // The write index should point to the beginning of the container.
+ const int32_t cached_index = QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ EXPECT_EQ(cached_index, 0);
+
+ auto it = qid_.DataBegin();
+ auto end = qid_.DataEnd();
+ for (int32_t i = 0; i < kSize - 1; ++i, ++it) {
+ EXPECT_EQ(it->val, i);
+ const int32_t off_by_one_i = i + 1;
+ const std::size_t current_iteraval_begin = off_by_one_i * kIntervalStep;
+ // Make sure the index has changed just from using |DataAt|
+ const int32_t index_before = QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ EXPECT_EQ(index_before, i);
+ // The |DataAt| method should find the correct interval.
+ auto lookup = qid_.DataAt(current_iteraval_begin);
+ EXPECT_EQ(off_by_one_i, lookup->val);
+ // Check that the index has changed.
+ const int32_t index_after = QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ const int32_t after_i = off_by_one_i == kSize ? -1 : off_by_one_i;
+ EXPECT_EQ(index_after, after_i);
+ EXPECT_NE(it, end);
+ }
+}
+
+// The goal of this test is to push data into the container at specific
+// intervals and show modify the structure with a live iterator.
+TEST_F(QuicIntervalDequeTest, IteratorInvalidation) {
+ // The write index should point to the beginning of the container.
+ const int32_t cached_index = QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ EXPECT_EQ(cached_index, 0);
+
+ const std::size_t iteraval_begin = (kSize - 1) * kIntervalStep;
+ auto lookup = qid_.DataAt(iteraval_begin);
+ EXPECT_EQ((*lookup).val, (kSize - 1));
+ qid_.PopFront();
+ EXPECT_QUIC_BUG(lookup++, "Iterator out of bounds.");
+ auto lookup_end = qid_.DataAt(iteraval_begin + kIntervalStep);
+ EXPECT_EQ(lookup_end, qid_.DataEnd());
+}
+
+// The goal of this test is the same as |InsertIterateWhole| but to
+// skip certain intervals and show the |cached_index| is updated properly.
+TEST_F(QuicIntervalDequeTest, InsertIterateSkip) {
+ // The write index should point to the beginning of the container.
+ const int32_t cached_index = QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ EXPECT_EQ(cached_index, 0);
+
+ const std::size_t step = 4;
+ for (int32_t i = 0; i < kSize; i += 4) {
+ if (i != 0) {
+ const int32_t before_i = (i - (step - 1));
+ EXPECT_EQ(QuicIntervalDequePeer::GetCachedIndex(&qid_), before_i);
+ }
+ const std::size_t current_iteraval_begin = i * kIntervalStep;
+ // The |DataAt| method should find the correct interval.
+ auto lookup = qid_.DataAt(current_iteraval_begin);
+ EXPECT_EQ(i, lookup->val);
+ // Make sure the index _has_ changed just from using |DataAt| since we're
+ // skipping data.
+ const int32_t index_before = QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ EXPECT_EQ(index_before, i);
+ // This increment should move the index forward.
+ lookup++;
+ // Check that the index has changed.
+ const int32_t index_after = QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ const int32_t after_i = (i + 1) == kSize ? -1 : (i + 1);
+ EXPECT_EQ(index_after, after_i);
+ }
+}
+
+// The goal of this test is the same as |InsertIterateWhole| but it has
+// |PopFront| calls interleaved to show the |cached_index| updates correctly.
+TEST_F(QuicIntervalDequeTest, InsertDeleteIterate) {
+ // The write index should point to the beginning of the container.
+ const int32_t index = QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ EXPECT_EQ(index, 0);
+
+ std::size_t limit = 0;
+ for (int32_t i = 0; limit < qid_.Size(); ++i, ++limit) {
+ // Always point to the beginning of the container.
+ auto it = qid_.DataBegin();
+ EXPECT_EQ(it->val, i);
+
+ // Get an iterator.
+ const std::size_t current_iteraval_begin = i * kIntervalStep;
+ auto lookup = qid_.DataAt(current_iteraval_begin);
+ const int32_t index_before = QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ // The index should always point to 0.
+ EXPECT_EQ(index_before, 0);
+ // This iterator increment should effect the index.
+ lookup++;
+ const int32_t index_after = QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ EXPECT_EQ(index_after, 1);
+ // Decrement the |temp_size| and pop from the front.
+ qid_.PopFront();
+ // Show the index has been updated to point to 0 again (from 1).
+ const int32_t index_after_pop =
+ QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ EXPECT_EQ(index_after_pop, 0);
+ }
+}
+
+// The goal of this test is to move the index to the end and then add more data
+// to show it can be reset to a valid index.
+TEST_F(QuicIntervalDequeTest, InsertIterateInsert) {
+ // The write index should point to the beginning of the container.
+ const int32_t index = QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ EXPECT_EQ(index, 0);
+
+ int32_t iterated_elements = 0;
+ for (int32_t i = 0; i < kSize; ++i, ++iterated_elements) {
+ // Get an iterator.
+ const std::size_t current_iteraval_begin = i * kIntervalStep;
+ auto lookup = qid_.DataAt(current_iteraval_begin);
+ const int32_t index_before = QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ // The index should always point to i.
+ EXPECT_EQ(index_before, i);
+ // This iterator increment should effect the index.
+ lookup++;
+ // Show the index has been updated to point to i + 1 or -1 if at the end.
+ const int32_t index_after = QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ const int32_t after_i = (i + 1) == kSize ? -1 : (i + 1);
+ EXPECT_EQ(index_after, after_i);
+ }
+ const int32_t invalid_index = QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ EXPECT_EQ(invalid_index, -1);
+
+ // Add more data to the container, making the index valid.
+ const std::size_t offset = qid_.Size();
+ for (int32_t i = 0; i < kSize; ++i) {
+ const std::size_t interval_begin = offset + (kIntervalStep * i);
+ const std::size_t interval_end = offset + interval_begin + kIntervalStep;
+ qid_.PushBack(TestIntervalItem(i + offset, interval_begin, interval_end));
+ const int32_t index_current = QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ // Index should now be valid and equal to the size of the container before
+ // adding more items to it.
+ EXPECT_EQ(index_current, iterated_elements);
+ }
+ // Show the index is still valid and hasn't changed since the first iteration
+ // of the loop.
+ const int32_t index_after_add = QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ EXPECT_EQ(index_after_add, iterated_elements);
+
+ // Iterate over all the data in the container and eventually reset the index
+ // as we did before.
+ for (int32_t i = 0; i < kSize; ++i, ++iterated_elements) {
+ const std::size_t interval_begin = offset + (kIntervalStep * i);
+ const int32_t index_current = QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ EXPECT_EQ(index_current, iterated_elements);
+ auto lookup = qid_.DataAt(interval_begin);
+ const int32_t expected_value = i + offset;
+ EXPECT_EQ(lookup->val, expected_value);
+ lookup++;
+ const int32_t after_inc =
+ (iterated_elements + 1) == (kSize * 2) ? -1 : (iterated_elements + 1);
+ const int32_t after_index = QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ EXPECT_EQ(after_index, after_inc);
+ }
+ // Show the index is now invalid.
+ const int32_t invalid_index_again =
+ QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ EXPECT_EQ(invalid_index_again, -1);
+}
+
+// The goal of this test is to push data into the container at specific
+// intervals and show how the |DataAt| can iterate over already scanned data.
+TEST_F(QuicIntervalDequeTest, RescanData) {
+ // The write index should point to the beginning of the container.
+ const int32_t index = QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ EXPECT_EQ(index, 0);
+
+ auto it = qid_.DataBegin();
+ auto end = qid_.DataEnd();
+ for (int32_t i = 0; i < kSize - 1; ++i, ++it) {
+ EXPECT_EQ(it->val, i);
+ const std::size_t current_iteraval_begin = i * kIntervalStep;
+ // The |DataAt| method should find the correct interval.
+ auto lookup = qid_.DataAt(current_iteraval_begin);
+ EXPECT_EQ(i, lookup->val);
+ // Make sure the index has changed just from using |DataAt|
+ const int32_t cached_index_before =
+ QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ EXPECT_EQ(cached_index_before, i);
+ // Ensure the real index has changed just from using |DataAt| and the
+ // off-by-one logic
+ const int32_t index_before = QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ const int32_t before_i = i;
+ EXPECT_EQ(index_before, before_i);
+ // This increment should move the cached index forward.
+ lookup++;
+ // Check that the cached index has moved foward.
+ const int32_t cached_index_after =
+ QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ const int32_t after_i = (i + 1);
+ EXPECT_EQ(cached_index_after, after_i);
+ EXPECT_NE(it, end);
+ }
+
+ // Iterate over items which have been consumed before.
+ int32_t expected_index = static_cast<int32_t>(kSize - 1);
+ for (int32_t i = 0; i < kSize - 1; ++i) {
+ const std::size_t current_iteraval_begin = i * kIntervalStep;
+ // The |DataAt| method should find the correct interval.
+ auto lookup = qid_.DataAt(current_iteraval_begin);
+ EXPECT_EQ(i, lookup->val);
+ // This increment shouldn't move the index forward as the index is currently
+ // ahead.
+ lookup++;
+ // Check that the index hasn't moved foward.
+ const int32_t index_after = QuicIntervalDequePeer::GetCachedIndex(&qid_);
+ EXPECT_EQ(index_after, expected_index);
+ EXPECT_NE(it, end);
+ }
+}
+
+// The goal of this test is to show that popping from an empty container is a
+// bug.
+TEST_F(QuicIntervalDequeTest, PopEmpty) {
+ QID qid;
+ EXPECT_TRUE(qid.Empty());
+ EXPECT_QUIC_BUG(qid.PopFront(), "Trying to pop from an empty container.");
+}
+
+// The goal of this test is to show that adding a zero-sized interval is a bug.
+TEST_F(QuicIntervalDequeTest, ZeroSizedInterval) {
+ QID qid;
+ EXPECT_QUIC_BUG(qid.PushBack(TestIntervalItem(0, 0, 0)),
+ "Trying to save empty interval to .");
+}
+
+// The goal of this test is to show that an iterator to an empty container
+// returns |DataEnd|.
+TEST_F(QuicIntervalDequeTest, IteratorEmpty) {
+ QID qid;
+ auto it = qid.DataAt(0);
+ EXPECT_EQ(it, qid.DataEnd());
+}
+
+} // namespace test
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector.cc b/chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector.cc
new file mode 100644
index 00000000000..9206ae47fb6
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector.cc
@@ -0,0 +1,78 @@
+// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/quic_network_blackhole_detector.h"
+
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
+
+namespace quic {
+
+namespace {
+
+class AlarmDelegate : public QuicAlarm::Delegate {
+ public:
+ explicit AlarmDelegate(QuicNetworkBlackholeDetector* detector)
+ : detector_(detector) {}
+ AlarmDelegate(const AlarmDelegate&) = delete;
+ AlarmDelegate& operator=(const AlarmDelegate&) = delete;
+
+ void OnAlarm() override { detector_->OnAlarm(); }
+
+ private:
+ QuicNetworkBlackholeDetector* detector_;
+};
+
+} // namespace
+
+QuicNetworkBlackholeDetector::QuicNetworkBlackholeDetector(
+ Delegate* delegate,
+ QuicConnectionArena* arena,
+ QuicAlarmFactory* alarm_factory)
+ : delegate_(delegate),
+ path_degrading_deadline_(QuicTime::Zero()),
+ blackhole_deadline_(QuicTime::Zero()),
+ alarm_(
+ alarm_factory->CreateAlarm(arena->New<AlarmDelegate>(this), arena)) {}
+
+void QuicNetworkBlackholeDetector::OnAlarm() {
+ if (path_degrading_deadline_.IsInitialized()) {
+ path_degrading_deadline_ = QuicTime::Zero();
+ delegate_->OnPathDegradingDetected();
+ // Switch to blackhole detection mode.
+ alarm_->Update(blackhole_deadline_, kAlarmGranularity);
+ return;
+ }
+ if (blackhole_deadline_.IsInitialized()) {
+ blackhole_deadline_ = QuicTime::Zero();
+ delegate_->OnBlackholeDetected();
+ }
+}
+
+void QuicNetworkBlackholeDetector::StopDetection() {
+ alarm_->Cancel();
+ path_degrading_deadline_ = QuicTime::Zero();
+ blackhole_deadline_ = QuicTime::Zero();
+}
+
+void QuicNetworkBlackholeDetector::RestartDetection(
+ QuicTime path_degrading_deadline,
+ QuicTime blackhole_deadline) {
+ path_degrading_deadline_ = path_degrading_deadline;
+ blackhole_deadline_ = blackhole_deadline;
+ QUIC_BUG_IF(path_degrading_deadline_.IsInitialized() &&
+ blackhole_deadline_.IsInitialized() &&
+ path_degrading_deadline_ > blackhole_deadline_)
+ << "Path degrading timeout is later than blackhole detection timeout";
+ alarm_->Update(path_degrading_deadline_, kAlarmGranularity);
+ if (alarm_->IsSet()) {
+ return;
+ }
+ alarm_->Update(blackhole_deadline_, kAlarmGranularity);
+}
+
+bool QuicNetworkBlackholeDetector::IsDetectionInProgress() const {
+ return alarm_->IsSet();
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector.h b/chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector.h
new file mode 100644
index 00000000000..b839d428574
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector.h
@@ -0,0 +1,76 @@
+// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_CORE_QUIC_NETWORK_BLACKHOLE_DETECTOR_H_
+#define QUICHE_QUIC_CORE_QUIC_NETWORK_BLACKHOLE_DETECTOR_H_
+
+#include "net/third_party/quiche/src/quic/core/quic_alarm.h"
+#include "net/third_party/quiche/src/quic/core/quic_alarm_factory.h"
+#include "net/third_party/quiche/src/quic/core/quic_one_block_arena.h"
+#include "net/third_party/quiche/src/quic/core/quic_time.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+
+namespace quic {
+
+namespace test {
+class QuicConnectionPeer;
+class QuicNetworkBlackholeDetectorPeer;
+} // namespace test
+
+// QuicNetworkBlackholeDetector can detect path degrading and/or network
+// blackhole. If both detections are in progress, detector will be in path
+// degrading detection mode. After reporting path degrading detected, detector
+// switches to blackhole detection mode. So blackhole detection deadline must
+// be later than path degrading deadline.
+class QUIC_EXPORT_PRIVATE QuicNetworkBlackholeDetector {
+ public:
+ class QUIC_EXPORT_PRIVATE Delegate {
+ public:
+ virtual ~Delegate() {}
+
+ // Called when the path degrading alarm fires.
+ virtual void OnPathDegradingDetected() = 0;
+
+ // Called when the path blackhole alarm fires.
+ virtual void OnBlackholeDetected() = 0;
+ };
+
+ QuicNetworkBlackholeDetector(Delegate* delegate,
+ QuicConnectionArena* arena,
+ QuicAlarmFactory* alarm_factory);
+
+ // Called to stop all detections.
+ void StopDetection();
+
+ // Called to restart path degrading or/and blackhole detections. Please note,
+ // if both deadlines are set, |blackhole_deadline| must be later than
+ // |path_degrading_deadline|.
+ void RestartDetection(QuicTime path_degrading_deadline,
+ QuicTime blackhole_deadline);
+
+ // Called when |alarm_| fires.
+ void OnAlarm();
+
+ // Returns true if |alarm_| is set.
+ bool IsDetectionInProgress() const;
+
+ private:
+ friend class test::QuicConnectionPeer;
+ friend class test::QuicNetworkBlackholeDetectorPeer;
+
+ Delegate* delegate_; // Not owned.
+
+ // Time that Delegate::OnPathDegrading will be called. 0 means no path
+ // degrading detection is in progress.
+ QuicTime path_degrading_deadline_;
+ // Time that Delegate::OnBlackholeDetected will be called. 0 means no
+ // blackhole detection is in progress.
+ QuicTime blackhole_deadline_;
+
+ QuicArenaScopedPtr<QuicAlarm> alarm_;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_QUIC_NETWORK_BLACKHOLE_DETECTOR_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector_test.cc
new file mode 100644
index 00000000000..eca50e3c1f3
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector_test.cc
@@ -0,0 +1,121 @@
+// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/quic_network_blackhole_detector.h"
+
+#include "net/third_party/quiche/src/quic/core/quic_one_block_arena.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+
+namespace quic {
+namespace test {
+
+class QuicNetworkBlackholeDetectorPeer {
+ public:
+ static QuicAlarm* GetAlarm(QuicNetworkBlackholeDetector* detector) {
+ return detector->alarm_.get();
+ }
+};
+
+namespace {
+class MockDelegate : public QuicNetworkBlackholeDetector::Delegate {
+ public:
+ MOCK_METHOD0(OnPathDegradingDetected, void());
+ MOCK_METHOD0(OnBlackholeDetected, void());
+};
+
+const size_t kPathDegradingDelayInSeconds = 5;
+const size_t kBlackholeDelayInSeconds = 10;
+
+class QuicNetworkBlackholeDetectorTest : public QuicTest {
+ public:
+ QuicNetworkBlackholeDetectorTest()
+ : detector_(&delegate_, &arena_, &alarm_factory_),
+ alarm_(static_cast<MockAlarmFactory::TestAlarm*>(
+ QuicNetworkBlackholeDetectorPeer::GetAlarm(&detector_))),
+ path_degrading_delay_(
+ QuicTime::Delta::FromSeconds(kPathDegradingDelayInSeconds)),
+ blackhole_delay_(
+ QuicTime::Delta::FromSeconds(kBlackholeDelayInSeconds)) {
+ clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
+ }
+
+ protected:
+ testing::StrictMock<MockDelegate> delegate_;
+ QuicConnectionArena arena_;
+ MockAlarmFactory alarm_factory_;
+
+ QuicNetworkBlackholeDetector detector_;
+
+ MockAlarmFactory::TestAlarm* alarm_;
+ MockClock clock_;
+ const QuicTime::Delta path_degrading_delay_;
+ const QuicTime::Delta blackhole_delay_;
+};
+
+TEST_F(QuicNetworkBlackholeDetectorTest, StartAndFire) {
+ EXPECT_FALSE(detector_.IsDetectionInProgress());
+
+ detector_.RestartDetection(clock_.Now() + path_degrading_delay_,
+ clock_.Now() + blackhole_delay_);
+ EXPECT_TRUE(detector_.IsDetectionInProgress());
+ EXPECT_EQ(clock_.Now() + path_degrading_delay_, alarm_->deadline());
+
+ // Fire path degrading alarm.
+ clock_.AdvanceTime(path_degrading_delay_);
+ EXPECT_CALL(delegate_, OnPathDegradingDetected());
+ alarm_->Fire();
+ // Verify blackhole detection is still in progress.
+ EXPECT_TRUE(detector_.IsDetectionInProgress());
+ EXPECT_EQ(clock_.Now() + blackhole_delay_ - path_degrading_delay_,
+ alarm_->deadline());
+
+ // Fire blackhole detection alarm.
+ clock_.AdvanceTime(blackhole_delay_ - path_degrading_delay_);
+ EXPECT_CALL(delegate_, OnBlackholeDetected());
+ alarm_->Fire();
+ EXPECT_FALSE(detector_.IsDetectionInProgress());
+}
+
+TEST_F(QuicNetworkBlackholeDetectorTest, RestartAndStop) {
+ detector_.RestartDetection(clock_.Now() + path_degrading_delay_,
+ clock_.Now() + blackhole_delay_);
+
+ clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
+ detector_.RestartDetection(clock_.Now() + path_degrading_delay_,
+ clock_.Now() + blackhole_delay_);
+ EXPECT_EQ(clock_.Now() + path_degrading_delay_, alarm_->deadline());
+
+ detector_.StopDetection();
+ EXPECT_FALSE(detector_.IsDetectionInProgress());
+}
+
+TEST_F(QuicNetworkBlackholeDetectorTest, PathDegradingFiresAndRestart) {
+ EXPECT_FALSE(detector_.IsDetectionInProgress());
+ detector_.RestartDetection(clock_.Now() + path_degrading_delay_,
+ clock_.Now() + blackhole_delay_);
+ EXPECT_TRUE(detector_.IsDetectionInProgress());
+ EXPECT_EQ(clock_.Now() + path_degrading_delay_, alarm_->deadline());
+
+ // Fire path degrading alarm.
+ clock_.AdvanceTime(path_degrading_delay_);
+ EXPECT_CALL(delegate_, OnPathDegradingDetected());
+ alarm_->Fire();
+ // Verify blackhole detection is still in progress.
+ EXPECT_TRUE(detector_.IsDetectionInProgress());
+ EXPECT_EQ(clock_.Now() + blackhole_delay_ - path_degrading_delay_,
+ alarm_->deadline());
+
+ // After 100ms, restart detections on forward progress.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(100));
+ detector_.RestartDetection(clock_.Now() + path_degrading_delay_,
+ clock_.Now() + blackhole_delay_);
+ // Verify alarm is armed based on path degrading deadline.
+ EXPECT_EQ(clock_.Now() + path_degrading_delay_, alarm_->deadline());
+}
+
+} // namespace
+
+} // namespace test
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_one_block_arena.h b/chromium/net/third_party/quiche/src/quic/core/quic_one_block_arena.h
index 41842f35963..d6b7ee99b55 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_one_block_arena.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_one_block_arena.h
@@ -75,7 +75,10 @@ QuicArenaScopedPtr<T> QuicOneBlockArena<ArenaSize>::New(Args&&... args) {
// QuicConnections currently use around 1KB of polymorphic types which would
// ordinarily be on the heap. Instead, store them inline in an arena.
-using QuicConnectionArena = QuicOneBlockArena<1024>;
+// TODO(fayang): Switch this and 1200 used in quic_arena_scoped_ptr_test and
+// quic_one_block_arena_test back to 1024 when deprecating
+// quic_use_blackhole_detector or quic_use_idle_network_detector.
+using QuicConnectionArena = QuicOneBlockArena<1200>;
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_one_block_arena_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_one_block_arena_test.cc
index 3175ac54abf..11b12de410a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_one_block_arena_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_one_block_arena_test.cc
@@ -23,14 +23,14 @@ struct TestObject {
class QuicOneBlockArenaTest : public QuicTest {};
TEST_F(QuicOneBlockArenaTest, AllocateSuccess) {
- QuicOneBlockArena<1024> arena;
+ QuicOneBlockArena<1200> arena;
QuicArenaScopedPtr<TestObject> ptr = arena.New<TestObject>();
EXPECT_TRUE(ptr.is_from_arena());
}
TEST_F(QuicOneBlockArenaTest, Exhaust) {
- QuicOneBlockArena<1024> arena;
- for (size_t i = 0; i < 1024 / kMaxAlign; ++i) {
+ QuicOneBlockArena<1200> arena;
+ for (size_t i = 0; i < 1200 / kMaxAlign; ++i) {
QuicArenaScopedPtr<TestObject> ptr = arena.New<TestObject>();
EXPECT_TRUE(ptr.is_from_arena());
}
@@ -41,10 +41,10 @@ TEST_F(QuicOneBlockArenaTest, Exhaust) {
}
TEST_F(QuicOneBlockArenaTest, NoOverlaps) {
- QuicOneBlockArena<1024> arena;
+ QuicOneBlockArena<1200> arena;
std::vector<QuicArenaScopedPtr<TestObject>> objects;
QuicIntervalSet<uintptr_t> used;
- for (size_t i = 0; i < 1024 / kMaxAlign; ++i) {
+ for (size_t i = 0; i < 1200 / kMaxAlign; ++i) {
QuicArenaScopedPtr<TestObject> ptr = arena.New<TestObject>();
EXPECT_TRUE(ptr.is_from_arena());
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.cc b/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.cc
index f95fe638ada..cea1a1be9cf 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.cc
@@ -21,15 +21,16 @@
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_aligned.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_exported_stats.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_server_stats.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
namespace {
@@ -53,6 +54,11 @@ QuicLongHeaderType EncryptionlevelToLongHeaderType(EncryptionLevel level) {
}
}
+void LogCoalesceStreamFrameStatus(bool success) {
+ QUIC_HISTOGRAM_BOOL("QuicSession.CoalesceStreamFrameStatus", success,
+ "Success rate of coalesing stream frames attempt.");
+}
+
// ScopedPacketContextSwitcher saves |packet|'s states and change states
// during its construction. When the switcher goes out of scope, it restores
// saved states.
@@ -214,8 +220,8 @@ void QuicPacketCreator::UpdatePacketNumberLength(
const uint64_t current_delta =
packet_.packet_number + 1 - least_packet_awaited_by_peer;
const uint64_t delta = std::max(current_delta, max_packets_in_flight);
- packet_.packet_number_length = QuicFramer::GetMinPacketNumberLength(
- framer_->transport_version(), QuicPacketNumber(delta * 4));
+ packet_.packet_number_length =
+ QuicFramer::GetMinPacketNumberLength(QuicPacketNumber(delta * 4));
}
void QuicPacketCreator::SkipNPacketNumbers(
@@ -329,17 +335,6 @@ bool QuicPacketCreator::HasRoomForMessageFrame(QuicByteCount length) {
return BytesFree() >= message_frame_size;
}
-// TODO(fkastenholz): this method should not use constant values for
-// the last-frame-in-packet and data-length parameters to
-// GetMinStreamFrameSize. Proper values should be plumbed in from
-// higher up. This was left this way for now for a few reasons. First,
-// higher up calls to StreamFramePacketOverhead() do not always know
-// this information, leading to a cascade of changes and B) the
-// higher-up software does not always loop, calling
-// StreamFramePacketOverhead() once for every packet -- eg there is
-// a test in quic_connection_test that calls it once and assumes that
-// the value is the same for all packets.
-
// static
size_t QuicPacketCreator::StreamFramePacketOverhead(
QuicTransportVersion version,
@@ -357,21 +352,10 @@ size_t QuicPacketCreator::StreamFramePacketOverhead(
packet_number_length, retry_token_length_length, 0,
length_length) +
- // Assumes this is a packet with a single stream frame in it. Since
- // last_frame_in_packet is set true, the size of the length field is
- // not included in the calculation. This is OK because in other places
- // in the code, the logic adds back 2 (the size of the Google QUIC
- // length) when a frame is not the last frame of the packet. This is
- // also acceptable for IETF Quic; even though the length field could be
- // 8 bytes long, in practice it will not be longer than 2 bytes (enough
- // to encode 16K). A length that would be encoded in 2 bytes (0xfff)
- // is passed just for cleanliness.
- //
- // TODO(fkastenholz): This is very hacky and feels brittle. Ideally we
- // would calculate the correct lengths at the correct time, based on
- // the state at that time/place.
+ // Assumes a packet with a single stream frame, which omits the length,
+ // causing the data length argument to be ignored.
QuicFramer::GetMinStreamFrameSize(version, 1u, offset, true,
- kMaxOutgoingPacketSize);
+ kMaxOutgoingPacketSize /* unused */);
}
void QuicPacketCreator::CreateStreamFrame(QuicStreamId id,
@@ -695,6 +679,15 @@ void QuicPacketCreator::SerializePacket(char* encrypted_buffer,
<< QuicFramesToString(queued_frames_) << " at encryption_level "
<< EncryptionLevelToString(packet_.encryption_level);
+ if (!framer_->HasEncrypterOfEncryptionLevel(packet_.encryption_level)) {
+ QUIC_BUG << ENDPOINT << "Attempting to serialize " << header
+ << QuicFramesToString(queued_frames_)
+ << " at missing encryption_level "
+ << EncryptionLevelToString(packet_.encryption_level) << " using "
+ << framer_->version();
+ return;
+ }
+
DCHECK_GE(max_plaintext_size_, packet_size_);
// Use the packet_size_ instead of the buffer size to ensure smaller
// packet sizes are properly used.
@@ -819,7 +812,7 @@ QuicPacketCreator::SerializePathChallengeConnectivityProbingPacket(
OwningSerializedPacketPointer
QuicPacketCreator::SerializePathResponseConnectivityProbingPacket(
- const QuicDeque<QuicPathFrameBuffer>& payloads,
+ const QuicCircularDeque<QuicPathFrameBuffer>& payloads,
const bool is_padded) {
QUIC_BUG_IF(!VersionHasIetfQuicFrames(framer_->transport_version()))
<< "Must be version 99 to serialize path response connectivity probe, is "
@@ -885,7 +878,7 @@ size_t QuicPacketCreator::BuildPathResponsePacket(
const QuicPacketHeader& header,
char* buffer,
size_t packet_length,
- const QuicDeque<QuicPathFrameBuffer>& payloads,
+ const QuicCircularDeque<QuicPathFrameBuffer>& payloads,
const bool is_padded,
EncryptionLevel level) {
if (payloads.empty()) {
@@ -954,10 +947,17 @@ size_t QuicPacketCreator::SerializeCoalescedPacket(
<< "Attempt to serialize empty coalesced packet";
size_t packet_length = 0;
if (coalesced.initial_packet() != nullptr) {
+ // Padding coalesced packet containing initial packet to full.
+ size_t padding_size = coalesced.max_packet_length() - coalesced.length();
+ if (framer_->perspective() == Perspective::IS_SERVER &&
+ QuicUtils::ContainsFrameType(
+ coalesced.initial_packet()->retransmittable_frames,
+ CONNECTION_CLOSE_FRAME)) {
+ // Do not pad server initial connection close packet.
+ padding_size = 0;
+ }
size_t initial_length = ReserializeInitialPacketInCoalescedPacket(
- *coalesced.initial_packet(),
- /*padding_size=*/coalesced.max_packet_length() - coalesced.length(),
- buffer, buffer_len);
+ *coalesced.initial_packet(), padding_size, buffer, buffer_len);
if (initial_length == 0) {
QUIC_BUG << "Failed to reserialize ENCRYPTION_INITIAL packet in "
"coalesced packet";
@@ -1069,16 +1069,16 @@ QuicVariableLengthIntegerLength QuicPacketCreator::GetRetryTokenLengthLength()
return VARIABLE_LENGTH_INTEGER_LENGTH_0;
}
-QuicStringPiece QuicPacketCreator::GetRetryToken() const {
+quiche::QuicheStringPiece QuicPacketCreator::GetRetryToken() const {
if (QuicVersionHasLongHeaderLengths(framer_->transport_version()) &&
HasIetfLongHeader() &&
EncryptionlevelToLongHeaderType(packet_.encryption_level) == INITIAL) {
return retry_token_;
}
- return QuicStringPiece();
+ return quiche::QuicheStringPiece();
}
-void QuicPacketCreator::SetRetryToken(QuicStringPiece retry_token) {
+void QuicPacketCreator::SetRetryToken(quiche::QuicheStringPiece retry_token) {
retry_token_ = std::string(retry_token);
}
@@ -1212,18 +1212,13 @@ QuicConsumedData QuicPacketCreator::ConsumeDataFastPath(
CreateAndSerializeStreamFrame(id, write_length, total_bytes_consumed,
offset + total_bytes_consumed, fin,
next_transmission_type_, &bytes_consumed);
- if (GetQuicReloadableFlag(
- quic_close_connection_on_failed_consume_data_fast_path)) {
- QUIC_RELOADABLE_FLAG_COUNT(
- quic_close_connection_on_failed_consume_data_fast_path);
- if (bytes_consumed == 0) {
- const std::string error_details =
- "Failed in CreateAndSerializeStreamFrame.";
- QUIC_BUG << error_details;
- delegate_->OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET,
- error_details);
- break;
- }
+ if (bytes_consumed == 0) {
+ const std::string error_details =
+ "Failed in CreateAndSerializeStreamFrame.";
+ QUIC_BUG << error_details;
+ delegate_->OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET,
+ error_details);
+ break;
}
total_bytes_consumed += bytes_consumed;
}
@@ -1458,19 +1453,21 @@ bool QuicPacketCreator::AddFrame(const QuicFrame& frame,
(packet_.encryption_level == ENCRYPTION_INITIAL ||
packet_.encryption_level == ENCRYPTION_HANDSHAKE)) {
const std::string error_details =
- QuicStrCat("Cannot send stream data with level: ",
- EncryptionLevelToString(packet_.encryption_level));
+ quiche::QuicheStrCat("Cannot send stream data with level: ",
+ EncryptionLevelToString(packet_.encryption_level));
QUIC_BUG << error_details;
delegate_->OnUnrecoverableError(
QUIC_ATTEMPT_TO_SEND_UNENCRYPTED_STREAM_DATA, error_details);
return false;
}
- if (GetQuicRestartFlag(quic_coalesce_stream_frames_2) &&
- frame.type == STREAM_FRAME &&
- MaybeCoalesceStreamFrame(frame.stream_frame)) {
- QUIC_RESTART_FLAG_COUNT_N(quic_coalesce_stream_frames_2, 1, 3);
- return true;
+ if (frame.type == STREAM_FRAME) {
+ if (MaybeCoalesceStreamFrame(frame.stream_frame)) {
+ LogCoalesceStreamFrameStatus(true);
+ return true;
+ } else {
+ LogCoalesceStreamFrameStatus(false);
+ }
}
size_t frame_len = framer_->GetSerializedFrameLength(
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.h b/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.h
index eb7b6274af3..508cd56256f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.h
@@ -21,11 +21,13 @@
#include <vector>
#include "net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_circular_deque.h"
#include "net/third_party/quiche/src/quic/core/quic_coalesced_packet.h"
#include "net/third_party/quiche/src/quic/core/quic_framer.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
@@ -221,7 +223,7 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// will pad the packet to be MTU bytes long, else it will not pad the packet.
// |payloads| is cleared.
OwningSerializedPacketPointer SerializePathResponseConnectivityProbingPacket(
- const QuicDeque<QuicPathFrameBuffer>& payloads,
+ const QuicCircularDeque<QuicPathFrameBuffer>& payloads,
const bool is_padded);
// Returns a dummy packet that is valid but contains no useful information.
@@ -286,7 +288,7 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
void AddPendingPadding(QuicByteCount size);
// Sets the retry token to be sent over the wire in IETF Initial packets.
- void SetRetryToken(QuicStringPiece retry_token);
+ void SetRetryToken(quiche::QuicheStringPiece retry_token);
// Consumes retransmittable control |frame|. Returns true if the frame is
// successfully consumed. Returns false otherwise.
@@ -403,12 +405,13 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// frame. Also fills the packet with padding if |is_padded| is
// true. |payloads| is always emptied, even if the packet can not be
// successfully built.
- size_t BuildPathResponsePacket(const QuicPacketHeader& header,
- char* buffer,
- size_t packet_length,
- const QuicDeque<QuicPathFrameBuffer>& payloads,
- const bool is_padded,
- EncryptionLevel level);
+ size_t BuildPathResponsePacket(
+ const QuicPacketHeader& header,
+ char* buffer,
+ size_t packet_length,
+ const QuicCircularDeque<QuicPathFrameBuffer>& payloads,
+ const bool is_padded,
+ EncryptionLevel level);
// Serializes a probing packet, which is a padded PING packet. Returns the
// length of the packet. Returns 0 if it fails to serialize.
@@ -510,7 +513,7 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// Returns the retry token to send over the wire, only sent in
// v99 IETF Initial packets.
- QuicStringPiece GetRetryToken() const;
+ quiche::QuicheStringPiece GetRetryToken() const;
// Returns length of the length variable length integer to send over the
// wire. Is non-zero for v99 IETF Initial, 0-RTT or Handshake packets.
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator_test.cc
index 6ca369cd5ec..1507ae5f34d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator_test.cc
@@ -20,18 +20,20 @@
#include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_framer_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/simple_data_producer.h"
#include "net/third_party/quiche/src/quic/test_tools/simple_quic_framer.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/test_tools/quiche_test_utils.h"
using testing::_;
using testing::DoAll;
@@ -64,8 +66,9 @@ struct TestParams {
// Used by ::testing::PrintToStringParamName().
std::string PrintToString(const TestParams& p) {
- return QuicStrCat(ParsedQuicVersionToString(p.version), "_",
- (p.version_serialization ? "Include" : "No"), "Version");
+ return quiche::QuicheStrCat(ParsedQuicVersionToString(p.version), "_",
+ (p.version_serialization ? "Include" : "No"),
+ "Version");
}
// Constructs various test permutations.
@@ -234,7 +237,8 @@ class QuicPacketCreatorTest : public QuicTestWithParam<TestParams> {
producer_.WriteStreamData(stream_id, frame.stream_frame.offset,
frame.stream_frame.data_length, &writer);
}
- EXPECT_EQ(data, QuicStringPiece(buf, frame.stream_frame.data_length));
+ EXPECT_EQ(data,
+ quiche::QuicheStringPiece(buf, frame.stream_frame.data_length));
EXPECT_EQ(offset, frame.stream_frame.offset);
EXPECT_EQ(fin, frame.stream_frame.fin);
}
@@ -311,12 +315,8 @@ TEST_P(QuicPacketCreatorTest, SerializeFrames) {
QuicStreamId stream_id = QuicUtils::GetFirstBidirectionalStreamId(
client_framer_.transport_version(), Perspective::IS_CLIENT);
if (level != ENCRYPTION_INITIAL && level != ENCRYPTION_HANDSHAKE) {
- frames_.push_back(
- QuicFrame(QuicStreamFrame(stream_id, false, 0u, QuicStringPiece())));
- if (!GetQuicRestartFlag(quic_coalesce_stream_frames_2)) {
- frames_.push_back(
- QuicFrame(QuicStreamFrame(stream_id, true, 0u, QuicStringPiece())));
- }
+ frames_.push_back(QuicFrame(
+ QuicStreamFrame(stream_id, false, 0u, quiche::QuicheStringPiece())));
}
SerializedPacket serialized = SerializeAllFrames(frames_);
EXPECT_EQ(level, serialized.encryption_level);
@@ -339,9 +339,6 @@ TEST_P(QuicPacketCreatorTest, SerializeFrames) {
.WillOnce(Return(true));
if (level != ENCRYPTION_INITIAL && level != ENCRYPTION_HANDSHAKE) {
EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
- if (!GetQuicRestartFlag(quic_coalesce_stream_frames_2)) {
- EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
- }
}
if (client_framer_.version().HasHeaderProtection()) {
EXPECT_CALL(framer_visitor_, OnPaddingFrame(_))
@@ -649,9 +646,9 @@ TEST_P(QuicPacketCreatorTest, BuildPathChallengePacket) {
MockRandom randomizer;
size_t length = creator_.BuildPaddedPathChallengePacket(
- header, buffer.get(), QUIC_ARRAYSIZE(packet), &payload, &randomizer,
+ header, buffer.get(), QUICHE_ARRAYSIZE(packet), &payload, &randomizer,
ENCRYPTION_INITIAL);
- EXPECT_EQ(length, QUIC_ARRAYSIZE(packet));
+ EXPECT_EQ(length, QUICHE_ARRAYSIZE(packet));
// Payload has the random bytes that were generated. Copy them into packet,
// above, before checking that the generated packet is correct.
@@ -660,9 +657,9 @@ TEST_P(QuicPacketCreatorTest, BuildPathChallengePacket) {
QuicPacket data(creator_.transport_version(), buffer.release(), length, true,
header);
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"constructed packet", data.data(), data.length(),
- reinterpret_cast<char*>(packet), QUIC_ARRAYSIZE(packet));
+ reinterpret_cast<char*>(packet), QUICHE_ARRAYSIZE(packet));
}
TEST_P(QuicPacketCreatorTest, BuildConnectivityProbingPacket) {
@@ -720,13 +717,13 @@ TEST_P(QuicPacketCreatorTest, BuildConnectivityProbingPacket) {
// clang-format on
unsigned char* p = packet;
- size_t packet_size = QUIC_ARRAYSIZE(packet);
+ size_t packet_size = QUICHE_ARRAYSIZE(packet);
if (VersionHasIetfQuicFrames(creator_.transport_version())) {
p = packet99;
- packet_size = QUIC_ARRAYSIZE(packet99);
+ packet_size = QUICHE_ARRAYSIZE(packet99);
} else if (creator_.transport_version() >= QUIC_VERSION_46) {
p = packet46;
- packet_size = QUIC_ARRAYSIZE(packet46);
+ packet_size = QUICHE_ARRAYSIZE(packet46);
}
std::unique_ptr<char[]> buffer(new char[kMaxOutgoingPacketSize]);
@@ -738,9 +735,9 @@ TEST_P(QuicPacketCreatorTest, BuildConnectivityProbingPacket) {
QuicPacket data(creator_.transport_version(), buffer.release(), length, true,
header);
- test::CompareCharArraysWithHexError("constructed packet", data.data(),
- data.length(), reinterpret_cast<char*>(p),
- packet_size);
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", data.data(), data.length(),
+ reinterpret_cast<char*>(p), packet_size);
}
// Several tests that the path response connectivity probing packet is
@@ -778,18 +775,18 @@ TEST_P(QuicPacketCreatorTest, BuildPathResponsePacket1ResponseUnpadded) {
};
// clang-format on
std::unique_ptr<char[]> buffer(new char[kMaxOutgoingPacketSize]);
- QuicDeque<QuicPathFrameBuffer> payloads;
+ QuicCircularDeque<QuicPathFrameBuffer> payloads;
payloads.push_back(payload0);
size_t length = creator_.BuildPathResponsePacket(
- header, buffer.get(), QUIC_ARRAYSIZE(packet), payloads,
+ header, buffer.get(), QUICHE_ARRAYSIZE(packet), payloads,
/*is_padded=*/false, ENCRYPTION_INITIAL);
- EXPECT_EQ(length, QUIC_ARRAYSIZE(packet));
+ EXPECT_EQ(length, QUICHE_ARRAYSIZE(packet));
QuicPacket data(creator_.transport_version(), buffer.release(), length, true,
header);
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"constructed packet", data.data(), data.length(),
- reinterpret_cast<char*>(packet), QUIC_ARRAYSIZE(packet));
+ reinterpret_cast<char*>(packet), QUICHE_ARRAYSIZE(packet));
}
TEST_P(QuicPacketCreatorTest, BuildPathResponsePacket1ResponsePadded) {
@@ -825,18 +822,18 @@ TEST_P(QuicPacketCreatorTest, BuildPathResponsePacket1ResponsePadded) {
};
// clang-format on
std::unique_ptr<char[]> buffer(new char[kMaxOutgoingPacketSize]);
- QuicDeque<QuicPathFrameBuffer> payloads;
+ QuicCircularDeque<QuicPathFrameBuffer> payloads;
payloads.push_back(payload0);
size_t length = creator_.BuildPathResponsePacket(
- header, buffer.get(), QUIC_ARRAYSIZE(packet), payloads,
+ header, buffer.get(), QUICHE_ARRAYSIZE(packet), payloads,
/*is_padded=*/true, ENCRYPTION_INITIAL);
- EXPECT_EQ(length, QUIC_ARRAYSIZE(packet));
+ EXPECT_EQ(length, QUICHE_ARRAYSIZE(packet));
QuicPacket data(creator_.transport_version(), buffer.release(), length, true,
header);
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"constructed packet", data.data(), data.length(),
- reinterpret_cast<char*>(packet), QUIC_ARRAYSIZE(packet));
+ reinterpret_cast<char*>(packet), QUICHE_ARRAYSIZE(packet));
}
TEST_P(QuicPacketCreatorTest, BuildPathResponsePacket3ResponsesUnpadded) {
@@ -875,20 +872,20 @@ TEST_P(QuicPacketCreatorTest, BuildPathResponsePacket3ResponsesUnpadded) {
// clang-format on
std::unique_ptr<char[]> buffer(new char[kMaxOutgoingPacketSize]);
- QuicDeque<QuicPathFrameBuffer> payloads;
+ QuicCircularDeque<QuicPathFrameBuffer> payloads;
payloads.push_back(payload0);
payloads.push_back(payload1);
payloads.push_back(payload2);
size_t length = creator_.BuildPathResponsePacket(
- header, buffer.get(), QUIC_ARRAYSIZE(packet), payloads,
+ header, buffer.get(), QUICHE_ARRAYSIZE(packet), payloads,
/*is_padded=*/false, ENCRYPTION_INITIAL);
- EXPECT_EQ(length, QUIC_ARRAYSIZE(packet));
+ EXPECT_EQ(length, QUICHE_ARRAYSIZE(packet));
QuicPacket data(creator_.transport_version(), buffer.release(), length, true,
header);
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"constructed packet", data.data(), data.length(),
- reinterpret_cast<char*>(packet), QUIC_ARRAYSIZE(packet));
+ reinterpret_cast<char*>(packet), QUICHE_ARRAYSIZE(packet));
}
TEST_P(QuicPacketCreatorTest, BuildPathResponsePacket3ResponsesPadded) {
@@ -929,20 +926,20 @@ TEST_P(QuicPacketCreatorTest, BuildPathResponsePacket3ResponsesPadded) {
// clang-format on
std::unique_ptr<char[]> buffer(new char[kMaxOutgoingPacketSize]);
- QuicDeque<QuicPathFrameBuffer> payloads;
+ QuicCircularDeque<QuicPathFrameBuffer> payloads;
payloads.push_back(payload0);
payloads.push_back(payload1);
payloads.push_back(payload2);
size_t length = creator_.BuildPathResponsePacket(
- header, buffer.get(), QUIC_ARRAYSIZE(packet), payloads,
+ header, buffer.get(), QUICHE_ARRAYSIZE(packet), payloads,
/*is_padded=*/true, ENCRYPTION_INITIAL);
- EXPECT_EQ(length, QUIC_ARRAYSIZE(packet));
+ EXPECT_EQ(length, QUICHE_ARRAYSIZE(packet));
QuicPacket data(creator_.transport_version(), buffer.release(), length, true,
header);
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"constructed packet", data.data(), data.length(),
- reinterpret_cast<char*>(packet), QUIC_ARRAYSIZE(packet));
+ reinterpret_cast<char*>(packet), QUICHE_ARRAYSIZE(packet));
}
TEST_P(QuicPacketCreatorTest, SerializeConnectivityProbingPacket) {
@@ -1024,7 +1021,7 @@ TEST_P(QuicPacketCreatorTest, SerializePathResponseProbePacket1PayloadPadded) {
EncryptionLevel level = static_cast<EncryptionLevel>(i);
creator_.set_encryption_level(level);
- QuicDeque<QuicPathFrameBuffer> payloads;
+ QuicCircularDeque<QuicPathFrameBuffer> payloads;
payloads.push_back(payload0);
OwningSerializedPacketPointer encrypted(
@@ -1058,7 +1055,7 @@ TEST_P(QuicPacketCreatorTest,
EncryptionLevel level = static_cast<EncryptionLevel>(i);
creator_.set_encryption_level(level);
- QuicDeque<QuicPathFrameBuffer> payloads;
+ QuicCircularDeque<QuicPathFrameBuffer> payloads;
payloads.push_back(payload0);
OwningSerializedPacketPointer encrypted(
@@ -1092,7 +1089,7 @@ TEST_P(QuicPacketCreatorTest, SerializePathResponseProbePacket2PayloadsPadded) {
EncryptionLevel level = static_cast<EncryptionLevel>(i);
creator_.set_encryption_level(level);
- QuicDeque<QuicPathFrameBuffer> payloads;
+ QuicCircularDeque<QuicPathFrameBuffer> payloads;
payloads.push_back(payload0);
payloads.push_back(payload1);
@@ -1129,7 +1126,7 @@ TEST_P(QuicPacketCreatorTest,
EncryptionLevel level = static_cast<EncryptionLevel>(i);
creator_.set_encryption_level(level);
- QuicDeque<QuicPathFrameBuffer> payloads;
+ QuicCircularDeque<QuicPathFrameBuffer> payloads;
payloads.push_back(payload0);
payloads.push_back(payload1);
@@ -1166,7 +1163,7 @@ TEST_P(QuicPacketCreatorTest, SerializePathResponseProbePacket3PayloadsPadded) {
EncryptionLevel level = static_cast<EncryptionLevel>(i);
creator_.set_encryption_level(level);
- QuicDeque<QuicPathFrameBuffer> payloads;
+ QuicCircularDeque<QuicPathFrameBuffer> payloads;
payloads.push_back(payload0);
payloads.push_back(payload1);
payloads.push_back(payload2);
@@ -1206,7 +1203,7 @@ TEST_P(QuicPacketCreatorTest,
EncryptionLevel level = static_cast<EncryptionLevel>(i);
creator_.set_encryption_level(level);
- QuicDeque<QuicPathFrameBuffer> payloads;
+ QuicCircularDeque<QuicPathFrameBuffer> payloads;
payloads.push_back(payload0);
payloads.push_back(payload1);
payloads.push_back(payload2);
@@ -1337,7 +1334,7 @@ TEST_P(QuicPacketCreatorTest, SerializeFrame) {
if (!QuicVersionUsesCryptoFrames(client_framer_.transport_version())) {
QuicStreamFrame stream_frame(
QuicUtils::GetCryptoStreamId(client_framer_.transport_version()),
- /*fin=*/false, 0u, QuicStringPiece());
+ /*fin=*/false, 0u, quiche::QuicheStringPiece());
frames_.push_back(QuicFrame(stream_frame));
} else {
producer_.SaveCryptoData(ENCRYPTION_INITIAL, 0, data);
@@ -1375,7 +1372,7 @@ TEST_P(QuicPacketCreatorTest, SerializeFrameShortData) {
if (!QuicVersionUsesCryptoFrames(client_framer_.transport_version())) {
QuicStreamFrame stream_frame(
QuicUtils::GetCryptoStreamId(client_framer_.transport_version()),
- /*fin=*/false, 0u, QuicStringPiece());
+ /*fin=*/false, 0u, quiche::QuicheStringPiece());
frames_.push_back(QuicFrame(stream_frame));
} else {
producer_.SaveCryptoData(ENCRYPTION_INITIAL, 0, data);
@@ -1595,7 +1592,7 @@ TEST_P(QuicPacketCreatorTest, AddUnencryptedStreamDataClosesConnection) {
creator_.set_encryption_level(ENCRYPTION_INITIAL);
EXPECT_CALL(delegate_, OnUnrecoverableError(_, _));
QuicStreamFrame stream_frame(GetNthClientInitiatedStreamId(0),
- /*fin=*/false, 0u, QuicStringPiece());
+ /*fin=*/false, 0u, quiche::QuicheStringPiece());
EXPECT_QUIC_BUG(
creator_.AddFrame(QuicFrame(stream_frame), NOT_RETRANSMISSION),
"Cannot send stream data with level: ENCRYPTION_INITIAL");
@@ -1610,7 +1607,7 @@ TEST_P(QuicPacketCreatorTest, SendStreamDataWithEncryptionHandshake) {
creator_.set_encryption_level(ENCRYPTION_HANDSHAKE);
EXPECT_CALL(delegate_, OnUnrecoverableError(_, _));
QuicStreamFrame stream_frame(GetNthClientInitiatedStreamId(0),
- /*fin=*/false, 0u, QuicStringPiece());
+ /*fin=*/false, 0u, quiche::QuicheStringPiece());
EXPECT_QUIC_BUG(
creator_.AddFrame(QuicFrame(stream_frame), NOT_RETRANSMISSION),
"Cannot send stream data with level: ENCRYPTION_HANDSHAKE");
@@ -1637,8 +1634,9 @@ TEST_P(QuicPacketCreatorTest, ChloTooLarge) {
message_data = framer.ConstructHandshakeMessage(message);
struct iovec iov;
- MakeIOVector(QuicStringPiece(message_data->data(), message_data->length()),
- &iov);
+ MakeIOVector(
+ quiche::QuicheStringPiece(message_data->data(), message_data->length()),
+ &iov);
QuicFrame frame;
EXPECT_CALL(delegate_, OnUnrecoverableError(QUIC_CRYPTO_CHLO_TOO_LARGE, _));
EXPECT_QUIC_BUG(
@@ -1715,7 +1713,7 @@ TEST_P(QuicPacketCreatorTest, ConsumeDataAndRandomPadding) {
.WillRepeatedly(
Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
// Send stream frame of size kStreamFramePayloadSize.
- MakeIOVector(QuicStringPiece(buf, kStreamFramePayloadSize), &iov_);
+ MakeIOVector(quiche::QuicheStringPiece(buf, kStreamFramePayloadSize), &iov_);
creator_.ConsumeDataToFillCurrentPacket(stream_id, &iov_, 1u, iov_.iov_len,
0u, 0u, false, false,
NOT_RETRANSMISSION, &frame);
@@ -1723,7 +1721,8 @@ TEST_P(QuicPacketCreatorTest, ConsumeDataAndRandomPadding) {
// 1 byte padding is sent.
EXPECT_EQ(pending_padding_bytes - 1, creator_.pending_padding_bytes());
// Send stream frame of size kStreamFramePayloadSize + 1.
- MakeIOVector(QuicStringPiece(buf, kStreamFramePayloadSize + 1), &iov_);
+ MakeIOVector(quiche::QuicheStringPiece(buf, kStreamFramePayloadSize + 1),
+ &iov_);
creator_.ConsumeDataToFillCurrentPacket(stream_id, &iov_, 1u, iov_.iov_len,
0u, kStreamFramePayloadSize, false,
false, NOT_RETRANSMISSION, &frame);
@@ -1829,7 +1828,7 @@ TEST_P(QuicPacketCreatorTest, MessageFrameConsumption) {
return;
}
std::string message_data(kDefaultMaxPacketSize, 'a');
- QuicStringPiece message_buffer(message_data);
+ quiche::QuicheStringPiece message_buffer(message_data);
QuicMemSliceStorage storage(nullptr, 0, nullptr, 0);
// Test all possible encryption levels of message frames.
for (EncryptionLevel level :
@@ -1840,9 +1839,10 @@ TEST_P(QuicPacketCreatorTest, MessageFrameConsumption) {
message_size <= creator_.GetCurrentLargestMessagePayload();
++message_size) {
QuicMessageFrame* frame = new QuicMessageFrame(
- 0, MakeSpan(&allocator_,
- QuicStringPiece(message_buffer.data(), message_size),
- &storage));
+ 0, MakeSpan(
+ &allocator_,
+ quiche::QuicheStringPiece(message_buffer.data(), message_size),
+ &storage));
EXPECT_TRUE(creator_.AddFrame(QuicFrame(frame), NOT_RETRANSMISSION));
EXPECT_TRUE(creator_.HasPendingFrames());
@@ -1895,7 +1895,8 @@ TEST_P(QuicPacketCreatorTest, PacketTransmissionType) {
QuicStreamId stream_id = QuicUtils::GetFirstBidirectionalStreamId(
client_framer_.transport_version(), Perspective::IS_CLIENT);
QuicFrame stream_frame(QuicStreamFrame(stream_id,
- /*fin=*/false, 0u, QuicStringPiece()));
+ /*fin=*/false, 0u,
+ quiche::QuicheStringPiece()));
ASSERT_TRUE(QuicUtils::IsRetransmittableFrame(stream_frame.type));
QuicFrame padding_frame{QuicPaddingFrame()};
@@ -1936,7 +1937,7 @@ TEST_P(QuicPacketCreatorTest, RetryToken) {
if (!QuicVersionUsesCryptoFrames(client_framer_.transport_version())) {
QuicStreamFrame stream_frame(
QuicUtils::GetCryptoStreamId(client_framer_.transport_version()),
- /*fin=*/false, 0u, QuicStringPiece());
+ /*fin=*/false, 0u, quiche::QuicheStringPiece());
frames_.push_back(QuicFrame(stream_frame));
} else {
producer_.SaveCryptoData(ENCRYPTION_INITIAL, 0, data);
@@ -1968,7 +1969,7 @@ TEST_P(QuicPacketCreatorTest, RetryToken) {
ASSERT_TRUE(header.version_flag);
ASSERT_EQ(header.long_packet_type, INITIAL);
ASSERT_EQ(header.retry_token.length(), sizeof(retry_token_bytes));
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"retry token", header.retry_token.data(), header.retry_token.length(),
retry_token_bytes, sizeof(retry_token_bytes));
DeleteFrames(&frames_);
@@ -1995,7 +1996,6 @@ TEST_P(QuicPacketCreatorTest, CoalesceStreamFrames) {
if (!GetParam().version_serialization) {
creator_.StopSendingVersion();
}
- SetQuicRestartFlag(quic_coalesce_stream_frames_2, true);
const size_t max_plaintext_size =
client_framer_.GetMaxPlaintextSize(creator_.max_packet_length());
EXPECT_FALSE(creator_.HasPendingFrames());
@@ -2105,8 +2105,8 @@ TEST_P(QuicPacketCreatorTest, SerializeCoalescedPacket) {
QuicAckFrame ack_frame(InitAckFrame(1));
frames_.push_back(QuicFrame(&ack_frame));
if (level != ENCRYPTION_INITIAL && level != ENCRYPTION_HANDSHAKE) {
- frames_.push_back(
- QuicFrame(QuicStreamFrame(1, false, 0u, QuicStringPiece())));
+ frames_.push_back(QuicFrame(
+ QuicStreamFrame(1, false, 0u, quiche::QuicheStringPiece())));
}
SerializedPacket serialized = SerializeAllFrames(frames_);
EXPECT_EQ(level, serialized.encryption_level);
@@ -2365,7 +2365,7 @@ class MultiplePacketsTestPacketCreator : public QuicPacketCreator {
}
size_t ConsumeCryptoData(EncryptionLevel level,
- QuicStringPiece data,
+ quiche::QuicheStringPiece data,
QuicStreamOffset offset) {
producer_->SaveCryptoData(level, offset, data);
if (!has_ack() && delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
@@ -2809,8 +2809,7 @@ TEST_F(QuicPacketCreatorMultiplePacketsTest, ConsumeData_BatchOperations) {
EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
PacketContents contents;
- contents.num_stream_frames =
- GetQuicRestartFlag(quic_coalesce_stream_frames_2) ? 1 : 2;
+ contents.num_stream_frames = 1;
CheckPacketContains(contents, 0);
}
@@ -3495,7 +3494,7 @@ TEST_F(QuicPacketCreatorMultiplePacketsTest,
ConnectionCloseFrameLargerThanPacketSize) {
delegate_.SetCanWriteAnything();
char buf[2000] = {};
- QuicStringPiece error_details(buf, 2000);
+ quiche::QuicheStringPiece error_details(buf, 2000);
const QuicErrorCode kQuicErrorCode = QUIC_PACKET_WRITE_ERROR;
QuicConnectionCloseFrame* frame = new QuicConnectionCloseFrame(
@@ -3535,7 +3534,7 @@ TEST_F(QuicPacketCreatorMultiplePacketsTest,
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(
Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
- MakeIOVector(QuicStringPiece(buf, kStreamFramePayloadSize), &iov_);
+ MakeIOVector(quiche::QuicheStringPiece(buf, kStreamFramePayloadSize), &iov_);
QuicConsumedData consumed = creator_.ConsumeData(
kDataStreamId, &iov_, 1u, iov_.iov_len, 0, FIN_AND_PADDING);
creator_.Flush();
@@ -3578,7 +3577,7 @@ TEST_F(QuicPacketCreatorMultiplePacketsTest,
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillRepeatedly(
Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
- MakeIOVector(QuicStringPiece(buf, kStreamFramePayloadSize), &iov_);
+ MakeIOVector(quiche::QuicheStringPiece(buf, kStreamFramePayloadSize), &iov_);
QuicConsumedData consumed = creator_.ConsumeData(
kDataStreamId, &iov_, 1u, iov_.iov_len, 0, FIN_AND_PADDING);
creator_.Flush();
@@ -3633,11 +3632,11 @@ TEST_F(QuicPacketCreatorMultiplePacketsTest,
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillRepeatedly(
Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
- MakeIOVector(QuicStringPiece(buf, kStreamFramePayloadSize), &iov_);
+ MakeIOVector(quiche::QuicheStringPiece(buf, kStreamFramePayloadSize), &iov_);
QuicConsumedData consumed = creator_.ConsumeData(
kDataStreamId1, &iov_, 1u, iov_.iov_len, 0, FIN_AND_PADDING);
EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed);
- MakeIOVector(QuicStringPiece(buf, kStreamFramePayloadSize), &iov_);
+ MakeIOVector(quiche::QuicheStringPiece(buf, kStreamFramePayloadSize), &iov_);
consumed = creator_.ConsumeData(kDataStreamId2, &iov_, 1u, iov_.iov_len, 0,
FIN_AND_PADDING);
EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed);
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_packet_reader.cc b/chromium/net/third_party/quiche/src/quic/core/quic_packet_reader.cc
index bd46c694cbc..33340423eaf 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_packet_reader.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_packet_reader.cc
@@ -4,57 +4,32 @@
#include "net/third_party/quiche/src/quic/core/quic_packet_reader.h"
-#include <errno.h>
-#ifndef __APPLE__
-// This is a GNU header that is not present on Apple platforms
-#include <features.h>
-#endif
-#include <string.h>
-#include <sys/socket.h>
-
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_process_packet_interface.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_ip_address.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_server_stats.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
-#include "net/quic/platform/impl/quic_socket_utils.h"
-
-#ifndef SO_RXQ_OVFL
-#define SO_RXQ_OVFL 40
-#endif
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
namespace quic {
-QuicPacketReader::QuicPacketReader() {
- Initialize();
-}
-
-void QuicPacketReader::Initialize() {
-#if MMSG_MORE
- // Zero initialize uninitialized memory.
- memset(mmsg_hdr_, 0, sizeof(mmsg_hdr_));
-
- for (int i = 0; i < kNumPacketsPerReadMmsgCall; ++i) {
- packets_[i].iov.iov_base = packets_[i].buf;
- packets_[i].iov.iov_len = sizeof(packets_[i].buf);
- memset(&packets_[i].raw_address, 0, sizeof(packets_[i].raw_address));
- memset(packets_[i].cbuf, 0, sizeof(packets_[i].cbuf));
- memset(packets_[i].buf, 0, sizeof(packets_[i].buf));
-
- msghdr* hdr = &mmsg_hdr_[i].msg_hdr;
- hdr->msg_name = &packets_[i].raw_address;
- hdr->msg_namelen = sizeof(sockaddr_storage);
- hdr->msg_iov = &packets_[i].iov;
- hdr->msg_iovlen = 1;
-
- hdr->msg_control = packets_[i].cbuf;
- hdr->msg_controllen = kCmsgSpaceForReadPacket;
+QuicPacketReader::QuicPacketReader()
+ : read_buffers_(kNumPacketsPerReadMmsgCall),
+ read_results_(kNumPacketsPerReadMmsgCall) {
+ DCHECK_EQ(read_buffers_.size(), read_results_.size());
+ for (size_t i = 0; i < read_results_.size(); ++i) {
+ read_results_[i].packet_buffer.buffer = read_buffers_[i].packet_buffer;
+ read_results_[i].packet_buffer.buffer_len =
+ sizeof(read_buffers_[i].packet_buffer);
+
+ read_results_[i].control_buffer.buffer = read_buffers_[i].control_buffer;
+ read_results_[i].control_buffer.buffer_len =
+ sizeof(read_buffers_[i].control_buffer);
}
-#endif
}
QuicPacketReader::~QuicPacketReader() = default;
@@ -64,168 +39,97 @@ bool QuicPacketReader::ReadAndDispatchPackets(
int port,
const QuicClock& clock,
ProcessPacketInterface* processor,
- QuicPacketCount* packets_dropped) {
-#if MMSG_MORE_NO_ANDROID
- return ReadAndDispatchManyPackets(fd, port, clock, processor,
- packets_dropped);
-#else
- return ReadAndDispatchSinglePacket(fd, port, clock, processor,
- packets_dropped);
-#endif
-}
-
-bool QuicPacketReader::ReadAndDispatchManyPackets(
- int fd,
- int port,
- const QuicClock& clock,
- ProcessPacketInterface* processor,
- QuicPacketCount* packets_dropped) {
-#if MMSG_MORE_NO_ANDROID
- // Re-set the length fields in case recvmmsg has changed them.
- for (int i = 0; i < kNumPacketsPerReadMmsgCall; ++i) {
- DCHECK_LE(kMaxOutgoingPacketSize, packets_[i].iov.iov_len);
- msghdr* hdr = &mmsg_hdr_[i].msg_hdr;
- hdr->msg_namelen = sizeof(sockaddr_storage);
- DCHECK_EQ(1u, hdr->msg_iovlen);
- hdr->msg_controllen = kCmsgSpaceForReadPacket;
- hdr->msg_flags = 0;
+ QuicPacketCount* /*packets_dropped*/) {
+ // Reset all read_results for reuse.
+ for (size_t i = 0; i < read_results_.size(); ++i) {
+ read_results_[i].Reset(
+ /*packet_buffer_length=*/sizeof(read_buffers_[i].packet_buffer));
}
- int packets_read =
- recvmmsg(fd, mmsg_hdr_, kNumPacketsPerReadMmsgCall, MSG_TRUNC, nullptr);
-
- if (packets_read <= 0) {
- return false; // recvmmsg failed.
- }
-
- bool use_quic_time =
- GetQuicReloadableFlag(quic_use_quic_time_for_received_timestamp);
- QuicTime fallback_timestamp(QuicTime::Zero());
- QuicWallTime fallback_walltimestamp = QuicWallTime::Zero();
- for (int i = 0; i < packets_read; ++i) {
- if (mmsg_hdr_[i].msg_len == 0) {
+ // Use clock.Now() as the packet receipt time, the time between packet
+ // arriving at the host and now is considered part of the network delay.
+ QuicTime now = clock.Now();
+
+ size_t packets_read = socket_api_.ReadMultiplePackets(
+ fd,
+ BitMask64(QuicUdpPacketInfoBit::DROPPED_PACKETS,
+ QuicUdpPacketInfoBit::PEER_ADDRESS,
+ QuicUdpPacketInfoBit::V4_SELF_IP,
+ QuicUdpPacketInfoBit::V6_SELF_IP,
+ QuicUdpPacketInfoBit::RECV_TIMESTAMP, QuicUdpPacketInfoBit::TTL,
+ QuicUdpPacketInfoBit::GOOGLE_PACKET_HEADER),
+ &read_results_);
+ for (size_t i = 0; i < packets_read; ++i) {
+ auto& result = read_results_[i];
+ if (!result.ok) {
+ QUIC_CODE_COUNT(quic_packet_reader_read_failure);
continue;
}
- if (QUIC_PREDICT_FALSE(mmsg_hdr_[i].msg_hdr.msg_flags & MSG_CTRUNC)) {
- QUIC_BUG << "Incorrectly set control length: "
- << mmsg_hdr_[i].msg_hdr.msg_controllen << ", expected "
- << kCmsgSpaceForReadPacket;
+ if (!result.packet_info.HasValue(QuicUdpPacketInfoBit::PEER_ADDRESS)) {
+ QUIC_BUG << "Unable to get peer socket address.";
continue;
}
- if (QUIC_PREDICT_FALSE(mmsg_hdr_[i].msg_hdr.msg_flags & MSG_TRUNC)) {
- QUIC_LOG_FIRST_N(WARNING, 100)
- << "Dropping truncated QUIC packet: buffer size:"
- << packets_[i].iov.iov_len << " packet size:" << mmsg_hdr_[i].msg_len;
- QUIC_SERVER_HISTOGRAM_COUNTS(
- "QuicPacketReader.DroppedPacketSize", mmsg_hdr_[i].msg_len, 1, 10000,
- 20, "In QuicPacketReader, the size of big packets that are dropped.");
- continue;
- }
+ QuicSocketAddress peer_address =
+ result.packet_info.peer_address().Normalized();
- QuicSocketAddress peer_address(packets_[i].raw_address);
- QuicIpAddress self_ip;
- QuicWallTime packet_walltimestamp = QuicWallTime::Zero();
- QuicSocketUtils::GetAddressAndTimestampFromMsghdr(
- &mmsg_hdr_[i].msg_hdr, &self_ip, &packet_walltimestamp);
+ QuicIpAddress self_ip = GetSelfIpFromPacketInfo(
+ result.packet_info, peer_address.host().IsIPv6());
if (!self_ip.IsInitialized()) {
QUIC_BUG << "Unable to get self IP address.";
continue;
}
- // This isn't particularly desirable, but not all platforms support socket
- // timestamping.
- QuicTime timestamp(QuicTime::Zero());
- if (!use_quic_time) {
- if (packet_walltimestamp.IsZero()) {
- if (fallback_walltimestamp.IsZero()) {
- fallback_walltimestamp = clock.WallNow();
- }
- packet_walltimestamp = fallback_walltimestamp;
- }
- timestamp = clock.ConvertWallTimeToQuicTime(packet_walltimestamp);
-
- } else {
- QUIC_RELOADABLE_FLAG_COUNT(quic_use_quic_time_for_received_timestamp);
- if (packet_walltimestamp.IsZero()) {
- if (!fallback_timestamp.IsInitialized()) {
- fallback_timestamp = clock.Now();
- }
- timestamp = fallback_timestamp;
- } else {
- timestamp = clock.ConvertWallTimeToQuicTime(packet_walltimestamp);
- }
+ bool has_ttl = result.packet_info.HasValue(QuicUdpPacketInfoBit::TTL);
+ int ttl = has_ttl ? result.packet_info.ttl() : 0;
+ if (!has_ttl) {
+ QUIC_CODE_COUNT(quic_packet_reader_no_ttl);
}
- int ttl = 0;
- bool has_ttl =
- QuicSocketUtils::GetTtlFromMsghdr(&mmsg_hdr_[i].msg_hdr, &ttl);
+
char* headers = nullptr;
size_t headers_length = 0;
- QuicSocketUtils::GetPacketHeadersFromMsghdr(&mmsg_hdr_[i].msg_hdr, &headers,
- &headers_length);
- QuicReceivedPacket packet(reinterpret_cast<char*>(packets_[i].iov.iov_base),
- mmsg_hdr_[i].msg_len, timestamp, false, ttl,
- has_ttl, headers, headers_length, false);
+ if (result.packet_info.HasValue(
+ QuicUdpPacketInfoBit::GOOGLE_PACKET_HEADER)) {
+ headers = result.packet_info.google_packet_headers().buffer;
+ headers_length = result.packet_info.google_packet_headers().buffer_len;
+ } else {
+ QUIC_CODE_COUNT(quic_packet_reader_no_google_packet_header);
+ }
+
+ QuicReceivedPacket packet(
+ result.packet_buffer.buffer, result.packet_buffer.buffer_len, now,
+ /*owns_buffer=*/false, ttl, has_ttl, headers, headers_length,
+ /*owns_header_buffer=*/false);
+
QuicSocketAddress self_address(self_ip, port);
processor->ProcessPacket(self_address, peer_address, packet);
}
- if (packets_dropped != nullptr) {
- QuicSocketUtils::GetOverflowFromMsghdr(&mmsg_hdr_[0].msg_hdr,
- packets_dropped);
- }
-
// We may not have read all of the packets available on the socket.
return packets_read == kNumPacketsPerReadMmsgCall;
-#else
- (void)fd;
- (void)port;
- (void)clock;
- (void)processor;
- (void)packets_dropped;
- QUIC_LOG(FATAL) << "Unsupported";
- return false;
-#endif
}
-/* static */
-bool QuicPacketReader::ReadAndDispatchSinglePacket(
- int fd,
- int port,
- const QuicClock& clock,
- ProcessPacketInterface* processor,
- QuicPacketCount* packets_dropped) {
- char buf[kMaxV4PacketSize];
-
- QuicSocketAddress peer_address;
- QuicIpAddress self_ip;
- QuicWallTime walltimestamp = QuicWallTime::Zero();
- int bytes_read =
- QuicSocketUtils::ReadPacket(fd, buf, QUIC_ARRAYSIZE(buf), packets_dropped,
- &self_ip, &walltimestamp, &peer_address);
- if (bytes_read < 0) {
- return false; // ReadPacket failed.
- }
-
- if (!self_ip.IsInitialized()) {
- QUIC_BUG << "Unable to get self IP address.";
- return false;
- }
- // This isn't particularly desirable, but not all platforms support socket
- // timestamping.
- if (walltimestamp.IsZero()) {
- walltimestamp = clock.WallNow();
+// static
+QuicIpAddress QuicPacketReader::GetSelfIpFromPacketInfo(
+ const QuicUdpPacketInfo& packet_info,
+ bool prefer_v6_ip) {
+ if (prefer_v6_ip) {
+ if (packet_info.HasValue(QuicUdpPacketInfoBit::V6_SELF_IP)) {
+ return packet_info.self_v6_ip();
+ }
+ if (packet_info.HasValue(QuicUdpPacketInfoBit::V4_SELF_IP)) {
+ return packet_info.self_v4_ip();
+ }
+ } else {
+ if (packet_info.HasValue(QuicUdpPacketInfoBit::V4_SELF_IP)) {
+ return packet_info.self_v4_ip();
+ }
+ if (packet_info.HasValue(QuicUdpPacketInfoBit::V6_SELF_IP)) {
+ return packet_info.self_v6_ip();
+ }
}
- QuicTime timestamp = clock.ConvertWallTimeToQuicTime(walltimestamp);
-
- QuicReceivedPacket packet(buf, bytes_read, timestamp, false);
- QuicSocketAddress self_address(self_ip, port);
- processor->ProcessPacket(self_address, peer_address, packet);
-
- // The socket read was successful, so return true even if packet dispatch
- // failed.
- return true;
+ return QuicIpAddress();
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_packet_reader.h b/chromium/net/third_party/quiche/src/quic/core/quic_packet_reader.h
index 1e644aaa07a..86eaa0ee9ad 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_packet_reader.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_packet_reader.h
@@ -7,23 +7,18 @@
#ifndef QUICHE_QUIC_CORE_QUIC_PACKET_READER_H_
#define QUICHE_QUIC_CORE_QUIC_PACKET_READER_H_
-#include <netinet/in.h>
-// Include here to guarantee this header gets included (for MSG_WAITFORONE)
-// regardless of how the below transitive header include set may change.
-#include <sys/socket.h>
-
+#include "net/third_party/quiche/src/quic/core/quic_clock.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_process_packet_interface.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
+#include "net/third_party/quiche/src/quic/core/quic_udp_socket.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_aligned.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
-#include "net/quic/platform/impl/quic_socket_utils.h"
namespace quic {
-#if MMSG_MORE
// Read in larger batches to minimize recvmmsg overhead.
const int kNumPacketsPerReadMmsgCall = 16;
-#endif
class QUIC_EXPORT_PRIVATE QuicPacketReader {
public:
@@ -47,42 +42,24 @@ class QUIC_EXPORT_PRIVATE QuicPacketReader {
QuicPacketCount* packets_dropped);
private:
- // Initialize the internal state of the reader.
- void Initialize();
-
- // Reads and dispatches many packets using recvmmsg.
- bool ReadAndDispatchManyPackets(int fd,
- int port,
- const QuicClock& clock,
- ProcessPacketInterface* processor,
- QuicPacketCount* packets_dropped);
+ // Return the self ip from |packet_info|.
+ // For dual stack sockets, |packet_info| may contain both a v4 and a v6 ip, in
+ // that case, |prefer_v6_ip| is used to determine which one is used as the
+ // return value. If neither v4 nor v6 ip exists, return an uninitialized ip.
+ static QuicIpAddress GetSelfIpFromPacketInfo(
+ const QuicUdpPacketInfo& packet_info,
+ bool prefer_v6_ip);
- // Reads and dispatches a single packet using recvmsg.
- static bool ReadAndDispatchSinglePacket(int fd,
- int port,
- const QuicClock& clock,
- ProcessPacketInterface* processor,
- QuicPacketCount* packets_dropped);
-
-#if MMSG_MORE
- // Storage only used when recvmmsg is available.
- // TODO(danzh): change it to be a pointer to avoid the allocation on the stack
- // from exceeding maximum allowed frame size.
- // packets_ and mmsg_hdr_ are used to supply cbuf and buf to the recvmmsg
- // call.
- struct QUIC_EXPORT_PRIVATE PacketData {
- iovec iov;
- // raw_address is used for address information provided by the recvmmsg
- // call on the packets.
- struct sockaddr_storage raw_address;
- // cbuf is used for ancillary data from the kernel on recvmmsg.
- char cbuf[kCmsgSpaceForReadPacket];
- // buf is used for the data read from the kernel on recvmmsg.
- char buf[kMaxV4PacketSize];
+ struct QUIC_EXPORT_PRIVATE ReadBuffer {
+ QUIC_CACHELINE_ALIGNED char
+ control_buffer[kDefaultUdpPacketControlBufferSize]; // For ancillary
+ // data.
+ QUIC_CACHELINE_ALIGNED char packet_buffer[kMaxIncomingPacketSize];
};
- PacketData packets_[kNumPacketsPerReadMmsgCall];
- mmsghdr mmsg_hdr_[kNumPacketsPerReadMmsgCall];
-#endif
+
+ QuicUdpSocketApi socket_api_;
+ std::vector<ReadBuffer> read_buffers_;
+ QuicUdpSocketApi::ReadPacketResults read_results_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_packet_writer.h b/chromium/net/third_party/quiche/src/quic/core/quic_packet_writer.h
index 5f6b6818979..bd10523e16a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_packet_writer.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_packet_writer.h
@@ -78,6 +78,26 @@ class QUIC_EXPORT_PRIVATE QuicPacketWriter {
//
// Options must be either null, or created for the particular QuicPacketWriter
// implementation. Options may be ignored, depending on the implementation.
+ //
+ // Some comment about memory management if |buffer| was previously acquired
+ // by a call to "GetNextWriteLocation()":
+ //
+ // a) When WRITE_STATUS_OK is returned, the caller expects the writer owns the
+ // packet buffers and they will be released when the write finishes.
+ //
+ // b) When this function returns any status >= WRITE_STATUS_ERROR, the caller
+ // expects the writer releases the buffer (if needed) before the function
+ // returns.
+ //
+ // c) When WRITE_STATUS_BLOCKED is returned, the caller makes a copy of the
+ // buffer and will retry after unblock, so if |payload| is allocated from
+ // GetNextWriteLocation(), it
+ // 1) needs to be released before return, and
+ // 2) the content of |payload| should not change after return.
+ //
+ // d) When WRITE_STATUS_BLOCKED_DATA_BUFFERED is returned, the caller expects
+ // 1) the writer owns the packet buffers, and 2) the writer will re-send the
+ // packet when it unblocks.
virtual WriteResult WritePacket(const char* buffer,
size_t buf_len,
const QuicIpAddress& self_address,
@@ -121,9 +141,13 @@ class QUIC_EXPORT_PRIVATE QuicPacketWriter {
// Try send all buffered packets.
// - Return WriteResult(WRITE_STATUS_OK, <bytes_flushed>) if all buffered
// packets were sent successfully.
- // - Return WRITE_STATUS_BLOCKED, or an error status, if the underlying socket
- // is blocked or returned an error while sending. Some packets may have been
- // sent, packets not sent will stay in the internal buffer.
+ // - Return WRITE_STATUS_BLOCKED if the underlying socket is blocked while
+ // sending. Some packets may have been sent, packets not sent will stay in
+ // the internal buffer.
+ // - Return a status >= WRITE_STATUS_ERROR if an error was encuontered while
+ // sending. As this is not a re-tryable error, any batched packets which
+ // were on memory acquired via GetNextWriteLocation() should be released and
+ // the batch should be dropped.
virtual WriteResult Flush() = 0;
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_packets.cc b/chromium/net/third_party/quiche/src/quic/core/quic_packets.cc
index 87b310e3a26..4123c27f94c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_packets.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_packets.cc
@@ -12,10 +12,10 @@
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
@@ -185,7 +185,7 @@ QuicPacketHeader::QuicPacketHeader()
long_packet_type(INITIAL),
possible_stateless_reset_token(0),
retry_token_length_length(VARIABLE_LENGTH_INTEGER_LENGTH_0),
- retry_token(QuicStringPiece()),
+ retry_token(quiche::QuicheStringPiece()),
length_length(VARIABLE_LENGTH_INTEGER_LENGTH_0),
remaining_packet_length(0) {}
@@ -193,6 +193,9 @@ QuicPacketHeader::QuicPacketHeader(const QuicPacketHeader& other) = default;
QuicPacketHeader::~QuicPacketHeader() {}
+QuicPacketHeader& QuicPacketHeader::operator=(const QuicPacketHeader& other) =
+ default;
+
QuicPublicResetPacket::QuicPublicResetPacket()
: connection_id(EmptyQuicConnectionId()), nonce_proof(0) {}
@@ -234,7 +237,8 @@ std::ostream& operator<<(std::ostream& os, const QuicPacketHeader& header) {
<< (header.source_connection_id_included == CONNECTION_ID_PRESENT
? "present"
: "absent")
- << "), packet_number_length: " << header.packet_number_length
+ << "), packet_number_length: "
+ << static_cast<int>(header.packet_number_length)
<< ", reset_flag: " << header.reset_flag
<< ", version_flag: " << header.version_flag;
if (header.version_flag) {
@@ -259,8 +263,8 @@ std::ostream& operator<<(std::ostream& os, const QuicPacketHeader& header) {
}
if (header.nonce != nullptr) {
os << ", diversification_nonce: "
- << QuicTextUtils::HexEncode(
- QuicStringPiece(header.nonce->data(), header.nonce->size()));
+ << quiche::QuicheTextUtils::HexEncode(quiche::QuicheStringPiece(
+ header.nonce->data(), header.nonce->size()));
}
os << ", packet_number: " << header.packet_number << " }\n";
return os;
@@ -272,7 +276,7 @@ QuicData::QuicData(const char* buffer, size_t length)
QuicData::QuicData(const char* buffer, size_t length, bool owns_buffer)
: buffer_(buffer), length_(length), owns_buffer_(owns_buffer) {}
-QuicData::QuicData(QuicStringPiece packet_data)
+QuicData::QuicData(quiche::QuicheStringPiece packet_data)
: buffer_(packet_data.data()),
length_(packet_data.length()),
owns_buffer_(false) {}
@@ -331,7 +335,7 @@ QuicEncryptedPacket::QuicEncryptedPacket(const char* buffer,
bool owns_buffer)
: QuicData(buffer, length, owns_buffer) {}
-QuicEncryptedPacket::QuicEncryptedPacket(QuicStringPiece data)
+QuicEncryptedPacket::QuicEncryptedPacket(quiche::QuicheStringPiece data)
: QuicData(data) {}
std::unique_ptr<QuicEncryptedPacket> QuicEncryptedPacket::Clone() const {
@@ -422,8 +426,9 @@ std::ostream& operator<<(std::ostream& os, const QuicReceivedPacket& s) {
return os;
}
-QuicStringPiece QuicPacket::AssociatedData(QuicTransportVersion version) const {
- return QuicStringPiece(
+quiche::QuicheStringPiece QuicPacket::AssociatedData(
+ QuicTransportVersion version) const {
+ return quiche::QuicheStringPiece(
data(),
GetStartOfEncryptedData(version, destination_connection_id_length_,
source_connection_id_length_, includes_version_,
@@ -432,13 +437,14 @@ QuicStringPiece QuicPacket::AssociatedData(QuicTransportVersion version) const {
retry_token_length_, length_length_));
}
-QuicStringPiece QuicPacket::Plaintext(QuicTransportVersion version) const {
+quiche::QuicheStringPiece QuicPacket::Plaintext(
+ QuicTransportVersion version) const {
const size_t start_of_encrypted_data = GetStartOfEncryptedData(
version, destination_connection_id_length_, source_connection_id_length_,
includes_version_, includes_diversification_nonce_, packet_number_length_,
retry_token_length_length_, retry_token_length_, length_length_);
- return QuicStringPiece(data() + start_of_encrypted_data,
- length() - start_of_encrypted_data);
+ return quiche::QuicheStringPiece(data() + start_of_encrypted_data,
+ length() - start_of_encrypted_data);
}
SerializedPacket::SerializedPacket(QuicPacketNumber packet_number,
@@ -551,11 +557,11 @@ ReceivedPacketInfo::ReceivedPacketInfo(const QuicSocketAddress& self_address,
ReceivedPacketInfo::~ReceivedPacketInfo() {}
std::string ReceivedPacketInfo::ToString() const {
- std::string output =
- QuicStrCat("{ self_address: ", self_address.ToString(),
- ", peer_address: ", peer_address.ToString(),
- ", packet_length: ", packet.length(),
- ", header_format: ", form, ", version_flag: ", version_flag);
+ std::string output = quiche::QuicheStrCat(
+ "{ self_address: ", self_address.ToString(),
+ ", peer_address: ", peer_address.ToString(),
+ ", packet_length: ", packet.length(), ", header_format: ", form,
+ ", version_flag: ", version_flag);
if (version_flag) {
QuicStrAppend(&output, ", version: ", ParsedQuicVersionToString(version));
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_packets.h b/chromium/net/third_party/quiche/src/quic/core/quic_packets.h
index 93417ac1d48..e8e1931b975 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_packets.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_packets.h
@@ -24,8 +24,8 @@
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_uint128.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -121,6 +121,8 @@ struct QUIC_EXPORT_PRIVATE QuicPacketHeader {
QuicPacketHeader(const QuicPacketHeader& other);
~QuicPacketHeader();
+ QuicPacketHeader& operator=(const QuicPacketHeader& other);
+
QUIC_EXPORT_PRIVATE friend std::ostream& operator<<(
std::ostream& os,
const QuicPacketHeader& header);
@@ -158,7 +160,7 @@ struct QUIC_EXPORT_PRIVATE QuicPacketHeader {
// carried only by v99 IETF Initial packets.
QuicVariableLengthIntegerLength retry_token_length_length;
// Retry token, carried only by v99 IETF Initial packets.
- QuicStringPiece retry_token;
+ quiche::QuicheStringPiece retry_token;
// Length of the length variable length integer field,
// carried only by v99 IETF Initial, 0-RTT and Handshake packets.
QuicVariableLengthIntegerLength length_length;
@@ -209,14 +211,15 @@ class QUIC_EXPORT_PRIVATE QuicData {
// Creates a QuicData from a buffer and length,
// optionally taking ownership of the buffer.
QuicData(const char* buffer, size_t length, bool owns_buffer);
- // Creates a QuicData from a QuicStringPiece. Does not own the buffer.
- QuicData(QuicStringPiece data);
+ // Creates a QuicData from a quiche::QuicheStringPiece. Does not own the
+ // buffer.
+ QuicData(quiche::QuicheStringPiece data);
QuicData(const QuicData&) = delete;
QuicData& operator=(const QuicData&) = delete;
virtual ~QuicData();
- QuicStringPiece AsStringPiece() const {
- return QuicStringPiece(data(), length());
+ quiche::QuicheStringPiece AsStringPiece() const {
+ return quiche::QuicheStringPiece(data(), length());
}
const char* data() const { return buffer_; }
@@ -249,8 +252,8 @@ class QUIC_EXPORT_PRIVATE QuicPacket : public QuicData {
QuicPacket(const QuicPacket&) = delete;
QuicPacket& operator=(const QuicPacket&) = delete;
- QuicStringPiece AssociatedData(QuicTransportVersion version) const;
- QuicStringPiece Plaintext(QuicTransportVersion version) const;
+ quiche::QuicheStringPiece AssociatedData(QuicTransportVersion version) const;
+ quiche::QuicheStringPiece Plaintext(QuicTransportVersion version) const;
char* mutable_data() { return buffer_; }
@@ -274,9 +277,9 @@ class QUIC_EXPORT_PRIVATE QuicEncryptedPacket : public QuicData {
// Creates a QuicEncryptedPacket from a buffer and length,
// optionally taking ownership of the buffer.
QuicEncryptedPacket(const char* buffer, size_t length, bool owns_buffer);
- // Creates a QuicEncryptedPacket from a QuicStringPiece.
+ // Creates a QuicEncryptedPacket from a quiche::QuicheStringPiece.
// Does not own the buffer.
- QuicEncryptedPacket(QuicStringPiece data);
+ QuicEncryptedPacket(quiche::QuicheStringPiece data);
QuicEncryptedPacket(const QuicEncryptedPacket&) = delete;
QuicEncryptedPacket& operator=(const QuicEncryptedPacket&) = delete;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_packets_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_packets_test.cc
index e080cd8265a..1ccaabc0a32 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_packets_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_packets_test.cc
@@ -7,6 +7,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/test_tools/quiche_test_utils.h"
namespace quic {
namespace test {
@@ -97,7 +98,7 @@ TEST_F(QuicPacketsTest, CopySerializedPacket) {
EXPECT_EQ(ACK_FRAME, copy->nonretransmittable_frames[0].type);
EXPECT_EQ(PADDING_FRAME, copy->nonretransmittable_frames[1].type);
EXPECT_EQ(1000u, copy->encrypted_length);
- test::CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"encrypted_buffer", copy->encrypted_buffer, copy->encrypted_length,
packet.encrypted_buffer, packet.encrypted_length);
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager.cc b/chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager.cc
index 908d04fb228..017ae2b1ddd 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager.cc
@@ -12,6 +12,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
#include "net/third_party/quiche/src/quic/core/quic_connection_stats.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
namespace quic {
@@ -50,6 +51,7 @@ QuicReceivedPacketManager::QuicReceivedPacketManager(QuicConnectionStats* stats)
ack_decimation_delay_(kAckDecimationDelay),
unlimited_ack_decimation_(false),
fast_ack_after_quiescence_(false),
+ one_immediate_ack_(false),
local_max_ack_delay_(
QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs)),
ack_timeout_(QuicTime::Zero()),
@@ -88,6 +90,9 @@ void QuicReceivedPacketManager::SetFromConfig(const QuicConfig& config,
if (config.HasClientSentConnectionOption(kACKQ, perspective)) {
fast_ack_after_quiescence_ = true;
}
+ if (config.HasClientSentConnectionOption(k1ACK, perspective)) {
+ one_immediate_ack_ = true;
+ }
}
void QuicReceivedPacketManager::RecordPacketReceived(
@@ -245,12 +250,16 @@ void QuicReceivedPacketManager::MaybeUpdateAckTimeout(
// before sending an ack.
QuicTime::Delta ack_delay = std::min(
local_max_ack_delay_, rtt_stats->min_rtt() * ack_decimation_delay_);
+ if (GetQuicReloadableFlag(quic_ack_delay_alarm_granularity)) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_ack_delay_alarm_granularity);
+ ack_delay = std::max(ack_delay, kAlarmGranularity);
+ }
if (fast_ack_after_quiescence_ && now - time_of_previous_received_packet_ >
rtt_stats->SmoothedOrInitialRtt()) {
// Ack the first packet out of queiscence faster, because QUIC does
// not pace the first few packets and commonly these may be handshake
// or TLP packets, which we'd like to acknowledge quickly.
- ack_delay = QuicTime::Delta::FromMilliseconds(1);
+ ack_delay = kAlarmGranularity;
}
MaybeUpdateAckTimeoutTo(now + ack_delay);
} else {
@@ -264,7 +273,7 @@ void QuicReceivedPacketManager::MaybeUpdateAckTimeout(
// Ack the first packet out of queiscence faster, because QUIC does
// not pace the first few packets and commonly these may be handshake
// or TLP packets, which we'd like to acknowledge quickly.
- MaybeUpdateAckTimeoutTo(now + QuicTime::Delta::FromMilliseconds(1));
+ MaybeUpdateAckTimeoutTo(now + kAlarmGranularity);
} else {
MaybeUpdateAckTimeoutTo(now + local_max_ack_delay_);
}
@@ -311,6 +320,9 @@ bool QuicReceivedPacketManager::HasMissingPackets() const {
}
bool QuicReceivedPacketManager::HasNewMissingPackets() const {
+ if (one_immediate_ack_) {
+ return HasMissingPackets() && ack_frame_.packets.LastIntervalLength() == 1;
+ }
return HasMissingPackets() &&
ack_frame_.packets.LastIntervalLength() <= kMaxPacketsAfterNewMissing;
}
@@ -332,4 +344,8 @@ QuicPacketNumber QuicReceivedPacketManager::PeerFirstSendingPacketNumber()
return least_received_packet_number_;
}
+bool QuicReceivedPacketManager::IsAckFrameEmpty() const {
+ return ack_frame_.packets.Empty();
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager.h b/chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager.h
index 293b03cf4db..b01390d1d59 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager.h
@@ -90,6 +90,9 @@ class QUIC_EXPORT_PRIVATE QuicReceivedPacketManager {
// received.
QuicPacketNumber PeerFirstSendingPacketNumber() const;
+ // Returns true if ack frame is empty.
+ bool IsAckFrameEmpty() const;
+
void set_connection_stats(QuicConnectionStats* stats) { stats_ = stats; }
// For logging purposes.
@@ -175,6 +178,8 @@ class QUIC_EXPORT_PRIVATE QuicReceivedPacketManager {
// When true, use a 1ms delayed ack timer if it's been an SRTT since a packet
// was received.
bool fast_ack_after_quiescence_;
+ // When true, only send 1 immediate ACK when reordering is detected.
+ bool one_immediate_ack_;
// The local node's maximum ack delay time. This is the maximum amount of
// time to wait before sending an acknowledgement.
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager_test.cc
index 9ce50dd31fb..bfdf33891cd 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager_test.cc
@@ -11,7 +11,9 @@
#include "net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
#include "net/third_party/quiche/src/quic/core/quic_connection_stats.h"
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
@@ -29,6 +31,11 @@ class QuicReceivedPacketManagerPeer {
manager->fast_ack_after_quiescence_ = fast_ack_after_quiescence;
}
+ static void SetOneImmediateAck(QuicReceivedPacketManager* manager,
+ bool one_immediate_ack) {
+ manager->one_immediate_ack_ = one_immediate_ack;
+ }
+
static void SetAckDecimationDelay(QuicReceivedPacketManager* manager,
float ack_decimation_delay) {
manager->ack_decimation_delay_ = ack_decimation_delay;
@@ -94,7 +101,8 @@ class QuicReceivedPacketManagerTest : public QuicTestWithParam<TestParams> {
}
void CheckAckTimeout(QuicTime time) {
- DCHECK(HasPendingAck() && received_manager_.ack_timeout() == time);
+ DCHECK(HasPendingAck());
+ DCHECK_EQ(received_manager_.ack_timeout(), time);
if (time <= clock_.ApproximateNow()) {
// ACK timeout expires, send an ACK.
received_manager_.ResetAckStates();
@@ -244,6 +252,16 @@ TEST_P(QuicReceivedPacketManagerTest, OutOfOrderReceiptCausesAckSent) {
// Delayed ack is scheduled.
CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime);
+ RecordPacketReceipt(5, clock_.ApproximateNow());
+ MaybeUpdateAckTimeout(kInstigateAck, 5);
+ // Immediate ack is sent.
+ CheckAckTimeout(clock_.ApproximateNow());
+
+ RecordPacketReceipt(6, clock_.ApproximateNow());
+ MaybeUpdateAckTimeout(kInstigateAck, 6);
+ // Immediate ack is scheduled, because 4 is still missing.
+ CheckAckTimeout(clock_.ApproximateNow());
+
RecordPacketReceipt(2, clock_.ApproximateNow());
MaybeUpdateAckTimeout(kInstigateAck, 2);
CheckAckTimeout(clock_.ApproximateNow());
@@ -253,10 +271,44 @@ TEST_P(QuicReceivedPacketManagerTest, OutOfOrderReceiptCausesAckSent) {
// Should ack immediately, since this fills the last hole.
CheckAckTimeout(clock_.ApproximateNow());
- RecordPacketReceipt(4, clock_.ApproximateNow());
- MaybeUpdateAckTimeout(kInstigateAck, 4);
+ RecordPacketReceipt(7, clock_.ApproximateNow());
+ MaybeUpdateAckTimeout(kInstigateAck, 7);
+ // Immediate ack is scheduled, because 4 is still missing.
+ CheckAckTimeout(clock_.ApproximateNow());
+}
+
+TEST_P(QuicReceivedPacketManagerTest, OutOfOrderReceiptCausesAckSent1Ack) {
+ QuicReceivedPacketManagerPeer::SetOneImmediateAck(&received_manager_, true);
+ EXPECT_FALSE(HasPendingAck());
+
+ RecordPacketReceipt(3, clock_.ApproximateNow());
+ MaybeUpdateAckTimeout(kInstigateAck, 3);
// Delayed ack is scheduled.
CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime);
+
+ RecordPacketReceipt(5, clock_.ApproximateNow());
+ MaybeUpdateAckTimeout(kInstigateAck, 5);
+ // Immediate ack is sent.
+ CheckAckTimeout(clock_.ApproximateNow());
+
+ RecordPacketReceipt(6, clock_.ApproximateNow());
+ MaybeUpdateAckTimeout(kInstigateAck, 6);
+ // Delayed ack is scheduled.
+ CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime);
+
+ RecordPacketReceipt(2, clock_.ApproximateNow());
+ MaybeUpdateAckTimeout(kInstigateAck, 2);
+ CheckAckTimeout(clock_.ApproximateNow());
+
+ RecordPacketReceipt(1, clock_.ApproximateNow());
+ MaybeUpdateAckTimeout(kInstigateAck, 1);
+ // Should ack immediately, since this fills the last hole.
+ CheckAckTimeout(clock_.ApproximateNow());
+
+ RecordPacketReceipt(7, clock_.ApproximateNow());
+ MaybeUpdateAckTimeout(kInstigateAck, 7);
+ // Delayed ack is scheduled, even though 4 is still missing.
+ CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime);
}
TEST_P(QuicReceivedPacketManagerTest, OutOfOrderAckReceiptCausesNoAck) {
@@ -414,6 +466,43 @@ TEST_P(QuicReceivedPacketManagerTest, SendDelayedAckDecimation) {
CheckAckTimeout(clock_.ApproximateNow());
}
+TEST_P(QuicReceivedPacketManagerTest, SendDelayedAckDecimationMin1ms) {
+ if (!GetQuicReloadableFlag(quic_ack_delay_alarm_granularity)) {
+ return;
+ }
+ EXPECT_FALSE(HasPendingAck());
+ QuicReceivedPacketManagerPeer::SetAckMode(&received_manager_, ACK_DECIMATION);
+ // Seed the min_rtt with a kAlarmGranularity signal.
+ rtt_stats_.UpdateRtt(kAlarmGranularity, QuicTime::Delta::Zero(),
+ clock_.ApproximateNow());
+ // The ack time should be based on kAlarmGranularity, since the RTT is 1ms.
+ QuicTime ack_time = clock_.ApproximateNow() + kAlarmGranularity;
+
+ // Process all the packets in order so there aren't missing packets.
+ uint64_t kFirstDecimatedPacket = 101;
+ for (uint64_t i = 1; i < kFirstDecimatedPacket; ++i) {
+ RecordPacketReceipt(i, clock_.ApproximateNow());
+ MaybeUpdateAckTimeout(kInstigateAck, i);
+ if (i % 2 == 0) {
+ // Ack every 2 packets by default.
+ CheckAckTimeout(clock_.ApproximateNow());
+ } else {
+ CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime);
+ }
+ }
+
+ RecordPacketReceipt(kFirstDecimatedPacket, clock_.ApproximateNow());
+ MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket);
+ CheckAckTimeout(ack_time);
+
+ // The 10th received packet causes an ack to be sent.
+ for (uint64_t i = 1; i < 10; ++i) {
+ RecordPacketReceipt(kFirstDecimatedPacket + i, clock_.ApproximateNow());
+ MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + i);
+ }
+ CheckAckTimeout(clock_.ApproximateNow());
+}
+
TEST_P(QuicReceivedPacketManagerTest,
SendDelayedAckAckDecimationAfterQuiescence) {
EXPECT_FALSE(HasPendingAck());
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.cc b/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.cc
index bd0343bdb51..0de1dadf17c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.cc
@@ -32,6 +32,9 @@ static const size_t kMaxRetransmissionsOnTimeout = 2;
// The path degrading delay is the sum of this number of consecutive RTO delays.
const size_t kNumRetransmissionDelaysForPathDegradingDelay = 2;
+// The blachkhole delay is the sum of this number of consecutive RTO delays.
+const size_t kNumRetransmissionDelaysForBlackholeDelay = 5;
+
// Ensure the handshake timer isnt't faster than 10ms.
// This limits the tenth retransmitted packet to 10s after the initial CHLO.
static const int64_t kMinHandshakeTimeoutMs = 10;
@@ -66,8 +69,7 @@ QuicSentPacketManager::QuicSentPacketManager(
const QuicClock* clock,
QuicRandom* random,
QuicConnectionStats* stats,
- CongestionControlType congestion_control_type,
- LossDetectionType loss_type)
+ CongestionControlType congestion_control_type)
: unacked_packets_(perspective),
clock_(clock),
random_(random),
@@ -76,7 +78,6 @@ QuicSentPacketManager::QuicSentPacketManager(
network_change_visitor_(nullptr),
initial_congestion_window_(kInitialCongestionWindow),
loss_algorithm_(GetInitialLossAlgorithm()),
- uber_loss_algorithm_(loss_type),
consecutive_rto_count_(0),
consecutive_tlp_count_(0),
consecutive_crypto_retransmission_count_(0),
@@ -92,7 +93,7 @@ QuicSentPacketManager::QuicSentPacketManager(
min_rto_timeout_(
QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs)),
largest_mtu_acked_(0),
- handshake_state_(HANDSHAKE_START),
+ handshake_finished_(false),
peer_max_ack_delay_(
QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs)),
rtt_updated_(false),
@@ -105,8 +106,11 @@ QuicSentPacketManager::QuicSentPacketManager(
always_include_max_ack_delay_for_pto_timeout_(true),
pto_exponential_backoff_start_point_(0),
pto_rttvar_multiplier_(4),
- neuter_handshake_packets_once_(
- GetQuicReloadableFlag(quic_neuter_handshake_packets_once2)) {
+ num_tlp_timeout_ptos_(0),
+ one_rtt_packet_acked_(false),
+ one_rtt_packet_sent_(false),
+ first_pto_srtt_multiplier_(0),
+ use_standard_deviation_for_pto_(false) {
SetSendAlgorithm(congestion_control_type);
}
@@ -141,28 +145,22 @@ void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) {
}
if (config.HasClientSentConnectionOption(kMAD2, perspective)) {
// Set the minimum to the alarm granularity.
- min_tlp_timeout_ = QuicTime::Delta::FromMilliseconds(1);
+ min_tlp_timeout_ = kAlarmGranularity;
}
if (config.HasClientSentConnectionOption(kMAD3, perspective)) {
// Set the minimum to the alarm granularity.
- min_rto_timeout_ = QuicTime::Delta::FromMilliseconds(1);
+ min_rto_timeout_ = kAlarmGranularity;
}
- if (GetQuicReloadableFlag(quic_enable_pto)) {
- if (config.HasClientSentConnectionOption(k2PTO, perspective)) {
- pto_enabled_ = true;
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_pto, 2, 8);
- }
- if (config.HasClientSentConnectionOption(k1PTO, perspective)) {
- pto_enabled_ = true;
- max_probe_packets_per_pto_ = 1;
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_pto, 1, 8);
- }
+ if (config.HasClientSentConnectionOption(k2PTO, perspective)) {
+ pto_enabled_ = true;
+ }
+ if (config.HasClientSentConnectionOption(k1PTO, perspective)) {
+ pto_enabled_ = true;
+ max_probe_packets_per_pto_ = 1;
}
- if (GetQuicReloadableFlag(quic_skip_packet_number_for_pto) &&
- config.HasClientSentConnectionOption(kPTOS, perspective)) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_skip_packet_number_for_pto);
+ if (config.HasClientSentConnectionOption(kPTOS, perspective)) {
if (!pto_enabled_) {
QUIC_PEER_BUG
<< "PTO is not enabled when receiving PTOS connection option.";
@@ -174,21 +172,43 @@ void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) {
if (pto_enabled_) {
if (config.HasClientSentConnectionOption(kPTOA, perspective)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_pto, 5, 8);
always_include_max_ack_delay_for_pto_timeout_ = false;
}
if (config.HasClientSentConnectionOption(kPEB1, perspective)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_pto, 6, 8);
StartExponentialBackoffAfterNthPto(1);
}
if (config.HasClientSentConnectionOption(kPEB2, perspective)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_pto, 7, 8);
StartExponentialBackoffAfterNthPto(2);
}
if (config.HasClientSentConnectionOption(kPVS1, perspective)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_pto, 8, 8);
pto_rttvar_multiplier_ = 2;
}
+ if (config.HasClientSentConnectionOption(kPAG1, perspective)) {
+ QUIC_CODE_COUNT(one_aggressive_pto);
+ num_tlp_timeout_ptos_ = 1;
+ }
+ if (config.HasClientSentConnectionOption(kPAG2, perspective)) {
+ QUIC_CODE_COUNT(two_aggressive_ptos);
+ num_tlp_timeout_ptos_ = 2;
+ }
+ if (GetQuicReloadableFlag(quic_arm_pto_with_earliest_sent_time)) {
+ if (config.HasClientSentConnectionOption(kPLE1, perspective) ||
+ config.HasClientSentConnectionOption(kTLPR, perspective)) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_arm_pto_with_earliest_sent_time, 1,
+ 2);
+ first_pto_srtt_multiplier_ = 0.5;
+ } else if (config.HasClientSentConnectionOption(kPLE2, perspective)) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_arm_pto_with_earliest_sent_time, 2,
+ 2);
+ first_pto_srtt_multiplier_ = 1.5;
+ }
+ }
+ if (GetQuicReloadableFlag(quic_use_standard_deviation_for_pto) &&
+ config.HasClientSentConnectionOption(kPSDA, perspective)) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_use_standard_deviation_for_pto);
+ use_standard_deviation_for_pto_ = true;
+ rtt_stats_.EnableStandardDeviationCalculation();
+ }
}
// Configure congestion control.
@@ -231,6 +251,11 @@ void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) {
send_algorithm_->SetInitialCongestionWindowInPackets(50);
}
}
+ if (GetQuicReloadableFlag(quic_bbr_mitigate_overly_large_bandwidth_sample) &&
+ config.HasClientRequestedIndependentOption(kBWS5, perspective)) {
+ initial_congestion_window_ = 10;
+ send_algorithm_->SetInitialCongestionWindowInPackets(10);
+ }
using_pacing_ = !GetQuicFlag(FLAGS_quic_disable_pacing_for_perf_tests);
@@ -250,43 +275,33 @@ void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) {
use_new_rto_ = true;
}
// Configure loss detection.
- if (config.HasClientRequestedIndependentOption(kTIME, perspective)) {
- uber_loss_algorithm_.SetLossDetectionType(kTime);
- }
- if (config.HasClientRequestedIndependentOption(kATIM, perspective)) {
- uber_loss_algorithm_.SetLossDetectionType(kAdaptiveTime);
- }
- if (config.HasClientRequestedIndependentOption(kLFAK, perspective)) {
- uber_loss_algorithm_.SetLossDetectionType(kLazyFack);
- }
- if (GetQuicReloadableFlag(quic_enable_ietf_loss_detection)) {
- if (config.HasClientRequestedIndependentOption(kILD0, perspective)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_ietf_loss_detection, 1, 5);
- uber_loss_algorithm_.SetLossDetectionType(kIetfLossDetection);
- }
- if (config.HasClientRequestedIndependentOption(kILD1, perspective)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_ietf_loss_detection, 2, 5);
- uber_loss_algorithm_.SetLossDetectionType(kIetfLossDetection);
- uber_loss_algorithm_.SetReorderingShift(kDefaultLossDelayShift);
- }
- if (config.HasClientRequestedIndependentOption(kILD2, perspective)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_ietf_loss_detection, 3, 5);
- uber_loss_algorithm_.SetLossDetectionType(kIetfLossDetection);
- uber_loss_algorithm_.EnableAdaptiveReorderingThreshold();
- }
- if (config.HasClientRequestedIndependentOption(kILD3, perspective)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_ietf_loss_detection, 4, 5);
- uber_loss_algorithm_.SetLossDetectionType(kIetfLossDetection);
- uber_loss_algorithm_.SetReorderingShift(kDefaultLossDelayShift);
- uber_loss_algorithm_.EnableAdaptiveReorderingThreshold();
- }
- if (config.HasClientRequestedIndependentOption(kILD4, perspective)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_ietf_loss_detection, 5, 5);
- uber_loss_algorithm_.SetLossDetectionType(kIetfLossDetection);
- uber_loss_algorithm_.SetReorderingShift(kDefaultLossDelayShift);
- uber_loss_algorithm_.EnableAdaptiveReorderingThreshold();
- uber_loss_algorithm_.EnableAdaptiveTimeThreshold();
- }
+ if (config.HasClientRequestedIndependentOption(kILD0, perspective)) {
+ uber_loss_algorithm_.SetReorderingShift(kDefaultIetfLossDelayShift);
+ uber_loss_algorithm_.DisableAdaptiveReorderingThreshold();
+ }
+ if (config.HasClientRequestedIndependentOption(kILD1, perspective)) {
+ uber_loss_algorithm_.SetReorderingShift(kDefaultLossDelayShift);
+ uber_loss_algorithm_.DisableAdaptiveReorderingThreshold();
+ }
+ if (config.HasClientRequestedIndependentOption(kILD2, perspective)) {
+ uber_loss_algorithm_.EnableAdaptiveReorderingThreshold();
+ uber_loss_algorithm_.SetReorderingShift(kDefaultIetfLossDelayShift);
+ }
+ if (config.HasClientRequestedIndependentOption(kILD3, perspective)) {
+ uber_loss_algorithm_.SetReorderingShift(kDefaultLossDelayShift);
+ uber_loss_algorithm_.EnableAdaptiveReorderingThreshold();
+ }
+ if (config.HasClientRequestedIndependentOption(kILD4, perspective)) {
+ uber_loss_algorithm_.SetReorderingShift(kDefaultLossDelayShift);
+ uber_loss_algorithm_.EnableAdaptiveReorderingThreshold();
+ uber_loss_algorithm_.EnableAdaptiveTimeThreshold();
+ }
+ if (GetQuicReloadableFlag(
+ quic_skip_packet_threshold_loss_detection_with_runt) &&
+ config.HasClientRequestedIndependentOption(kRUNT, perspective)) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(
+ quic_skip_packet_threshold_loss_detection_with_runt, 1, 2);
+ uber_loss_algorithm_.DisablePacketThresholdForRuntPackets();
}
if (config.HasClientSentConnectionOption(kCONH, perspective)) {
conservative_handshake_retransmits_ = true;
@@ -335,19 +350,29 @@ void QuicSentPacketManager::AdjustNetworkParameters(
}
}
+void QuicSentPacketManager::SetLossDetectionTuner(
+ std::unique_ptr<LossDetectionTunerInterface> tuner) {
+ uber_loss_algorithm_.SetLossDetectionTuner(std::move(tuner));
+}
+
+void QuicSentPacketManager::OnConfigNegotiated() {
+ loss_algorithm_->OnConfigNegotiated();
+}
+
+void QuicSentPacketManager::OnConnectionClosed() {
+ loss_algorithm_->OnConnectionClosed();
+}
+
void QuicSentPacketManager::SetHandshakeConfirmed() {
- if (!neuter_handshake_packets_once_ ||
- handshake_state_ < HANDSHAKE_COMPLETE) {
- if (neuter_handshake_packets_once_) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_neuter_handshake_packets_once2, 1, 3);
- }
- handshake_state_ = HANDSHAKE_COMPLETE;
+ if (!handshake_finished_) {
+ handshake_finished_ = true;
NeuterHandshakePackets();
}
}
void QuicSentPacketManager::PostProcessNewlyAckedPackets(
QuicPacketNumber ack_packet_number,
+ EncryptionLevel ack_decrypted_level,
const QuicAckFrame& ack_frame,
QuicTime ack_receive_time,
bool rtt_updated,
@@ -392,9 +417,9 @@ void QuicSentPacketManager::PostProcessNewlyAckedPackets(
}
if (debug_delegate_ != nullptr) {
- debug_delegate_->OnIncomingAck(ack_packet_number, ack_frame,
- ack_receive_time, LargestAcked(ack_frame),
- rtt_updated, GetLeastUnacked());
+ debug_delegate_->OnIncomingAck(
+ ack_packet_number, ack_decrypted_level, ack_frame, ack_receive_time,
+ LargestAcked(ack_frame), rtt_updated, GetLeastUnacked());
}
// Remove packets below least unacked from all_packets_acked_ and
// last_ack_frame_.
@@ -450,42 +475,33 @@ void QuicSentPacketManager::RetransmitUnackedPackets(
}
void QuicSentPacketManager::NeuterUnencryptedPackets() {
- QuicPacketNumber packet_number = unacked_packets_.GetLeastUnacked();
- for (QuicUnackedPacketMap::iterator it = unacked_packets_.begin();
- it != unacked_packets_.end(); ++it, ++packet_number) {
- if (!it->retransmittable_frames.empty() &&
- it->encryption_level == ENCRYPTION_INITIAL) {
- // Once the connection swithes to forward secure, no unencrypted packets
- // will be sent. The data has been abandoned in the cryto stream. Remove
- // it from in flight.
- unacked_packets_.RemoveFromInFlight(packet_number);
- if (neuter_handshake_packets_once_) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_neuter_handshake_packets_once2, 2, 3);
- it->state = NEUTERED;
- DCHECK(!unacked_packets_.HasRetransmittableFrames(*it));
- }
+ for (QuicPacketNumber packet_number :
+ unacked_packets_.NeuterUnencryptedPackets()) {
+ if (avoid_overestimate_bandwidth_with_aggregation_) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(
+ quic_avoid_overestimate_bandwidth_with_aggregation, 1, 4);
+ send_algorithm_->OnPacketNeutered(packet_number);
}
}
+ if (handshake_mode_disabled_) {
+ consecutive_pto_count_ = 0;
+ uber_loss_algorithm_.ResetLossDetection(INITIAL_DATA);
+ }
}
void QuicSentPacketManager::NeuterHandshakePackets() {
- QuicPacketNumber packet_number = unacked_packets_.GetLeastUnacked();
- for (QuicUnackedPacketMap::iterator it = unacked_packets_.begin();
- it != unacked_packets_.end(); ++it, ++packet_number) {
- if (!it->retransmittable_frames.empty() &&
- unacked_packets_.GetPacketNumberSpace(it->encryption_level) ==
- HANDSHAKE_DATA) {
- unacked_packets_.RemoveFromInFlight(packet_number);
- if (neuter_handshake_packets_once_) {
- // Notify session that the data has been delivered (but do not notify
- // send algorithm).
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_neuter_handshake_packets_once2, 3, 3);
- it->state = NEUTERED;
- unacked_packets_.NotifyFramesAcked(*it, QuicTime::Delta::Zero(),
- QuicTime::Zero());
- }
+ for (QuicPacketNumber packet_number :
+ unacked_packets_.NeuterHandshakePackets()) {
+ if (avoid_overestimate_bandwidth_with_aggregation_) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(
+ quic_avoid_overestimate_bandwidth_with_aggregation, 2, 4);
+ send_algorithm_->OnPacketNeutered(packet_number);
}
}
+ if (handshake_mode_disabled_) {
+ consecutive_pto_count_ = 0;
+ uber_loss_algorithm_.ResetLossDetection(HANDSHAKE_DATA);
+ }
}
bool QuicSentPacketManager::ShouldAddMaxAckDelay() const {
@@ -519,6 +535,40 @@ bool QuicSentPacketManager::ShouldAddMaxAckDelay() const {
return true;
}
+QuicTime QuicSentPacketManager::GetEarliestPacketSentTimeForPto(
+ PacketNumberSpace* packet_number_space) const {
+ DCHECK(supports_multiple_packet_number_spaces());
+ QuicTime earliest_sent_time = QuicTime::Zero();
+ for (int8_t i = 0; i < NUM_PACKET_NUMBER_SPACES; ++i) {
+ const QuicTime sent_time = unacked_packets_.GetLastInFlightPacketSentTime(
+ static_cast<PacketNumberSpace>(i));
+ if (!ShouldArmPtoForApplicationData() && i == APPLICATION_DATA) {
+ continue;
+ }
+ if (!sent_time.IsInitialized() || (earliest_sent_time.IsInitialized() &&
+ earliest_sent_time <= sent_time)) {
+ continue;
+ }
+ earliest_sent_time = sent_time;
+ *packet_number_space = static_cast<PacketNumberSpace>(i);
+ }
+
+ return earliest_sent_time;
+}
+
+bool QuicSentPacketManager::ShouldArmPtoForApplicationData() const {
+ DCHECK(supports_multiple_packet_number_spaces());
+ // Application data must be ignored before handshake completes (1-RTT key
+ // is available). Not arming PTO for application data to prioritize the
+ // completion of handshake. On the server side, handshake_finished_
+ // indicates handshake complete (and confirmed). On the client side,
+ // one_rtt_packet_sent_ indicates handshake complete (while handshake
+ // confirmation will happen later).
+ return handshake_finished_ ||
+ (unacked_packets_.perspective() == Perspective::IS_CLIENT &&
+ one_rtt_packet_sent_);
+}
+
void QuicSentPacketManager::MarkForRetransmission(
QuicPacketNumber packet_number,
TransmissionType transmission_type) {
@@ -624,6 +674,7 @@ void QuicSentPacketManager::MarkPacketHandled(QuicPacketNumber packet_number,
loss_algorithm_->SpuriousLossDetected(unacked_packets_, rtt_stats_,
ack_receive_time, packet_number,
previous_largest_acked);
+ ++stats_->packet_spuriously_detected_lost;
}
if (network_change_visitor_ != nullptr &&
@@ -661,6 +712,10 @@ bool QuicSentPacketManager::OnPacketSent(
serialized_packet->encrypted_length, has_retransmittable_data);
}
+ if (serialized_packet->encryption_level == ENCRYPTION_FORWARD_SECURE) {
+ one_rtt_packet_sent_ = true;
+ }
+
unacked_packets_.AddSentPacket(serialized_packet, transmission_type,
sent_time, in_flight);
// Reset the retransmission timer anytime a pending packet is sent.
@@ -670,7 +725,7 @@ bool QuicSentPacketManager::OnPacketSent(
QuicSentPacketManager::RetransmissionTimeoutMode
QuicSentPacketManager::OnRetransmissionTimeout() {
DCHECK(unacked_packets_.HasInFlightPackets() ||
- (handshake_mode_disabled_ && handshake_state_ < HANDSHAKE_COMPLETE));
+ (handshake_mode_disabled_ && !handshake_finished_));
DCHECK_EQ(0u, pending_timer_transmission_count_);
// Handshake retransmission, timer based loss detection, TLP, and RTO are
// implemented with a single alarm. The handshake alarm is set when the
@@ -775,7 +830,7 @@ void QuicSentPacketManager::RetransmitRtoPackets() {
if (it->state == OUTSTANDING &&
unacked_packets_.HasRetransmittableFrames(*it) &&
pending_timer_transmission_count_ < max_rto_packets_) {
- DCHECK(!neuter_handshake_packets_once_ || it->in_flight);
+ DCHECK(it->in_flight);
retransmissions.push_back(packet_number);
++pending_timer_transmission_count_;
}
@@ -802,13 +857,26 @@ void QuicSentPacketManager::MaybeSendProbePackets() {
if (pending_timer_transmission_count_ == 0) {
return;
}
+ PacketNumberSpace packet_number_space;
+ if (supports_multiple_packet_number_spaces()) {
+ // Find out the packet number space to send probe packets.
+ if (!GetEarliestPacketSentTimeForPto(&packet_number_space)
+ .IsInitialized()) {
+ QUIC_BUG << "earlist_sent_time not initialized when trying to send PTO "
+ "retransmissions";
+ return;
+ }
+ }
QuicPacketNumber packet_number = unacked_packets_.GetLeastUnacked();
std::vector<QuicPacketNumber> probing_packets;
for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin();
it != unacked_packets_.end(); ++it, ++packet_number) {
if (it->state == OUTSTANDING &&
- unacked_packets_.HasRetransmittableFrames(*it)) {
- DCHECK(!neuter_handshake_packets_once_ || it->in_flight);
+ unacked_packets_.HasRetransmittableFrames(*it) &&
+ (!supports_multiple_packet_number_spaces() ||
+ unacked_packets_.GetPacketNumberSpace(it->encryption_level) ==
+ packet_number_space)) {
+ DCHECK(it->in_flight);
probing_packets.push_back(packet_number);
if (probing_packets.size() == pending_timer_transmission_count_) {
break;
@@ -837,7 +905,12 @@ void QuicSentPacketManager::AdjustPendingTimerTransmissions() {
void QuicSentPacketManager::EnableIetfPtoAndLossDetection() {
pto_enabled_ = true;
handshake_mode_disabled_ = true;
- uber_loss_algorithm_.SetLossDetectionType(kIetfLossDetection);
+ // Default to 1 packet per PTO and skip a packet number. Arm the 1st PTO with
+ // max of earliest in flight sent time + PTO delay and 1.5 * srtt from
+ // last in flight packet.
+ max_probe_packets_per_pto_ = 1;
+ skip_packet_number_for_pto_ = true;
+ first_pto_srtt_multiplier_ = 1.5;
}
void QuicSentPacketManager::StartExponentialBackoffAfterNthPto(
@@ -848,8 +921,8 @@ void QuicSentPacketManager::StartExponentialBackoffAfterNthPto(
QuicSentPacketManager::RetransmissionTimeoutMode
QuicSentPacketManager::GetRetransmissionMode() const {
DCHECK(unacked_packets_.HasInFlightPackets() ||
- (handshake_mode_disabled_ && handshake_state_ < HANDSHAKE_COMPLETE));
- if (!handshake_mode_disabled_ && handshake_state_ < HANDSHAKE_COMPLETE &&
+ (handshake_mode_disabled_ && !handshake_finished_));
+ if (!handshake_mode_disabled_ && !handshake_finished_ &&
unacked_packets_.HasPendingCryptoPackets()) {
return HANDSHAKE_MODE;
}
@@ -877,12 +950,20 @@ void QuicSentPacketManager::InvokeLossDetection(QuicTime time) {
largest_newly_acked_, packets_acked_,
&packets_lost_);
for (const LostPacket& packet : packets_lost_) {
+ QuicTransmissionInfo* info =
+ unacked_packets_.GetMutableTransmissionInfo(packet.packet_number);
++stats_->packets_lost;
+ if (time > info->sent_time) {
+ stats_->total_loss_detection_time =
+ stats_->total_loss_detection_time + (time - info->sent_time);
+ }
if (debug_delegate_ != nullptr) {
- debug_delegate_->OnPacketLoss(packet.packet_number, LOSS_RETRANSMISSION,
+ debug_delegate_->OnPacketLoss(packet.packet_number,
+ info->encryption_level, LOSS_RETRANSMISSION,
time);
}
- unacked_packets_.RemoveFromInFlight(packet.packet_number);
+ unacked_packets_.RemoveFromInFlight(info);
+
MarkForRetransmission(packet.packet_number, LOSS_RETRANSMISSION);
}
}
@@ -910,8 +991,13 @@ bool QuicSentPacketManager::MaybeUpdateRTT(QuicPacketNumber largest_acked,
}
QuicTime::Delta send_delta = ack_receive_time - transmission_info.sent_time;
+ const bool min_rtt_available = !rtt_stats_.min_rtt().IsZero();
rtt_stats_.UpdateRtt(send_delta, ack_delay_time, ack_receive_time);
+ if (!min_rtt_available && !rtt_stats_.min_rtt().IsZero()) {
+ loss_algorithm_->OnMinRttAvailable();
+ }
+
return true;
}
@@ -934,7 +1020,7 @@ QuicTime::Delta QuicSentPacketManager::TimeUntilSend(QuicTime now) const {
const QuicTime QuicSentPacketManager::GetRetransmissionTime() const {
if (!unacked_packets_.HasInFlightPackets() &&
- (!handshake_mode_disabled_ || handshake_state_ >= HANDSHAKE_COMPLETE ||
+ (!handshake_mode_disabled_ || handshake_finished_ ||
unacked_packets_.perspective() == Perspective::IS_SERVER)) {
// Do not set the timer if there is nothing in flight. However, to avoid
// handshake deadlock due to anti-amplification limit, client needs to set
@@ -974,10 +1060,53 @@ const QuicTime QuicSentPacketManager::GetRetransmissionTime() const {
return std::max(tlp_time, rto_time);
}
case PTO_MODE: {
- // Ensure PTO never gets set to a time in the past.
+ if (!supports_multiple_packet_number_spaces()) {
+ if (first_pto_srtt_multiplier_ > 0 &&
+ unacked_packets_.HasInFlightPackets() &&
+ consecutive_pto_count_ == 0) {
+ // Arm 1st PTO with earliest in flight sent time, and make sure at
+ // least first_pto_srtt_multiplier_ * RTT has been passed since last
+ // in flight packet.
+ return std::max(
+ clock_->ApproximateNow(),
+ std::max(unacked_packets_.GetFirstInFlightTransmissionInfo()
+ ->sent_time +
+ GetProbeTimeoutDelay(),
+ unacked_packets_.GetLastInFlightPacketSentTime() +
+ first_pto_srtt_multiplier_ *
+ rtt_stats_.SmoothedOrInitialRtt()));
+ }
+ // Ensure PTO never gets set to a time in the past.
+ return std::max(clock_->ApproximateNow(),
+ unacked_packets_.GetLastInFlightPacketSentTime() +
+ GetProbeTimeoutDelay());
+ }
+
+ PacketNumberSpace packet_number_space = NUM_PACKET_NUMBER_SPACES;
+ // earliest_right_edge is the earliest sent time of the last in flight
+ // packet of all packet number spaces.
+ const QuicTime earliest_right_edge =
+ GetEarliestPacketSentTimeForPto(&packet_number_space);
+ if (first_pto_srtt_multiplier_ > 0 &&
+ packet_number_space == APPLICATION_DATA &&
+ consecutive_pto_count_ == 0) {
+ const QuicTransmissionInfo* first_application_info =
+ unacked_packets_.GetFirstInFlightTransmissionInfoOfSpace(
+ APPLICATION_DATA);
+ if (first_application_info != nullptr) {
+ // Arm 1st PTO with earliest in flight sent time, and make sure at
+ // least first_pto_srtt_multiplier_ * RTT has been passed since last
+ // in flight packet. Only do this for application data.
+ return std::max(
+ clock_->ApproximateNow(),
+ std::max(
+ first_application_info->sent_time + GetProbeTimeoutDelay(),
+ earliest_right_edge + first_pto_srtt_multiplier_ *
+ rtt_stats_.SmoothedOrInitialRtt()));
+ }
+ }
return std::max(clock_->ApproximateNow(),
- unacked_packets_.GetLastInFlightPacketSentTime() +
- GetProbeTimeoutDelay());
+ earliest_right_edge + GetProbeTimeoutDelay());
}
}
DCHECK(false);
@@ -985,14 +1114,13 @@ const QuicTime QuicSentPacketManager::GetRetransmissionTime() const {
}
const QuicTime::Delta QuicSentPacketManager::GetPathDegradingDelay() const {
- QuicTime::Delta delay = QuicTime::Delta::Zero();
- for (size_t i = 0; i < max_tail_loss_probes_; ++i) {
- delay = delay + GetTailLossProbeDelay(i);
- }
- for (size_t i = 0; i < kNumRetransmissionDelaysForPathDegradingDelay; ++i) {
- delay = delay + GetRetransmissionDelay(i);
- }
- return delay;
+ return GetNConsecutiveRetransmissionTimeoutDelay(
+ max_tail_loss_probes_ + kNumRetransmissionDelaysForPathDegradingDelay);
+}
+
+const QuicTime::Delta QuicSentPacketManager::GetNetworkBlackholeDelay() const {
+ return GetNConsecutiveRetransmissionTimeoutDelay(
+ max_tail_loss_probes_ + kNumRetransmissionDelaysForBlackholeDelay);
}
const QuicTime::Delta QuicSentPacketManager::GetCryptoRetransmissionDelay()
@@ -1014,10 +1142,9 @@ const QuicTime::Delta QuicSentPacketManager::GetCryptoRetransmissionDelay()
delay_ms << consecutive_crypto_retransmission_count_);
}
-const QuicTime::Delta QuicSentPacketManager::GetTailLossProbeDelay(
- size_t consecutive_tlp_count) const {
+const QuicTime::Delta QuicSentPacketManager::GetTailLossProbeDelay() const {
QuicTime::Delta srtt = rtt_stats_.SmoothedOrInitialRtt();
- if (enable_half_rtt_tail_loss_probe_ && consecutive_tlp_count == 0u) {
+ if (enable_half_rtt_tail_loss_probe_ && consecutive_tlp_count_ == 0u) {
if (unacked_packets().HasUnackedStreamData()) {
// Enable TLPR if there are pending data packets.
return std::max(min_tlp_timeout_, srtt * 0.5);
@@ -1032,8 +1159,7 @@ const QuicTime::Delta QuicSentPacketManager::GetTailLossProbeDelay(
return std::max(min_tlp_timeout_, 2 * srtt);
}
-const QuicTime::Delta QuicSentPacketManager::GetRetransmissionDelay(
- size_t consecutive_rto_count) const {
+const QuicTime::Delta QuicSentPacketManager::GetRetransmissionDelay() const {
QuicTime::Delta retransmission_delay = QuicTime::Delta::Zero();
if (rtt_stats_.smoothed_rtt().IsZero()) {
// We are in the initial state, use default timeout values.
@@ -1050,7 +1176,7 @@ const QuicTime::Delta QuicSentPacketManager::GetRetransmissionDelay(
// Calculate exponential back off.
retransmission_delay =
retransmission_delay *
- (1 << std::min<size_t>(consecutive_rto_count, kMaxRetransmissions));
+ (1 << std::min<size_t>(consecutive_rto_count_, kMaxRetransmissions));
if (retransmission_delay.ToMilliseconds() > kMaxRetransmissionTimeMs) {
return QuicTime::Delta::FromMilliseconds(kMaxRetransmissionTimeMs);
@@ -1066,14 +1192,27 @@ const QuicTime::Delta QuicSentPacketManager::GetProbeTimeoutDelay() const {
}
return 2 * rtt_stats_.initial_rtt();
}
- const QuicTime::Delta pto_delay =
+ const QuicTime::Delta rtt_var = use_standard_deviation_for_pto_
+ ? rtt_stats_.GetStandardOrMeanDeviation()
+ : rtt_stats_.mean_deviation();
+ QuicTime::Delta pto_delay =
rtt_stats_.smoothed_rtt() +
- std::max(pto_rttvar_multiplier_ * rtt_stats_.mean_deviation(),
- QuicTime::Delta::FromMilliseconds(1)) +
+ std::max(pto_rttvar_multiplier_ * rtt_var, kAlarmGranularity) +
(ShouldAddMaxAckDelay() ? peer_max_ack_delay_ : QuicTime::Delta::Zero());
- return pto_delay * (1 << (consecutive_pto_count_ -
- std::min(consecutive_pto_count_,
- pto_exponential_backoff_start_point_)));
+ pto_delay =
+ pto_delay * (1 << (consecutive_pto_count_ -
+ std::min(consecutive_pto_count_,
+ pto_exponential_backoff_start_point_)));
+ if (consecutive_pto_count_ < num_tlp_timeout_ptos_) {
+ // Make first n PTOs similar to TLPs.
+ if (pto_delay > 2 * rtt_stats_.smoothed_rtt()) {
+ QUIC_CODE_COUNT(quic_delayed_pto);
+ pto_delay = std::max(kAlarmGranularity, 2 * rtt_stats_.smoothed_rtt());
+ } else {
+ QUIC_CODE_COUNT(quic_faster_pto);
+ }
+ }
+ return pto_delay;
}
QuicTime::Delta QuicSentPacketManager::GetSlowStartDuration() const {
@@ -1091,9 +1230,14 @@ std::string QuicSentPacketManager::GetDebugState() const {
void QuicSentPacketManager::SetSendAlgorithm(
CongestionControlType congestion_control_type) {
+ if (send_algorithm_ &&
+ send_algorithm_->GetCongestionControlType() == congestion_control_type) {
+ return;
+ }
+
SetSendAlgorithm(SendAlgorithmInterface::Create(
clock_, &rtt_stats_, &unacked_packets_, congestion_control_type, random_,
- stats_, initial_congestion_window_));
+ stats_, initial_congestion_window_, send_algorithm_.get()));
}
void QuicSentPacketManager::SetSendAlgorithm(
@@ -1120,6 +1264,9 @@ void QuicSentPacketManager::OnAckFrameStart(QuicPacketNumber largest_acked,
QuicTime ack_receive_time) {
DCHECK(packets_acked_.empty());
DCHECK_LE(largest_acked, unacked_packets_.largest_sent_packet());
+ if (ack_delay_time > peer_max_ack_delay()) {
+ ack_delay_time = peer_max_ack_delay();
+ }
rtt_updated_ =
MaybeUpdateRTT(largest_acked, ack_delay_time, ack_receive_time);
last_ack_frame_.ack_delay_time = ack_delay_time;
@@ -1221,7 +1368,7 @@ AckResult QuicSentPacketManager::OnAckFrameEnd(
}
last_ack_frame_.packets.Add(acked_packet.packet_number);
if (info->encryption_level == ENCRYPTION_FORWARD_SECURE) {
- handshake_state_ = HANDSHAKE_CONFIRMED;
+ one_rtt_packet_acked_ = true;
}
largest_packet_peer_knows_is_acked_.UpdateMax(info->largest_acked);
if (supports_multiple_packet_number_spaces()) {
@@ -1243,8 +1390,8 @@ AckResult QuicSentPacketManager::OnAckFrameEnd(
acked_packet.receive_timestamp);
}
const bool acked_new_packet = !packets_acked_.empty();
- PostProcessNewlyAckedPackets(ack_packet_number, last_ack_frame_,
- ack_receive_time, rtt_updated_,
+ PostProcessNewlyAckedPackets(ack_packet_number, ack_decrypted_level,
+ last_ack_frame_, ack_receive_time, rtt_updated_,
prior_bytes_in_flight);
return acked_new_packet ? PACKETS_NEWLY_ACKED : NO_PACKETS_NEWLY_ACKED;
@@ -1278,6 +1425,7 @@ void QuicSentPacketManager::SetInitialRtt(QuicTime::Delta rtt) {
}
void QuicSentPacketManager::EnableMultiplePacketNumberSpacesSupport() {
+ EnableIetfPtoAndLossDetection();
unacked_packets_.EnableMultiplePacketNumberSpacesSupport();
}
@@ -1288,13 +1436,6 @@ QuicPacketNumber QuicSentPacketManager::GetLargestAckedPacket(
QuicUtils::GetPacketNumberSpace(decrypted_packet_level));
}
-QuicPacketNumber QuicSentPacketManager::GetLargestSentPacket(
- EncryptionLevel decrypted_packet_level) const {
- DCHECK(supports_multiple_packet_number_spaces());
- return unacked_packets_.GetLargestSentPacketOfPacketNumberSpace(
- decrypted_packet_level);
-}
-
QuicPacketNumber QuicSentPacketManager::GetLargestPacketPeerKnowsIsAcked(
EncryptionLevel decrypted_packet_level) const {
DCHECK(supports_multiple_packet_number_spaces());
@@ -1302,5 +1443,39 @@ QuicPacketNumber QuicSentPacketManager::GetLargestPacketPeerKnowsIsAcked(
decrypted_packet_level)];
}
+QuicTime::Delta
+QuicSentPacketManager::GetNConsecutiveRetransmissionTimeoutDelay(
+ int num_timeouts) const {
+ QuicTime::Delta total_delay = QuicTime::Delta::Zero();
+ const QuicTime::Delta srtt = rtt_stats_.SmoothedOrInitialRtt();
+ int num_tlps =
+ std::min(num_timeouts, static_cast<int>(max_tail_loss_probes_));
+ num_timeouts -= num_tlps;
+ if (num_tlps > 0) {
+ if (enable_half_rtt_tail_loss_probe_ &&
+ unacked_packets().HasUnackedStreamData()) {
+ total_delay = total_delay + std::max(min_tlp_timeout_, srtt * 0.5);
+ --num_tlps;
+ }
+ if (num_tlps > 0) {
+ const QuicTime::Delta tlp_delay =
+ std::max(2 * srtt, unacked_packets_.HasMultipleInFlightPackets()
+ ? min_tlp_timeout_
+ : (1.5 * srtt + (min_rto_timeout_ * 0.5)));
+ total_delay = total_delay + num_tlps * tlp_delay;
+ }
+ }
+ if (num_timeouts == 0) {
+ return total_delay;
+ }
+
+ const QuicTime::Delta retransmission_delay =
+ rtt_stats_.smoothed_rtt().IsZero()
+ ? QuicTime::Delta::FromMilliseconds(kDefaultRetransmissionTimeMs)
+ : std::max(srtt + 4 * rtt_stats_.mean_deviation(), min_rto_timeout_);
+ total_delay = total_delay + ((1 << num_timeouts) - 1) * retransmission_delay;
+ return total_delay;
+}
+
#undef ENDPOINT // undef for jumbo builds
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h b/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h
index 5a3f2ca05d7..5f1de705bb3 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h
@@ -57,6 +57,7 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
QuicByteCount /*byte_size*/) {}
virtual void OnIncomingAck(QuicPacketNumber /*ack_packet_number*/,
+ EncryptionLevel /*ack_decrypted_level*/,
const QuicAckFrame& /*ack_frame*/,
QuicTime /*ack_receive_time*/,
QuicPacketNumber /*largest_observed*/,
@@ -65,6 +66,7 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
}
virtual void OnPacketLoss(QuicPacketNumber /*lost_packet_number*/,
+ EncryptionLevel /*encryption_level*/,
TransmissionType /*transmission_type*/,
QuicTime /*detection_time*/) {}
@@ -107,31 +109,11 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
PTO_MODE,
};
- // Handshake state of this connection.
- enum HandshakeState {
- // Initial state.
- HANDSHAKE_START,
- // Only used in IETF QUIC with TLS handshake. State proceeds to
- // HANDSHAKE_PROCESSED after a packet of HANDSHAKE packet number space
- // gets successfully processed, and the initial key can be dropped.
- HANDSHAKE_PROCESSED,
- // In QUIC crypto, state proceeds to HANDSHAKE_COMPLETE if client receives
- // SHLO or server successfully processes an ENCRYPTION_FORWARD_SECURE
- // packet, such that the handshake packets can be neutered. In IETF QUIC
- // with TLS handshake, state proceeds to HANDSHAKE_COMPLETE once the
- // endpoint has both 1-RTT send and receive keys.
- HANDSHAKE_COMPLETE,
- // Only used in IETF QUIC with TLS handshake. State proceeds to
- // HANDSHAKE_CONFIRMED if a 1-RTT packet gets acknowledged.
- HANDSHAKE_CONFIRMED,
- };
-
QuicSentPacketManager(Perspective perspective,
const QuicClock* clock,
QuicRandom* random,
QuicConnectionStats* stats,
- CongestionControlType congestion_control_type,
- LossDetectionType loss_type);
+ CongestionControlType congestion_control_type);
QuicSentPacketManager(const QuicSentPacketManager&) = delete;
QuicSentPacketManager& operator=(const QuicSentPacketManager&) = delete;
virtual ~QuicSentPacketManager();
@@ -171,6 +153,11 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
void AdjustNetworkParameters(
const SendAlgorithmInterface::NetworkParams& params);
+ void SetLossDetectionTuner(
+ std::unique_ptr<LossDetectionTunerInterface> tuner);
+ void OnConfigNegotiated();
+ void OnConnectionClosed();
+
// Retransmits the oldest pending packet there is still a tail loss probe
// pending. Invoked after OnRetransmissionTimeout.
bool MaybeRetransmitTailLossProbe();
@@ -180,7 +167,6 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
// Removes the retransmittable frames from all unencrypted packets to ensure
// they don't get retransmitted.
- // TODO(fayang): Consider replace this function with NeuterHandshakePackets.
void NeuterUnencryptedPackets();
// Returns true if there's outstanding crypto data.
@@ -227,6 +213,9 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
// notify the session that this connection is degrading.
const QuicTime::Delta GetPathDegradingDelay() const;
+ // Returns the current delay for detecting network blackhole.
+ const QuicTime::Delta GetNetworkBlackholeDelay() const;
+
const RttStats* GetRttStats() const { return &rtt_stats_; }
// Returns the estimated bandwidth calculated by the congestion algorithm.
@@ -323,9 +312,6 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
return unacked_packets_.largest_sent_packet();
}
- QuicPacketNumber GetLargestSentPacket(
- EncryptionLevel decrypted_packet_level) const;
-
QuicPacketNumber GetLargestPacketPeerKnowsIsAcked(
EncryptionLevel decrypted_packet_level) const;
@@ -364,8 +350,6 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
return largest_packet_peer_knows_is_acked_;
}
- HandshakeState handshake_state() const { return handshake_state_; }
-
size_t pending_timer_transmission_count() const {
return pending_timer_transmission_count_;
}
@@ -419,6 +403,8 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
return skip_packet_number_for_pto_;
}
+ bool one_rtt_packet_acked() const { return one_rtt_packet_acked_; }
+
private:
friend class test::QuicConnectionPeer;
friend class test::QuicSentPacketManagerPeer;
@@ -436,28 +422,13 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
// Returns the timeout for retransmitting crypto handshake packets.
const QuicTime::Delta GetCryptoRetransmissionDelay() const;
- // Returns the timeout for a new tail loss probe. |consecutive_tlp_count| is
- // the number of consecutive tail loss probes that have already been sent.
- const QuicTime::Delta GetTailLossProbeDelay(
- size_t consecutive_tlp_count) const;
-
// Calls GetTailLossProbeDelay() with values from the current state of this
// packet manager as its params.
- const QuicTime::Delta GetTailLossProbeDelay() const {
- return GetTailLossProbeDelay(consecutive_tlp_count_);
- }
-
- // Returns the retransmission timeout, after which a full RTO occurs.
- // |consecutive_rto_count| is the number of consecutive RTOs that have already
- // occurred.
- const QuicTime::Delta GetRetransmissionDelay(
- size_t consecutive_rto_count) const;
+ const QuicTime::Delta GetTailLossProbeDelay() const;
// Calls GetRetransmissionDelay() with values from the current state of this
// packet manager as its params.
- const QuicTime::Delta GetRetransmissionDelay() const {
- return GetRetransmissionDelay(consecutive_rto_count_);
- }
+ const QuicTime::Delta GetRetransmissionDelay() const;
// Returns the probe timeout.
const QuicTime::Delta GetProbeTimeoutDelay() const;
@@ -504,6 +475,7 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
// Called after packets have been marked handled with last received ack frame.
void PostProcessNewlyAckedPackets(QuicPacketNumber ack_packet_number,
+ EncryptionLevel ack_decrypted_level,
const QuicAckFrame& ack_frame,
QuicTime ack_receive_time,
bool rtt_updated,
@@ -524,14 +496,26 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
// Called when handshake is confirmed to remove the retransmittable frames
// from all packets of HANDSHAKE_DATA packet number space to ensure they don't
// get retransmitted and will eventually be removed from unacked packets map.
- // Please note, this only applies to QUIC Crypto and needs to be changed when
- // switches to IETF QUIC with QUIC TLS.
void NeuterHandshakePackets();
// Indicates whether including peer_max_ack_delay_ when calculating PTO
// timeout.
bool ShouldAddMaxAckDelay() const;
+ // Gets the earliest in flight packet sent time to calculate PTO. Also
+ // updates |packet_number_space| if a PTO timer should be armed.
+ QuicTime GetEarliestPacketSentTimeForPto(
+ PacketNumberSpace* packet_number_space) const;
+
+ // Returns true if application data should be used to arm PTO. Only used when
+ // multiple packet number space is enabled.
+ bool ShouldArmPtoForApplicationData() const;
+
+ // A helper function to return total delay of |num_timeouts| retransmission
+ // timeout with TLP and RTO mode.
+ QuicTime::Delta GetNConsecutiveRetransmissionTimeoutDelay(
+ int num_timeouts) const;
+
// Newly serialized retransmittable packets are added to this map, which
// contains owning pointers to any contained frames. If a packet is
// retransmitted, this map will contain entries for both the old and the new
@@ -551,7 +535,7 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
QuicPacketCount initial_congestion_window_;
RttStats rtt_stats_;
std::unique_ptr<SendAlgorithmInterface> send_algorithm_;
- // Not owned. Always points to |general_loss_algorithm_| outside of tests.
+ // Not owned. Always points to |uber_loss_algorithm_| outside of tests.
LossDetectionInterface* loss_algorithm_;
UberLossAlgorithm uber_loss_algorithm_;
@@ -595,8 +579,9 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
// Calls into |send_algorithm_| for the underlying congestion control.
PacingSender pacing_sender_;
- // Indicates current handshake state.
- HandshakeState handshake_state_;
+ // Indicates whether handshake is finished. This is purely used to determine
+ // retransmission mode. DONOT use this to infer handshake state.
+ bool handshake_finished_;
// Records bandwidth from server to client in normal operation, over periods
// of time with no loss events.
@@ -652,8 +637,25 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
// The multiplier of rttvar when calculating PTO timeout.
int pto_rttvar_multiplier_;
- // Latched value of quic_neuter_handshake_packets_once2.
- const bool neuter_handshake_packets_once_;
+ // Number of PTOs similar to TLPs.
+ size_t num_tlp_timeout_ptos_;
+
+ // True if any 1-RTT packet gets acknowledged.
+ bool one_rtt_packet_acked_;
+
+ // True if any 1-RTT packet gets sent.
+ bool one_rtt_packet_sent_;
+
+ // If > 0, arm the 1st PTO with max of earliest in flight sent time + PTO
+ // delay and multiplier * srtt from last in flight packet.
+ float first_pto_srtt_multiplier_;
+
+ // If true, use standard deviation (instead of mean deviation) when
+ // calculating PTO timeout.
+ bool use_standard_deviation_for_pto_;
+
+ const bool avoid_overestimate_bandwidth_with_aggregation_ =
+ GetQuicReloadableFlag(quic_avoid_overestimate_bandwidth_with_aggregation);
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager_test.cc
index 8dd0c30faea..98e6af0cfea 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager_test.cc
@@ -7,13 +7,13 @@
#include <memory>
#include <utility>
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
using testing::_;
using testing::AnyNumber;
@@ -46,8 +46,9 @@ class MockDebugDelegate : public QuicSentPacketManager::DebugDelegate {
MOCK_METHOD2(OnSpuriousPacketRetransmission,
void(TransmissionType transmission_type,
QuicByteCount byte_size));
- MOCK_METHOD3(OnPacketLoss,
+ MOCK_METHOD4(OnPacketLoss,
void(QuicPacketNumber lost_packet_number,
+ EncryptionLevel encryption_level,
TransmissionType transmission_type,
QuicTime detection_time));
};
@@ -61,7 +62,7 @@ class QuicSentPacketManagerTest : public QuicTest {
kDefaultLength, HAS_RETRANSMITTABLE_DATA));
SerializedPacket packet(CreatePacket(packet_number, false));
packet.retransmittable_frames.push_back(
- QuicFrame(QuicStreamFrame(1, false, 0, QuicStringPiece())));
+ QuicFrame(QuicStreamFrame(1, false, 0, quiche::QuicheStringPiece())));
packet.has_crypto_handshake = IS_HANDSHAKE;
manager_.OnPacketSent(&packet, clock_.Now(), HANDSHAKE_RETRANSMISSION,
HAS_RETRANSMITTABLE_DATA);
@@ -85,13 +86,13 @@ class QuicSentPacketManagerTest : public QuicTest {
}
protected:
+ const CongestionControlType kInitialCongestionControlType = kCubicBytes;
QuicSentPacketManagerTest()
: manager_(Perspective::IS_SERVER,
&clock_,
QuicRandom::GetInstance(),
&stats_,
- kCubicBytes,
- kNack),
+ kInitialCongestionControlType),
send_algorithm_(new StrictMock<MockSendAlgorithm>),
network_change_visitor_(new StrictMock<MockNetworkChangeVisitor>) {
QuicSentPacketManagerPeer::SetSendAlgorithm(&manager_, send_algorithm_);
@@ -102,6 +103,8 @@ class QuicSentPacketManagerTest : public QuicTest {
manager_.SetNetworkChangeVisitor(network_change_visitor_.get());
manager_.SetSessionNotifier(&notifier_);
+ EXPECT_CALL(*send_algorithm_, GetCongestionControlType())
+ .WillRepeatedly(Return(kInitialCongestionControlType));
EXPECT_CALL(*send_algorithm_, HasReliableBandwidthEstimate())
.Times(AnyNumber());
EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
@@ -109,6 +112,7 @@ class QuicSentPacketManagerTest : public QuicTest {
.WillRepeatedly(Return(QuicBandwidth::Zero()));
EXPECT_CALL(*send_algorithm_, InSlowStart()).Times(AnyNumber());
EXPECT_CALL(*send_algorithm_, InRecovery()).Times(AnyNumber());
+ EXPECT_CALL(*send_algorithm_, OnPacketNeutered(_)).Times(AnyNumber());
EXPECT_CALL(*network_change_visitor_, OnPathMtuIncreased(1000))
.Times(AnyNumber());
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(true));
@@ -244,8 +248,8 @@ class QuicSentPacketManagerTest : public QuicTest {
PACKET_4BYTE_PACKET_NUMBER, nullptr, kDefaultLength,
false, false);
if (retransmittable) {
- packet.retransmittable_frames.push_back(
- QuicFrame(QuicStreamFrame(kStreamId, false, 0, QuicStringPiece())));
+ packet.retransmittable_frames.push_back(QuicFrame(
+ QuicStreamFrame(kStreamId, false, 0, quiche::QuicheStringPiece())));
}
return packet;
}
@@ -291,7 +295,7 @@ class QuicSentPacketManagerTest : public QuicTest {
kDefaultLength, HAS_RETRANSMITTABLE_DATA));
SerializedPacket packet(CreatePacket(packet_number, false));
packet.retransmittable_frames.push_back(
- QuicFrame(QuicStreamFrame(1, false, 0, QuicStringPiece())));
+ QuicFrame(QuicStreamFrame(1, false, 0, quiche::QuicheStringPiece())));
packet.has_crypto_handshake = IS_HANDSHAKE;
manager_.OnPacketSent(&packet, clock_.Now(), NOT_RETRANSMISSION,
HAS_RETRANSMITTABLE_DATA);
@@ -317,7 +321,6 @@ class QuicSentPacketManagerTest : public QuicTest {
}
void EnablePto(QuicTag tag) {
- SetQuicReloadableFlag(quic_enable_pto, true);
QuicConfig config;
QuicTagVector options;
options.push_back(tag);
@@ -341,10 +344,10 @@ TEST_F(QuicSentPacketManagerTest, IsUnacked) {
SendDataPacket(1);
uint64_t unacked[] = {1};
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ VerifyUnackedPackets(unacked, QUICHE_ARRAYSIZE(unacked));
uint64_t retransmittable[] = {1};
VerifyRetransmittablePackets(retransmittable,
- QUIC_ARRAYSIZE(retransmittable));
+ QUICHE_ARRAYSIZE(retransmittable));
}
TEST_F(QuicSentPacketManagerTest, IsUnAckedRetransmit) {
@@ -353,7 +356,7 @@ TEST_F(QuicSentPacketManagerTest, IsUnAckedRetransmit) {
EXPECT_TRUE(QuicSentPacketManagerPeer::IsRetransmission(&manager_, 2));
uint64_t unacked[] = {1, 2};
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ VerifyUnackedPackets(unacked, QUICHE_ARRAYSIZE(unacked));
std::vector<uint64_t> retransmittable = {1, 2};
VerifyRetransmittablePackets(&retransmittable[0], retransmittable.size());
}
@@ -373,7 +376,7 @@ TEST_F(QuicSentPacketManagerTest, RetransmitThenAck) {
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
// Packet 1 is unacked, pending, but not retransmittable.
uint64_t unacked[] = {1};
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ VerifyUnackedPackets(unacked, QUICHE_ARRAYSIZE(unacked));
EXPECT_TRUE(manager_.HasInFlightPackets());
VerifyRetransmittablePackets(nullptr, 0);
}
@@ -396,7 +399,7 @@ TEST_F(QuicSentPacketManagerTest, RetransmitThenAckBeforeSend) {
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
uint64_t unacked[] = {2};
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ VerifyUnackedPackets(unacked, QUICHE_ARRAYSIZE(unacked));
// We do not know packet 2 is a spurious retransmission until it gets acked.
VerifyRetransmittablePackets(nullptr, 0);
EXPECT_EQ(0u, stats_.packets_spuriously_retransmitted);
@@ -411,7 +414,7 @@ TEST_F(QuicSentPacketManagerTest, RetransmitThenStopRetransmittingBeforeSend) {
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
uint64_t unacked[] = {1};
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ VerifyUnackedPackets(unacked, QUICHE_ARRAYSIZE(unacked));
VerifyRetransmittablePackets(nullptr, 0);
EXPECT_EQ(0u, stats_.packets_spuriously_retransmitted);
}
@@ -433,7 +436,7 @@ TEST_F(QuicSentPacketManagerTest, RetransmitThenAckPrevious) {
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
// 2 remains unacked, but no packets have retransmittable data.
uint64_t unacked[] = {2};
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ VerifyUnackedPackets(unacked, QUICHE_ARRAYSIZE(unacked));
EXPECT_TRUE(manager_.HasInFlightPackets());
VerifyRetransmittablePackets(nullptr, 0);
// Ack 2 causes 2 be considered as spurious retransmission.
@@ -470,7 +473,9 @@ TEST_F(QuicSentPacketManagerTest, RetransmitThenAckPreviousThenNackRetransmit) {
clock_.AdvanceTime(rtt);
// Next, NACK packet 2 three times.
- ExpectAck(3);
+ EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
+ EXPECT_CALL(notifier_, OnFrameLost(_)).Times(1);
+ ExpectAckAndLoss(true, 3, 2);
manager_.OnAckFrameStart(QuicPacketNumber(3), QuicTime::Delta::Infinite(),
clock_.Now());
manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(4));
@@ -488,12 +493,7 @@ TEST_F(QuicSentPacketManagerTest, RetransmitThenAckPreviousThenNackRetransmit) {
manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(3),
ENCRYPTION_INITIAL));
- ExpectAckAndLoss(true, 5, 2);
- // Frames in all packets are acked.
- EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
- // Notify session that stream frame in packet 2 gets lost although it is
- // not outstanding.
- EXPECT_CALL(notifier_, OnFrameLost(_)).Times(1);
+ ExpectAck(5);
manager_.OnAckFrameStart(QuicPacketNumber(5), QuicTime::Delta::Infinite(),
clock_.Now());
manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(6));
@@ -503,7 +503,7 @@ TEST_F(QuicSentPacketManagerTest, RetransmitThenAckPreviousThenNackRetransmit) {
ENCRYPTION_INITIAL));
uint64_t unacked[] = {2};
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ VerifyUnackedPackets(unacked, QUICHE_ARRAYSIZE(unacked));
EXPECT_FALSE(manager_.HasInFlightPackets());
VerifyRetransmittablePackets(nullptr, 0);
@@ -536,7 +536,7 @@ TEST_F(QuicSentPacketManagerTest,
// Since 2 was marked for retransmit, when 1 is acked, 2 is kept for RTT.
uint64_t unacked[] = {2};
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ VerifyUnackedPackets(unacked, QUICHE_ARRAYSIZE(unacked));
EXPECT_FALSE(manager_.HasInFlightPackets());
VerifyRetransmittablePackets(nullptr, 0);
@@ -573,7 +573,7 @@ TEST_F(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) {
// 2 and 3 remain unacked, but no packets have retransmittable data.
uint64_t unacked[] = {2, 3};
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ VerifyUnackedPackets(unacked, QUICHE_ARRAYSIZE(unacked));
EXPECT_TRUE(manager_.HasInFlightPackets());
VerifyRetransmittablePackets(nullptr, 0);
@@ -584,7 +584,7 @@ TEST_F(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) {
.WillOnce(Return(false))
.WillRepeatedly(Return(true));
uint64_t acked[] = {3, 4};
- ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
+ ExpectAcksAndLosses(true, acked, QUICHE_ARRAYSIZE(acked), nullptr, 0);
manager_.OnAckFrameStart(QuicPacketNumber(4), QuicTime::Delta::Infinite(),
clock_.Now());
manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(5));
@@ -594,13 +594,13 @@ TEST_F(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) {
ENCRYPTION_INITIAL));
uint64_t unacked2[] = {2};
- VerifyUnackedPackets(unacked2, QUIC_ARRAYSIZE(unacked2));
+ VerifyUnackedPackets(unacked2, QUICHE_ARRAYSIZE(unacked2));
EXPECT_TRUE(manager_.HasInFlightPackets());
SendDataPacket(5);
ExpectAckAndLoss(true, 5, 2);
EXPECT_CALL(debug_delegate,
- OnPacketLoss(QuicPacketNumber(2), LOSS_RETRANSMISSION, _));
+ OnPacketLoss(QuicPacketNumber(2), _, LOSS_RETRANSMISSION, _));
// Frames in all packets are acked.
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
// Notify session that stream frame in packet 2 gets lost although it is
@@ -615,11 +615,13 @@ TEST_F(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) {
ENCRYPTION_INITIAL));
uint64_t unacked3[] = {2};
- VerifyUnackedPackets(unacked3, QUIC_ARRAYSIZE(unacked3));
+ VerifyUnackedPackets(unacked3, QUICHE_ARRAYSIZE(unacked3));
EXPECT_FALSE(manager_.HasInFlightPackets());
// Spurious retransmission is detected when packet 3 gets acked. We cannot
// know packet 2 is a spurious until it gets acked.
EXPECT_EQ(1u, stats_.packets_spuriously_retransmitted);
+ EXPECT_EQ(1u, stats_.packets_lost);
+ EXPECT_LT(QuicTime::Delta::Zero(), stats_.total_loss_detection_time);
}
TEST_F(QuicSentPacketManagerTest, AckOriginalTransmission) {
@@ -661,7 +663,7 @@ TEST_F(QuicSentPacketManagerTest, AckOriginalTransmission) {
// Ack 3, which causes SpuriousRetransmitDetected to be called.
{
uint64_t acked[] = {3};
- ExpectAcksAndLosses(false, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
+ ExpectAcksAndLosses(false, acked, QUICHE_ARRAYSIZE(acked), nullptr, 0);
EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _, _));
EXPECT_CALL(*loss_algorithm,
SpuriousLossDetected(_, _, _, QuicPacketNumber(3),
@@ -670,9 +672,11 @@ TEST_F(QuicSentPacketManagerTest, AckOriginalTransmission) {
clock_.Now());
manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(5));
manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
+ EXPECT_EQ(0u, stats_.packet_spuriously_detected_lost);
EXPECT_EQ(PACKETS_NEWLY_ACKED,
manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(3),
ENCRYPTION_INITIAL));
+ EXPECT_EQ(1u, stats_.packet_spuriously_detected_lost);
// Ack 3 will not cause 5 be considered as a spurious retransmission. Ack
// 5 will cause 5 be considered as a spurious retransmission as no new
// data gets acked.
@@ -705,7 +709,7 @@ TEST_F(QuicSentPacketManagerTest, AckAckAndUpdateRtt) {
// Now ack the ack and expect an RTT update.
uint64_t acked[] = {1, 2};
- ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
+ ExpectAcksAndLosses(true, acked, QUICHE_ARRAYSIZE(acked), nullptr, 0);
manager_.OnAckFrameStart(QuicPacketNumber(2),
QuicTime::Delta::FromMilliseconds(5), clock_.Now());
manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(3));
@@ -718,7 +722,7 @@ TEST_F(QuicSentPacketManagerTest, AckAckAndUpdateRtt) {
// Now ack the ack and expect only an RTT update.
uint64_t acked2[] = {3};
- ExpectAcksAndLosses(true, acked2, QUIC_ARRAYSIZE(acked2), nullptr, 0);
+ ExpectAcksAndLosses(true, acked2, QUICHE_ARRAYSIZE(acked2), nullptr, 0);
manager_.OnAckFrameStart(QuicPacketNumber(3), QuicTime::Delta::Infinite(),
clock_.Now());
manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(4));
@@ -779,6 +783,31 @@ TEST_F(QuicSentPacketManagerTest, RttWithInfiniteDelta) {
EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt());
}
+TEST_F(QuicSentPacketManagerTest, RttWithDeltaExceedingLimit) {
+ // Initialize min and smoothed rtt to 10ms.
+ RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
+ rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(10),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+
+ QuicTime::Delta send_delta = QuicTime::Delta::FromMilliseconds(100);
+ QuicTime::Delta ack_delay =
+ QuicTime::Delta::FromMilliseconds(5) + manager_.peer_max_ack_delay();
+ ASSERT_GT(send_delta - rtt_stats->min_rtt(), ack_delay);
+ SendDataPacket(1);
+ clock_.AdvanceTime(send_delta);
+
+ ExpectAck(1);
+ manager_.OnAckFrameStart(QuicPacketNumber(1), ack_delay, clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
+ EXPECT_EQ(PACKETS_NEWLY_ACKED,
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1),
+ ENCRYPTION_FORWARD_SECURE));
+
+ QuicTime::Delta expected_rtt_sample =
+ send_delta - manager_.peer_max_ack_delay();
+ EXPECT_EQ(expected_rtt_sample, manager_.GetRttStats()->latest_rtt());
+}
+
TEST_F(QuicSentPacketManagerTest, RttZeroDelta) {
// Expect that the RTT is the time between send and receive since the
// ack_delay_time is zero.
@@ -837,8 +866,8 @@ TEST_F(QuicSentPacketManagerTest, TailLossProbeTimeout) {
SendDataPacket(5);
uint64_t acked[] = {4, 5};
uint64_t lost[] = {1, 2};
- ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), lost,
- QUIC_ARRAYSIZE(lost));
+ ExpectAcksAndLosses(true, acked, QUICHE_ARRAYSIZE(acked), lost,
+ QUICHE_ARRAYSIZE(lost));
// Frames in all packets are acked.
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
// Notify session that stream frame in packets 1 and 2 get lost although
@@ -968,8 +997,8 @@ TEST_F(QuicSentPacketManagerTest, CryptoHandshakeTimeout) {
// Crypto packets remain in flight, so any that aren't acked will be lost.
uint64_t acked[] = {3, 4, 5, 8, 9};
uint64_t lost[] = {1, 2, 6};
- ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), lost,
- QUIC_ARRAYSIZE(lost));
+ ExpectAcksAndLosses(true, acked, QUICHE_ARRAYSIZE(acked), lost,
+ QUICHE_ARRAYSIZE(lost));
EXPECT_CALL(notifier_, OnFrameLost(_)).Times(3);
EXPECT_CALL(notifier_, HasUnackedCryptoData()).WillRepeatedly(Return(false));
manager_.OnAckFrameStart(QuicPacketNumber(9), QuicTime::Delta::Infinite(),
@@ -1020,7 +1049,7 @@ TEST_F(QuicSentPacketManagerTest, CryptoHandshakeTimeoutVersionNegotiation) {
// Least unacked isn't raised until an ack is received, so ack the
// crypto packets.
uint64_t acked[] = {8, 9};
- ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
+ ExpectAcksAndLosses(true, acked, QUICHE_ARRAYSIZE(acked), nullptr, 0);
manager_.OnAckFrameStart(QuicPacketNumber(9), QuicTime::Delta::Infinite(),
clock_.Now());
manager_.OnAckRange(QuicPacketNumber(8), QuicPacketNumber(10));
@@ -1049,7 +1078,7 @@ TEST_F(QuicSentPacketManagerTest, CryptoHandshakeSpuriousRetransmission) {
// Now ack the second crypto packet, and ensure the first gets removed, but
// the third does not.
uint64_t acked[] = {2};
- ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
+ ExpectAcksAndLosses(true, acked, QUICHE_ARRAYSIZE(acked), nullptr, 0);
EXPECT_CALL(notifier_, HasUnackedCryptoData()).WillRepeatedly(Return(false));
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(),
@@ -1061,7 +1090,7 @@ TEST_F(QuicSentPacketManagerTest, CryptoHandshakeSpuriousRetransmission) {
EXPECT_FALSE(manager_.HasUnackedCryptoPackets());
uint64_t unacked[] = {1, 3};
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ VerifyUnackedPackets(unacked, QUICHE_ARRAYSIZE(unacked));
}
TEST_F(QuicSentPacketManagerTest, CryptoHandshakeTimeoutUnsentDataPacket) {
@@ -1130,14 +1159,14 @@ TEST_F(QuicSentPacketManagerTest,
manager_.NeuterUnencryptedPackets();
EXPECT_FALSE(manager_.HasUnackedCryptoPackets());
uint64_t unacked[] = {1, 2, 3};
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ VerifyUnackedPackets(unacked, QUICHE_ARRAYSIZE(unacked));
VerifyRetransmittablePackets(nullptr, 0);
EXPECT_FALSE(manager_.HasUnackedCryptoPackets());
EXPECT_FALSE(manager_.HasInFlightPackets());
// Ensure both packets get discarded when packet 2 is acked.
uint64_t acked[] = {3};
- ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
+ ExpectAcksAndLosses(true, acked, QUICHE_ARRAYSIZE(acked), nullptr, 0);
manager_.OnAckFrameStart(QuicPacketNumber(3), QuicTime::Delta::Infinite(),
clock_.Now());
manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(4));
@@ -1181,7 +1210,7 @@ TEST_F(QuicSentPacketManagerTest, RetransmissionTimeout) {
// packets lost.
for (int i = 1; i <= 99; ++i) {
EXPECT_CALL(debug_delegate,
- OnPacketLoss(QuicPacketNumber(i), LOSS_RETRANSMISSION, _));
+ OnPacketLoss(QuicPacketNumber(i), _, LOSS_RETRANSMISSION, _));
}
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(true));
// Packets [1, 99] are considered as lost, although stream frame in packet
@@ -1598,14 +1627,15 @@ TEST_F(QuicSentPacketManagerTest, GetTransmissionTimeSpuriousRTO) {
// Ack a packet before the first RTO and ensure the RTO timeout returns to the
// original value and OnRetransmissionTimeout is not called or reverted.
- ExpectAck(2);
- manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(),
+ uint64_t acked[] = {1, 2};
+ ExpectAcksAndLosses(true, acked, QUICHE_ARRAYSIZE(acked), nullptr, 0);
+ manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Zero(),
clock_.Now());
- manager_.OnAckRange(QuicPacketNumber(2), QuicPacketNumber(3));
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(3));
EXPECT_EQ(PACKETS_NEWLY_ACKED,
manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1),
ENCRYPTION_INITIAL));
- EXPECT_EQ(5 * kDefaultLength, manager_.GetBytesInFlight());
+ EXPECT_EQ(4 * kDefaultLength, manager_.GetBytesInFlight());
// Wait 2RTTs from now for the RTO, since it's the max of the RTO time
// and the TLP time. In production, there would always be two TLP's first.
@@ -1630,8 +1660,6 @@ TEST_F(QuicSentPacketManagerTest, GetTransmissionDelayMin) {
for (int i = 0; i < 5; ++i) {
EXPECT_EQ(delay,
QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_));
- EXPECT_EQ(delay,
- QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_, i));
delay = delay + delay;
EXPECT_CALL(notifier_, RetransmitFrames(_, _))
.WillOnce(WithArgs<1>(Invoke([this, i](TransmissionType type) {
@@ -1650,8 +1678,6 @@ TEST_F(QuicSentPacketManagerTest, GetTransmissionDelayMax) {
EXPECT_EQ(QuicTime::Delta::FromSeconds(60),
QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_));
- EXPECT_EQ(QuicTime::Delta::FromSeconds(60),
- QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_, 0));
}
TEST_F(QuicSentPacketManagerTest, GetTransmissionDelayExponentialBackoff) {
@@ -1662,8 +1688,6 @@ TEST_F(QuicSentPacketManagerTest, GetTransmissionDelayExponentialBackoff) {
for (int i = 0; i < 5; ++i) {
EXPECT_EQ(delay,
QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_));
- EXPECT_EQ(delay,
- QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_, i));
delay = delay + delay;
EXPECT_CALL(notifier_, RetransmitFrames(_, _))
.WillOnce(WithArgs<1>(Invoke([this, i](TransmissionType type) {
@@ -1688,8 +1712,6 @@ TEST_F(QuicSentPacketManagerTest, RetransmissionDelay) {
QuicTime::Delta::FromMilliseconds(kRttMs + kRttMs / 2 * 4);
EXPECT_EQ(expected_delay,
QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_));
- EXPECT_EQ(expected_delay,
- QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_, 0));
for (int i = 0; i < 100; ++i) {
// Run to make sure that we converge.
@@ -1707,8 +1729,6 @@ TEST_F(QuicSentPacketManagerTest, RetransmissionDelay) {
QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_)
.ToMilliseconds(),
1);
- EXPECT_EQ(QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_, 0),
- QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_));
}
TEST_F(QuicSentPacketManagerTest, GetLossDelay) {
@@ -1742,26 +1762,13 @@ TEST_F(QuicSentPacketManagerTest, GetLossDelay) {
manager_.OnRetransmissionTimeout();
}
-TEST_F(QuicSentPacketManagerTest, NegotiateTimeLossDetectionFromOptions) {
- EXPECT_EQ(kNack, QuicSentPacketManagerPeer::GetLossAlgorithm(&manager_)
- ->GetLossDetectionType());
-
- QuicConfig config;
- QuicTagVector options;
- options.push_back(kTIME);
- QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
- EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
- EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
- manager_.SetFromConfig(config);
-
- EXPECT_EQ(kTime, QuicSentPacketManagerPeer::GetLossAlgorithm(&manager_)
- ->GetLossDetectionType());
-}
-
TEST_F(QuicSentPacketManagerTest, NegotiateIetfLossDetectionFromOptions) {
- SetQuicReloadableFlag(quic_enable_ietf_loss_detection, true);
- EXPECT_EQ(kNack, QuicSentPacketManagerPeer::GetLossAlgorithm(&manager_)
- ->GetLossDetectionType());
+ EXPECT_TRUE(
+ QuicSentPacketManagerPeer::AdaptiveReorderingThresholdEnabled(&manager_));
+ EXPECT_FALSE(
+ QuicSentPacketManagerPeer::AdaptiveTimeThresholdEnabled(&manager_));
+ EXPECT_EQ(kDefaultLossDelayShift,
+ QuicSentPacketManagerPeer::GetReorderingShift(&manager_));
QuicConfig config;
QuicTagVector options;
@@ -1771,9 +1778,6 @@ TEST_F(QuicSentPacketManagerTest, NegotiateIetfLossDetectionFromOptions) {
EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
manager_.SetFromConfig(config);
- EXPECT_EQ(kIetfLossDetection,
- QuicSentPacketManagerPeer::GetLossAlgorithm(&manager_)
- ->GetLossDetectionType());
EXPECT_EQ(3, QuicSentPacketManagerPeer::GetReorderingShift(&manager_));
EXPECT_FALSE(
QuicSentPacketManagerPeer::AdaptiveReorderingThresholdEnabled(&manager_));
@@ -1781,9 +1785,12 @@ TEST_F(QuicSentPacketManagerTest, NegotiateIetfLossDetectionFromOptions) {
TEST_F(QuicSentPacketManagerTest,
NegotiateIetfLossDetectionOneFourthRttFromOptions) {
- SetQuicReloadableFlag(quic_enable_ietf_loss_detection, true);
- EXPECT_EQ(kNack, QuicSentPacketManagerPeer::GetLossAlgorithm(&manager_)
- ->GetLossDetectionType());
+ EXPECT_TRUE(
+ QuicSentPacketManagerPeer::AdaptiveReorderingThresholdEnabled(&manager_));
+ EXPECT_FALSE(
+ QuicSentPacketManagerPeer::AdaptiveTimeThresholdEnabled(&manager_));
+ EXPECT_EQ(kDefaultLossDelayShift,
+ QuicSentPacketManagerPeer::GetReorderingShift(&manager_));
QuicConfig config;
QuicTagVector options;
@@ -1793,9 +1800,6 @@ TEST_F(QuicSentPacketManagerTest,
EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
manager_.SetFromConfig(config);
- EXPECT_EQ(kIetfLossDetection,
- QuicSentPacketManagerPeer::GetLossAlgorithm(&manager_)
- ->GetLossDetectionType());
EXPECT_EQ(kDefaultLossDelayShift,
QuicSentPacketManagerPeer::GetReorderingShift(&manager_));
EXPECT_FALSE(
@@ -1804,11 +1808,12 @@ TEST_F(QuicSentPacketManagerTest,
TEST_F(QuicSentPacketManagerTest,
NegotiateIetfLossDetectionAdaptiveReorderingThreshold) {
- SetQuicReloadableFlag(quic_enable_ietf_loss_detection, true);
- EXPECT_EQ(kNack, QuicSentPacketManagerPeer::GetLossAlgorithm(&manager_)
- ->GetLossDetectionType());
- EXPECT_FALSE(
+ EXPECT_TRUE(
QuicSentPacketManagerPeer::AdaptiveReorderingThresholdEnabled(&manager_));
+ EXPECT_FALSE(
+ QuicSentPacketManagerPeer::AdaptiveTimeThresholdEnabled(&manager_));
+ EXPECT_EQ(kDefaultLossDelayShift,
+ QuicSentPacketManagerPeer::GetReorderingShift(&manager_));
QuicConfig config;
QuicTagVector options;
@@ -1818,9 +1823,6 @@ TEST_F(QuicSentPacketManagerTest,
EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
manager_.SetFromConfig(config);
- EXPECT_EQ(kIetfLossDetection,
- QuicSentPacketManagerPeer::GetLossAlgorithm(&manager_)
- ->GetLossDetectionType());
EXPECT_EQ(3, QuicSentPacketManagerPeer::GetReorderingShift(&manager_));
EXPECT_TRUE(
QuicSentPacketManagerPeer::AdaptiveReorderingThresholdEnabled(&manager_));
@@ -1828,11 +1830,12 @@ TEST_F(QuicSentPacketManagerTest,
TEST_F(QuicSentPacketManagerTest,
NegotiateIetfLossDetectionAdaptiveReorderingThreshold2) {
- SetQuicReloadableFlag(quic_enable_ietf_loss_detection, true);
- EXPECT_EQ(kNack, QuicSentPacketManagerPeer::GetLossAlgorithm(&manager_)
- ->GetLossDetectionType());
- EXPECT_FALSE(
+ EXPECT_TRUE(
QuicSentPacketManagerPeer::AdaptiveReorderingThresholdEnabled(&manager_));
+ EXPECT_FALSE(
+ QuicSentPacketManagerPeer::AdaptiveTimeThresholdEnabled(&manager_));
+ EXPECT_EQ(kDefaultLossDelayShift,
+ QuicSentPacketManagerPeer::GetReorderingShift(&manager_));
QuicConfig config;
QuicTagVector options;
@@ -1841,10 +1844,6 @@ TEST_F(QuicSentPacketManagerTest,
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
manager_.SetFromConfig(config);
-
- EXPECT_EQ(kIetfLossDetection,
- QuicSentPacketManagerPeer::GetLossAlgorithm(&manager_)
- ->GetLossDetectionType());
EXPECT_EQ(kDefaultLossDelayShift,
QuicSentPacketManagerPeer::GetReorderingShift(&manager_));
EXPECT_TRUE(
@@ -1853,13 +1852,12 @@ TEST_F(QuicSentPacketManagerTest,
TEST_F(QuicSentPacketManagerTest,
NegotiateIetfLossDetectionAdaptiveReorderingAndTimeThreshold) {
- SetQuicReloadableFlag(quic_enable_ietf_loss_detection, true);
- EXPECT_EQ(kNack, QuicSentPacketManagerPeer::GetLossAlgorithm(&manager_)
- ->GetLossDetectionType());
- EXPECT_FALSE(
+ EXPECT_TRUE(
QuicSentPacketManagerPeer::AdaptiveReorderingThresholdEnabled(&manager_));
EXPECT_FALSE(
QuicSentPacketManagerPeer::AdaptiveTimeThresholdEnabled(&manager_));
+ EXPECT_EQ(kDefaultLossDelayShift,
+ QuicSentPacketManagerPeer::GetReorderingShift(&manager_));
QuicConfig config;
QuicTagVector options;
@@ -1869,9 +1867,6 @@ TEST_F(QuicSentPacketManagerTest,
EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
manager_.SetFromConfig(config);
- EXPECT_EQ(kIetfLossDetection,
- QuicSentPacketManagerPeer::GetLossAlgorithm(&manager_)
- ->GetLossDetectionType());
EXPECT_EQ(kDefaultLossDelayShift,
QuicSentPacketManagerPeer::GetReorderingShift(&manager_));
EXPECT_TRUE(
@@ -1982,8 +1977,6 @@ TEST_F(QuicSentPacketManagerTest, NegotiateNoMinTLPFromOptionsAtServer) {
// The TLP with fewer than 2 packets outstanding includes 1/2 min RTO(200ms).
EXPECT_EQ(QuicTime::Delta::FromMicroseconds(100002),
QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_));
- EXPECT_EQ(QuicTime::Delta::FromMicroseconds(100002),
- QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_, 0));
// Send two packets, and the TLP should be 1ms.
QuicTime::Delta expected_tlp_delay = QuicTime::Delta::FromMilliseconds(1);
@@ -1991,8 +1984,6 @@ TEST_F(QuicSentPacketManagerTest, NegotiateNoMinTLPFromOptionsAtServer) {
SendDataPacket(2);
EXPECT_EQ(expected_tlp_delay,
QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_));
- EXPECT_EQ(expected_tlp_delay,
- QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_, 0));
}
TEST_F(QuicSentPacketManagerTest, NegotiateNoMinTLPFromOptionsAtClient) {
@@ -2015,16 +2006,12 @@ TEST_F(QuicSentPacketManagerTest, NegotiateNoMinTLPFromOptionsAtClient) {
// The TLP with fewer than 2 packets outstanding includes 1/2 min RTO(200ms).
EXPECT_EQ(QuicTime::Delta::FromMicroseconds(100002),
QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_));
- EXPECT_EQ(QuicTime::Delta::FromMicroseconds(100002),
- QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_, 0));
// Send two packets, and the TLP should be 1ms.
QuicTime::Delta expected_tlp_delay = QuicTime::Delta::FromMilliseconds(1);
SendDataPacket(1);
SendDataPacket(2);
EXPECT_EQ(expected_tlp_delay,
QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_));
- EXPECT_EQ(expected_tlp_delay,
- QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_, 0));
}
TEST_F(QuicSentPacketManagerTest, NegotiateNoMinRTOFromOptionsAtServer) {
@@ -2043,14 +2030,10 @@ TEST_F(QuicSentPacketManagerTest, NegotiateNoMinRTOFromOptionsAtServer) {
QuicTime::Delta expected_rto_delay = QuicTime::Delta::FromMilliseconds(1);
EXPECT_EQ(expected_rto_delay,
QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_));
- EXPECT_EQ(expected_rto_delay,
- QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_, 0));
// The TLP with fewer than 2 packets outstanding includes 1/2 min RTO(0ms).
QuicTime::Delta expected_tlp_delay = QuicTime::Delta::FromMicroseconds(502);
EXPECT_EQ(expected_tlp_delay,
QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_));
- EXPECT_EQ(expected_tlp_delay,
- QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_, 0));
}
TEST_F(QuicSentPacketManagerTest, NegotiateNoMinRTOFromOptionsAtClient) {
@@ -2070,14 +2053,10 @@ TEST_F(QuicSentPacketManagerTest, NegotiateNoMinRTOFromOptionsAtClient) {
QuicTime::Delta expected_rto_delay = QuicTime::Delta::FromMilliseconds(1);
EXPECT_EQ(expected_rto_delay,
QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_));
- EXPECT_EQ(expected_rto_delay,
- QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_, 0));
// The TLP with fewer than 2 packets outstanding includes 1/2 min RTO(0ms).
QuicTime::Delta expected_tlp_delay = QuicTime::Delta::FromMicroseconds(502);
EXPECT_EQ(expected_tlp_delay,
QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_));
- EXPECT_EQ(expected_tlp_delay,
- QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_, 0));
}
TEST_F(QuicSentPacketManagerTest, NegotiateNoTLPFromOptionsAtServer) {
@@ -2301,8 +2280,8 @@ TEST_F(QuicSentPacketManagerTest, OnAckRangeSlowPath) {
// Ack [5, 7), [10, 12), [15, 17).
uint64_t acked1[] = {5, 6, 10, 11, 15, 16};
uint64_t lost1[] = {1, 2, 3, 4, 7, 8, 9, 12, 13};
- ExpectAcksAndLosses(true, acked1, QUIC_ARRAYSIZE(acked1), lost1,
- QUIC_ARRAYSIZE(lost1));
+ ExpectAcksAndLosses(true, acked1, QUICHE_ARRAYSIZE(acked1), lost1,
+ QUICHE_ARRAYSIZE(lost1));
EXPECT_CALL(notifier_, OnFrameLost(_)).Times(AnyNumber());
manager_.OnAckFrameStart(QuicPacketNumber(16), QuicTime::Delta::Infinite(),
clock_.Now());
@@ -2317,7 +2296,7 @@ TEST_F(QuicSentPacketManagerTest, OnAckRangeSlowPath) {
// Ack [4, 8), [9, 13), [14, 21).
uint64_t acked2[] = {4, 7, 9, 12, 14, 17, 18, 19, 20};
- ExpectAcksAndLosses(true, acked2, QUIC_ARRAYSIZE(acked2), nullptr, 0);
+ ExpectAcksAndLosses(true, acked2, QUICHE_ARRAYSIZE(acked2), nullptr, 0);
manager_.OnAckFrameStart(QuicPacketNumber(20), QuicTime::Delta::Infinite(),
clock_.Now());
manager_.OnAckRange(QuicPacketNumber(14), QuicPacketNumber(21));
@@ -2336,8 +2315,8 @@ TEST_F(QuicSentPacketManagerTest, TolerateReneging) {
// Ack [5, 7), [10, 12), [15, 17).
uint64_t acked1[] = {5, 6, 10, 11, 15, 16};
uint64_t lost1[] = {1, 2, 3, 4, 7, 8, 9, 12, 13};
- ExpectAcksAndLosses(true, acked1, QUIC_ARRAYSIZE(acked1), lost1,
- QUIC_ARRAYSIZE(lost1));
+ ExpectAcksAndLosses(true, acked1, QUICHE_ARRAYSIZE(acked1), lost1,
+ QUICHE_ARRAYSIZE(lost1));
EXPECT_CALL(notifier_, OnFrameLost(_)).Times(AnyNumber());
manager_.OnAckFrameStart(QuicPacketNumber(16), QuicTime::Delta::Infinite(),
clock_.Now());
@@ -2350,7 +2329,7 @@ TEST_F(QuicSentPacketManagerTest, TolerateReneging) {
// Making sure reneged ACK does not harm. Ack [4, 8), [9, 13).
uint64_t acked2[] = {4, 7, 9, 12};
- ExpectAcksAndLosses(true, acked2, QUIC_ARRAYSIZE(acked2), nullptr, 0);
+ ExpectAcksAndLosses(true, acked2, QUICHE_ARRAYSIZE(acked2), nullptr, 0);
manager_.OnAckFrameStart(QuicPacketNumber(12), QuicTime::Delta::Infinite(),
clock_.Now());
manager_.OnAckRange(QuicPacketNumber(9), QuicPacketNumber(13));
@@ -2363,16 +2342,23 @@ TEST_F(QuicSentPacketManagerTest, TolerateReneging) {
TEST_F(QuicSentPacketManagerTest, MultiplePacketNumberSpaces) {
manager_.EnableMultiplePacketNumberSpacesSupport();
+ const QuicUnackedPacketMap* unacked_packets =
+ QuicSentPacketManagerPeer::GetUnackedPacketMap(&manager_);
EXPECT_FALSE(
- manager_.GetLargestSentPacket(ENCRYPTION_INITIAL).IsInitialized());
+ unacked_packets
+ ->GetLargestSentRetransmittableOfPacketNumberSpace(INITIAL_DATA)
+ .IsInitialized());
EXPECT_FALSE(
manager_.GetLargestAckedPacket(ENCRYPTION_INITIAL).IsInitialized());
// Send packet 1.
SendDataPacket(1, ENCRYPTION_INITIAL);
EXPECT_EQ(QuicPacketNumber(1),
- manager_.GetLargestSentPacket(ENCRYPTION_INITIAL));
+ unacked_packets->GetLargestSentRetransmittableOfPacketNumberSpace(
+ INITIAL_DATA));
EXPECT_FALSE(
- manager_.GetLargestSentPacket(ENCRYPTION_HANDSHAKE).IsInitialized());
+ unacked_packets
+ ->GetLargestSentRetransmittableOfPacketNumberSpace(HANDSHAKE_DATA)
+ .IsInitialized());
// Ack packet 1.
ExpectAck(1);
manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(),
@@ -2389,11 +2375,15 @@ TEST_F(QuicSentPacketManagerTest, MultiplePacketNumberSpaces) {
SendDataPacket(2, ENCRYPTION_HANDSHAKE);
SendDataPacket(3, ENCRYPTION_HANDSHAKE);
EXPECT_EQ(QuicPacketNumber(1),
- manager_.GetLargestSentPacket(ENCRYPTION_INITIAL));
+ unacked_packets->GetLargestSentRetransmittableOfPacketNumberSpace(
+ INITIAL_DATA));
EXPECT_EQ(QuicPacketNumber(3),
- manager_.GetLargestSentPacket(ENCRYPTION_HANDSHAKE));
+ unacked_packets->GetLargestSentRetransmittableOfPacketNumberSpace(
+ HANDSHAKE_DATA));
EXPECT_FALSE(
- manager_.GetLargestSentPacket(ENCRYPTION_ZERO_RTT).IsInitialized());
+ unacked_packets
+ ->GetLargestSentRetransmittableOfPacketNumberSpace(APPLICATION_DATA)
+ .IsInitialized());
// Ack packet 2.
ExpectAck(2);
manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(),
@@ -2422,13 +2412,14 @@ TEST_F(QuicSentPacketManagerTest, MultiplePacketNumberSpaces) {
SendDataPacket(4, ENCRYPTION_ZERO_RTT);
SendDataPacket(5, ENCRYPTION_ZERO_RTT);
EXPECT_EQ(QuicPacketNumber(1),
- manager_.GetLargestSentPacket(ENCRYPTION_INITIAL));
+ unacked_packets->GetLargestSentRetransmittableOfPacketNumberSpace(
+ INITIAL_DATA));
EXPECT_EQ(QuicPacketNumber(3),
- manager_.GetLargestSentPacket(ENCRYPTION_HANDSHAKE));
+ unacked_packets->GetLargestSentRetransmittableOfPacketNumberSpace(
+ HANDSHAKE_DATA));
EXPECT_EQ(QuicPacketNumber(5),
- manager_.GetLargestSentPacket(ENCRYPTION_ZERO_RTT));
- EXPECT_EQ(QuicPacketNumber(5),
- manager_.GetLargestSentPacket(ENCRYPTION_FORWARD_SECURE));
+ unacked_packets->GetLargestSentRetransmittableOfPacketNumberSpace(
+ APPLICATION_DATA));
// Ack packet 5.
ExpectAck(5);
manager_.OnAckFrameStart(QuicPacketNumber(5), QuicTime::Delta::Infinite(),
@@ -2449,16 +2440,17 @@ TEST_F(QuicSentPacketManagerTest, MultiplePacketNumberSpaces) {
SendDataPacket(7, ENCRYPTION_FORWARD_SECURE);
SendDataPacket(8, ENCRYPTION_FORWARD_SECURE);
EXPECT_EQ(QuicPacketNumber(1),
- manager_.GetLargestSentPacket(ENCRYPTION_INITIAL));
+ unacked_packets->GetLargestSentRetransmittableOfPacketNumberSpace(
+ INITIAL_DATA));
EXPECT_EQ(QuicPacketNumber(3),
- manager_.GetLargestSentPacket(ENCRYPTION_HANDSHAKE));
- EXPECT_EQ(QuicPacketNumber(8),
- manager_.GetLargestSentPacket(ENCRYPTION_ZERO_RTT));
+ unacked_packets->GetLargestSentRetransmittableOfPacketNumberSpace(
+ HANDSHAKE_DATA));
EXPECT_EQ(QuicPacketNumber(8),
- manager_.GetLargestSentPacket(ENCRYPTION_FORWARD_SECURE));
+ unacked_packets->GetLargestSentRetransmittableOfPacketNumberSpace(
+ APPLICATION_DATA));
// Ack all packets.
uint64_t acked[] = {4, 6, 7, 8};
- ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
+ ExpectAcksAndLosses(true, acked, QUICHE_ARRAYSIZE(acked), nullptr, 0);
manager_.OnAckFrameStart(QuicPacketNumber(8), QuicTime::Delta::Infinite(),
clock_.Now());
manager_.OnAckRange(QuicPacketNumber(4), QuicPacketNumber(9));
@@ -2528,7 +2520,7 @@ TEST_F(QuicSentPacketManagerTest,
// Packet 1 gets acked in the wrong packet number space. Since packet 1 has
// been acked in the correct packet number space, tolerate it.
uint64_t acked[] = {2, 3};
- ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
+ ExpectAcksAndLosses(true, acked, QUICHE_ARRAYSIZE(acked), nullptr, 0);
manager_.OnAckFrameStart(QuicPacketNumber(3), QuicTime::Delta::Infinite(),
clock_.Now());
manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(4));
@@ -2567,7 +2559,7 @@ TEST_F(QuicSentPacketManagerTest, PacketInLimbo) {
// Received Ack of packets 1, 3 and 4.
uint64_t acked[] = {1, 3, 4};
- ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
+ ExpectAcksAndLosses(true, acked, QUICHE_ARRAYSIZE(acked), nullptr, 0);
manager_.OnAckFrameStart(QuicPacketNumber(4), QuicTime::Delta::Infinite(),
clock_.Now());
manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(5));
@@ -2580,8 +2572,8 @@ TEST_F(QuicSentPacketManagerTest, PacketInLimbo) {
uint64_t loss[] = {2};
// Verify packet 2 is detected lost.
EXPECT_CALL(notifier_, OnFrameLost(_)).Times(1);
- ExpectAcksAndLosses(true, acked2, QUIC_ARRAYSIZE(acked2), loss,
- QUIC_ARRAYSIZE(loss));
+ ExpectAcksAndLosses(true, acked2, QUICHE_ARRAYSIZE(acked2), loss,
+ QUICHE_ARRAYSIZE(loss));
manager_.OnAckFrameStart(QuicPacketNumber(6), QuicTime::Delta::Infinite(),
clock_.Now());
manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(7));
@@ -2663,7 +2655,7 @@ TEST_F(QuicSentPacketManagerTest, ComputingProbeTimeout) {
// Received ACK for packets 1 and 2.
uint64_t acked[] = {1, 2};
- ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
+ ExpectAcksAndLosses(true, acked, QUICHE_ARRAYSIZE(acked), nullptr, 0);
manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(),
clock_.Now());
manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(3));
@@ -2757,46 +2749,6 @@ TEST_F(QuicSentPacketManagerTest, DisableHandshakeModeServer) {
EXPECT_EQ(QuicTime::Zero(), manager_.GetRetransmissionTime());
}
-TEST_F(QuicSentPacketManagerTest, ForwardSecurePacketAcked) {
- EXPECT_LT(manager_.handshake_state(),
- QuicSentPacketManager::HANDSHAKE_CONFIRMED);
- SendDataPacket(1, ENCRYPTION_INITIAL);
- // Ack packet 1.
- ExpectAck(1);
- manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(),
- clock_.Now());
- manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
- EXPECT_EQ(PACKETS_NEWLY_ACKED,
- manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1),
- ENCRYPTION_INITIAL));
- EXPECT_LT(manager_.handshake_state(),
- QuicSentPacketManager::HANDSHAKE_CONFIRMED);
-
- SendDataPacket(2, ENCRYPTION_ZERO_RTT);
- // Ack packet 2.
- ExpectAck(2);
- manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(),
- clock_.Now());
- manager_.OnAckRange(QuicPacketNumber(2), QuicPacketNumber(3));
- EXPECT_EQ(PACKETS_NEWLY_ACKED,
- manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(2),
- ENCRYPTION_FORWARD_SECURE));
- EXPECT_LT(manager_.handshake_state(),
- QuicSentPacketManager::HANDSHAKE_CONFIRMED);
-
- SendDataPacket(3, ENCRYPTION_FORWARD_SECURE);
- // Ack packet 3.
- ExpectAck(3);
- manager_.OnAckFrameStart(QuicPacketNumber(3), QuicTime::Delta::Infinite(),
- clock_.Now());
- manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(4));
- EXPECT_EQ(PACKETS_NEWLY_ACKED,
- manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(3),
- ENCRYPTION_FORWARD_SECURE));
- EXPECT_EQ(manager_.handshake_state(),
- QuicSentPacketManager::HANDSHAKE_CONFIRMED);
-}
-
TEST_F(QuicSentPacketManagerTest, PtoTimeoutIncludesMaxAckDelay) {
EnablePto(k1PTO);
// Use PTOS and PTOA.
@@ -2858,7 +2810,7 @@ TEST_F(QuicSentPacketManagerTest, PtoTimeoutIncludesMaxAckDelay) {
// Received ACK for packets 1 and 2.
uint64_t acked[] = {1, 2};
- ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
+ ExpectAcksAndLosses(true, acked, QUICHE_ARRAYSIZE(acked), nullptr, 0);
manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(),
clock_.Now());
manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(3));
@@ -3067,17 +3019,13 @@ TEST_F(QuicSentPacketManagerTest, PtoTimeoutRttVarMultiple) {
TEST_F(QuicSentPacketManagerTest, RtoNotInFlightPacket) {
QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 2);
// Send SHLO.
- QuicStreamFrame crypto_frame(1, false, 0, QuicStringPiece());
+ QuicStreamFrame crypto_frame(1, false, 0, quiche::QuicheStringPiece());
SendCryptoPacket(1);
// Send data packet.
SendDataPacket(2, ENCRYPTION_FORWARD_SECURE);
// Successfully decrypt a forward secure packet.
- if (GetQuicReloadableFlag(quic_neuter_handshake_packets_once2)) {
- EXPECT_CALL(notifier_, OnFrameAcked(_, _, _)).Times(1);
- } else {
- EXPECT_CALL(notifier_, OnFrameAcked(_, _, _)).Times(0);
- }
+ EXPECT_CALL(notifier_, OnFrameAcked(_, _, _)).Times(1);
manager_.SetHandshakeConfirmed();
// 1st TLP.
@@ -3097,21 +3045,738 @@ TEST_F(QuicSentPacketManagerTest, RtoNotInFlightPacket) {
manager_.MaybeRetransmitTailLossProbe();
// RTO retransmits SHLO although it is not in flight.
- size_t num_rto_packets = 2;
- if (GetQuicReloadableFlag(quic_neuter_handshake_packets_once2)) {
- num_rto_packets = 1;
- }
EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .Times(num_rto_packets)
.WillOnce(WithArgs<0>(Invoke([&crypto_frame](const QuicFrames& frames) {
EXPECT_EQ(1u, frames.size());
- if (GetQuicReloadableFlag(quic_neuter_handshake_packets_once2)) {
- EXPECT_NE(crypto_frame, frames[0].stream_frame);
- } else {
- EXPECT_EQ(crypto_frame, frames[0].stream_frame);
- }
+ EXPECT_NE(crypto_frame, frames[0].stream_frame);
+ })));
+ manager_.OnRetransmissionTimeout();
+}
+
+TEST_F(QuicSentPacketManagerTest, Aggressive1Pto) {
+ EnablePto(k1PTO);
+ // Let the first PTO be aggressive.
+ QuicConfig config;
+ QuicTagVector options;
+ options.push_back(kPTOS);
+ options.push_back(kPAG1);
+ QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+ manager_.SetFromConfig(config);
+
+ EXPECT_CALL(*send_algorithm_, PacingRate(_))
+ .WillRepeatedly(Return(QuicBandwidth::Zero()));
+ EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
+ .WillRepeatedly(Return(10 * kDefaultTCPMSS));
+ RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
+ rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ QuicTime::Delta srtt = rtt_stats->smoothed_rtt();
+ SendDataPacket(1, ENCRYPTION_FORWARD_SECURE);
+ // Verify PTO is correctly set.
+ QuicTime::Delta expected_pto_delay = 2 * srtt;
+ EXPECT_EQ(clock_.Now() + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ // Invoke PTO.
+ clock_.AdvanceTime(expected_pto_delay);
+ manager_.OnRetransmissionTimeout();
+ EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
+ EXPECT_EQ(1u, stats_.pto_count);
+
+ // Verify 1 probe packets get sent and packet number gets skipped.
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
+ RetransmitDataPacket(3, type, ENCRYPTION_FORWARD_SECURE);
+ })));
+ manager_.MaybeSendProbePackets();
+
+ // Verify PTO period gets set correctly.
+ QuicTime sent_time = clock_.Now();
+ expected_pto_delay =
+ srtt + 4 * rtt_stats->mean_deviation() +
+ QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs);
+ EXPECT_EQ(sent_time + expected_pto_delay * 2,
+ manager_.GetRetransmissionTime());
+}
+
+TEST_F(QuicSentPacketManagerTest, Aggressive2Ptos) {
+ EnablePto(k1PTO);
+ // Let the first PTO be aggressive.
+ QuicConfig config;
+ QuicTagVector options;
+ options.push_back(kPTOS);
+ options.push_back(kPAG2);
+ QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+ manager_.SetFromConfig(config);
+
+ EXPECT_CALL(*send_algorithm_, PacingRate(_))
+ .WillRepeatedly(Return(QuicBandwidth::Zero()));
+ EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
+ .WillRepeatedly(Return(10 * kDefaultTCPMSS));
+ RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
+ rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ QuicTime::Delta srtt = rtt_stats->smoothed_rtt();
+ SendDataPacket(1, ENCRYPTION_FORWARD_SECURE);
+ // Verify PTO is correctly set.
+ QuicTime::Delta expected_pto_delay = 2 * srtt;
+ EXPECT_EQ(clock_.Now() + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ // Invoke PTO.
+ clock_.AdvanceTime(expected_pto_delay);
+ manager_.OnRetransmissionTimeout();
+ EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
+ EXPECT_EQ(1u, stats_.pto_count);
+
+ // Verify 1 probe packets get sent and packet number gets skipped.
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
+ RetransmitDataPacket(3, type, ENCRYPTION_FORWARD_SECURE);
+ })));
+ manager_.MaybeSendProbePackets();
+
+ // Verify PTO period gets set correctly.
+ EXPECT_EQ(clock_.Now() + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ // Invoke 2nd PTO.
+ clock_.AdvanceTime(expected_pto_delay);
+ manager_.OnRetransmissionTimeout();
+ EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
+ EXPECT_EQ(2u, stats_.pto_count);
+
+ // Verify 1 probe packets get sent and packet number gets skipped.
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
+ RetransmitDataPacket(5, type, ENCRYPTION_FORWARD_SECURE);
+ })));
+ manager_.MaybeSendProbePackets();
+ expected_pto_delay =
+ srtt + 4 * rtt_stats->mean_deviation() +
+ QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs);
+
+ // Verify PTO period gets set correctly.
+ EXPECT_EQ(clock_.Now() + expected_pto_delay * 4,
+ manager_.GetRetransmissionTime());
+}
+
+TEST_F(QuicSentPacketManagerTest, IW10ForUpAndDown) {
+ SetQuicReloadableFlag(quic_bbr_mitigate_overly_large_bandwidth_sample, true);
+ QuicConfig config;
+ QuicTagVector options;
+ options.push_back(kBWS5);
+ QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ EXPECT_CALL(*send_algorithm_, SetInitialCongestionWindowInPackets(10));
+ EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+ manager_.SetFromConfig(config);
+
+ EXPECT_EQ(10u, manager_.initial_congestion_window());
+}
+
+TEST_F(QuicSentPacketManagerTest, ClientMultiplePacketNumberSpacePtoTimeout) {
+ manager_.EnableMultiplePacketNumberSpacesSupport();
+ EnablePto(k1PTO);
+ EXPECT_CALL(*send_algorithm_, PacingRate(_))
+ .WillRepeatedly(Return(QuicBandwidth::Zero()));
+ EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
+ .WillRepeatedly(Return(10 * kDefaultTCPMSS));
+ RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
+ rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ QuicTime::Delta srtt = rtt_stats->smoothed_rtt();
+ QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT);
+
+ // Send packet 1.
+ SendDataPacket(1, ENCRYPTION_INITIAL);
+ // Verify PTO is correctly set.
+ QuicTime::Delta expected_pto_delay =
+ srtt + 4 * rtt_stats->mean_deviation() +
+ QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs);
+ EXPECT_EQ(clock_.Now() + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ // Discard initial key and send packet 2 in handshake.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+ EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
+ manager_.NeuterUnencryptedPackets();
+
+ EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(true));
+ SendDataPacket(2, ENCRYPTION_HANDSHAKE);
+ // Verify PTO is correctly set based on sent time of packet 2.
+ EXPECT_EQ(clock_.Now() + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+ // Invoke PTO.
+ clock_.AdvanceTime(expected_pto_delay);
+ manager_.OnRetransmissionTimeout();
+ EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
+ EXPECT_EQ(1u, stats_.pto_count);
+
+ // Verify probe packet gets sent.
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
+ RetransmitDataPacket(3, type, ENCRYPTION_HANDSHAKE);
+ })));
+ manager_.MaybeSendProbePackets();
+ // Verify PTO period gets set to twice the current value.
+ const QuicTime packet3_sent_time = clock_.Now();
+ EXPECT_EQ(packet3_sent_time + expected_pto_delay * 2,
+ manager_.GetRetransmissionTime());
+
+ // Send packet 4 in application data with 0-RTT.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+ SendDataPacket(4, ENCRYPTION_ZERO_RTT);
+ const QuicTime packet4_sent_time = clock_.Now();
+ // Verify PTO timeout is still based on packet 3.
+ EXPECT_EQ(packet3_sent_time + expected_pto_delay * 2,
+ manager_.GetRetransmissionTime());
+
+ // Send packet 5 in handshake.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+ SendDataPacket(5, ENCRYPTION_HANDSHAKE);
+ const QuicTime packet5_sent_time = clock_.Now();
+ // Verify PTO timeout is now based on packet 5 because packet 4 should be
+ // ignored.
+ EXPECT_EQ(clock_.Now() + expected_pto_delay * 2,
+ manager_.GetRetransmissionTime());
+
+ // Send packet 6 in 1-RTT.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+ SendDataPacket(6, ENCRYPTION_FORWARD_SECURE);
+ const QuicTime packet6_sent_time = clock_.Now();
+ // Verify PTO timeout is now based on packet 5.
+ EXPECT_EQ(packet5_sent_time + expected_pto_delay * 2,
+ manager_.GetRetransmissionTime());
+
+ // Send packet 7 in handshake.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+ SendDataPacket(7, ENCRYPTION_HANDSHAKE);
+ // Verify PTO timeout is now based on packet 6.
+ EXPECT_EQ(packet6_sent_time + expected_pto_delay * 2,
+ manager_.GetRetransmissionTime());
+
+ // Neuter handshake key.
+ manager_.SetHandshakeConfirmed();
+ // Forward progress has been made, verify PTO counter gets reset. PTO timeout
+ // is armed by left edge.
+ EXPECT_EQ(packet4_sent_time + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+}
+
+TEST_F(QuicSentPacketManagerTest, ServerMultiplePacketNumberSpacePtoTimeout) {
+ manager_.EnableMultiplePacketNumberSpacesSupport();
+ EnablePto(k1PTO);
+ EXPECT_CALL(*send_algorithm_, PacingRate(_))
+ .WillRepeatedly(Return(QuicBandwidth::Zero()));
+ EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
+ .WillRepeatedly(Return(10 * kDefaultTCPMSS));
+ RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
+ rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ QuicTime::Delta srtt = rtt_stats->smoothed_rtt();
+
+ // Send packet 1.
+ SendDataPacket(1, ENCRYPTION_INITIAL);
+ const QuicTime packet1_sent_time = clock_.Now();
+ // Verify PTO is correctly set.
+ QuicTime::Delta expected_pto_delay =
+ srtt + 4 * rtt_stats->mean_deviation() +
+ QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs);
+ EXPECT_EQ(packet1_sent_time + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ // Send packet 2 in handshake.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+ SendDataPacket(2, ENCRYPTION_HANDSHAKE);
+ const QuicTime packet2_sent_time = clock_.Now();
+ // Verify PTO timeout is still based on packet 1.
+ EXPECT_EQ(packet1_sent_time + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ // Discard initial keys.
+ EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
+ manager_.NeuterUnencryptedPackets();
+
+ // Send packet 3 in 1-RTT.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+ SendDataPacket(3, ENCRYPTION_FORWARD_SECURE);
+ // Verify PTO timeout is based on packet 2.
+ const QuicTime packet3_sent_time = clock_.Now();
+ EXPECT_EQ(packet2_sent_time + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ // Send packet 4 in handshake.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+ SendDataPacket(4, ENCRYPTION_HANDSHAKE);
+ // Verify PTO timeout is based on packet 4 as application data is ignored.
+ EXPECT_EQ(clock_.Now() + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ // Discard handshake keys.
+ manager_.SetHandshakeConfirmed();
+ // Verify PTO timeout is now based on packet 3 as handshake is
+ // complete/confirmed.
+ EXPECT_EQ(packet3_sent_time + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+}
+
+TEST_F(QuicSentPacketManagerTest, ComputingProbeTimeoutByLeftEdge) {
+ SetQuicReloadableFlag(quic_arm_pto_with_earliest_sent_time, true);
+ EnablePto(k1PTO);
+ // Use PTOS and PLE1.
+ QuicConfig config;
+ QuicTagVector options;
+ options.push_back(kPTOS);
+ options.push_back(kPLE1);
+ QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+ manager_.SetFromConfig(config);
+ EXPECT_TRUE(manager_.skip_packet_number_for_pto());
+ EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
+ EXPECT_CALL(*send_algorithm_, PacingRate(_))
+ .WillRepeatedly(Return(QuicBandwidth::Zero()));
+ EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
+ .WillRepeatedly(Return(10 * kDefaultTCPMSS));
+ RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
+ rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ QuicTime::Delta srtt = rtt_stats->smoothed_rtt();
+
+ SendDataPacket(1, ENCRYPTION_FORWARD_SECURE);
+ // Verify PTO is correctly set.
+ QuicTime::Delta expected_pto_delay =
+ srtt + 4 * rtt_stats->mean_deviation() +
+ QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs);
+ const QuicTime packet1_sent_time = clock_.Now();
+ EXPECT_EQ(packet1_sent_time + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+ SendDataPacket(2, ENCRYPTION_FORWARD_SECURE);
+ // Verify PTO is still based on packet 1.
+ EXPECT_EQ(packet1_sent_time + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+ EXPECT_EQ(0u, stats_.pto_count);
+
+ // Invoke PTO.
+ clock_.AdvanceTime(expected_pto_delay);
+ manager_.OnRetransmissionTimeout();
+ EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
+ EXPECT_EQ(1u, stats_.pto_count);
+
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
+ RetransmitDataPacket(3, type, ENCRYPTION_FORWARD_SECURE);
})));
+ manager_.MaybeSendProbePackets();
+ // Verify PTO period gets set to twice the current value and based on packet3.
+ QuicTime packet3_sent_time = clock_.Now();
+ EXPECT_EQ(packet3_sent_time + expected_pto_delay * 2,
+ manager_.GetRetransmissionTime());
+
+ // Received ACK for packets 1 and 2.
+ uint64_t acked[] = {1, 2};
+ ExpectAcksAndLosses(true, acked, QUICHE_ARRAYSIZE(acked), nullptr, 0);
+ manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(3));
+ EXPECT_EQ(PACKETS_NEWLY_ACKED,
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1),
+ ENCRYPTION_FORWARD_SECURE));
+ expected_pto_delay =
+ rtt_stats->SmoothedOrInitialRtt() +
+ std::max(4 * rtt_stats->mean_deviation(),
+ QuicTime::Delta::FromMilliseconds(1)) +
+ QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs);
+
+ // Verify PTO is correctly re-armed based on sent time of packet 4.
+ EXPECT_EQ(packet3_sent_time + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+}
+
+TEST_F(QuicSentPacketManagerTest, ComputingProbeTimeoutByLeftEdge2) {
+ SetQuicReloadableFlag(quic_arm_pto_with_earliest_sent_time, true);
+ EnablePto(k1PTO);
+ // Use PTOS and PLE2.
+ QuicConfig config;
+ QuicTagVector options;
+ options.push_back(kPTOS);
+ options.push_back(kPLE2);
+ QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+ manager_.SetFromConfig(config);
+ EXPECT_TRUE(manager_.skip_packet_number_for_pto());
+ EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
+ EXPECT_CALL(*send_algorithm_, PacingRate(_))
+ .WillRepeatedly(Return(QuicBandwidth::Zero()));
+ EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
+ .WillRepeatedly(Return(10 * kDefaultTCPMSS));
+ RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
+ rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ QuicTime::Delta srtt = rtt_stats->smoothed_rtt();
+
+ SendDataPacket(1, ENCRYPTION_FORWARD_SECURE);
+ // Verify PTO is correctly set.
+ QuicTime::Delta expected_pto_delay =
+ srtt + 4 * rtt_stats->mean_deviation() +
+ QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs);
+ const QuicTime packet1_sent_time = clock_.Now();
+ EXPECT_EQ(packet1_sent_time + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ // Sent a packet 10ms before PTO expiring.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(
+ expected_pto_delay.ToMilliseconds() - 10));
+ SendDataPacket(2, ENCRYPTION_FORWARD_SECURE);
+ // Verify PTO expands to packet 2 sent time + 1.5 * srtt.
+ expected_pto_delay = 1.5 * rtt_stats->smoothed_rtt();
+ EXPECT_EQ(clock_.Now() + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+ EXPECT_EQ(0u, stats_.pto_count);
+
+ // Invoke PTO.
+ clock_.AdvanceTime(expected_pto_delay);
manager_.OnRetransmissionTimeout();
+ EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
+ EXPECT_EQ(1u, stats_.pto_count);
+
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
+ RetransmitDataPacket(3, type, ENCRYPTION_FORWARD_SECURE);
+ })));
+ manager_.MaybeSendProbePackets();
+ // Verify PTO period gets set to twice the expected value and based on
+ // packet3 (right edge).
+ expected_pto_delay =
+ srtt + 4 * rtt_stats->mean_deviation() +
+ QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs);
+ QuicTime packet3_sent_time = clock_.Now();
+ EXPECT_EQ(packet3_sent_time + expected_pto_delay * 2,
+ manager_.GetRetransmissionTime());
+
+ // Received ACK for packets 1 and 2.
+ uint64_t acked[] = {1, 2};
+ ExpectAcksAndLosses(true, acked, QUICHE_ARRAYSIZE(acked), nullptr, 0);
+ manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(3));
+ EXPECT_EQ(PACKETS_NEWLY_ACKED,
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1),
+ ENCRYPTION_FORWARD_SECURE));
+ expected_pto_delay =
+ rtt_stats->SmoothedOrInitialRtt() +
+ std::max(4 * rtt_stats->mean_deviation(),
+ QuicTime::Delta::FromMilliseconds(1)) +
+ QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs);
+
+ // Verify PTO is correctly re-armed based on sent time of packet 3 (left
+ // edge).
+ EXPECT_EQ(packet3_sent_time + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+}
+
+TEST_F(QuicSentPacketManagerTest, ComputingProbeTimeoutUsingStandardDeviation) {
+ SetQuicReloadableFlag(quic_use_standard_deviation_for_pto, true);
+ EnablePto(k1PTO);
+ // Use PTOS and PSDA.
+ QuicConfig config;
+ QuicTagVector options;
+ options.push_back(kPTOS);
+ options.push_back(kPSDA);
+ QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+ manager_.SetFromConfig(config);
+ EXPECT_TRUE(manager_.skip_packet_number_for_pto());
+ EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
+ EXPECT_CALL(*send_algorithm_, PacingRate(_))
+ .WillRepeatedly(Return(QuicBandwidth::Zero()));
+ EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
+ .WillRepeatedly(Return(10 * kDefaultTCPMSS));
+ RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
+ rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(50),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(50),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(75),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ QuicTime::Delta srtt = rtt_stats->smoothed_rtt();
+
+ SendDataPacket(1, ENCRYPTION_FORWARD_SECURE);
+ // Verify PTO is correctly set using standard deviation.
+ QuicTime::Delta expected_pto_delay =
+ srtt + 4 * rtt_stats->GetStandardOrMeanDeviation() +
+ QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs);
+ EXPECT_EQ(clock_.Now() + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+}
+
+TEST_F(QuicSentPacketManagerTest,
+ ComputingProbeTimeoutByLeftEdgeMultiplePacketNumberSpaces) {
+ SetQuicReloadableFlag(quic_arm_pto_with_earliest_sent_time, true);
+ manager_.EnableMultiplePacketNumberSpacesSupport();
+ EnablePto(k1PTO);
+ // Use PTOS and PLE1.
+ QuicConfig config;
+ QuicTagVector options;
+ options.push_back(kPTOS);
+ options.push_back(kPLE1);
+ QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+ manager_.SetFromConfig(config);
+ EXPECT_TRUE(manager_.skip_packet_number_for_pto());
+ EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
+ EXPECT_CALL(*send_algorithm_, PacingRate(_))
+ .WillRepeatedly(Return(QuicBandwidth::Zero()));
+ EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
+ .WillRepeatedly(Return(10 * kDefaultTCPMSS));
+ RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
+ rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ QuicTime::Delta srtt = rtt_stats->smoothed_rtt();
+
+ // Send packet 1.
+ SendDataPacket(1, ENCRYPTION_INITIAL);
+ const QuicTime packet1_sent_time = clock_.Now();
+ // Verify PTO is correctly set.
+ QuicTime::Delta expected_pto_delay =
+ srtt + 4 * rtt_stats->mean_deviation() +
+ QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs);
+ EXPECT_EQ(packet1_sent_time + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ // Send packet 2 in handshake.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+ SendDataPacket(2, ENCRYPTION_HANDSHAKE);
+ const QuicTime packet2_sent_time = clock_.Now();
+ // Verify PTO timeout is still based on packet 1.
+ EXPECT_EQ(packet1_sent_time + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ // Discard initial keys.
+ EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
+ manager_.NeuterUnencryptedPackets();
+
+ // Send packet 3 in 1-RTT.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+ SendDataPacket(3, ENCRYPTION_FORWARD_SECURE);
+ // Verify PTO timeout is based on packet 2.
+ const QuicTime packet3_sent_time = clock_.Now();
+ EXPECT_EQ(packet2_sent_time + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ // Send packet 4 in handshake.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+ SendDataPacket(4, ENCRYPTION_HANDSHAKE);
+ // Verify PTO timeout is based on packet 4 as application data is ignored.
+ EXPECT_EQ(clock_.Now() + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ // Discard handshake keys.
+ manager_.SetHandshakeConfirmed();
+ // Verify PTO timeout is now based on packet 3 as handshake is
+ // complete/confirmed.
+ EXPECT_EQ(packet3_sent_time + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+ SendDataPacket(5, ENCRYPTION_FORWARD_SECURE);
+ // Verify PTO timeout is still based on packet 3.
+ EXPECT_EQ(packet3_sent_time + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+}
+
+TEST_F(QuicSentPacketManagerTest,
+ ComputingProbeTimeoutByLeftEdge2MultiplePacketNumberSpaces) {
+ SetQuicReloadableFlag(quic_arm_pto_with_earliest_sent_time, true);
+ manager_.EnableMultiplePacketNumberSpacesSupport();
+ EnablePto(k1PTO);
+ // Use PTOS and PLE2.
+ QuicConfig config;
+ QuicTagVector options;
+ options.push_back(kPTOS);
+ options.push_back(kPLE2);
+ QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+ manager_.SetFromConfig(config);
+ EXPECT_TRUE(manager_.skip_packet_number_for_pto());
+ EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
+ EXPECT_CALL(*send_algorithm_, PacingRate(_))
+ .WillRepeatedly(Return(QuicBandwidth::Zero()));
+ EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
+ .WillRepeatedly(Return(10 * kDefaultTCPMSS));
+ RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
+ rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ QuicTime::Delta srtt = rtt_stats->smoothed_rtt();
+
+ // Send packet 1.
+ SendDataPacket(1, ENCRYPTION_INITIAL);
+ const QuicTime packet1_sent_time = clock_.Now();
+ // Verify PTO is correctly set.
+ QuicTime::Delta expected_pto_delay =
+ srtt + 4 * rtt_stats->mean_deviation() +
+ QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs);
+ EXPECT_EQ(packet1_sent_time + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ // Send packet 2 in handshake.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+ SendDataPacket(2, ENCRYPTION_HANDSHAKE);
+ const QuicTime packet2_sent_time = clock_.Now();
+ // Verify PTO timeout is still based on packet 1.
+ EXPECT_EQ(packet1_sent_time + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ // Discard initial keys.
+ EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
+ manager_.NeuterUnencryptedPackets();
+
+ // Send packet 3 in 1-RTT.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+ SendDataPacket(3, ENCRYPTION_FORWARD_SECURE);
+ // Verify PTO timeout is based on packet 2.
+ const QuicTime packet3_sent_time = clock_.Now();
+ EXPECT_EQ(packet2_sent_time + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ // Send packet 4 in handshake.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+ SendDataPacket(4, ENCRYPTION_HANDSHAKE);
+ // Verify PTO timeout is based on packet 4 as application data is ignored.
+ EXPECT_EQ(clock_.Now() + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ // Discard handshake keys.
+ manager_.SetHandshakeConfirmed();
+ // Verify PTO timeout is now based on packet 3 as handshake is
+ // complete/confirmed.
+ EXPECT_EQ(packet3_sent_time + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ // Send packet 5 10ms before PTO expiring.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(
+ expected_pto_delay.ToMilliseconds() - 10));
+ SendDataPacket(5, ENCRYPTION_FORWARD_SECURE);
+ // Verify PTO timeout expands to packet 5 sent time + 1.5 * srtt.
+ EXPECT_EQ(clock_.Now() + 1.5 * rtt_stats->smoothed_rtt(),
+ manager_.GetRetransmissionTime());
+}
+
+TEST_F(QuicSentPacketManagerTest, SetHandshakeConfirmed) {
+ QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT);
+ manager_.EnableMultiplePacketNumberSpacesSupport();
+
+ SendDataPacket(1, ENCRYPTION_INITIAL);
+
+ SendDataPacket(2, ENCRYPTION_HANDSHAKE);
+
+ EXPECT_CALL(notifier_, OnFrameAcked(_, _, _))
+ .WillOnce(
+ Invoke([](const QuicFrame& /*frame*/, QuicTime::Delta ack_delay_time,
+ QuicTime receive_timestamp) {
+ EXPECT_TRUE(ack_delay_time.IsZero());
+ EXPECT_EQ(receive_timestamp, QuicTime::Zero());
+ return true;
+ }));
+
+ if (GetQuicReloadableFlag(
+ quic_avoid_overestimate_bandwidth_with_aggregation)) {
+ EXPECT_CALL(*send_algorithm_, OnPacketNeutered(QuicPacketNumber(2)))
+ .Times(1);
+ }
+ manager_.SetHandshakeConfirmed();
+}
+
+// Regresstion test for b/148841700.
+TEST_F(QuicSentPacketManagerTest, NeuterUnencryptedPackets) {
+ SendCryptoPacket(1);
+ SendPingPacket(2, ENCRYPTION_INITIAL);
+ // Crypto data has been discarded but ping does not.
+ EXPECT_CALL(notifier_, OnFrameAcked(_, _, _))
+ .Times(2)
+ .WillOnce(Return(false))
+ .WillOnce(Return(true));
+ EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
+ if (GetQuicReloadableFlag(
+ quic_avoid_overestimate_bandwidth_with_aggregation)) {
+ EXPECT_CALL(*send_algorithm_, OnPacketNeutered(QuicPacketNumber(1)))
+ .Times(1);
+ }
+ manager_.NeuterUnencryptedPackets();
+}
+
+TEST_F(QuicSentPacketManagerTest, NoPacketThresholdDetectionForRuntPackets) {
+ EXPECT_TRUE(
+ QuicSentPacketManagerPeer::UsePacketThresholdForRuntPackets(&manager_));
+
+ SetQuicReloadableFlag(quic_skip_packet_threshold_loss_detection_with_runt,
+ true);
+ QuicConfig config;
+ QuicTagVector options;
+ options.push_back(kRUNT);
+ QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+ manager_.SetFromConfig(config);
+
+ EXPECT_FALSE(
+ QuicSentPacketManagerPeer::UsePacketThresholdForRuntPackets(&manager_));
+}
+
+TEST_F(QuicSentPacketManagerTest, GetPathDegradingDelay) {
+ QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 2);
+ // Before RTT sample is available.
+ // 2 TLPs + 2 RTOs.
+ QuicTime::Delta expected_delay = QuicTime::Delta::Zero();
+ for (size_t i = 0; i < 2; ++i) {
+ QuicSentPacketManagerPeer::SetConsecutiveTlpCount(&manager_, i);
+ expected_delay =
+ expected_delay +
+ QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_);
+ }
+ for (size_t i = 0; i < 2; ++i) {
+ QuicSentPacketManagerPeer::SetConsecutiveRtoCount(&manager_, i);
+ expected_delay =
+ expected_delay +
+ QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_);
+ }
+ EXPECT_EQ(expected_delay, manager_.GetPathDegradingDelay());
+
+ expected_delay = QuicTime::Delta::Zero();
+ QuicSentPacketManagerPeer::SetConsecutiveTlpCount(&manager_, 0);
+ QuicSentPacketManagerPeer::SetConsecutiveRtoCount(&manager_, 0);
+
+ // After RTT sample is available.
+ RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
+ rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ // 2 TLPs + 2 RTOs.
+ for (size_t i = 0; i < 2; ++i) {
+ QuicSentPacketManagerPeer::SetConsecutiveTlpCount(&manager_, i);
+ expected_delay =
+ expected_delay +
+ QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_);
+ }
+ for (size_t i = 0; i < 2; ++i) {
+ QuicSentPacketManagerPeer::SetConsecutiveRtoCount(&manager_, i);
+ expected_delay =
+ expected_delay +
+ QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_);
+ }
+ EXPECT_EQ(expected_delay, manager_.GetPathDegradingDelay());
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_server_id.cc b/chromium/net/third_party/quiche/src/quic/core/quic_server_id.cc
index 6a4e56f88b9..653152df84b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_server_id.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_server_id.cc
@@ -8,7 +8,6 @@
#include <tuple>
#include "net/third_party/quiche/src/quic/platform/api/quic_estimate_memory_usage.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_session.cc b/chromium/net/third_party/quiche/src/quic/core/quic_session.cc
index ada8bf41d9d..5376bfdddde 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_session.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_session.cc
@@ -22,7 +22,8 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_server_stats.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_stack_trace.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
using spdy::SpdyPriority;
@@ -44,6 +45,24 @@ class ClosedStreamsCleanUpDelegate : public QuicAlarm::Delegate {
QuicSession* session_;
};
+// TODO(renjietang): remove this function once
+// gfe2_reloadable_flag_quic_write_with_transmission is deprecated.
+void CountTransmissionTypeFlag(TransmissionType type) {
+ switch (type) {
+ case NOT_RETRANSMISSION:
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_write_with_transmission, 1, 4);
+ break;
+ case HANDSHAKE_RETRANSMISSION:
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_write_with_transmission, 2, 4);
+ break;
+ case LOSS_RETRANSMISSION:
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_write_with_transmission, 3, 4);
+ break;
+ default:
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_write_with_transmission, 4, 4);
+ }
+}
+
} // namespace
#define ENDPOINT \
@@ -56,21 +75,22 @@ QuicSession::QuicSession(
const ParsedQuicVersionVector& supported_versions,
QuicStreamCount num_expected_unidirectional_static_streams)
: connection_(connection),
+ perspective_(connection->perspective()),
visitor_(owner),
write_blocked_streams_(connection->transport_version()),
config_(config),
- stream_id_manager_(this,
+ stream_id_manager_(perspective(),
+ connection->transport_version(),
kDefaultMaxStreamsPerConnection,
- config_.GetMaxIncomingBidirectionalStreamsToSend()),
- v99_streamid_manager_(
- perspective(),
- connection->version(),
- this,
- num_expected_unidirectional_static_streams,
- kDefaultMaxStreamsPerConnection,
- kDefaultMaxStreamsPerConnection,
- config_.GetMaxIncomingBidirectionalStreamsToSend(),
- config_.GetMaxIncomingUnidirectionalStreamsToSend()),
+ config_.GetMaxBidirectionalStreamsToSend()),
+ v99_streamid_manager_(perspective(),
+ connection->version(),
+ this,
+ 0,
+ num_expected_unidirectional_static_streams,
+ config_.GetMaxBidirectionalStreamsToSend(),
+ config_.GetMaxUnidirectionalStreamsToSend() +
+ num_expected_unidirectional_static_streams),
num_dynamic_incoming_streams_(0),
num_draining_incoming_streams_(0),
num_outgoing_static_streams_(0),
@@ -92,13 +112,16 @@ QuicSession::QuicSession(
goaway_received_(false),
control_frame_manager_(this),
last_message_id_(0),
+ datagram_queue_(this),
closed_streams_clean_up_alarm_(nullptr),
supported_versions_(supported_versions),
use_http2_priority_write_scheduler_(false),
is_configured_(false),
num_expected_unidirectional_static_streams_(
num_expected_unidirectional_static_streams),
- enable_round_robin_scheduling_(false) {
+ enable_round_robin_scheduling_(false),
+ write_with_transmission_(
+ GetQuicReloadableFlag(quic_write_with_transmission)) {
closed_streams_clean_up_alarm_ =
QuicWrapUnique<QuicAlarm>(connection_->alarm_factory()->CreateAlarm(
new ClosedStreamsCleanUpDelegate(this)));
@@ -116,8 +139,7 @@ void QuicSession::Initialize() {
// On the server side, version negotiation has been done by the dispatcher,
// and the server session is created with the right version.
- if (connection_->quic_version_negotiated_by_default_at_server() &&
- perspective() == Perspective::IS_SERVER) {
+ if (perspective() == Perspective::IS_SERVER) {
connection_->OnSuccessfulVersionNegotiation();
}
@@ -131,6 +153,16 @@ void QuicSession::Initialize() {
QuicSession::~QuicSession() {
QUIC_LOG_IF(WARNING, !zombie_streams_.empty()) << "Still have zombie streams";
+ QUIC_LOG_IF(WARNING, num_locally_closed_incoming_streams_highest_offset() >
+ stream_id_manager_.max_open_incoming_streams())
+ << "Surprisingly high number of locally closed peer initiated streams"
+ "still waiting for final byte offset: "
+ << num_locally_closed_incoming_streams_highest_offset();
+ QUIC_LOG_IF(WARNING, GetNumLocallyClosedOutgoingStreamsHighestOffset() >
+ stream_id_manager_.max_open_outgoing_streams())
+ << "Surprisingly high number of locally closed self initiated streams"
+ "still waiting for final byte offset: "
+ << GetNumLocallyClosedOutgoingStreamsHighestOffset();
}
void QuicSession::PendingStreamOnStreamFrame(const QuicStreamFrame& frame) {
@@ -164,7 +196,6 @@ void QuicSession::PendingStreamOnStreamFrame(const QuicStreamFrame& frame) {
}
void QuicSession::OnStreamFrame(const QuicStreamFrame& frame) {
- // TODO(rch) deal with the error case of stream id 0.
QuicStreamId stream_id = frame.stream_id;
if (stream_id == QuicUtils::GetInvalidStreamId(transport_version())) {
connection()->CloseConnection(
@@ -194,12 +225,6 @@ void QuicSession::OnStreamFrame(const QuicStreamFrame& frame) {
}
return;
}
- if (frame.fin && stream->is_static()) {
- connection()->CloseConnection(
- QUIC_INVALID_STREAM_ID, "Attempt to close a static stream",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- return;
- }
stream->OnStreamFrame(frame);
}
@@ -210,9 +235,13 @@ void QuicSession::OnCryptoFrame(const QuicCryptoFrame& frame) {
void QuicSession::OnStopSendingFrame(const QuicStopSendingFrame& frame) {
// STOP_SENDING is in IETF QUIC only.
DCHECK(VersionHasIetfQuicFrames(transport_version()));
+ DCHECK(QuicVersionUsesCryptoFrames(transport_version()));
QuicStreamId stream_id = frame.stream_id;
// If Stream ID is invalid then close the connection.
+ // TODO(ianswett): This check is redundant to checks for IsClosedStream,
+ // but removing it requires removing multiple DCHECKs.
+ // TODO(ianswett): Multiple QUIC_DVLOGs could be QUIC_PEER_BUGs.
if (stream_id == QuicUtils::GetInvalidStreamId(transport_version())) {
QUIC_DVLOG(1) << ENDPOINT
<< "Received STOP_SENDING with invalid stream_id: "
@@ -223,53 +252,34 @@ void QuicSession::OnStopSendingFrame(const QuicStopSendingFrame& frame) {
return;
}
- if (visitor_) {
- visitor_->OnStopSendingReceived(frame);
- }
-
- // If stream is closed, ignore the frame
- if (IsClosedStream(stream_id)) {
- QUIC_DVLOG(1)
- << ENDPOINT
- << "Received STOP_SENDING for closed or non-existent stream, id: "
- << stream_id << " Ignoring.";
- return;
- }
- // If stream is non-existent, close the connection
- StreamMap::iterator it = stream_map_.find(stream_id);
- if (it == stream_map_.end()) {
+ // If stream_id is READ_UNIDIRECTIONAL, close the connection.
+ if (QuicUtils::GetStreamType(stream_id, perspective(),
+ IsIncomingStream(stream_id)) ==
+ READ_UNIDIRECTIONAL) {
QUIC_DVLOG(1) << ENDPOINT
- << "Received STOP_SENDING for non-existent stream, id: "
- << stream_id << " Closing connection";
+ << "Received STOP_SENDING for a read-only stream_id: "
+ << stream_id << ".";
connection()->CloseConnection(
- IETF_QUIC_PROTOCOL_VIOLATION,
- "Received STOP_SENDING for a non-existent stream",
+ QUIC_INVALID_STREAM_ID, "Received STOP_SENDING for a read-only stream",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return;
}
- QuicStream* stream = it->second.get();
- if (stream == nullptr) {
- QUIC_BUG << ENDPOINT
- << "Received STOP_SENDING for NULL QuicStream, stream_id: "
- << stream_id << ". Ignoring.";
- return;
+ if (visitor_) {
+ visitor_->OnStopSendingReceived(frame);
}
- if (stream->is_static()) {
- QUIC_DVLOG(1) << ENDPOINT
- << "Received STOP_SENDING for a static stream, id: "
- << stream_id << " Closing connection";
- connection()->CloseConnection(
- QUIC_INVALID_STREAM_ID, "Received STOP_SENDING for a static stream",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ QuicStream* stream = GetOrCreateStream(stream_id);
+ if (!stream) {
+ // Errors are handled by GetOrCreateStream.
return;
}
- stream->OnStopSending(frame.application_error_code);
+ if (!stream->OnStopSending(frame.application_error_code)) {
+ return;
+ }
- stream->set_stream_error(
- static_cast<QuicRstStreamErrorCode>(frame.application_error_code));
+ // TODO(renjietang): Consider moving those code into the stream.
if (connection()->connected()) {
MaybeSendRstStreamFrame(
stream->id(),
@@ -287,6 +297,10 @@ void QuicSession::OnPacketDecrypted(EncryptionLevel level) {
GetMutableCryptoStream()->OnPacketDecrypted(level);
}
+void QuicSession::OnOneRttPacketAcknowledged() {
+ GetMutableCryptoStream()->OnOneRttPacketAcknowledged();
+}
+
void QuicSession::PendingStreamOnRstStream(const QuicRstStreamFrame& frame) {
DCHECK(VersionUsesHttp3(transport_version()));
QuicStreamId stream_id = frame.stream_id;
@@ -344,12 +358,6 @@ void QuicSession::OnRstStream(const QuicRstStreamFrame& frame) {
HandleRstOnValidNonexistentStream(frame);
return; // Errors are handled by GetOrCreateStream.
}
- if (stream->is_static()) {
- connection()->CloseConnection(
- QUIC_INVALID_STREAM_ID, "Attempt to reset a static stream",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- return;
- }
stream->OnStreamReset(frame);
}
@@ -357,11 +365,16 @@ void QuicSession::OnGoAway(const QuicGoAwayFrame& /*frame*/) {
goaway_received_ = true;
}
-void QuicSession::OnMessageReceived(QuicStringPiece message) {
+void QuicSession::OnMessageReceived(quiche::QuicheStringPiece message) {
QUIC_DVLOG(1) << ENDPOINT << "Received message, length: " << message.length()
<< ", " << message;
}
+void QuicSession::OnHandshakeDoneReceived() {
+ QUIC_DVLOG(1) << ENDPOINT << "OnHandshakeDoneReceived";
+ GetMutableCryptoStream()->OnHandshakeDoneReceived();
+}
+
// static
void QuicSession::RecordConnectionCloseAtServer(QuicErrorCode error,
ConnectionCloseSource source) {
@@ -433,9 +446,7 @@ void QuicSession::OnWriteBlocked() {
}
void QuicSession::OnSuccessfulVersionNegotiation(
- const ParsedQuicVersion& version) {
- GetMutableCryptoStream()->OnSuccessfulVersionNegotiation(version);
-}
+ const ParsedQuicVersion& /*version*/) {}
void QuicSession::OnPacketReceived(const QuicSocketAddress& /*self_address*/,
const QuicSocketAddress& peer_address,
@@ -547,7 +558,9 @@ void QuicSession::OnCanWrite() {
"write blocked.";
return;
}
- SetTransmissionType(NOT_RETRANSMISSION);
+ if (!write_with_transmission_) {
+ SetTransmissionType(NOT_RETRANSMISSION);
+ }
// We limit the number of writes to the number of pending streams. If more
// streams become pending, WillingAndAbleToWrite will be true, which will
// cause the connection to request resumption before yielding to other
@@ -559,6 +572,7 @@ void QuicSession::OnCanWrite() {
? write_blocked_streams_.NumBlockedSpecialStreams()
: write_blocked_streams_.NumBlockedStreams();
if (num_writes == 0 && !control_frame_manager_.WillingToWrite() &&
+ datagram_queue_.empty() &&
(!QuicVersionUsesCryptoFrames(transport_version()) ||
!GetCryptoStream()->HasBufferedCryptoFrames())) {
return;
@@ -579,11 +593,30 @@ void QuicSession::OnCanWrite() {
if (control_frame_manager_.WillingToWrite()) {
control_frame_manager_.OnCanWrite();
}
+ // TODO(b/147146815): this makes all datagrams go before stream data. We
+ // should have a better priority scheme for this.
+ if (!datagram_queue_.empty()) {
+ size_t written = datagram_queue_.SendDatagrams();
+ QUIC_DVLOG(1) << ENDPOINT << "Sent " << written << " datagrams";
+ if (!datagram_queue_.empty()) {
+ return;
+ }
+ }
+ std::vector<QuicStreamId> last_writing_stream_ids;
for (size_t i = 0; i < num_writes; ++i) {
if (!(write_blocked_streams_.HasWriteBlockedSpecialStream() ||
write_blocked_streams_.HasWriteBlockedDataStreams())) {
// Writing one stream removed another!? Something's broken.
- QUIC_BUG << "WriteBlockedStream is missing";
+ QUIC_BUG << "WriteBlockedStream is missing, num_writes: " << num_writes
+ << ", finished_writes: " << i
+ << ", connected: " << connection_->connected()
+ << ", connection level flow control blocked: "
+ << flow_controller_.IsBlocked() << ", scheduler type: "
+ << spdy::WriteSchedulerTypeToString(
+ write_blocked_streams_.scheduler_type());
+ for (QuicStreamId id : last_writing_stream_ids) {
+ QUIC_LOG(WARNING) << "last_writing_stream_id: " << id;
+ }
connection_->CloseConnection(QUIC_INTERNAL_ERROR,
"WriteBlockedStream is missing",
ConnectionCloseBehavior::SILENT_CLOSE);
@@ -593,6 +626,7 @@ void QuicSession::OnCanWrite() {
return;
}
currently_writing_stream_id_ = write_blocked_streams_.PopFront();
+ last_writing_stream_ids.push_back(currently_writing_stream_id_);
QUIC_DVLOG(1) << ENDPOINT << "Removing stream "
<< currently_writing_stream_id_ << " from write-blocked list";
QuicStream* stream = GetOrCreateStream(currently_writing_stream_id_);
@@ -662,53 +696,78 @@ void QuicSession::ProcessUdpPacket(const QuicSocketAddress& self_address,
connection_->ProcessUdpPacket(self_address, peer_address, packet);
}
-QuicConsumedData QuicSession::WritevData(QuicStream* stream,
- QuicStreamId id,
- size_t write_length,
- QuicStreamOffset offset,
- StreamSendingState state) {
- // This check is an attempt to deal with potential memory corruption
- // in which |id| ends up set to 1 (the crypto stream id). If this happen
- // it might end up resulting in unencrypted stream data being sent.
- // While this is impossible to avoid given sufficient corruption, this
- // seems like a reasonable mitigation.
- if (QuicUtils::IsCryptoStreamId(transport_version(), id) &&
- stream != GetMutableCryptoStream()) {
- QUIC_BUG << "Stream id mismatch";
- connection_->CloseConnection(
- QUIC_INTERNAL_ERROR,
- "Non-crypto stream attempted to write data as crypto stream.",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- return QuicConsumedData(0, false);
- }
+QuicConsumedData QuicSession::WritevData(
+ QuicStreamId id,
+ size_t write_length,
+ QuicStreamOffset offset,
+ StreamSendingState state,
+ TransmissionType type,
+ quiche::QuicheOptional<EncryptionLevel> level) {
+ DCHECK(connection_->connected())
+ << ENDPOINT << "Try to write stream data when connection is closed.";
if (!IsEncryptionEstablished() &&
!QuicUtils::IsCryptoStreamId(transport_version(), id)) {
// Do not let streams write without encryption. The calling stream will end
// up write blocked until OnCanWrite is next called.
+ QUIC_BUG << ENDPOINT << "Try to send data of stream " << id
+ << " before encryption is established.";
return QuicConsumedData(0, false);
}
+ if (write_with_transmission_) {
+ SetTransmissionType(type);
+ CountTransmissionTypeFlag(type);
+ }
+ const auto current_level = connection()->encryption_level();
+ if (level.has_value()) {
+ connection()->SetDefaultEncryptionLevel(level.value());
+ }
+
QuicConsumedData data =
connection_->SendStreamData(id, write_length, offset, state);
- if (offset >= stream->stream_bytes_written()) {
+ if (type == NOT_RETRANSMISSION) {
// This is new stream data.
write_blocked_streams_.UpdateBytesForStream(id, data.bytes_consumed);
}
+
+ // Restore the encryption level.
+ if (level.has_value()) {
+ connection()->SetDefaultEncryptionLevel(current_level);
+ }
+
return data;
}
-bool QuicSession::WriteControlFrame(const QuicFrame& frame) {
+size_t QuicSession::SendCryptoData(EncryptionLevel level,
+ size_t write_length,
+ QuicStreamOffset offset,
+ TransmissionType type) {
+ DCHECK(QuicVersionUsesCryptoFrames(transport_version()));
+ if (write_with_transmission_) {
+ SetTransmissionType(type);
+ CountTransmissionTypeFlag(type);
+ }
+ const auto current_level = connection()->encryption_level();
+ connection_->SetDefaultEncryptionLevel(level);
+ const auto bytes_consumed =
+ connection_->SendCryptoData(level, write_length, offset);
+ // Restores encryption level.
+ connection_->SetDefaultEncryptionLevel(current_level);
+ return bytes_consumed;
+}
+
+bool QuicSession::WriteControlFrame(const QuicFrame& frame,
+ TransmissionType type) {
+ if (write_with_transmission_) {
+ SetTransmissionType(type);
+ CountTransmissionTypeFlag(type);
+ }
return connection_->SendControlFrame(frame);
}
void QuicSession::SendRstStream(QuicStreamId id,
QuicRstStreamErrorCode error,
QuicStreamOffset bytes_written) {
- if (!GetQuicReloadableFlag(quic_delete_send_rst_stream_inner)) {
- SendRstStreamInner(id, error, bytes_written, false);
- return;
- }
- QUIC_RELOADABLE_FLAG_COUNT(quic_delete_send_rst_stream_inner);
if (connection()->connected()) {
QuicConnection::ScopedPacketFlusher flusher(connection());
MaybeSendRstStreamFrame(id, error, bytes_written);
@@ -724,42 +783,6 @@ void QuicSession::SendRstStream(QuicStreamId id,
CloseStreamInner(id, true);
}
-void QuicSession::SendRstStreamInner(QuicStreamId id,
- QuicRstStreamErrorCode error,
- QuicStreamOffset bytes_written,
- bool close_write_side_only) {
- if (connection()->connected()) {
- // Only send if still connected.
- if (VersionHasIetfQuicFrames(transport_version())) {
- // Send a RST_STREAM frame plus, if version 99, an IETF
- // QUIC STOP_SENDING frame. Both sre sent to emulate
- // the two-way close that Google QUIC's RST_STREAM does.
- QuicConnection::ScopedPacketFlusher flusher(connection());
- if (QuicUtils::GetStreamType(id, perspective(), IsIncomingStream(id)) !=
- READ_UNIDIRECTIONAL) {
- control_frame_manager_.WriteOrBufferRstStream(id, error, bytes_written);
- }
- if (!close_write_side_only &&
- QuicUtils::GetStreamType(id, perspective(), IsIncomingStream(id)) !=
- WRITE_UNIDIRECTIONAL) {
- control_frame_manager_.WriteOrBufferStopSending(error, id);
- }
- } else {
- DCHECK(!close_write_side_only);
- control_frame_manager_.WriteOrBufferRstStream(id, error, bytes_written);
- }
- connection_->OnStreamReset(id, error);
- }
- if (error != QUIC_STREAM_NO_ERROR && QuicContainsKey(zombie_streams_, id)) {
- OnStreamDoneWaitingForAcks(id);
- return;
- }
-
- if (!close_write_side_only) {
- CloseStreamInner(id, true);
- }
-}
-
void QuicSession::MaybeSendRstStreamFrame(QuicStreamId id,
QuicRstStreamErrorCode error,
QuicStreamOffset bytes_written) {
@@ -802,7 +825,8 @@ void QuicSession::SendWindowUpdate(QuicStreamId id,
control_frame_manager_.WriteOrBufferWindowUpdate(id, byte_offset);
}
-void QuicSession::OnError(QuicErrorCode error_code, std::string error_details) {
+void QuicSession::OnStreamError(QuicErrorCode error_code,
+ std::string error_details) {
connection_->CloseConnection(
error_code, error_details,
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
@@ -810,15 +834,13 @@ void QuicSession::OnError(QuicErrorCode error_code, std::string error_details) {
void QuicSession::SendMaxStreams(QuicStreamCount stream_count,
bool unidirectional) {
+ if (!is_configured_) {
+ QUIC_BUG << "Try to send max streams before config negotiated.";
+ return;
+ }
control_frame_manager_.WriteOrBufferMaxStreams(stream_count, unidirectional);
}
-void QuicSession::SendStreamsBlocked(QuicStreamCount stream_count,
- bool unidirectional) {
- control_frame_manager_.WriteOrBufferStreamsBlocked(stream_count,
- unidirectional);
-}
-
void QuicSession::CloseStream(QuicStreamId stream_id) {
CloseStreamInner(stream_id, false);
}
@@ -832,7 +854,7 @@ void QuicSession::InsertLocallyClosedStreamsHighestOffset(
}
}
-void QuicSession::CloseStreamInner(QuicStreamId stream_id, bool locally_reset) {
+void QuicSession::CloseStreamInner(QuicStreamId stream_id, bool rst_sent) {
QUIC_DVLOG(1) << ENDPOINT << "Closing stream " << stream_id;
StreamMap::iterator it = stream_map_.find(stream_id);
@@ -856,7 +878,7 @@ void QuicSession::CloseStreamInner(QuicStreamId stream_id, bool locally_reset) {
StreamType type = stream->type();
// Tell the stream that a RST has been sent.
- if (locally_reset) {
+ if (rst_sent) {
stream->set_rst_sent(true);
}
@@ -897,7 +919,8 @@ void QuicSession::CloseStreamInner(QuicStreamId stream_id, bool locally_reset) {
} else if (VersionHasIetfQuicFrames(transport_version())) {
// Stream was not draining, but we did have a fin or rst, so we can now
// free the stream ID if version 99.
- if (had_fin_or_rst) {
+ if (had_fin_or_rst && connection_->connected()) {
+ // Do not bother informing stream ID manager if connection is closed.
v99_streamid_manager_.OnStreamClosed(stream_id);
}
}
@@ -916,7 +939,8 @@ void QuicSession::ClosePendingStream(QuicStreamId stream_id) {
QUIC_DVLOG(1) << ENDPOINT << "Closing stream " << stream_id;
pending_stream_map_.erase(stream_id);
- if (VersionHasIetfQuicFrames(transport_version())) {
+ if (VersionHasIetfQuicFrames(transport_version()) &&
+ connection_->connected()) {
v99_streamid_manager_.OnStreamClosed(stream_id);
}
}
@@ -963,11 +987,11 @@ bool QuicSession::IsEncryptionEstablished() const {
return GetCryptoStream()->encryption_established();
}
-bool QuicSession::IsCryptoHandshakeConfirmed() const {
+bool QuicSession::OneRttKeysAvailable() const {
if (GetCryptoStream() == nullptr) {
return false;
}
- return GetCryptoStream()->handshake_confirmed();
+ return GetCryptoStream()->one_rtt_keys_available();
}
void QuicSession::OnConfigNegotiated() {
@@ -976,26 +1000,41 @@ void QuicSession::OnConfigNegotiated() {
if (VersionHasIetfQuicFrames(transport_version())) {
uint32_t max_streams = 0;
- if (config_.HasReceivedMaxIncomingBidirectionalStreams()) {
- max_streams = config_.ReceivedMaxIncomingBidirectionalStreams();
+ if (config_.HasReceivedMaxBidirectionalStreams()) {
+ max_streams = config_.ReceivedMaxBidirectionalStreams();
}
QUIC_DVLOG(1) << ENDPOINT
<< "Setting Bidirectional outgoing_max_streams_ to "
<< max_streams;
- v99_streamid_manager_.SetMaxOpenOutgoingBidirectionalStreams(max_streams);
+ if (v99_streamid_manager_.MaybeAllowNewOutgoingBidirectionalStreams(
+ max_streams)) {
+ OnCanCreateNewOutgoingStream(/*unidirectional = */ false);
+ }
max_streams = 0;
- if (config_.HasReceivedMaxIncomingUnidirectionalStreams()) {
- max_streams = config_.ReceivedMaxIncomingUnidirectionalStreams();
+ if (config_.HasReceivedMaxUnidirectionalStreams()) {
+ max_streams = config_.ReceivedMaxUnidirectionalStreams();
+ }
+ if (max_streams < num_expected_unidirectional_static_streams_) {
+ // TODO(ianswett): Change this to an application error for HTTP/3.
+ QUIC_DLOG(ERROR) << "Received unidirectional stream limit of "
+ << max_streams << " < "
+ << num_expected_unidirectional_static_streams_;
+ connection_->CloseConnection(
+ QUIC_MAX_STREAMS_ERROR, "New unidirectional stream limit is too low.",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
}
QUIC_DVLOG(1) << ENDPOINT
<< "Setting Unidirectional outgoing_max_streams_ to "
<< max_streams;
- v99_streamid_manager_.SetMaxOpenOutgoingUnidirectionalStreams(max_streams);
+ if (v99_streamid_manager_.MaybeAllowNewOutgoingUnidirectionalStreams(
+ max_streams)) {
+ OnCanCreateNewOutgoingStream(/*unidirectional = */ true);
+ }
} else {
uint32_t max_streams = 0;
- if (config_.HasReceivedMaxIncomingBidirectionalStreams()) {
- max_streams = config_.ReceivedMaxIncomingBidirectionalStreams();
+ if (config_.HasReceivedMaxBidirectionalStreams()) {
+ max_streams = config_.ReceivedMaxBidirectionalStreams();
}
QUIC_DVLOG(1) << ENDPOINT << "Setting max_open_outgoing_streams_ to "
<< max_streams;
@@ -1021,32 +1060,23 @@ void QuicSession::OnConfigNegotiated() {
if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFWA)) {
AdjustInitialFlowControlWindows(1024 * 1024);
}
- if (GetQuicReloadableFlag(quic_use_http2_priority_write_scheduler) &&
- ContainsQuicTag(config_.ReceivedConnectionOptions(), kH2PR) &&
+ if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kH2PR) &&
!VersionHasIetfQuicFrames(transport_version())) {
// Enable HTTP2 (tree-style) priority write scheduler.
use_http2_priority_write_scheduler_ =
write_blocked_streams_.SwitchWriteScheduler(
spdy::WriteSchedulerType::HTTP2, transport_version());
- } else if (GetQuicReloadableFlag(quic_enable_fifo_write_scheduler) &&
- ContainsQuicTag(config_.ReceivedConnectionOptions(), kFIFO)) {
+ } else if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kFIFO)) {
// Enable FIFO write scheduler.
- if (write_blocked_streams_.SwitchWriteScheduler(
- spdy::WriteSchedulerType::FIFO, transport_version())) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_enable_fifo_write_scheduler);
- }
- } else if (GetQuicReloadableFlag(quic_enable_lifo_write_scheduler) &&
- ContainsQuicTag(config_.ReceivedConnectionOptions(), kLIFO)) {
+ write_blocked_streams_.SwitchWriteScheduler(
+ spdy::WriteSchedulerType::FIFO, transport_version());
+ } else if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kLIFO)) {
// Enable LIFO write scheduler.
- if (write_blocked_streams_.SwitchWriteScheduler(
- spdy::WriteSchedulerType::LIFO, transport_version())) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_enable_lifo_write_scheduler);
- }
- } else if (GetQuicReloadableFlag(quic_enable_rr_write_scheduler) &&
- ContainsQuicTag(config_.ReceivedConnectionOptions(), kRRWS) &&
+ write_blocked_streams_.SwitchWriteScheduler(
+ spdy::WriteSchedulerType::LIFO, transport_version());
+ } else if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kRRWS) &&
write_blocked_streams_.scheduler_type() ==
spdy::WriteSchedulerType::SPDY) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_enable_rr_write_scheduler);
enable_round_robin_scheduling_ = true;
}
}
@@ -1056,9 +1086,9 @@ void QuicSession::OnConfigNegotiated() {
if (VersionHasIetfQuicFrames(transport_version())) {
v99_streamid_manager_.SetMaxOpenIncomingBidirectionalStreams(
- config_.GetMaxIncomingBidirectionalStreamsToSend());
+ config_.GetMaxBidirectionalStreamsToSend());
v99_streamid_manager_.SetMaxOpenIncomingUnidirectionalStreams(
- config_.GetMaxIncomingUnidirectionalStreamsToSend());
+ config_.GetMaxUnidirectionalStreamsToSend());
} else {
// A small number of additional incoming streams beyond the limit should be
// allowed. This helps avoid early connection termination when FIN/RSTs for
@@ -1066,7 +1096,7 @@ void QuicSession::OnConfigNegotiated() {
// Use a minimum number of additional streams, or a percentage increase,
// whichever is larger.
uint32_t max_incoming_streams_to_send =
- config_.GetMaxIncomingBidirectionalStreamsToSend();
+ config_.GetMaxBidirectionalStreamsToSend();
uint32_t max_incoming_streams =
std::max(max_incoming_streams_to_send + kMaxStreamsMinimumIncrement,
static_cast<uint32_t>(max_incoming_streams_to_send *
@@ -1103,14 +1133,7 @@ void QuicSession::OnConfigNegotiated() {
config_.ReceivedInitialSessionFlowControlWindowBytes());
}
is_configured_ = true;
-
- // Inform stream ID manager so that it can reevaluate any deferred
- // STREAMS_BLOCKED or MAX_STREAMS frames against the config and either send
- // the frames or discard them.
- if (VersionHasIetfQuicFrames(connection_->transport_version())) {
- QuicConnection::ScopedPacketFlusher flusher(connection());
- v99_streamid_manager_.OnConfigNegotiated();
- }
+ connection()->OnConfigNegotiated();
// Ask flow controllers to try again since the config could have unblocked us.
if (connection_->version().AllowsLowFlowControlLimits()) {
@@ -1149,6 +1172,12 @@ void QuicSession::HandleFrameOnNonexistentOutgoingStream(
DCHECK(!IsClosedStream(stream_id));
// Received a frame for a locally-created stream that is not currently
// active. This is an error.
+ if (VersionHasIetfQuicFrames(transport_version())) {
+ connection()->CloseConnection(
+ QUIC_HTTP_STREAM_WRONG_DIRECTION, "Data for nonexistent stream",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return;
+ }
connection()->CloseConnection(
QUIC_INVALID_STREAM_ID, "Data for nonexistent stream",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
@@ -1272,52 +1301,51 @@ void QuicSession::OnNewSessionFlowControlWindow(QuicStreamOffset new_window) {
flow_controller_.UpdateSendWindowOffset(new_window);
}
-void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
- DCHECK(!use_handshake_delegate());
- switch (event) {
- case ENCRYPTION_ESTABLISHED:
- // Retransmit originally packets that were sent, since they can't be
- // decrypted by the peer.
- connection_->RetransmitUnackedPackets(ALL_INITIAL_RETRANSMISSION);
- // Given any streams blocked by encryption a chance to write.
- OnCanWrite();
- break;
-
- case HANDSHAKE_CONFIRMED:
- QUIC_BUG_IF(!config_.negotiated())
- << ENDPOINT << "Handshake confirmed without parameter negotiation.";
- // Discard originally encrypted packets, since they can't be decrypted by
- // the peer.
- NeuterUnencryptedData();
- break;
-
- default:
- QUIC_LOG(ERROR) << ENDPOINT << "Got unknown handshake event: " << event;
+bool QuicSession::OnNewDecryptionKeyAvailable(
+ EncryptionLevel level,
+ std::unique_ptr<QuicDecrypter> decrypter,
+ bool set_alternative_decrypter,
+ bool latch_once_used) {
+ if (connection_->version().handshake_protocol == PROTOCOL_TLS1_3 &&
+ !connection()->framer().HasEncrypterOfEncryptionLevel(
+ QuicUtils::GetEncryptionLevel(
+ QuicUtils::GetPacketNumberSpace(level)))) {
+ // This should never happen because connection should never decrypt a packet
+ // while an ACK for it cannot be encrypted.
+ return false;
}
-}
-
-void QuicSession::OnNewKeysAvailable(EncryptionLevel level,
- std::unique_ptr<QuicDecrypter> decrypter,
- bool set_alternative_decrypter,
- bool latch_once_used,
- std::unique_ptr<QuicEncrypter> encrypter) {
- DCHECK(use_handshake_delegate());
- // Install new keys.
- connection()->SetEncrypter(level, std::move(encrypter));
if (connection()->version().KnowsWhichDecrypterToUse()) {
connection()->InstallDecrypter(level, std::move(decrypter));
- return;
+ return true;
}
if (set_alternative_decrypter) {
connection()->SetAlternativeDecrypter(level, std::move(decrypter),
latch_once_used);
- return;
+ return true;
}
connection()->SetDecrypter(level, std::move(decrypter));
+ return true;
+}
+
+void QuicSession::OnNewEncryptionKeyAvailable(
+ EncryptionLevel level,
+ std::unique_ptr<QuicEncrypter> encrypter) {
+ connection()->SetEncrypter(level, std::move(encrypter));
+
+ if (GetQuicRestartFlag(quic_send_settings_on_write_key_available) &&
+ connection_->version().handshake_protocol == PROTOCOL_TLS1_3 &&
+ level == ENCRYPTION_FORWARD_SECURE) {
+ // Set connection's default encryption level once 1-RTT write key is
+ // available.
+ QUIC_RESTART_FLAG_COUNT_N(quic_send_settings_on_write_key_available, 1, 2);
+ QUIC_DVLOG(1) << ENDPOINT << "Set default encryption level to "
+ << EncryptionLevelToString(level);
+ connection()->SetDefaultEncryptionLevel(level);
+ }
}
void QuicSession::SetDefaultEncryptionLevel(EncryptionLevel level) {
- DCHECK(use_handshake_delegate());
+ DCHECK_EQ(PROTOCOL_QUIC_CRYPTO, connection_->version().handshake_protocol);
QUIC_DVLOG(1) << ENDPOINT << "Set default encryption level to "
<< EncryptionLevelToString(level);
connection()->SetDefaultEncryptionLevel(level);
@@ -1326,17 +1354,22 @@ void QuicSession::SetDefaultEncryptionLevel(EncryptionLevel level) {
case ENCRYPTION_INITIAL:
break;
case ENCRYPTION_ZERO_RTT:
- // Retransmit old 0-RTT data (if any) with the new 0-RTT keys, since they
- // can't be decrypted by the peer.
- connection_->RetransmitUnackedPackets(ALL_INITIAL_RETRANSMISSION);
- // Given any streams blocked by encryption a chance to write.
- OnCanWrite();
+ if (perspective() == Perspective::IS_CLIENT) {
+ // Retransmit old 0-RTT data (if any) with the new 0-RTT keys, since
+ // they can't be decrypted by the server.
+ connection_->RetransmitUnackedPackets(ALL_INITIAL_RETRANSMISSION);
+ // Given any streams blocked by encryption a chance to write.
+ OnCanWrite();
+ }
break;
case ENCRYPTION_HANDSHAKE:
break;
case ENCRYPTION_FORWARD_SECURE:
QUIC_BUG_IF(!config_.negotiated())
<< ENDPOINT << "Handshake confirmed without parameter negotiation.";
+ if (!GetQuicReloadableFlag(quic_bw_sampler_app_limited_starting_value)) {
+ connection_->ResetHasNonAppLimitedSampleAfterHandshakeCompletion();
+ }
break;
default:
QUIC_BUG << "Unknown encryption level: "
@@ -1344,28 +1377,48 @@ void QuicSession::SetDefaultEncryptionLevel(EncryptionLevel level) {
}
}
+void QuicSession::OnOneRttKeysAvailable() {
+ DCHECK_EQ(PROTOCOL_TLS1_3, connection_->version().handshake_protocol);
+ if (!GetQuicRestartFlag(quic_send_settings_on_write_key_available)) {
+ QUIC_DVLOG(1) << ENDPOINT << "Set default encryption level to "
+ << EncryptionLevelToString(ENCRYPTION_FORWARD_SECURE);
+ connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ }
+
+ QUIC_BUG_IF(!GetCryptoStream()->crypto_negotiated_params().cipher_suite)
+ << ENDPOINT << "Handshake completes without cipher suite negotiation.";
+ QUIC_BUG_IF(!config_.negotiated())
+ << ENDPOINT << "Handshake completes without parameter negotiation.";
+ if (connection()->version().HasHandshakeDone() &&
+ perspective_ == Perspective::IS_SERVER) {
+ // Server sends HANDSHAKE_DONE to signal confirmation of the handshake
+ // to the client.
+ control_frame_manager_.WriteOrBufferHandshakeDone();
+ }
+ if (!GetQuicReloadableFlag(quic_bw_sampler_app_limited_starting_value)) {
+ connection_->ResetHasNonAppLimitedSampleAfterHandshakeCompletion();
+ }
+}
+
void QuicSession::DiscardOldDecryptionKey(EncryptionLevel level) {
- DCHECK(use_handshake_delegate());
if (!connection()->version().KnowsWhichDecrypterToUse()) {
- // TODO(fayang): actually discard keys.
return;
}
connection()->RemoveDecrypter(level);
}
void QuicSession::DiscardOldEncryptionKey(EncryptionLevel level) {
- DCHECK(use_handshake_delegate());
QUIC_DVLOG(1) << ENDPOINT << "Discard keys of "
<< EncryptionLevelToString(level);
- // TODO(fayang): actually discard keys.
+ if (connection()->version().handshake_protocol == PROTOCOL_TLS1_3) {
+ connection()->RemoveEncrypter(level);
+ }
switch (level) {
case ENCRYPTION_INITIAL:
NeuterUnencryptedData();
break;
case ENCRYPTION_HANDSHAKE:
- DCHECK(false);
- // TODO(fayang): implement this when handshake keys discarding settles
- // down.
+ NeuterHandshakeData();
break;
case ENCRYPTION_ZERO_RTT:
break;
@@ -1379,7 +1432,6 @@ void QuicSession::DiscardOldEncryptionKey(EncryptionLevel level) {
}
void QuicSession::NeuterHandshakeData() {
- DCHECK(use_handshake_delegate());
connection()->OnHandshakeComplete();
}
@@ -1459,19 +1511,43 @@ QuicStreamId QuicSession::GetNextOutgoingUnidirectionalStreamId() {
}
bool QuicSession::CanOpenNextOutgoingBidirectionalStream() {
- if (VersionHasIetfQuicFrames(transport_version())) {
- return v99_streamid_manager_.CanOpenNextOutgoingBidirectionalStream();
+ if (!VersionHasIetfQuicFrames(transport_version())) {
+ return stream_id_manager_.CanOpenNextOutgoingStream(
+ GetNumOpenOutgoingStreams());
+ }
+ if (v99_streamid_manager_.CanOpenNextOutgoingBidirectionalStream()) {
+ return true;
}
- return stream_id_manager_.CanOpenNextOutgoingStream(
- GetNumOpenOutgoingStreams());
+ if (is_configured_) {
+ // Send STREAM_BLOCKED after config negotiated.
+ control_frame_manager_.WriteOrBufferStreamsBlocked(
+ v99_streamid_manager_.max_outgoing_bidirectional_streams(),
+ /*unidirectional=*/false);
+ }
+ return false;
}
bool QuicSession::CanOpenNextOutgoingUnidirectionalStream() {
- if (VersionHasIetfQuicFrames(transport_version())) {
- return v99_streamid_manager_.CanOpenNextOutgoingUnidirectionalStream();
+ if (!VersionHasIetfQuicFrames(transport_version())) {
+ return stream_id_manager_.CanOpenNextOutgoingStream(
+ GetNumOpenOutgoingStreams());
+ }
+ if (v99_streamid_manager_.CanOpenNextOutgoingUnidirectionalStream()) {
+ return true;
}
- return stream_id_manager_.CanOpenNextOutgoingStream(
- GetNumOpenOutgoingStreams());
+ if (is_configured_) {
+ // Send STREAM_BLOCKED after config negotiated.
+ control_frame_manager_.WriteOrBufferStreamsBlocked(
+ v99_streamid_manager_.max_outgoing_unidirectional_streams(),
+ /*unidirectional=*/true);
+ }
+ return false;
+}
+
+QuicStreamCount QuicSession::GetAdvertisedMaxIncomingBidirectionalStreams()
+ const {
+ DCHECK(VersionHasIetfQuicFrames(transport_version()));
+ return v99_streamid_manager_.advertised_max_incoming_bidirectional_streams();
}
QuicStream* QuicSession::GetOrCreateStream(const QuicStreamId stream_id) {
@@ -1547,9 +1623,25 @@ void QuicSession::StreamDraining(QuicStreamId stream_id) {
bool QuicSession::MaybeIncreaseLargestPeerStreamId(
const QuicStreamId stream_id) {
if (VersionHasIetfQuicFrames(transport_version())) {
- return v99_streamid_manager_.MaybeIncreaseLargestPeerStreamId(stream_id);
+ std::string error_details;
+ if (v99_streamid_manager_.MaybeIncreaseLargestPeerStreamId(
+ stream_id, &error_details)) {
+ return true;
+ }
+ connection()->CloseConnection(
+ QUIC_INVALID_STREAM_ID, error_details,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
}
- return stream_id_manager_.MaybeIncreaseLargestPeerStreamId(stream_id);
+ if (!stream_id_manager_.MaybeIncreaseLargestPeerStreamId(stream_id)) {
+ connection()->CloseConnection(
+ QUIC_TOO_MANY_AVAILABLE_STREAMS,
+ quiche::QuicheStrCat(stream_id, " exceeds available streams ",
+ stream_id_manager_.MaxAvailableStreams()),
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
+ }
+ return true;
}
bool QuicSession::ShouldYield(QuicStreamId stream_id) {
@@ -1578,11 +1670,7 @@ PendingStream* QuicSession::GetOrCreatePendingStream(QuicStreamId stream_id) {
void QuicSession::set_largest_peer_created_stream_id(
QuicStreamId largest_peer_created_stream_id) {
- if (VersionHasIetfQuicFrames(transport_version())) {
- v99_streamid_manager_.SetLargestPeerCreatedStreamId(
- largest_peer_created_stream_id);
- return;
- }
+ DCHECK(!VersionHasIetfQuicFrames(transport_version()));
stream_id_manager_.set_largest_peer_created_stream_id(
largest_peer_created_stream_id);
}
@@ -1594,6 +1682,25 @@ QuicStreamId QuicSession::GetLargestPeerCreatedStreamId(
return v99_streamid_manager_.GetLargestPeerCreatedStreamId(unidirectional);
}
+void QuicSession::DeleteConnection() {
+ if (connection_) {
+ delete connection_;
+ connection_ = nullptr;
+ }
+}
+
+bool QuicSession::MaybeSetStreamPriority(
+ QuicStreamId stream_id,
+ const spdy::SpdyStreamPrecedence& precedence) {
+ auto active_stream = stream_map_.find(stream_id);
+ if (active_stream != stream_map_.end()) {
+ active_stream->second->SetPriority(precedence);
+ return true;
+ }
+
+ return false;
+}
+
bool QuicSession::IsClosedStream(QuicStreamId id) {
DCHECK_NE(QuicUtils::GetInvalidStreamId(transport_version()), id);
if (IsOpenStream(id)) {
@@ -1813,7 +1920,8 @@ bool QuicSession::OnFrameAcked(const QuicFrame& frame,
QuicByteCount newly_acked_length = 0;
new_stream_data_acked = stream->OnStreamFrameAcked(
frame.stream_frame.offset, frame.stream_frame.data_length,
- frame.stream_frame.fin, ack_delay_time, &newly_acked_length);
+ frame.stream_frame.fin, ack_delay_time, receive_timestamp,
+ &newly_acked_length);
if (!stream->HasPendingRetransmission()) {
streams_with_pending_retransmission_.erase(stream->id());
}
@@ -1866,18 +1974,20 @@ void QuicSession::OnFrameLost(const QuicFrame& frame) {
void QuicSession::RetransmitFrames(const QuicFrames& frames,
TransmissionType type) {
QuicConnection::ScopedPacketFlusher retransmission_flusher(connection_);
- SetTransmissionType(type);
+ if (!write_with_transmission_) {
+ SetTransmissionType(type);
+ }
for (const QuicFrame& frame : frames) {
if (frame.type == MESSAGE_FRAME) {
// Do not retransmit MESSAGE frames.
continue;
}
if (frame.type == CRYPTO_FRAME) {
- GetMutableCryptoStream()->RetransmitData(frame.crypto_frame);
+ GetMutableCryptoStream()->RetransmitData(frame.crypto_frame, type);
continue;
}
if (frame.type != STREAM_FRAME) {
- if (!control_frame_manager_.RetransmitControlFrame(frame)) {
+ if (!control_frame_manager_.RetransmitControlFrame(frame, type)) {
break;
}
continue;
@@ -1886,7 +1996,7 @@ void QuicSession::RetransmitFrames(const QuicFrames& frames,
if (stream != nullptr &&
!stream->RetransmitStreamData(frame.stream_frame.offset,
frame.stream_frame.data_length,
- frame.stream_frame.fin)) {
+ frame.stream_frame.fin, type)) {
break;
}
}
@@ -1920,6 +2030,10 @@ bool QuicSession::HasUnackedStreamData() const {
return !streams_waiting_for_acks_.empty();
}
+HandshakeState QuicSession::GetHandshakeState() const {
+ return GetCryptoStream()->GetHandshakeState();
+}
+
WriteStreamDataResult QuicSession::WriteStreamData(QuicStreamId id,
QuicStreamOffset offset,
QuicByteCount data_length,
@@ -1956,14 +2070,18 @@ bool QuicSession::RetransmitLostData() {
bool uses_crypto_frames = QuicVersionUsesCryptoFrames(transport_version());
QuicCryptoStream* crypto_stream = GetMutableCryptoStream();
if (uses_crypto_frames && crypto_stream->HasPendingCryptoRetransmission()) {
- SetTransmissionType(HANDSHAKE_RETRANSMISSION);
+ if (!write_with_transmission_) {
+ SetTransmissionType(HANDSHAKE_RETRANSMISSION);
+ }
crypto_stream->WritePendingCryptoRetransmission();
}
// Retransmit crypto data in stream 1 frames (version < 47).
if (!uses_crypto_frames &&
QuicContainsKey(streams_with_pending_retransmission_,
QuicUtils::GetCryptoStreamId(transport_version()))) {
- SetTransmissionType(HANDSHAKE_RETRANSMISSION);
+ if (!write_with_transmission_) {
+ SetTransmissionType(HANDSHAKE_RETRANSMISSION);
+ }
// Retransmit crypto data first.
QuicStream* crypto_stream =
GetStream(QuicUtils::GetCryptoStreamId(transport_version()));
@@ -1978,7 +2096,9 @@ bool QuicSession::RetransmitLostData() {
}
}
if (control_frame_manager_.HasPendingRetransmission()) {
- SetTransmissionType(LOSS_RETRANSMISSION);
+ if (!write_with_transmission_) {
+ SetTransmissionType(LOSS_RETRANSMISSION);
+ }
control_frame_manager_.OnCanWrite();
if (control_frame_manager_.HasPendingRetransmission()) {
return false;
@@ -1992,7 +2112,9 @@ bool QuicSession::RetransmitLostData() {
const QuicStreamId id = streams_with_pending_retransmission_.begin()->first;
QuicStream* stream = GetStream(id);
if (stream != nullptr) {
- SetTransmissionType(LOSS_RETRANSMISSION);
+ if (!write_with_transmission_) {
+ SetTransmissionType(LOSS_RETRANSMISSION);
+ }
stream->OnCanWrite();
DCHECK(CheckStreamWriteBlocked(stream));
if (stream->HasPendingRetransmission()) {
@@ -2034,6 +2156,8 @@ MessageResult QuicSession::SendMessage(QuicMemSliceSpan message) {
}
MessageResult QuicSession::SendMessage(QuicMemSliceSpan message, bool flush) {
+ DCHECK(connection_->connected())
+ << ENDPOINT << "Try to write messages when connection is closed.";
if (!IsEncryptionEstablished()) {
return {MESSAGE_STATUS_ENCRYPTION_NOT_ESTABLISHED, 0};
}
@@ -2071,8 +2195,6 @@ void QuicSession::SendStopSending(uint16_t code, QuicStreamId stream_id) {
control_frame_manager_.WriteOrBufferStopSending(code, stream_id);
}
-void QuicSession::OnCanCreateNewOutgoingStream(bool /*unidirectional*/) {}
-
QuicStreamId QuicSession::next_outgoing_bidirectional_stream_id() const {
if (VersionHasIetfQuicFrames(transport_version())) {
return v99_streamid_manager_.next_outgoing_bidirectional_stream_id();
@@ -2088,11 +2210,28 @@ QuicStreamId QuicSession::next_outgoing_unidirectional_stream_id() const {
}
bool QuicSession::OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) {
- return v99_streamid_manager_.OnMaxStreamsFrame(frame);
+ const bool allow_new_streams =
+ frame.unidirectional
+ ? v99_streamid_manager_.MaybeAllowNewOutgoingUnidirectionalStreams(
+ frame.stream_count)
+ : v99_streamid_manager_.MaybeAllowNewOutgoingBidirectionalStreams(
+ frame.stream_count);
+ if (allow_new_streams) {
+ OnCanCreateNewOutgoingStream(frame.unidirectional);
+ }
+
+ return true;
}
bool QuicSession::OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) {
- return v99_streamid_manager_.OnStreamsBlockedFrame(frame);
+ std::string error_details;
+ if (v99_streamid_manager_.OnStreamsBlockedFrame(frame, &error_details)) {
+ return true;
+ }
+ connection_->CloseConnection(
+ QUIC_STREAMS_BLOCKED_ERROR, error_details,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
}
size_t QuicSession::max_open_incoming_bidirectional_streams() const {
@@ -2109,13 +2248,13 @@ size_t QuicSession::max_open_incoming_unidirectional_streams() const {
return stream_id_manager_.max_open_incoming_streams();
}
-std::vector<QuicStringPiece>::const_iterator QuicSession::SelectAlpn(
- const std::vector<QuicStringPiece>& alpns) const {
+std::vector<quiche::QuicheStringPiece>::const_iterator QuicSession::SelectAlpn(
+ const std::vector<quiche::QuicheStringPiece>& alpns) const {
const std::string alpn = AlpnForVersion(connection()->version());
return std::find(alpns.cbegin(), alpns.cend(), alpn);
}
-void QuicSession::OnAlpnSelected(QuicStringPiece alpn) {
+void QuicSession::OnAlpnSelected(quiche::QuicheStringPiece alpn) {
QUIC_DLOG(INFO) << (perspective() == Perspective::IS_SERVER ? "Server: "
: "Client: ")
<< "ALPN selected: " << alpn;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_session.h b/chromium/net/third_party/quiche/src/quic/core/quic_session.h
index c6861f93ca5..ac99a3f7584 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_session.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_session.h
@@ -19,6 +19,7 @@
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
#include "net/third_party/quiche/src/quic/core/quic_control_frame_manager.h"
#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
+#include "net/third_party/quiche/src/quic/core/quic_datagram_queue.h"
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/core/quic_packet_creator.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
@@ -27,10 +28,12 @@
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
#include "net/third_party/quiche/src/quic/core/session_notifier_interface.h"
+#include "net/third_party/quiche/src/quic/core/stream_delegate_interface.h"
#include "net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -48,7 +51,8 @@ class QUIC_EXPORT_PRIVATE QuicSession
public SessionNotifierInterface,
public QuicStreamFrameDataProducer,
public QuicStreamIdManager::DelegateInterface,
- public HandshakerDelegateInterface {
+ public HandshakerDelegateInterface,
+ public StreamDelegateInterface {
public:
// An interface from the session to the entity owning the session.
// This lets the session notify its owner (the Dispatcher) when the connection
@@ -74,18 +78,6 @@ class QUIC_EXPORT_PRIVATE QuicSession
virtual void OnStopSendingReceived(const QuicStopSendingFrame& frame) = 0;
};
- // CryptoHandshakeEvent enumerates the events generated by a QuicCryptoStream.
- // TODO(fayang): Replace this enum and with HandshakeState.
- enum CryptoHandshakeEvent {
- // ENCRYPTION_ESTABLISHED indicates that a client hello has been sent and
- // subsequent packets will be encrypted. (Client only.)
- ENCRYPTION_ESTABLISHED,
- // HANDSHAKE_CONFIRMED, in a client, indicates the server has accepted
- // our handshake. In a server it indicates that a full, valid client hello
- // has been received. (Client and server.)
- HANDSHAKE_CONFIRMED,
- };
-
// Does not take ownership of |connection| or |visitor|.
QuicSession(QuicConnection* connection,
Visitor* owner,
@@ -104,7 +96,8 @@ class QUIC_EXPORT_PRIVATE QuicSession
void OnCryptoFrame(const QuicCryptoFrame& frame) override;
void OnRstStream(const QuicRstStreamFrame& frame) override;
void OnGoAway(const QuicGoAwayFrame& frame) override;
- void OnMessageReceived(QuicStringPiece message) override;
+ void OnMessageReceived(quiche::QuicheStringPiece message) override;
+ void OnHandshakeDoneReceived() override;
void OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override;
void OnBlockedFrame(const QuicBlockedFrame& frame) override;
void OnConnectionClosed(const QuicConnectionCloseFrame& frame,
@@ -126,11 +119,13 @@ class QUIC_EXPORT_PRIVATE QuicSession
bool HasPendingHandshake() const override;
void OnPathDegrading() override;
bool AllowSelfAddressChange() const override;
+ HandshakeState GetHandshakeState() const override;
void OnForwardProgressConfirmed() override;
bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) override;
bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override;
void OnStopSendingFrame(const QuicStopSendingFrame& frame) override;
void OnPacketDecrypted(EncryptionLevel level) override;
+ void OnOneRttPacketAcknowledged() override;
// QuicStreamFrameDataProducer
WriteStreamDataResult WriteStreamData(QuicStreamId id,
@@ -154,32 +149,17 @@ class QUIC_EXPORT_PRIVATE QuicSession
bool HasUnackedCryptoData() const override;
bool HasUnackedStreamData() const override;
- // QuicStreamIdManager::DelegateInterface methods:
- void OnError(QuicErrorCode error_code, std::string error_details) override;
void SendMaxStreams(QuicStreamCount stream_count,
bool unidirectional) override;
- void SendStreamsBlocked(QuicStreamCount stream_count,
- bool unidirectional) override;
// The default implementation does nothing. Subclasses should override if
// for example they queue up stream requests.
- void OnCanCreateNewOutgoingStream(bool unidirectional) override;
+ virtual void OnCanCreateNewOutgoingStream(bool /*unidirectional*/) {}
// Called on every incoming packet. Passes |packet| through to |connection_|.
virtual void ProcessUdpPacket(const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
const QuicReceivedPacket& packet);
- // Called by streams when they want to write data to the peer.
- // Returns a pair with the number of bytes consumed from data, and a boolean
- // indicating if the fin bit was consumed. This does not indicate the data
- // has been sent on the wire: it may have been turned into a packet and queued
- // if the socket was unexpectedly blocked.
- virtual QuicConsumedData WritevData(QuicStream* stream,
- QuicStreamId id,
- size_t write_length,
- QuicStreamOffset offset,
- StreamSendingState state);
-
// Called by application to send |message|. Data copy can be avoided if
// |message| is provided in reference counted memory.
// Please note, |message| provided in reference counted memory would be moved
@@ -214,8 +194,9 @@ class QUIC_EXPORT_PRIVATE QuicSession
virtual void OnMessageLost(QuicMessageId message_id);
// Called by control frame manager when it wants to write control frames to
- // the peer. Returns true if |frame| is consumed, false otherwise.
- virtual bool WriteControlFrame(const QuicFrame& frame);
+ // the peer. Returns true if |frame| is consumed, false otherwise. The frame
+ // will be sent in specified transmission |type|.
+ bool WriteControlFrame(const QuicFrame& frame, TransmissionType type);
// Close the stream in both directions.
// TODO(renjietang): rename this method as it sends both RST_STREAM and
@@ -243,34 +224,60 @@ class QUIC_EXPORT_PRIVATE QuicSession
// hasn't confirmed the handshake yet.
virtual bool IsEncryptionEstablished() const;
- // For a client, returns true if the server has confirmed our handshake. For
- // a server, returns true if a full, valid client hello has been received.
- bool IsCryptoHandshakeConfirmed() const;
+ // Returns true if 1RTT keys are available.
+ bool OneRttKeysAvailable() const;
// Called by the QuicCryptoStream when a new QuicConfig has been negotiated.
virtual void OnConfigNegotiated();
- // Called by the QuicCryptoStream when the handshake enters a new state.
- //
- // Clients will call this function in the order:
- // zero or more ENCRYPTION_ESTABLISHED
- // HANDSHAKE_CONFIRMED
- //
- // Servers will simply call it once with HANDSHAKE_CONFIRMED.
- virtual void OnCryptoHandshakeEvent(CryptoHandshakeEvent event);
-
// From HandshakerDelegateInterface
- void OnNewKeysAvailable(EncryptionLevel level,
- std::unique_ptr<QuicDecrypter> decrypter,
- bool set_alternative_decrypter,
- bool latch_once_used,
- std::unique_ptr<QuicEncrypter> encrypter) override;
+ bool OnNewDecryptionKeyAvailable(EncryptionLevel level,
+ std::unique_ptr<QuicDecrypter> decrypter,
+ bool set_alternative_decrypter,
+ bool latch_once_used) override;
+ void OnNewEncryptionKeyAvailable(
+ EncryptionLevel level,
+ std::unique_ptr<QuicEncrypter> encrypter) override;
void SetDefaultEncryptionLevel(EncryptionLevel level) override;
+ void OnOneRttKeysAvailable() override;
void DiscardOldDecryptionKey(EncryptionLevel level) override;
void DiscardOldEncryptionKey(EncryptionLevel level) override;
void NeuterUnencryptedData() override;
void NeuterHandshakeData() override;
+ // Implement StreamDelegateInterface.
+ void OnStreamError(QuicErrorCode error_code,
+ std::string error_details) override;
+ // Sets priority in the write blocked list.
+ void RegisterStreamPriority(
+ QuicStreamId id,
+ bool is_static,
+ const spdy::SpdyStreamPrecedence& precedence) override;
+ // Clears priority from the write blocked list.
+ void UnregisterStreamPriority(QuicStreamId id, bool is_static) override;
+ // Updates priority on the write blocked list.
+ void UpdateStreamPriority(
+ QuicStreamId id,
+ const spdy::SpdyStreamPrecedence& new_precedence) override;
+
+ // Called by streams when they want to write data to the peer.
+ // Returns a pair with the number of bytes consumed from data, and a boolean
+ // indicating if the fin bit was consumed. This does not indicate the data
+ // has been sent on the wire: it may have been turned into a packet and queued
+ // if the socket was unexpectedly blocked.
+ QuicConsumedData WritevData(
+ QuicStreamId id,
+ size_t write_length,
+ QuicStreamOffset offset,
+ StreamSendingState state,
+ TransmissionType type,
+ quiche::QuicheOptional<EncryptionLevel> level) override;
+
+ size_t SendCryptoData(EncryptionLevel level,
+ size_t write_length,
+ QuicStreamOffset offset,
+ TransmissionType type) override;
+
// Called by the QuicCryptoStream when a handshake message is sent.
virtual void OnCryptoHandshakeMessageSent(
const CryptoHandshakeMessage& message);
@@ -279,20 +286,6 @@ class QUIC_EXPORT_PRIVATE QuicSession
virtual void OnCryptoHandshakeMessageReceived(
const CryptoHandshakeMessage& message);
- // Called by the stream on creation to set priority in the write blocked list.
- virtual void RegisterStreamPriority(
- QuicStreamId id,
- bool is_static,
- const spdy::SpdyStreamPrecedence& precedence);
- // Called by the stream on deletion to clear priority from the write blocked
- // list.
- virtual void UnregisterStreamPriority(QuicStreamId id, bool is_static);
- // Called by the stream on SetPriority to update priority on the write blocked
- // list.
- virtual void UpdateStreamPriority(
- QuicStreamId id,
- const spdy::SpdyStreamPrecedence& new_precedence);
-
// Returns mutable config for this session. Returned config is owned
// by QuicSession.
QuicConfig* config();
@@ -389,7 +382,7 @@ class QUIC_EXPORT_PRIVATE QuicSession
return on_closed_frame_.application_error_code;
}
- Perspective perspective() const { return connection_->perspective(); }
+ Perspective perspective() const { return perspective_; }
QuicFlowController* flow_controller() { return &flow_controller_; }
@@ -419,6 +412,8 @@ class QUIC_EXPORT_PRIVATE QuicSession
virtual bool ShouldYield(QuicStreamId stream_id);
// Set transmission type of next sending packets.
+ // TODO(b/136274541): Remove this method or or make it private after
+ // gfe2_reloadable_flag_quic_write_with_transmission is deprecated.
void SetTransmissionType(TransmissionType type);
// Clean up closed_streams_.
@@ -440,17 +435,6 @@ class QUIC_EXPORT_PRIVATE QuicSession
return num_locally_closed_incoming_streams_highest_offset_;
}
- // Does actual work of sending reset-stream or reset-stream&stop-sending
- // If the connection is not version 99/IETF QUIC, will always send a
- // RESET_STREAM and close_write_side_only is ignored. If the connection is
- // IETF QUIC/Version 99 then will send a RESET_STREAM and STOP_SENDING if
- // close_write_side_only is false, just a RESET_STREAM if
- // close_write_side_only is true.
- virtual void SendRstStreamInner(QuicStreamId id,
- QuicRstStreamErrorCode error,
- QuicStreamOffset bytes_written,
- bool close_write_side_only);
-
// Record errors when a connection is closed at the server side, should only
// be called from server's perspective.
// Noop if |error| is QUIC_NO_ERROR.
@@ -461,14 +445,12 @@ class QUIC_EXPORT_PRIVATE QuicSession
return connection_->transport_version();
}
+ inline ParsedQuicVersion version() const { return connection_->version(); }
+
bool use_http2_priority_write_scheduler() const {
return use_http2_priority_write_scheduler_;
}
- bool use_handshake_delegate() const {
- return connection_->use_handshake_delegate();
- }
-
bool is_configured() const { return is_configured_; }
QuicStreamCount num_expected_unidirectional_static_streams() const {
@@ -477,8 +459,8 @@ class QUIC_EXPORT_PRIVATE QuicSession
// Set the number of unidirectional stream that the peer is allowed to open to
// be |max_stream| + |num_expected_static_streams_|.
- void ConfigureMaxIncomingDynamicStreamsToSend(QuicStreamCount max_stream) {
- config_.SetMaxIncomingUnidirectionalStreamsToSend(
+ void ConfigureMaxDynamicStreamsToSend(QuicStreamCount max_stream) {
+ config_.SetMaxUnidirectionalStreamsToSend(
max_stream + num_expected_unidirectional_static_streams_);
}
@@ -491,12 +473,14 @@ class QUIC_EXPORT_PRIVATE QuicSession
// Provided a list of ALPNs offered by the client, selects an ALPN from the
// list, or alpns.end() if none of the ALPNs are acceptable.
- virtual std::vector<QuicStringPiece>::const_iterator SelectAlpn(
- const std::vector<QuicStringPiece>& alpns) const;
+ virtual std::vector<quiche::QuicheStringPiece>::const_iterator SelectAlpn(
+ const std::vector<quiche::QuicheStringPiece>& alpns) const;
// Called when the ALPN of the connection is established for a connection that
// uses TLS handshake.
- virtual void OnAlpnSelected(QuicStringPiece alpn);
+ virtual void OnAlpnSelected(quiche::QuicheStringPiece alpn);
+
+ bool write_with_transmission() const { return write_with_transmission_; }
protected:
using StreamMap = QuicSmallMap<QuicStreamId, std::unique_ptr<QuicStream>, 10>;
@@ -540,9 +524,13 @@ class QUIC_EXPORT_PRIVATE QuicSession
// Returns the number of open dynamic streams.
uint64_t GetNumOpenDynamicStreams() const;
- // Performs the work required to close |stream_id|. If |locally_reset|
- // then the stream has been reset by this endpoint, not by the peer.
- virtual void CloseStreamInner(QuicStreamId stream_id, bool locally_reset);
+ // Returns the maximum bidirectional streams parameter sent with the handshake
+ // as a transport parameter, or in the most recent MAX_STREAMS frame.
+ QuicStreamCount GetAdvertisedMaxIncomingBidirectionalStreams() const;
+
+ // Performs the work required to close |stream_id|. If |rst_sent| then a
+ // Reset Stream frame has already been sent for this stream.
+ virtual void CloseStreamInner(QuicStreamId stream_id, bool rst_sent);
// When a stream is closed locally, it may not yet know how many bytes the
// peer sent on that stream.
@@ -615,6 +603,8 @@ class QUIC_EXPORT_PRIVATE QuicSession
return stream_id_manager_;
}
+ QuicDatagramQueue* datagram_queue() { return &datagram_queue_; }
+
// Processes the stream type information of |pending| depending on
// different kinds of sessions' own rules. Returns true if the pending stream
// is converted into a normal stream.
@@ -626,6 +616,19 @@ class QUIC_EXPORT_PRIVATE QuicSession
// indicated by |unidirectional|.
QuicStreamId GetLargestPeerCreatedStreamId(bool unidirectional) const;
+ // Deletes the connection and sets it to nullptr, so calling it mulitiple
+ // times is safe.
+ void DeleteConnection();
+
+ // Call SetPriority() on stream id |id| and return true if stream is active.
+ bool MaybeSetStreamPriority(QuicStreamId stream_id,
+ const spdy::SpdyStreamPrecedence& precedence);
+
+ void SetLossDetectionTuner(
+ std::unique_ptr<LossDetectionTunerInterface> tuner) {
+ connection()->SetLossDetectionTuner(std::move(tuner));
+ }
+
private:
friend class test::QuicSessionPeer;
@@ -702,6 +705,10 @@ class QUIC_EXPORT_PRIVATE QuicSession
QuicConnection* connection_;
+ // Store perspective on QuicSession during the constructor as it may be needed
+ // during our destructor when connection_ may have already been destroyed.
+ Perspective perspective_;
+
// May be null.
Visitor* visitor_;
@@ -779,6 +786,9 @@ class QUIC_EXPORT_PRIVATE QuicSession
// Id of latest successfully sent message.
QuicMessageId last_message_id_;
+ // The buffer used to queue the DATAGRAM frames.
+ QuicDatagramQueue datagram_queue_;
+
// TODO(fayang): switch to linked_hash_set when chromium supports it. The bool
// is not used here.
// List of streams with pending retransmissions.
@@ -804,6 +814,9 @@ class QUIC_EXPORT_PRIVATE QuicSession
// If true, enables round robin scheduling.
bool enable_round_robin_scheduling_;
+
+ // Latched value of gfe2_reloadable_flag_quic_write_with_transmission.
+ const bool write_with_transmission_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_session_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_session_test.cc
index afb5641d8f9..4da502dc422 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_session_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_session_test.cc
@@ -12,6 +12,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/transport_parameters.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_max_streams_frame.h"
#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
@@ -19,14 +20,11 @@
#include "net/third_party/quiche/src/quic/core/quic_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice_storage.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test_mem_slice_vector.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_quic_session_visitor.h"
@@ -38,6 +36,10 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_stream_send_buffer_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_optional.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
using spdy::kV3HighestPriority;
using spdy::SpdyPriority;
@@ -60,12 +62,15 @@ class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {
: QuicCryptoStream(session),
QuicCryptoHandshaker(this, session),
encryption_established_(false),
- handshake_confirmed_(false),
- params_(new QuicCryptoNegotiatedParameters) {}
+ one_rtt_keys_available_(false),
+ params_(new QuicCryptoNegotiatedParameters) {
+ // Simulate a negotiated cipher_suite with a fake value.
+ params_->cipher_suite = 1;
+ }
void OnHandshakeMessage(const CryptoHandshakeMessage& /*message*/) override {
encryption_established_ = true;
- handshake_confirmed_ = true;
+ one_rtt_keys_available_ = true;
QuicErrorCode error;
std::string error_details;
session()->config()->SetInitialStreamFlowControlWindowToSend(
@@ -87,21 +92,22 @@ class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {
}
EXPECT_THAT(error, IsQuicNoError());
session()->OnConfigNegotiated();
- if (session()->use_handshake_delegate()) {
- session()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
- session()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
+ if (session()->connection()->version().handshake_protocol ==
+ PROTOCOL_TLS1_3) {
+ session()->OnOneRttKeysAvailable();
} else {
- session()->connection()->SetDefaultEncryptionLevel(
- ENCRYPTION_FORWARD_SECURE);
- session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
+ session()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
}
+ session()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
}
// QuicCryptoStream implementation
bool encryption_established() const override {
return encryption_established_;
}
- bool handshake_confirmed() const override { return handshake_confirmed_; }
+ bool one_rtt_keys_available() const override {
+ return one_rtt_keys_available_;
+ }
const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
const override {
return *params_;
@@ -110,6 +116,11 @@ class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {
return QuicCryptoHandshaker::crypto_message_parser();
}
void OnPacketDecrypted(EncryptionLevel /*level*/) override {}
+ void OnOneRttPacketAcknowledged() override {}
+ void OnHandshakeDoneReceived() override {}
+ HandshakeState GetHandshakeState() const override {
+ return one_rtt_keys_available() ? HANDSHAKE_COMPLETE : HANDSHAKE_START;
+ }
MOCK_METHOD0(OnCanWrite, void());
bool HasPendingCryptoRetransmission() const override { return false; }
@@ -120,7 +131,7 @@ class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {
using QuicCryptoStream::session;
bool encryption_established_;
- bool handshake_confirmed_;
+ bool one_rtt_keys_available_;
QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
};
@@ -145,8 +156,8 @@ class TestStream : public QuicStream {
void OnDataAvailable() override {}
MOCK_METHOD0(OnCanWrite, void());
- MOCK_METHOD3(RetransmitStreamData,
- bool(QuicStreamOffset, QuicByteCount, bool));
+ MOCK_METHOD4(RetransmitStreamData,
+ bool(QuicStreamOffset, QuicByteCount, bool, TransmissionType));
MOCK_CONST_METHOD0(HasPendingRetransmission, bool());
};
@@ -170,9 +181,7 @@ class TestSession : public QuicSession {
std::make_unique<NullEncrypter>(connection->perspective()));
}
- ~TestSession() override {
- delete connection();
- }
+ ~TestSession() override { DeleteConnection(); }
TestCryptoStream* GetMutableCryptoStream() override {
return &crypto_stream_;
@@ -259,19 +268,18 @@ class TestSession : public QuicSession {
return GetNumActiveStreams() > 0;
}
- QuicConsumedData WritevData(QuicStream* stream,
- QuicStreamId id,
- size_t write_length,
- QuicStreamOffset offset,
- StreamSendingState state) override {
+ QuicConsumedData WritevData(
+ QuicStreamId id,
+ size_t write_length,
+ QuicStreamOffset offset,
+ StreamSendingState state,
+ TransmissionType type,
+ quiche::QuicheOptional<EncryptionLevel> level) override {
bool fin = state != NO_FIN;
QuicConsumedData consumed(write_length, fin);
if (!writev_consumes_all_data_) {
consumed =
- QuicSession::WritevData(stream, id, write_length, offset, state);
- }
- if (fin && consumed.fin_consumed) {
- stream->set_fin_sent(true);
+ QuicSession::WritevData(id, write_length, offset, state, type, level);
}
QuicSessionPeer::GetWriteBlockedStreams(this)->UpdateBytesForStream(
id, consumed.bytes_consumed);
@@ -293,7 +301,8 @@ class TestSession : public QuicSession {
}
MakeIOVector("not empty", &iov);
QuicStreamPeer::SendBuffer(stream).SaveStreamData(&iov, 1, 0, 9);
- QuicConsumedData consumed = WritevData(stream, stream->id(), 9, 0, FIN);
+ QuicConsumedData consumed =
+ WritevData(stream->id(), 9, 0, FIN, NOT_RETRANSMISSION, QuicheNullOpt);
QuicStreamPeer::SendBuffer(stream).OnStreamDataConsumed(
consumed.bytes_consumed);
return consumed;
@@ -309,7 +318,8 @@ class TestSession : public QuicSession {
QuicConsumedData SendLargeFakeData(QuicStream* stream, int bytes) {
DCHECK(writev_consumes_all_data_);
- return WritevData(stream, stream->id(), bytes, 0, FIN);
+ return WritevData(stream->id(), bytes, 0, FIN, NOT_RETRANSMISSION,
+ QuicheNullOpt);
}
bool UsesPendingStreams() const override { return uses_pending_streams_; }
@@ -323,8 +333,11 @@ class TestSession : public QuicSession {
}
using QuicSession::ActivateStream;
+ using QuicSession::CanOpenNextOutgoingBidirectionalStream;
using QuicSession::CanOpenNextOutgoingUnidirectionalStream;
using QuicSession::closed_streams;
+ using QuicSession::GetNextOutgoingBidirectionalStreamId;
+ using QuicSession::GetNextOutgoingUnidirectionalStreamId;
using QuicSession::zombie_streams;
private:
@@ -352,9 +365,13 @@ class QuicSessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
kInitialSessionFlowControlWindowForTest);
if (configure_session) {
- QuicConfigPeer::SetReceivedMaxIncomingBidirectionalStreams(
+ if (VersionHasIetfQuicFrames(transport_version())) {
+ EXPECT_CALL(session_, OnCanCreateNewOutgoingStream(false)).Times(1);
+ EXPECT_CALL(session_, OnCanCreateNewOutgoingStream(true)).Times(1);
+ }
+ QuicConfigPeer::SetReceivedMaxBidirectionalStreams(
session_.config(), kDefaultMaxStreamsPerConnection);
- QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams(
+ QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(
session_.config(), kDefaultMaxStreamsPerConnection);
QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesUnidirectional(
session_.config(), kMinimumFlowControlSendWindow);
@@ -370,6 +387,7 @@ class QuicSessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
.Times(testing::AnyNumber());
+ testing::Mock::VerifyAndClearExpectations(&session_);
}
~QuicSessionTestBase() {
@@ -564,11 +582,14 @@ TEST_P(QuicSessionTestServer, DontCallOnWriteBlockedForDisconnectedConnection) {
session_.OnWriteBlocked();
}
-TEST_P(QuicSessionTestServer, IsCryptoHandshakeConfirmed) {
- EXPECT_FALSE(session_.IsCryptoHandshakeConfirmed());
+TEST_P(QuicSessionTestServer, OneRttKeysAvailable) {
+ EXPECT_FALSE(session_.OneRttKeysAvailable());
CryptoHandshakeMessage message;
+ if (connection_->version().HasHandshakeDone()) {
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ }
session_.GetMutableCryptoStream()->OnHandshakeMessage(message);
- EXPECT_TRUE(session_.IsCryptoHandshakeConfirmed());
+ EXPECT_TRUE(session_.OneRttKeysAvailable());
}
TEST_P(QuicSessionTestServer, IsClosedStreamDefault) {
@@ -794,9 +815,7 @@ TEST_P(QuicSessionTestServer, ManyAvailableBidirectionalStreams) {
*connection_,
CloseConnection(QUIC_INVALID_STREAM_ID,
"Stream id 798 would exceed stream count limit 50",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET
-
- ))
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET))
.Times(1);
EXPECT_EQ(nullptr, session_.GetOrCreateStream(
GetNthClientInitiatedUnidirectionalId(199)));
@@ -849,19 +868,14 @@ TEST_P(QuicSessionTestServer, ManyAvailableUnidirectionalStreams) {
}
TEST_P(QuicSessionTestServer, DebugDFatalIfMarkingClosedStreamWriteBlocked) {
- // EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
- if (GetParam() != AllSupportedVersions()[0]) {
- return;
- }
-
TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
QuicStreamId closed_stream_id = stream2->id();
// Close the stream.
EXPECT_CALL(*connection_, SendControlFrame(_));
EXPECT_CALL(*connection_, OnStreamReset(closed_stream_id, _));
stream2->Reset(QUIC_BAD_APPLICATION_PAYLOAD);
- std::string msg =
- QuicStrCat("Marking unknown stream ", closed_stream_id, " blocked.");
+ std::string msg = quiche::QuicheStrCat("Marking unknown stream ",
+ closed_stream_id, " blocked.");
EXPECT_QUIC_BUG(session_.MarkConnectionLevelWriteBlocked(closed_stream_id),
msg);
}
@@ -966,7 +980,6 @@ TEST_P(QuicSessionTestServer, Http2Priority) {
// The test is using HTTP/2 priority which is not supported in IETF QUIC.
return;
}
- SetQuicReloadableFlag(quic_use_http2_priority_write_scheduler, true);
QuicTagVector copt;
copt.push_back(kH2PR);
QuicConfigPeer::SetReceivedConnectionOptions(session_.config(), copt);
@@ -1049,7 +1062,6 @@ TEST_P(QuicSessionTestServer, RoundRobinScheduling) {
// IETF QUIC currently doesn't support PRIORITY.
return;
}
- SetQuicReloadableFlag(quic_enable_rr_write_scheduler, true);
QuicTagVector copt;
copt.push_back(kRRWS);
QuicConfigPeer::SetReceivedConnectionOptions(session_.config(), copt);
@@ -1091,6 +1103,10 @@ TEST_P(QuicSessionTestServer, RoundRobinScheduling) {
TEST_P(QuicSessionTestServer, OnCanWriteBundlesStreams) {
// Encryption needs to be established before data can be sent.
+ if (connection_->version().HasHandshakeDone()) {
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillRepeatedly(Invoke(&ClearControlFrame));
+ }
CryptoHandshakeMessage msg;
MockPacketWriter* writer = static_cast<MockPacketWriter*>(
QuicConnectionPeer::GetWriter(session_.connection()));
@@ -1202,6 +1218,41 @@ TEST_P(QuicSessionTestServer, OnCanWriteWriterBlocks) {
EXPECT_TRUE(session_.WillingAndAbleToWrite());
}
+TEST_P(QuicSessionTestServer, SendStreamsBlocked) {
+ if (!VersionHasIetfQuicFrames(transport_version())) {
+ return;
+ }
+ for (size_t i = 0; i < kDefaultMaxStreamsPerConnection; ++i) {
+ ASSERT_TRUE(session_.CanOpenNextOutgoingBidirectionalStream());
+ session_.GetNextOutgoingBidirectionalStreamId();
+ }
+ // Next checking causes STREAMS_BLOCKED to be sent.
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillOnce(Invoke([](const QuicFrame& frame) {
+ EXPECT_FALSE(frame.streams_blocked_frame.unidirectional);
+ EXPECT_EQ(kDefaultMaxStreamsPerConnection,
+ frame.streams_blocked_frame.stream_count);
+ ClearControlFrame(frame);
+ return true;
+ }));
+ EXPECT_FALSE(session_.CanOpenNextOutgoingBidirectionalStream());
+
+ for (size_t i = 0; i < kDefaultMaxStreamsPerConnection; ++i) {
+ ASSERT_TRUE(session_.CanOpenNextOutgoingUnidirectionalStream());
+ session_.GetNextOutgoingUnidirectionalStreamId();
+ }
+ // Next checking causes STREAM_BLOCKED to be sent.
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillOnce(Invoke([](const QuicFrame& frame) {
+ EXPECT_TRUE(frame.streams_blocked_frame.unidirectional);
+ EXPECT_EQ(kDefaultMaxStreamsPerConnection,
+ frame.streams_blocked_frame.stream_count);
+ ClearControlFrame(frame);
+ return true;
+ }));
+ EXPECT_FALSE(session_.CanOpenNextOutgoingUnidirectionalStream());
+}
+
TEST_P(QuicSessionTestServer, BufferedHandshake) {
// This test is testing behavior of crypto stream flow control, but when
// CRYPTO frames are used, there is no flow control for the crypto handshake.
@@ -1433,6 +1484,9 @@ TEST_P(QuicSessionTestServer, ServerReplyToConnectivityProbes) {
TEST_P(QuicSessionTestServer, IncreasedTimeoutAfterCryptoHandshake) {
EXPECT_EQ(kInitialIdleTimeoutSecs + 3,
QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds());
+ if (connection_->version().HasHandshakeDone()) {
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ }
CryptoHandshakeMessage msg;
session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
EXPECT_EQ(kMaximumIdleTimeoutSecs + 3,
@@ -1451,7 +1505,8 @@ TEST_P(QuicSessionTestServer, OnStreamFrameFinStaticStreamId) {
/*is_static*/ true, BIDIRECTIONAL);
QuicSessionPeer::ActivateStream(&session_, std::move(fake_headers_stream));
// Send two bytes of payload.
- QuicStreamFrame data1(headers_stream_id, true, 0, QuicStringPiece("HT"));
+ QuicStreamFrame data1(headers_stream_id, true, 0,
+ quiche::QuicheStringPiece("HT"));
EXPECT_CALL(*connection_,
CloseConnection(
QUIC_INVALID_STREAM_ID, "Attempt to close a static stream",
@@ -1459,32 +1514,11 @@ TEST_P(QuicSessionTestServer, OnStreamFrameFinStaticStreamId) {
session_.OnStreamFrame(data1);
}
-TEST_P(QuicSessionTestServer, OnRstStreamStaticStreamId) {
- if (VersionUsesHttp3(connection_->transport_version())) {
- // The test relies on headers stream, which no longer exists in IETF QUIC.
- return;
- }
- QuicStreamId headers_stream_id =
- QuicUtils::GetHeadersStreamId(connection_->transport_version());
- std::unique_ptr<TestStream> fake_headers_stream =
- std::make_unique<TestStream>(headers_stream_id, &session_,
- /*is_static*/ true, BIDIRECTIONAL);
- QuicSessionPeer::ActivateStream(&session_, std::move(fake_headers_stream));
- // Send two bytes of payload.
- QuicRstStreamFrame rst1(kInvalidControlFrameId, headers_stream_id,
- QUIC_ERROR_PROCESSING_STREAM, 0);
- EXPECT_CALL(*connection_,
- CloseConnection(
- QUIC_INVALID_STREAM_ID, "Attempt to reset a static stream",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
- session_.OnRstStream(rst1);
-}
-
TEST_P(QuicSessionTestServer, OnStreamFrameInvalidStreamId) {
// Send two bytes of payload.
QuicStreamFrame data1(
QuicUtils::GetInvalidStreamId(connection_->transport_version()), true, 0,
- QuicStringPiece("HT"));
+ quiche::QuicheStringPiece("HT"));
EXPECT_CALL(*connection_,
CloseConnection(
QUIC_INVALID_STREAM_ID, "Received data for an invalid stream",
@@ -1610,10 +1644,8 @@ TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingRstOutOfOrder) {
QUIC_STREAM_CANCELLED, kByteOffset);
session_.OnRstStream(rst_frame);
if (VersionHasIetfQuicFrames(transport_version())) {
- // The test is predicated on the stream being fully closed. For IETF QUIC,
- // the RST_STREAM only does one side (the read side from the perspective of
- // the node receiving the RST_STREAM). This is needed to fully close the
- // stream and therefore fulfill all of the expects.
+ // The test requires the stream to be fully closed in both directions. For
+ // IETF QUIC, the RST_STREAM only closes one side.
QuicStopSendingFrame frame(kInvalidControlFrameId, stream->id(),
QUIC_STREAM_CANCELLED);
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
@@ -1674,7 +1706,8 @@ TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingFinAfterRst) {
// account the total number of bytes sent by the peer.
const QuicStreamOffset kByteOffset = 5678;
std::string body = "hello";
- QuicStreamFrame frame(stream->id(), true, kByteOffset, QuicStringPiece(body));
+ QuicStreamFrame frame(stream->id(), true, kByteOffset,
+ quiche::QuicheStringPiece(body));
session_.OnStreamFrame(frame);
QuicStreamOffset total_stream_bytes_sent_by_peer =
@@ -1777,7 +1810,8 @@ TEST_P(QuicSessionTestServer, FlowControlWithInvalidFinalOffset) {
EXPECT_CALL(*connection_, SendControlFrame(_));
EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
stream->Reset(QUIC_STREAM_CANCELLED);
- QuicStreamFrame frame(stream->id(), true, kLargeOffset, QuicStringPiece());
+ QuicStreamFrame frame(stream->id(), true, kLargeOffset,
+ quiche::QuicheStringPiece());
session_.OnStreamFrame(frame);
// Check that RST results in connection close.
@@ -1804,7 +1838,7 @@ TEST_P(QuicSessionTestServer, TooManyUnfinishedStreamsCauseServerRejectStream) {
// FIN or a RST_STREAM from the client.
for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId;
i += QuicUtils::StreamIdDelta(connection_->transport_version())) {
- QuicStreamFrame data1(i, false, 0, QuicStringPiece("HT"));
+ QuicStreamFrame data1(i, false, 0, quiche::QuicheStringPiece("HT"));
session_.OnStreamFrame(data1);
// EXPECT_EQ(1u, session_.GetNumOpenStreams());
if (VersionHasIetfQuicFrames(transport_version())) {
@@ -1835,7 +1869,8 @@ TEST_P(QuicSessionTestServer, TooManyUnfinishedStreamsCauseServerRejectStream) {
.Times(1);
}
// Create one more data streams to exceed limit of open stream.
- QuicStreamFrame data1(kFinalStreamId, false, 0, QuicStringPiece("HT"));
+ QuicStreamFrame data1(kFinalStreamId, false, 0,
+ quiche::QuicheStringPiece("HT"));
session_.OnStreamFrame(data1);
}
@@ -1845,7 +1880,7 @@ TEST_P(QuicSessionTestServer, DrainingStreamsDoNotCountAsOpenedOutgoing) {
// protocol point of view).
TestStream* stream = session_.CreateOutgoingBidirectionalStream();
QuicStreamId stream_id = stream->id();
- QuicStreamFrame data1(stream_id, true, 0, QuicStringPiece("HT"));
+ QuicStreamFrame data1(stream_id, true, 0, quiche::QuicheStringPiece("HT"));
session_.OnStreamFrame(data1);
EXPECT_CALL(session_, OnCanCreateNewOutgoingStream(false)).Times(1);
session_.StreamDraining(stream_id);
@@ -1856,11 +1891,11 @@ TEST_P(QuicSessionTestServer, NoPendingStreams) {
QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
transport_version(), Perspective::IS_CLIENT);
- QuicStreamFrame data1(stream_id, true, 10, QuicStringPiece("HT"));
+ QuicStreamFrame data1(stream_id, true, 10, quiche::QuicheStringPiece("HT"));
session_.OnStreamFrame(data1);
EXPECT_EQ(1, session_.num_incoming_streams_created());
- QuicStreamFrame data2(stream_id, false, 0, QuicStringPiece("HT"));
+ QuicStreamFrame data2(stream_id, false, 0, quiche::QuicheStringPiece("HT"));
session_.OnStreamFrame(data2);
EXPECT_EQ(1, session_.num_incoming_streams_created());
}
@@ -1873,12 +1908,12 @@ TEST_P(QuicSessionTestServer, PendingStreams) {
QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
transport_version(), Perspective::IS_CLIENT);
- QuicStreamFrame data1(stream_id, true, 10, QuicStringPiece("HT"));
+ QuicStreamFrame data1(stream_id, true, 10, quiche::QuicheStringPiece("HT"));
session_.OnStreamFrame(data1);
EXPECT_TRUE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
EXPECT_EQ(0, session_.num_incoming_streams_created());
- QuicStreamFrame data2(stream_id, false, 0, QuicStringPiece("HT"));
+ QuicStreamFrame data2(stream_id, false, 0, quiche::QuicheStringPiece("HT"));
session_.OnStreamFrame(data2);
EXPECT_FALSE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
EXPECT_EQ(1, session_.num_incoming_streams_created());
@@ -1892,7 +1927,7 @@ TEST_P(QuicSessionTestServer, RstPendingStreams) {
QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
transport_version(), Perspective::IS_CLIENT);
- QuicStreamFrame data1(stream_id, true, 10, QuicStringPiece("HT"));
+ QuicStreamFrame data1(stream_id, true, 10, quiche::QuicheStringPiece("HT"));
session_.OnStreamFrame(data1);
EXPECT_TRUE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
EXPECT_EQ(0, session_.num_incoming_streams_created());
@@ -1905,7 +1940,7 @@ TEST_P(QuicSessionTestServer, RstPendingStreams) {
EXPECT_EQ(0, session_.num_incoming_streams_created());
EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
- QuicStreamFrame data2(stream_id, false, 0, QuicStringPiece("HT"));
+ QuicStreamFrame data2(stream_id, false, 0, quiche::QuicheStringPiece("HT"));
session_.OnStreamFrame(data2);
EXPECT_FALSE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
EXPECT_EQ(0, session_.num_incoming_streams_created());
@@ -1936,7 +1971,7 @@ TEST_P(QuicSessionTestServer, PendingStreamOnWindowUpdate) {
session_.set_uses_pending_streams(true);
QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
transport_version(), Perspective::IS_CLIENT);
- QuicStreamFrame data1(stream_id, true, 10, QuicStringPiece("HT"));
+ QuicStreamFrame data1(stream_id, true, 10, quiche::QuicheStringPiece("HT"));
session_.OnStreamFrame(data1);
EXPECT_TRUE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
EXPECT_EQ(0, session_.num_incoming_streams_created());
@@ -1976,7 +2011,7 @@ TEST_P(QuicSessionTestServer, DrainingStreamsDoNotCountAsOpened) {
GetNthClientInitiatedBidirectionalId(2 * kMaxStreams + 1);
for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId;
i += QuicUtils::StreamIdDelta(connection_->transport_version())) {
- QuicStreamFrame data1(i, true, 0, QuicStringPiece("HT"));
+ QuicStreamFrame data1(i, true, 0, quiche::QuicheStringPiece("HT"));
session_.OnStreamFrame(data1);
EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams());
session_.StreamDraining(i);
@@ -2013,6 +2048,23 @@ TEST_P(QuicSessionTestClient, AvailableBidirectionalStreamsClient) {
&session_, GetNthClientInitiatedBidirectionalId(1)));
}
+TEST_P(QuicSessionTestClient, OnMaxStreamFrame) {
+ if (!VersionUsesHttp3(transport_version())) {
+ return;
+ }
+ QuicMaxStreamsFrame frame;
+ frame.unidirectional = false;
+ frame.stream_count = 120;
+ EXPECT_CALL(session_, OnCanCreateNewOutgoingStream(false)).Times(1);
+ session_.OnMaxStreamsFrame(frame);
+
+ QuicMaxStreamsFrame frame2;
+ frame2.unidirectional = false;
+ frame2.stream_count = 110;
+ EXPECT_CALL(session_, OnCanCreateNewOutgoingStream(false)).Times(0);
+ session_.OnMaxStreamsFrame(frame2);
+}
+
TEST_P(QuicSessionTestClient, AvailableUnidirectionalStreamsClient) {
ASSERT_TRUE(session_.GetOrCreateStream(
GetNthServerInitiatedUnidirectionalId(2)) != nullptr);
@@ -2041,7 +2093,7 @@ TEST_P(QuicSessionTestClient, RecordFinAfterReadSideClosed) {
QuicStreamPeer::CloseReadSide(stream);
// Receive a stream data frame with FIN.
- QuicStreamFrame frame(stream_id, true, 0, QuicStringPiece());
+ QuicStreamFrame frame(stream_id, true, 0, quiche::QuicheStringPiece());
session_.OnStreamFrame(frame);
EXPECT_TRUE(stream->fin_received());
@@ -2062,6 +2114,22 @@ TEST_P(QuicSessionTestClient, RecordFinAfterReadSideClosed) {
QuicSessionPeer::GetLocallyClosedStreamsHighestOffset(&session_).size());
}
+TEST_P(QuicSessionTestClient, IncomingStreamWithClientInitiatedStreamId) {
+ const QuicErrorCode expected_error =
+ VersionHasIetfQuicFrames(transport_version())
+ ? QUIC_HTTP_STREAM_WRONG_DIRECTION
+ : QUIC_INVALID_STREAM_ID;
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(expected_error, "Data for nonexistent stream",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
+
+ QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(1),
+ /* fin = */ false, /* offset = */ 0,
+ quiche::QuicheStringPiece("foo"));
+ session_.OnStreamFrame(frame);
+}
+
TEST_P(QuicSessionTestServer, ZombieStreams) {
TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
QuicStreamPeer::SetStreamBytesWritten(3, stream2);
@@ -2122,10 +2190,8 @@ TEST_P(QuicSessionTestServer, TestZombieStreams) {
stream2->OnStreamReset(rst_frame);
if (VersionHasIetfQuicFrames(transport_version())) {
- // The test is predicated on the stream being fully closed. For IETF QUIC,
- // the RST_STREAM only does one side (the read side from the perspective of
- // the node receiving the RST_STREAM). This is needed to fully close the
- // stream and therefore fulfill all of the expects.
+ // The test requires the stream to be fully closed in both directions. For
+ // IETF QUIC, the RST_STREAM only closes one side.
QuicStopSendingFrame frame(kInvalidControlFrameId, stream2->id(),
QUIC_STREAM_CANCELLED);
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
@@ -2295,11 +2361,14 @@ TEST_P(QuicSessionTestServer, RetransmitFrames) {
frames.push_back(QuicFrame(frame3));
EXPECT_FALSE(session_.WillingAndAbleToWrite());
- EXPECT_CALL(*stream2, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
+ EXPECT_CALL(*stream2, RetransmitStreamData(_, _, _, _))
+ .WillOnce(Return(true));
EXPECT_CALL(*connection_, SendControlFrame(_))
.WillOnce(Invoke(&ClearControlFrame));
- EXPECT_CALL(*stream4, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
- EXPECT_CALL(*stream6, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
+ EXPECT_CALL(*stream4, RetransmitStreamData(_, _, _, _))
+ .WillOnce(Return(true));
+ EXPECT_CALL(*stream6, RetransmitStreamData(_, _, _, _))
+ .WillOnce(Return(true));
EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
session_.RetransmitFrames(frames, TLP_RETRANSMISSION);
}
@@ -2336,7 +2405,7 @@ TEST_P(QuicSessionTestServer, RetransmitLostDataCausesConnectionClose) {
TEST_P(QuicSessionTestServer, SendMessage) {
// Cannot send message when encryption is not established.
- EXPECT_FALSE(session_.IsCryptoHandshakeConfirmed());
+ EXPECT_FALSE(session_.OneRttKeysAvailable());
quic::QuicMemSliceStorage storage(nullptr, 0, nullptr, 0);
EXPECT_EQ(MessageResult(MESSAGE_STATUS_ENCRYPTION_NOT_ESTABLISHED, 0),
session_.SendMessage(
@@ -2344,11 +2413,14 @@ TEST_P(QuicSessionTestServer, SendMessage) {
"", &storage)));
// Finish handshake.
+ if (connection_->version().HasHandshakeDone()) {
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ }
CryptoHandshakeMessage handshake_message;
session_.GetMutableCryptoStream()->OnHandshakeMessage(handshake_message);
- EXPECT_TRUE(session_.IsCryptoHandshakeConfirmed());
+ EXPECT_TRUE(session_.OneRttKeysAvailable());
- QuicStringPiece message;
+ quiche::QuicheStringPiece message;
EXPECT_CALL(*connection_, SendMessage(1, _, false))
.WillOnce(Return(MESSAGE_STATUS_SUCCESS));
EXPECT_EQ(MessageResult(MESSAGE_STATUS_SUCCESS, 1),
@@ -2521,8 +2593,8 @@ TEST_P(QuicSessionTestServer, WriteMemSlicesOnReadUnidirectionalStream) {
.Times(1);
char data[1024];
std::vector<std::pair<char*, size_t>> buffers;
- buffers.push_back(std::make_pair(data, QUIC_ARRAYSIZE(data)));
- buffers.push_back(std::make_pair(data, QUIC_ARRAYSIZE(data)));
+ buffers.push_back(std::make_pair(data, QUICHE_ARRAYSIZE(data)));
+ buffers.push_back(std::make_pair(data, QUICHE_ARRAYSIZE(data)));
QuicTestMemSliceVector vector(buffers);
stream4->WriteMemSlices(vector.span(), false);
}
@@ -2622,15 +2694,12 @@ TEST_P(QuicSessionTestServer, NewStreamIdAboveLimit) {
session_.OnStreamFrame(unidirectional_stream_frame);
}
-// Check that the OnStopSendingFrame upcall handles bad input properly
-// First test checks that invalid stream ids are handled.
-TEST_P(QuicSessionTestServer, OnStopSendingInputInvalidStreamId) {
+// Checks that invalid stream ids are handled.
+TEST_P(QuicSessionTestServer, OnStopSendingInvalidStreamId) {
if (!VersionHasIetfQuicFrames(transport_version())) {
- // Applicable only to IETF QUIC
return;
}
// Check that "invalid" stream ids are rejected.
- // Note that the notion of an invalid stream id is Google-specific.
QuicStopSendingFrame frame(1, -1, 123);
EXPECT_CALL(
*connection_,
@@ -2639,11 +2708,22 @@ TEST_P(QuicSessionTestServer, OnStopSendingInputInvalidStreamId) {
session_.OnStopSendingFrame(frame);
}
-// Second test, streams in the static stream map are not subject to
-// STOP_SENDING; it's ignored.
-TEST_P(QuicSessionTestServer, OnStopSendingInputStaticStreams) {
+TEST_P(QuicSessionTestServer, OnStopSendingReadUnidirectional) {
+ if (!VersionHasIetfQuicFrames(transport_version())) {
+ return;
+ }
+ // It's illegal to send STOP_SENDING with a stream ID that is read-only.
+ QuicStopSendingFrame frame(1, GetNthClientInitiatedUnidirectionalId(1), 123);
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_INVALID_STREAM_ID,
+ "Received STOP_SENDING for a read-only stream", _));
+ session_.OnStopSendingFrame(frame);
+}
+
+// Static streams ignore STOP_SENDING.
+TEST_P(QuicSessionTestServer, OnStopSendingStaticStreams) {
if (!VersionHasIetfQuicFrames(transport_version())) {
- // Applicable only to IETF QUIC
return;
}
QuicStreamId stream_id = 0;
@@ -2651,7 +2731,6 @@ TEST_P(QuicSessionTestServer, OnStopSendingInputStaticStreams) {
stream_id, &session_, /*is_static*/ true, BIDIRECTIONAL);
QuicSessionPeer::ActivateStream(&session_, std::move(fake_static_stream));
// Check that a stream id in the static stream map is ignored.
- // Note that the notion of a static stream is Google-specific.
QuicStopSendingFrame frame(1, stream_id, 123);
EXPECT_CALL(*connection_,
CloseConnection(QUIC_INVALID_STREAM_ID,
@@ -2659,44 +2738,72 @@ TEST_P(QuicSessionTestServer, OnStopSendingInputStaticStreams) {
session_.OnStopSendingFrame(frame);
}
-// Third test, if stream id specifies a closed stream:
-// return true and do not close the connection.
-TEST_P(QuicSessionTestServer, OnStopSendingInputClosedStream) {
+// If stream is write closed, do not send a RESET_STREAM frame.
+TEST_P(QuicSessionTestServer, OnStopSendingForWriteClosedStream) {
if (!VersionHasIetfQuicFrames(transport_version())) {
- // Applicable only to IETF QUIC
return;
}
TestStream* stream = session_.CreateOutgoingBidirectionalStream();
QuicStreamId stream_id = stream->id();
- // Expect these as side effect of the close operations.
+ stream->CloseWriteSide();
+ EXPECT_TRUE(stream->write_side_closed());
+ QuicStopSendingFrame frame(1, stream_id, 123);
+ EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
+ session_.OnStopSendingFrame(frame);
+}
+
+// If stream is closed, return true and do not close the connection.
+TEST_P(QuicSessionTestServer, OnStopSendingClosedStream) {
+ if (!VersionHasIetfQuicFrames(transport_version())) {
+ return;
+ }
+
+ TestStream* stream = session_.CreateOutgoingBidirectionalStream();
+ QuicStreamId stream_id = stream->id();
+ // Expect these as side effect of closing the stream.
EXPECT_CALL(*connection_, SendControlFrame(_));
EXPECT_CALL(*connection_, OnStreamReset(_, _));
- stream->CloseWriteSide();
- stream->CloseReadSide();
+ session_.CloseStream(stream_id);
QuicStopSendingFrame frame(1, stream_id, 123);
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
session_.OnStopSendingFrame(frame);
}
-// Fourth test, if stream id specifies a nonexistent stream, return false and
-// close the connection
-TEST_P(QuicSessionTestServer, OnStopSendingInputNonExistentStream) {
+// If stream id is a nonexistent local stream, return false and close the
+// connection.
+TEST_P(QuicSessionTestServer, OnStopSendingInputNonExistentLocalStream) {
if (!VersionHasIetfQuicFrames(transport_version())) {
- // Applicable only to IETF QUIC
return;
}
QuicStopSendingFrame frame(1, GetNthServerInitiatedBidirectionalId(123456),
123);
- EXPECT_CALL(
- *connection_,
- CloseConnection(IETF_QUIC_PROTOCOL_VIOLATION,
- "Received STOP_SENDING for a non-existent stream", _))
+ EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_STREAM_WRONG_DIRECTION,
+ "Data for nonexistent stream", _))
.Times(1);
session_.OnStopSendingFrame(frame);
}
+// If a STOP_SENDING is received for a peer initiated stream, the new stream
+// will be created.
+TEST_P(QuicSessionTestServer, OnStopSendingNewStream) {
+ if (!VersionHasIetfQuicFrames(transport_version())) {
+ return;
+ }
+ QuicStopSendingFrame frame(1, GetNthClientInitiatedBidirectionalId(1), 123);
+
+ // A Rst will be sent as a response for STOP_SENDING.
+ EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
+ EXPECT_CALL(*connection_, OnStreamReset(_, _)).Times(1);
+ session_.OnStopSendingFrame(frame);
+
+ QuicStream* stream =
+ session_.GetOrCreateStream(GetNthClientInitiatedBidirectionalId(1));
+ EXPECT_TRUE(stream);
+ EXPECT_TRUE(stream->write_side_closed());
+}
+
// For a valid stream, ensure that all works
TEST_P(QuicSessionTestServer, OnStopSendingInputValidStream) {
if (!VersionHasIetfQuicFrames(transport_version())) {
@@ -2757,14 +2864,8 @@ TEST_P(QuicSessionTestServer, StreamFrameReceivedAfterFin) {
session_.OnStreamFrame(frame);
QuicStreamFrame frame1(stream->id(), false, 1, ",");
- if (!GetQuicReloadableFlag(quic_close_connection_on_wrong_offset)) {
- EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_,
- OnStreamReset(stream->id(), QUIC_DATA_AFTER_CLOSE_OFFSET));
- } else {
- EXPECT_CALL(*connection_,
- CloseConnection(QUIC_STREAM_DATA_BEYOND_CLOSE_OFFSET, _, _));
- }
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_STREAM_DATA_BEYOND_CLOSE_OFFSET, _, _));
session_.OnStreamFrame(frame1);
}
@@ -2796,6 +2897,33 @@ TEST_P(QuicSessionTestServer, ResetForIETFStreamTypes) {
session_.SendRstStream(bidirectional, QUIC_STREAM_CANCELLED, 0);
}
+TEST_P(QuicSessionTestServer, DecryptionKeyAvailableBeforeEncryptionKey) {
+ if (connection_->version().handshake_protocol != PROTOCOL_TLS1_3) {
+ return;
+ }
+ ASSERT_FALSE(connection_->framer().HasEncrypterOfEncryptionLevel(
+ ENCRYPTION_HANDSHAKE));
+ EXPECT_FALSE(session_.OnNewDecryptionKeyAvailable(
+ ENCRYPTION_HANDSHAKE, /*decrypter=*/nullptr,
+ /*set_alternative_decrypter=*/false, /*latch_once_used=*/false));
+}
+
+TEST_P(QuicSessionTestServer, IncomingStreamWithServerInitiatedStreamId) {
+ const QuicErrorCode expected_error =
+ VersionHasIetfQuicFrames(transport_version())
+ ? QUIC_HTTP_STREAM_WRONG_DIRECTION
+ : QUIC_INVALID_STREAM_ID;
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(expected_error, "Data for nonexistent stream",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
+
+ QuicStreamFrame frame(GetNthServerInitiatedBidirectionalId(1),
+ /* fin = */ false, /* offset = */ 0,
+ quiche::QuicheStringPiece("foo"));
+ session_.OnStreamFrame(frame);
+}
+
// A client test class that can be used when the automatic configuration is not
// desired.
class QuicSessionTestClientUnconfigured : public QuicSessionTestBase {
@@ -2810,106 +2938,13 @@ INSTANTIATE_TEST_SUITE_P(Tests,
::testing::ValuesIn(AllSupportedVersions()),
::testing::PrintToStringParamName());
-TEST_P(QuicSessionTestClientUnconfigured, HoldMaxStreamsFrame) {
- if (!VersionHasIetfQuicFrames(transport_version())) {
- return;
- }
- QuicStreamIdManager* stream_id_manager =
- QuicSessionPeer::v99_unidirectional_stream_id_manager(&session_);
-
- EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
- QuicStreamsBlockedFrame frame(1u, 0u, /*unidirectional=*/true);
- session_.OnStreamsBlockedFrame(frame);
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .Times(1)
- .WillRepeatedly(Invoke(&session_, &TestSession::SaveFrame));
- session_.OnConfigNegotiated();
- EXPECT_EQ(MAX_STREAMS_FRAME, session_.save_frame().type);
- EXPECT_EQ(stream_id_manager->incoming_actual_max_streams(),
- session_.save_frame().max_streams_frame.stream_count);
- EXPECT_EQ(1u, session_.save_frame().max_streams_frame.control_frame_id);
-}
-
-TEST_P(QuicSessionTestClientUnconfigured, HoldStreamsBlockedFrameXmit) {
- if (!VersionHasIetfQuicFrames(transport_version())) {
- // Applicable only to IETF QUIC
- return;
- }
- QuicStreamIdManager* stream_id_manager =
- QuicSessionPeer::v99_unidirectional_stream_id_manager(&session_);
-
- // Set the stream limit to 0 which will cause
- // CanOpenNextOutgoingUnidirectionalStream()
- // to generated a STREAMS_BLOCKED frame.
- QuicStreamIdManagerPeer::set_outgoing_max_streams(stream_id_manager, 0);
-
- // Since the stream limit is 0 and no sreams can be created this should return
- // false and have forced a streams-blocked to be queued up, with the
- // blocked stream id == 0.
- EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
- EXPECT_FALSE(session_.CanOpenNextOutgoingUnidirectionalStream());
-
- // We will expect two calls to SendControlFrame: The first is because
- // OnConfigNegotiated does not increase the limit, so the app still can not
- // create new streams (and therefore needs the STREAMS-BLOCKED to go out). The
- // second is because the ensuing CanOpenNext.. call will fail (this test not
- // actually increasing the limit) and that will send another STREAMS-BLOCKED.
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .Times(2)
- .WillRepeatedly(Invoke(&session_, &TestSession::SaveFrame));
- // Set configuration data so that when the config happens, the stream limit is
- // not increased and another STREAMS-BLOCKED will be needed..
- QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams(session_.config(),
- 0);
-
- session_.OnConfigNegotiated();
-
- EXPECT_EQ(STREAMS_BLOCKED_FRAME, session_.save_frame().type);
- EXPECT_EQ(0u, session_.save_frame().streams_blocked_frame.stream_count);
- EXPECT_EQ(1u, session_.save_frame().streams_blocked_frame.control_frame_id);
-
- EXPECT_FALSE(session_.CanOpenNextOutgoingUnidirectionalStream());
- EXPECT_EQ(STREAMS_BLOCKED_FRAME, session_.save_frame().type);
- EXPECT_EQ(0u, session_.save_frame().streams_blocked_frame.stream_count);
- EXPECT_EQ(2u, session_.save_frame().streams_blocked_frame.control_frame_id);
-}
-
-TEST_P(QuicSessionTestClientUnconfigured, HoldStreamsBlockedFrameNoXmit) {
- if (!VersionHasIetfQuicFrames(transport_version())) {
- return;
- }
- QuicStreamIdManager* stream_id_manager =
- QuicSessionPeer::v99_unidirectional_stream_id_manager(&session_);
-
- // Set the stream limit to 0 which will cause
- // CanOpenNextOutgoingUnidirectionalStream()
- // to generated a STREAMS_BLOCKED frame.
- QuicStreamIdManagerPeer::set_outgoing_max_streams(stream_id_manager, 0);
-
- // Since the stream limit is 0 and no streams can be created this should
- // return false and have forced a streams-blocked to be queued up, with the
- // blocked stream id == 0.
- EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
- EXPECT_FALSE(session_.CanOpenNextOutgoingUnidirectionalStream());
-
- // Set configuration data so that when the config happens, the stream limit is
- // increased.
- QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams(session_.config(),
- 10);
-
- // STREAMS_BLOCKED frame should not be sent because streams can now be
- // created.
- EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
- session_.OnConfigNegotiated();
- EXPECT_TRUE(session_.CanOpenNextOutgoingUnidirectionalStream());
-}
-
TEST_P(QuicSessionTestClientUnconfigured, StreamInitiallyBlockedThenUnblocked) {
if (!connection_->version().AllowsLowFlowControlLimits()) {
return;
}
// Create a stream before negotiating the config and verify it starts off
// blocked.
+ QuicSessionPeer::SetMaxOpenOutgoingBidirectionalStreams(&session_, 10);
TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
EXPECT_TRUE(stream2->flow_controller()->IsBlocked());
EXPECT_TRUE(session_.IsConnectionFlowControlBlocked());
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_socket_address_coder_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_socket_address_coder_test.cc
index 7ab1383e1c0..cbfe04f7d86 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_socket_address_coder_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_socket_address_coder_test.cc
@@ -6,8 +6,8 @@
#include <string>
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
namespace quic {
namespace test {
@@ -111,7 +111,7 @@ TEST_F(QuicSocketAddressCoderTest, EncodeAndDecode) {
{"::1", 65534},
};
- for (size_t i = 0; i < QUIC_ARRAYSIZE(test_case); i++) {
+ for (size_t i = 0; i < QUICHE_ARRAYSIZE(test_case); i++) {
QuicIpAddress ip;
ASSERT_TRUE(ip.FromString(test_case[i].ip_literal));
QuicSocketAddressCoder encoder(QuicSocketAddress(ip, test_case[i].port));
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream.cc b/chromium/net/third_party/quiche/src/quic/core/quic_stream.cc
index 20373272d4f..86beaef0f7b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream.cc
@@ -15,14 +15,17 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_optional.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+using quiche::QuicheOptional;
using spdy::SpdyPriority;
namespace quic {
#define ENDPOINT \
- (session_->perspective() == Perspective::IS_SERVER ? "Server: " : "Client: ")
+ (perspective_ == Perspective::IS_SERVER ? "Server: " : "Client: ")
namespace {
@@ -105,9 +108,13 @@ size_t GetReceivedFlowControlWindow(QuicSession* session,
// static
const SpdyPriority QuicStream::kDefaultPriority;
+// static
+const int QuicStream::kDefaultUrgency;
+
PendingStream::PendingStream(QuicStreamId id, QuicSession* session)
: id_(id),
session_(session),
+ stream_delegate_(session),
stream_bytes_read_(0),
fin_received_(false),
connection_flow_controller_(session->flow_controller()),
@@ -139,26 +146,18 @@ void PendingStream::AddBytesConsumed(QuicByteCount bytes) {
void PendingStream::Reset(QuicRstStreamErrorCode /*error*/) {
// Currently PendingStream is only read-unidirectional. It shouldn't send
// Reset.
- DCHECK_EQ(READ_UNIDIRECTIONAL,
- QuicUtils::GetStreamType(id_, session_->perspective(),
- /*peer_initiated = */ true));
QUIC_NOTREACHED();
}
-void PendingStream::CloseConnectionWithDetails(QuicErrorCode error,
- const std::string& details) {
- session_->connection()->CloseConnection(
- error, details, ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+void PendingStream::OnUnrecoverableError(QuicErrorCode error,
+ const std::string& details) {
+ stream_delegate_->OnStreamError(error, details);
}
QuicStreamId PendingStream::id() const {
return id_;
}
-const QuicSocketAddress& PendingStream::PeerAddressOfLatestPacket() const {
- return session_->connection()->last_packet_source_address();
-}
-
void PendingStream::OnStreamFrame(const QuicStreamFrame& frame) {
DCHECK_EQ(frame.stream_id, id_);
@@ -170,16 +169,15 @@ void PendingStream::OnStreamFrame(const QuicStreamFrame& frame) {
QUIC_PEER_BUG
<< "Receive stream frame reaches max stream length. frame offset "
<< frame.offset << " length " << frame.data_length;
- CloseConnectionWithDetails(
- QUIC_STREAM_LENGTH_OVERFLOW,
- "Peer sends more data than allowed on this stream.");
+ OnUnrecoverableError(QUIC_STREAM_LENGTH_OVERFLOW,
+ "Peer sends more data than allowed on this stream.");
return;
}
if (frame.offset + frame.data_length > sequencer_.close_offset()) {
- CloseConnectionWithDetails(
+ OnUnrecoverableError(
QUIC_STREAM_DATA_BEYOND_CLOSE_OFFSET,
- QuicStrCat(
+ quiche::QuicheStrCat(
"Stream ", id_,
" received data with offset: ", frame.offset + frame.data_length,
", which is beyond close offset: ", sequencer()->close_offset()));
@@ -202,9 +200,8 @@ void PendingStream::OnStreamFrame(const QuicStreamFrame& frame) {
// violation of flow control.
if (flow_controller_.FlowControlViolation() ||
connection_flow_controller_->FlowControlViolation()) {
- CloseConnectionWithDetails(
- QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA,
- "Flow control violation after increasing offset");
+ OnUnrecoverableError(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA,
+ "Flow control violation after increasing offset");
return;
}
}
@@ -217,8 +214,8 @@ void PendingStream::OnRstStreamFrame(const QuicRstStreamFrame& frame) {
if (frame.byte_offset > kMaxStreamLength) {
// Peer are not suppose to write bytes more than maxium allowed.
- CloseConnectionWithDetails(QUIC_STREAM_LENGTH_OVERFLOW,
- "Reset frame stream offset overflow.");
+ OnUnrecoverableError(QUIC_STREAM_LENGTH_OVERFLOW,
+ "Reset frame stream offset overflow.");
return;
}
@@ -226,21 +223,20 @@ void PendingStream::OnRstStreamFrame(const QuicRstStreamFrame& frame) {
std::numeric_limits<QuicStreamOffset>::max();
if (sequencer()->close_offset() != kMaxOffset &&
frame.byte_offset != sequencer()->close_offset()) {
- CloseConnectionWithDetails(
+ OnUnrecoverableError(
QUIC_STREAM_MULTIPLE_OFFSET,
- QuicStrCat("Stream ", id_,
- " received new final offset: ", frame.byte_offset,
- ", which is different from close offset: ",
- sequencer()->close_offset()));
+ quiche::QuicheStrCat("Stream ", id_,
+ " received new final offset: ", frame.byte_offset,
+ ", which is different from close offset: ",
+ sequencer()->close_offset()));
return;
}
MaybeIncreaseHighestReceivedOffset(frame.byte_offset);
if (flow_controller_.FlowControlViolation() ||
connection_flow_controller_->FlowControlViolation()) {
- CloseConnectionWithDetails(
- QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA,
- "Flow control violation after increasing offset");
+ OnUnrecoverableError(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA,
+ "Flow control violation after increasing offset");
return;
}
}
@@ -285,15 +281,15 @@ QuicStream::QuicStream(PendingStream* pending, StreamType type, bool is_static)
namespace {
-QuicOptional<QuicFlowController> FlowController(QuicStreamId id,
- QuicSession* session,
- StreamType type) {
+QuicheOptional<QuicFlowController> FlowController(QuicStreamId id,
+ QuicSession* session,
+ StreamType type) {
if (type == CRYPTO) {
// The only QuicStream with a StreamType of CRYPTO is QuicCryptoStream, when
// it is using crypto frames instead of stream frames. The QuicCryptoStream
// doesn't have any flow control in that case, so we don't create a
// QuicFlowController for it.
- return QuicOptional<QuicFlowController>();
+ return QuicheOptional<QuicFlowController>();
}
return QuicFlowController(
session, id,
@@ -328,17 +324,13 @@ QuicStream::QuicStream(QuicStreamId id,
StreamType type,
uint64_t stream_bytes_read,
bool fin_received,
- QuicOptional<QuicFlowController> flow_controller,
+ QuicheOptional<QuicFlowController> flow_controller,
QuicFlowController* connection_flow_controller)
: sequencer_(std::move(sequencer)),
id_(id),
session_(session),
- precedence_(
- session->use_http2_priority_write_scheduler()
- ? spdy::SpdyStreamPrecedence(0,
- spdy::kHttp2DefaultStreamWeight,
- false)
- : spdy::SpdyStreamPrecedence(kDefaultPriority)),
+ stream_delegate_(session),
+ precedence_(CalculateDefaultPriority(session)),
stream_bytes_read_(stream_bytes_read),
stream_error_(QUIC_STREAM_NO_ERROR),
connection_error_(QUIC_NO_ERROR),
@@ -366,7 +358,8 @@ QuicStream::QuicStream(QuicStreamId id,
? QuicUtils::GetStreamType(id_,
session->perspective(),
session->IsIncomingStream(id_))
- : type) {
+ : type),
+ perspective_(session->perspective()) {
if (type_ == WRITE_UNIDIRECTIONAL) {
set_fin_received(true);
CloseReadSide();
@@ -375,7 +368,7 @@ QuicStream::QuicStream(QuicStreamId id,
CloseWriteSide();
}
if (type_ != CRYPTO) {
- session_->RegisterStreamPriority(id, is_static_, precedence_);
+ stream_delegate_->RegisterStreamPriority(id, is_static_, precedence_);
}
}
@@ -387,8 +380,8 @@ QuicStream::~QuicStream() {
<< send_buffer_.stream_bytes_outstanding()
<< ", fin_outstanding: " << fin_outstanding_;
}
- if (session_ != nullptr && type_ != CRYPTO) {
- session_->UnregisterStreamPriority(id(), is_static_);
+ if (stream_delegate_ != nullptr && type_ != CRYPTO) {
+ stream_delegate_->UnregisterStreamPriority(id(), is_static_);
}
}
@@ -397,10 +390,15 @@ void QuicStream::OnStreamFrame(const QuicStreamFrame& frame) {
DCHECK(!(read_side_closed_ && write_side_closed_));
+ if (frame.fin && is_static_) {
+ OnUnrecoverableError(QUIC_INVALID_STREAM_ID,
+ "Attempt to close a static stream");
+ return;
+ }
+
if (type_ == WRITE_UNIDIRECTIONAL) {
- CloseConnectionWithDetails(
- QUIC_DATA_RECEIVED_ON_WRITE_UNIDIRECTIONAL_STREAM,
- "Data received on write unidirectional stream");
+ OnUnrecoverableError(QUIC_DATA_RECEIVED_ON_WRITE_UNIDIRECTIONAL_STREAM,
+ "Data received on write unidirectional stream");
return;
}
@@ -413,23 +411,19 @@ void QuicStream::OnStreamFrame(const QuicStreamFrame& frame) {
<< " reaches max stream length. frame offset " << frame.offset
<< " length " << frame.data_length << ". "
<< sequencer_.DebugString();
- CloseConnectionWithDetails(
+ OnUnrecoverableError(
QUIC_STREAM_LENGTH_OVERFLOW,
- QuicStrCat("Peer sends more data than allowed on stream ", id_,
- ". frame: offset = ", frame.offset, ", length = ",
- frame.data_length, ". ", sequencer_.DebugString()));
+ quiche::QuicheStrCat("Peer sends more data than allowed on stream ",
+ id_, ". frame: offset = ", frame.offset,
+ ", length = ", frame.data_length, ". ",
+ sequencer_.DebugString()));
return;
}
if (frame.offset + frame.data_length > sequencer_.close_offset()) {
- if (!GetQuicReloadableFlag(quic_close_connection_on_wrong_offset)) {
- Reset(QUIC_DATA_AFTER_CLOSE_OFFSET);
- return;
- }
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_close_connection_on_wrong_offset, 1, 2);
- CloseConnectionWithDetails(
+ OnUnrecoverableError(
QUIC_STREAM_DATA_BEYOND_CLOSE_OFFSET,
- QuicStrCat(
+ quiche::QuicheStrCat(
"Stream ", id_,
" received data with offset: ", frame.offset + frame.data_length,
", which is beyond close offset: ", sequencer_.close_offset()));
@@ -463,9 +457,8 @@ void QuicStream::OnStreamFrame(const QuicStreamFrame& frame) {
// violation of flow control.
if (flow_controller_->FlowControlViolation() ||
connection_flow_controller_->FlowControlViolation()) {
- CloseConnectionWithDetails(
- QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA,
- "Flow control violation after increasing offset");
+ OnUnrecoverableError(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA,
+ "Flow control violation after increasing offset");
return;
}
}
@@ -473,6 +466,28 @@ void QuicStream::OnStreamFrame(const QuicStreamFrame& frame) {
sequencer_.OnStreamFrame(frame);
}
+bool QuicStream::OnStopSending(uint16_t code) {
+ // Do not reset the stream if all data has been sent and acknowledged.
+ if (write_side_closed() && !IsWaitingForAcks()) {
+ QUIC_DVLOG(1) << ENDPOINT
+ << "Ignoring STOP_SENDING for a write closed stream, id: "
+ << id_;
+ return false;
+ }
+
+ if (is_static_) {
+ QUIC_DVLOG(1) << ENDPOINT
+ << "Received STOP_SENDING for a static stream, id: " << id_
+ << " Closing connection";
+ OnUnrecoverableError(QUIC_INVALID_STREAM_ID,
+ "Received STOP_SENDING for a static stream");
+ return false;
+ }
+
+ stream_error_ = static_cast<QuicRstStreamErrorCode>(code);
+ return true;
+}
+
int QuicStream::num_frames_received() const {
return sequencer_.num_frames_received();
}
@@ -485,33 +500,29 @@ void QuicStream::OnStreamReset(const QuicRstStreamFrame& frame) {
rst_received_ = true;
if (frame.byte_offset > kMaxStreamLength) {
// Peer are not suppose to write bytes more than maxium allowed.
- CloseConnectionWithDetails(QUIC_STREAM_LENGTH_OVERFLOW,
- "Reset frame stream offset overflow.");
+ OnUnrecoverableError(QUIC_STREAM_LENGTH_OVERFLOW,
+ "Reset frame stream offset overflow.");
return;
}
- if (GetQuicReloadableFlag(quic_close_connection_on_wrong_offset)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_close_connection_on_wrong_offset, 2, 2);
- const QuicStreamOffset kMaxOffset =
- std::numeric_limits<QuicStreamOffset>::max();
- if (sequencer()->close_offset() != kMaxOffset &&
- frame.byte_offset != sequencer()->close_offset()) {
- CloseConnectionWithDetails(
- QUIC_STREAM_MULTIPLE_OFFSET,
- QuicStrCat("Stream ", id_,
- " received new final offset: ", frame.byte_offset,
- ", which is different from close offset: ",
- sequencer_.close_offset()));
- return;
- }
+ const QuicStreamOffset kMaxOffset =
+ std::numeric_limits<QuicStreamOffset>::max();
+ if (sequencer()->close_offset() != kMaxOffset &&
+ frame.byte_offset != sequencer()->close_offset()) {
+ OnUnrecoverableError(
+ QUIC_STREAM_MULTIPLE_OFFSET,
+ quiche::QuicheStrCat("Stream ", id_,
+ " received new final offset: ", frame.byte_offset,
+ ", which is different from close offset: ",
+ sequencer_.close_offset()));
+ return;
}
MaybeIncreaseHighestReceivedOffset(frame.byte_offset);
if (flow_controller_->FlowControlViolation() ||
connection_flow_controller_->FlowControlViolation()) {
- CloseConnectionWithDetails(
- QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA,
- "Flow control violation after increasing offset");
+ OnUnrecoverableError(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA,
+ "Flow control violation after increasing offset");
return;
}
@@ -556,10 +567,9 @@ void QuicStream::Reset(QuicRstStreamErrorCode error) {
rst_sent_ = true;
}
-void QuicStream::CloseConnectionWithDetails(QuicErrorCode error,
- const std::string& details) {
- session()->connection()->CloseConnection(
- error, details, ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+void QuicStream::OnUnrecoverableError(QuicErrorCode error,
+ const std::string& details) {
+ stream_delegate_->OnStreamError(error, details);
}
const spdy::SpdyStreamPrecedence& QuicStream::precedence() const {
@@ -568,11 +578,14 @@ const spdy::SpdyStreamPrecedence& QuicStream::precedence() const {
void QuicStream::SetPriority(const spdy::SpdyStreamPrecedence& precedence) {
precedence_ = precedence;
- session_->UpdateStreamPriority(id(), precedence);
+
+ MaybeSendPriorityUpdateFrame();
+
+ stream_delegate_->UpdateStreamPriority(id(), precedence);
}
void QuicStream::WriteOrBufferData(
- QuicStringPiece data,
+ quiche::QuicheStringPiece data,
bool fin,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
if (data.empty() && !fin) {
@@ -588,9 +601,8 @@ void QuicStream::WriteOrBufferData(
QUIC_DLOG(ERROR) << ENDPOINT
<< "Attempt to write when the write side is closed";
if (type_ == READ_UNIDIRECTIONAL) {
- CloseConnectionWithDetails(
- QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM,
- "Try to send data on read unidirectional stream");
+ OnUnrecoverableError(QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM,
+ "Try to send data on read unidirectional stream");
}
return;
}
@@ -605,9 +617,9 @@ void QuicStream::WriteOrBufferData(
QuicStreamOffset offset = send_buffer_.stream_offset();
if (kMaxStreamLength - offset < data.length()) {
QUIC_BUG << "Write too many data via stream " << id_;
- CloseConnectionWithDetails(
+ OnUnrecoverableError(
QUIC_STREAM_LENGTH_OVERFLOW,
- QuicStrCat("Write too many data via stream ", id_));
+ quiche::QuicheStrCat("Write too many data via stream ", id_));
return;
}
send_buffer_.SaveStreamData(&iov, 1, 0, data.length());
@@ -683,9 +695,8 @@ QuicConsumedData QuicStream::WriteMemSlices(QuicMemSliceSpan span, bool fin) {
QUIC_DLOG(ERROR) << ENDPOINT << "Stream " << id()
<< " attempting to write when the write side is closed";
if (type_ == READ_UNIDIRECTIONAL) {
- CloseConnectionWithDetails(
- QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM,
- "Try to send data on read unidirectional stream");
+ OnUnrecoverableError(QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM,
+ "Try to send data on read unidirectional stream");
}
return consumed_data;
}
@@ -700,9 +711,9 @@ QuicConsumedData QuicStream::WriteMemSlices(QuicMemSliceSpan span, bool fin) {
if (offset > send_buffer_.stream_offset() ||
kMaxStreamLength < send_buffer_.stream_offset()) {
QUIC_BUG << "Write too many data via stream " << id_;
- CloseConnectionWithDetails(
+ OnUnrecoverableError(
QUIC_STREAM_LENGTH_OVERFLOW,
- QuicStrCat("Write too many data via stream ", id_));
+ quiche::QuicheStrCat("Write too many data via stream ", id_));
return consumed_data;
}
OnDataBuffered(offset, consumed_data.bytes_consumed, nullptr);
@@ -775,10 +786,6 @@ void QuicStream::StopReading() {
sequencer_.StopReading();
}
-const QuicSocketAddress& QuicStream::PeerAddressOfLatestPacket() const {
- return session_->connection()->last_packet_source_address();
-}
-
void QuicStream::OnClose() {
CloseReadSide();
CloseWriteSide();
@@ -810,7 +817,7 @@ void QuicStream::OnClose() {
void QuicStream::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) {
if (type_ == READ_UNIDIRECTIONAL) {
- CloseConnectionWithDetails(
+ OnUnrecoverableError(
QUIC_WINDOW_UPDATE_RECEIVED_ON_READ_UNIDIRECTIONAL_STREAM,
"WindowUpdateFrame received on READ_UNIDIRECTIONAL stream.");
return;
@@ -880,6 +887,7 @@ bool QuicStream::OnStreamFrameAcked(QuicStreamOffset offset,
QuicByteCount data_length,
bool fin_acked,
QuicTime::Delta /*ack_delay_time*/,
+ QuicTime /*receive_timestamp*/,
QuicByteCount* newly_acked_length) {
QUIC_DVLOG(1) << ENDPOINT << "stream " << id_ << " Acking "
<< "[" << offset << ", " << offset + data_length << "]"
@@ -887,13 +895,11 @@ bool QuicStream::OnStreamFrameAcked(QuicStreamOffset offset,
*newly_acked_length = 0;
if (!send_buffer_.OnStreamDataAcked(offset, data_length,
newly_acked_length)) {
- CloseConnectionWithDetails(QUIC_INTERNAL_ERROR,
- "Trying to ack unsent data.");
+ OnUnrecoverableError(QUIC_INTERNAL_ERROR, "Trying to ack unsent data.");
return false;
}
if (!fin_sent_ && fin_acked) {
- CloseConnectionWithDetails(QUIC_INTERNAL_ERROR,
- "Trying to ack unsent fin.");
+ OnUnrecoverableError(QUIC_INTERNAL_ERROR, "Trying to ack unsent fin.");
return false;
}
// Indicates whether ack listener's OnPacketAcked should be called.
@@ -934,7 +940,10 @@ void QuicStream::OnStreamFrameLost(QuicStreamOffset offset,
bool QuicStream::RetransmitStreamData(QuicStreamOffset offset,
QuicByteCount data_length,
- bool fin) {
+ bool fin,
+ TransmissionType type) {
+ DCHECK(type == PTO_RETRANSMISSION || type == RTO_RETRANSMISSION ||
+ type == TLP_RETRANSMISSION || type == PROBING_RETRANSMISSION);
if (HasDeadlinePassed()) {
OnDeadlinePassed();
return true;
@@ -953,9 +962,9 @@ bool QuicStream::RetransmitStreamData(QuicStreamOffset offset,
const bool can_bundle_fin =
retransmit_fin && (retransmission_offset + retransmission_length ==
stream_bytes_written());
- consumed = session()->WritevData(this, id_, retransmission_length,
- retransmission_offset,
- can_bundle_fin ? FIN : NO_FIN);
+ consumed = stream_delegate_->WritevData(
+ id_, retransmission_length, retransmission_offset,
+ can_bundle_fin ? FIN : NO_FIN, type, QuicheNullOpt);
QUIC_DVLOG(1) << ENDPOINT << "stream " << id_
<< " is forced to retransmit stream data ["
<< retransmission_offset << ", "
@@ -976,7 +985,8 @@ bool QuicStream::RetransmitStreamData(QuicStreamOffset offset,
if (retransmit_fin) {
QUIC_DVLOG(1) << ENDPOINT << "stream " << id_
<< " retransmits fin only frame.";
- consumed = session()->WritevData(this, id_, 0, stream_bytes_written(), FIN);
+ consumed = stream_delegate_->WritevData(id_, 0, stream_bytes_written(), FIN,
+ type, QuicheNullOpt);
if (!consumed.fin_consumed) {
return false;
}
@@ -1040,14 +1050,17 @@ void QuicStream::WriteBufferedData() {
QUIC_DVLOG(1) << "stream " << id() << " shortens write length to "
<< write_length << " due to flow control";
}
- session_->SetTransmissionType(NOT_RETRANSMISSION);
+ if (!session_->write_with_transmission()) {
+ session_->SetTransmissionType(NOT_RETRANSMISSION);
+ }
StreamSendingState state = fin ? FIN : NO_FIN;
if (fin && add_random_padding_after_fin_) {
state = FIN_AND_PADDING;
}
- QuicConsumedData consumed_data = session_->WritevData(
- this, id(), write_length, stream_bytes_written(), state);
+ QuicConsumedData consumed_data =
+ stream_delegate_->WritevData(id(), write_length, stream_bytes_written(),
+ state, NOT_RETRANSMISSION, QuicheNullOpt);
OnStreamDataConsumed(consumed_data.bytes_consumed);
@@ -1122,7 +1135,8 @@ void QuicStream::WritePendingRetransmission() {
QUIC_DVLOG(1) << ENDPOINT << "stream " << id_
<< " retransmits fin only frame.";
consumed =
- session()->WritevData(this, id_, 0, stream_bytes_written(), FIN);
+ stream_delegate_->WritevData(id_, 0, stream_bytes_written(), FIN,
+ LOSS_RETRANSMISSION, QuicheNullOpt);
fin_lost_ = !consumed.fin_consumed;
if (fin_lost_) {
// Connection is write blocked.
@@ -1135,9 +1149,9 @@ void QuicStream::WritePendingRetransmission() {
const bool can_bundle_fin =
fin_lost_ &&
(pending.offset + pending.length == stream_bytes_written());
- consumed =
- session()->WritevData(this, id_, pending.length, pending.offset,
- can_bundle_fin ? FIN : NO_FIN);
+ consumed = stream_delegate_->WritevData(
+ id_, pending.length, pending.offset, can_bundle_fin ? FIN : NO_FIN,
+ LOSS_RETRANSMISSION, QuicheNullOpt);
QUIC_DVLOG(1) << ENDPOINT << "stream " << id_
<< " tries to retransmit stream data [" << pending.offset
<< ", " << pending.offset + pending.length
@@ -1196,4 +1210,19 @@ void QuicStream::SendStopSending(uint16_t code) {
session_->SendStopSending(code, id_);
}
+// static
+spdy::SpdyStreamPrecedence QuicStream::CalculateDefaultPriority(
+ const QuicSession* session) {
+ if (VersionUsesHttp3(session->transport_version())) {
+ return spdy::SpdyStreamPrecedence(QuicStream::kDefaultUrgency);
+ }
+
+ if (session->use_http2_priority_write_scheduler()) {
+ return spdy::SpdyStreamPrecedence(0, spdy::kHttp2DefaultStreamWeight,
+ false);
+ }
+
+ return spdy::SpdyStreamPrecedence(QuicStream::kDefaultPriority);
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream.h b/chromium/net/third_party/quiche/src/quic/core/quic_stream.h
index c936bc71264..aa2e11d5a60 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream.h
@@ -28,11 +28,12 @@
#include "net/third_party/quiche/src/quic/core/quic_stream_sequencer.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/session_notifier_interface.h"
+#include "net/third_party/quiche/src/quic/core/stream_delegate_interface.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice_span.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_optional.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_reference_counted.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_optional.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
namespace quic {
@@ -58,10 +59,9 @@ class QUIC_EXPORT_PRIVATE PendingStream
void OnFinRead() override;
void AddBytesConsumed(QuicByteCount bytes) override;
void Reset(QuicRstStreamErrorCode error) override;
- void CloseConnectionWithDetails(QuicErrorCode error,
- const std::string& details) override;
+ void OnUnrecoverableError(QuicErrorCode error,
+ const std::string& details) override;
QuicStreamId id() const override;
- const QuicSocketAddress& PeerAddressOfLatestPacket() const override;
// Buffers the contents of |frame|. Frame must have a non-zero offset.
// If the data violates flow control, the connection will be closed.
@@ -91,7 +91,9 @@ class QUIC_EXPORT_PRIVATE PendingStream
QuicStreamId id_;
// Session which owns this.
+ // TODO(b/136274541): Remove session pointer from streams.
QuicSession* session_;
+ StreamDelegateInterface* stream_delegate_;
// Bytes read refers to payload bytes only: they do not include framing,
// encryption overhead etc.
@@ -114,11 +116,15 @@ class QUIC_EXPORT_PRIVATE QuicStream
// This is somewhat arbitrary. It's possible, but unlikely, we will either
// fail to set a priority client-side, or cancel a stream before stripping the
// priority from the wire server-side. In either case, start out with a
- // priority in the middle.
+ // priority in the middle in case of Google QUIC.
static const spdy::SpdyPriority kDefaultPriority = 3;
static_assert(kDefaultPriority ==
(spdy::kV3LowestPriority + spdy::kV3HighestPriority) / 2,
"Unexpected value of kDefaultPriority");
+ // On the other hand, when using IETF QUIC, use the default value defined by
+ // the priority extension at
+ // https://httpwg.org/http-extensions/draft-ietf-httpbis-priority.html#default.
+ static const int kDefaultUrgency = 1;
// Creates a new stream with stream_id |id| associated with |session|. If
// |is_static| is true, then the stream will be given precedence
@@ -148,11 +154,8 @@ class QUIC_EXPORT_PRIVATE QuicStream
// Called by the subclass or the sequencer to close the entire connection from
// this end.
- void CloseConnectionWithDetails(QuicErrorCode error,
- const std::string& details) override;
-
- // Get peer IP of the lastest packet which connection is dealing/delt with.
- const QuicSocketAddress& PeerAddressOfLatestPacket() const override;
+ void OnUnrecoverableError(QuicErrorCode error,
+ const std::string& details) override;
// Called by the session when a (potentially duplicate) stream frame has been
// received for this stream.
@@ -179,8 +182,14 @@ class QUIC_EXPORT_PRIVATE QuicStream
const spdy::SpdyStreamPrecedence& precedence() const;
- // Sets priority_ to priority. This should only be called before bytes are
- // written to the server.
+ // Send PRIORITY_UPDATE frame if application protocol supports it.
+ virtual void MaybeSendPriorityUpdateFrame() {}
+
+ // Sets |priority_| to priority. This should only be called before bytes are
+ // written to the server. For a server stream, this is called when a
+ // PRIORITY_UPDATE frame is received. This calls
+ // MaybeSendPriorityUpdateFrame(), which for a client stream might send a
+ // PRIORITY_UPDATE frame.
void SetPriority(const spdy::SpdyStreamPrecedence& precedence);
// Returns true if this stream is still waiting for acks of sent data.
@@ -269,7 +278,7 @@ class QUIC_EXPORT_PRIVATE QuicStream
// If fin is true: if it is immediately passed on to the session,
// write_side_closed() becomes true, otherwise fin_buffered_ becomes true.
void WriteOrBufferData(
- QuicStringPiece data,
+ quiche::QuicheStringPiece data,
bool fin,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
@@ -288,6 +297,7 @@ class QUIC_EXPORT_PRIVATE QuicStream
QuicByteCount data_length,
bool fin_acked,
QuicTime::Delta ack_delay_time,
+ QuicTime receive_timestamp,
QuicByteCount* newly_acked_length);
// Called when data [offset, offset + data_length) was retransmitted.
@@ -303,10 +313,12 @@ class QUIC_EXPORT_PRIVATE QuicStream
bool fin_lost);
// Called to retransmit outstanding portion in data [offset, offset +
- // data_length) and |fin|. Returns true if all data gets retransmitted.
+ // data_length) and |fin| with Transmission |type|.
+ // Returns true if all data gets retransmitted.
virtual bool RetransmitStreamData(QuicStreamOffset offset,
QuicByteCount data_length,
- bool fin);
+ bool fin,
+ TransmissionType type);
// Sets deadline of this stream to be now + |ttl|, returns true if the setting
// succeeds.
@@ -336,8 +348,9 @@ class QUIC_EXPORT_PRIVATE QuicStream
// this method or not.
void SendStopSending(uint16_t code);
- // Handle received StopSending frame.
- virtual void OnStopSending(uint16_t /*code*/) {}
+ // Handle received StopSending frame. Returns true if the processing finishes
+ // gracefully.
+ virtual bool OnStopSending(uint16_t code);
// Close the write side of the socket. Further writes will fail.
// Can be called by the subclass or internally.
@@ -347,6 +360,9 @@ class QUIC_EXPORT_PRIVATE QuicStream
// Returns true if the stream is static.
bool is_static() const { return is_static_; }
+ static spdy::SpdyStreamPrecedence CalculateDefaultPriority(
+ const QuicSession* session);
+
protected:
// Close the read side of the socket. May cause the stream to be closed.
// Subclasses and consumers should use StopReading to terminate reading early
@@ -387,6 +403,8 @@ class QUIC_EXPORT_PRIVATE QuicStream
// this virtual so that subclasses can implement their own logics.
virtual void OnDeadlinePassed();
+ StreamDelegateInterface* stream_delegate() { return stream_delegate_; }
+
bool fin_buffered() const { return fin_buffered_; }
const QuicSession* session() const { return session_; }
@@ -416,7 +434,7 @@ class QUIC_EXPORT_PRIVATE QuicStream
StreamType type,
uint64_t stream_bytes_read,
bool fin_received,
- QuicOptional<QuicFlowController> flow_controller,
+ quiche::QuicheOptional<QuicFlowController> flow_controller,
QuicFlowController* connection_flow_controller);
// Calls MaybeSendBlocked on the stream's flow controller and the connection
@@ -438,7 +456,9 @@ class QUIC_EXPORT_PRIVATE QuicStream
QuicStreamSequencer sequencer_;
QuicStreamId id_;
// Pointer to the owning QuicSession object.
+ // TODO(b/136274541): Remove session pointer from streams.
QuicSession* session_;
+ StreamDelegateInterface* stream_delegate_;
// The precedence of the stream, once parsed.
spdy::SpdyStreamPrecedence precedence_;
// Bytes read refers to payload bytes only: they do not include framing,
@@ -480,7 +500,7 @@ class QUIC_EXPORT_PRIVATE QuicStream
// True if this stream has received a RST_STREAM frame.
bool rst_received_;
- QuicOptional<QuicFlowController> flow_controller_;
+ quiche::QuicheOptional<QuicFlowController> flow_controller_;
// The connection level flow controller. Not owned.
QuicFlowController* connection_flow_controller_;
@@ -515,6 +535,8 @@ class QUIC_EXPORT_PRIVATE QuicStream
// Indicates whether this stream is bidirectional, read unidirectional or
// write unidirectional.
const StreamType type_;
+
+ Perspective perspective_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.cc b/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.cc
index b39d85ec880..c6869a23b12 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "net/third_party/quiche/src/quic/core/quic_stream_id_manager.h"
+#include <cstdint>
#include <string>
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
@@ -12,7 +13,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
namespace quic {
@@ -24,19 +25,15 @@ QuicStreamIdManager::QuicStreamIdManager(
bool unidirectional,
Perspective perspective,
QuicTransportVersion transport_version,
- QuicStreamCount num_expected_static_streams,
QuicStreamCount max_allowed_outgoing_streams,
QuicStreamCount max_allowed_incoming_streams)
: delegate_(delegate),
unidirectional_(unidirectional),
perspective_(perspective),
transport_version_(transport_version),
- num_expected_static_streams_(num_expected_static_streams),
- is_config_negotiated_(false),
outgoing_max_streams_(max_allowed_outgoing_streams),
next_outgoing_stream_id_(GetFirstOutgoingStreamId()),
outgoing_stream_count_(0),
- using_default_max_streams_(true),
incoming_actual_max_streams_(max_allowed_incoming_streams),
// Advertised max starts at actual because it's communicated in the
// handshake.
@@ -45,42 +42,25 @@ QuicStreamIdManager::QuicStreamIdManager(
incoming_stream_count_(0),
largest_peer_created_stream_id_(
QuicUtils::GetInvalidStreamId(transport_version)),
- max_streams_window_(0),
- pending_max_streams_(false),
- pending_streams_blocked_(
- QuicUtils::GetInvalidStreamId(transport_version)) {
+ max_streams_window_(0) {
CalculateIncomingMaxStreamsWindow();
}
QuicStreamIdManager::~QuicStreamIdManager() {}
-bool QuicStreamIdManager::OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) {
- // Ensure that the frame has the correct directionality.
- DCHECK_EQ(frame.unidirectional, unidirectional_);
- QUIC_CODE_COUNT_N(quic_max_streams_received, 2, 2);
-
- // Set the limit to be exactly the stream count in the frame.
- // Also informs the higher layers that they can create more
- // streams if the limit is increased.
- return SetMaxOpenOutgoingStreams(frame.stream_count);
-}
-
// The peer sends a streams blocked frame when it can not open any more
// streams because it has runs into the limit.
bool QuicStreamIdManager::OnStreamsBlockedFrame(
- const QuicStreamsBlockedFrame& frame) {
+ const QuicStreamsBlockedFrame& frame,
+ std::string* error_details) {
// Ensure that the frame has the correct directionality.
DCHECK_EQ(frame.unidirectional, unidirectional_);
- QUIC_CODE_COUNT_N(quic_streams_blocked_received, 2, 2);
-
if (frame.stream_count > incoming_advertised_max_streams_) {
// Peer thinks it can send more streams that we've told it.
// This is a protocol error.
- // TODO(fkastenholz): revise when proper IETF Connection Close support is
- // done.
- QUIC_CODE_COUNT(quic_streams_blocked_too_big);
- delegate_->OnError(QUIC_STREAMS_BLOCKED_ERROR,
- "Invalid stream count specified");
+ *error_details = quiche::QuicheStrCat(
+ "StreamsBlockedFrame's stream count ", frame.stream_count,
+ " exceeds incoming max stream ", incoming_advertised_max_streams_);
return false;
}
if (frame.stream_count < incoming_actual_max_streams_) {
@@ -89,72 +69,36 @@ bool QuicStreamIdManager::OnStreamsBlockedFrame(
// frame in this case is not controlled by the window.
SendMaxStreamsFrame();
}
- QUIC_CODE_COUNT(quic_streams_blocked_id_correct);
return true;
}
-// Used when configuration has been done and we have an initial
-// maximum stream count from the peer.
-bool QuicStreamIdManager::SetMaxOpenOutgoingStreams(size_t max_open_streams) {
- if (max_open_streams < num_expected_static_streams_) {
- QUIC_DLOG(ERROR) << "Received max streams " << max_open_streams << " < "
- << num_expected_static_streams_;
- delegate_->OnError(QUIC_MAX_STREAMS_ERROR,
- unidirectional_
- ? "New unidirectional stream limit is too low."
- : "New bidirectional stream limit is too low.");
-
- return false;
- }
- if (using_default_max_streams_) {
- // This is the first MAX_STREAMS/transport negotiation we've received. Treat
- // this a bit differently than later ones. The difference is that
- // outgoing_max_streams_ is currently an estimate. The MAX_STREAMS frame or
- // transport negotiation is authoritative and can reduce
- // outgoing_max_streams_ -- so long as outgoing_max_streams_ is not set to
- // be less than the number of existing outgoing streams. If that happens,
- // close the connection.
- if (max_open_streams < outgoing_stream_count_) {
- delegate_->OnError(QUIC_MAX_STREAMS_ERROR,
- "Stream limit less than existing stream count");
- return false;
- }
- using_default_max_streams_ = false;
- } else if (max_open_streams <= outgoing_max_streams_) {
- // Is not the 1st MAX_STREAMS or negotiation.
+bool QuicStreamIdManager::MaybeAllowNewOutgoingStreams(
+ QuicStreamCount max_open_streams) {
+ if (max_open_streams <= outgoing_max_streams_) {
// Only update the stream count if it would increase the limit.
- // If it decreases the limit, or doesn't change it, then do not update.
- // Note that this handles the case of receiving a count of 0 in the frame
- return true;
+ return false;
}
// This implementation only supports 32 bit Stream IDs, so limit max streams
// if it would exceed the max 32 bits can express.
- outgoing_max_streams_ = std::min<size_t>(
- max_open_streams,
- QuicUtils::GetMaxStreamCount(unidirectional_, perspective_));
-
- // Inform the higher layers that the stream limit has increased and that
- // new streams may be created.
- delegate_->OnCanCreateNewOutgoingStream(unidirectional_);
+ outgoing_max_streams_ =
+ std::min(max_open_streams, QuicUtils::GetMaxStreamCount());
return true;
}
-void QuicStreamIdManager::SetMaxOpenIncomingStreams(size_t max_open_streams) {
- QuicStreamCount implementation_max =
- QuicUtils::GetMaxStreamCount(unidirectional_, perspective());
- QuicStreamCount new_max = std::min(
- implementation_max, static_cast<QuicStreamCount>(max_open_streams));
- if (new_max < incoming_stream_count_) {
- delegate_->OnError(QUIC_MAX_STREAMS_ERROR,
- "Stream limit less than existing stream count");
- return;
- }
- incoming_actual_max_streams_ = new_max;
- incoming_advertised_max_streams_ = new_max;
- incoming_initial_max_open_streams_ =
- std::min(max_open_streams, static_cast<size_t>(implementation_max));
+void QuicStreamIdManager::SetMaxOpenIncomingStreams(
+ QuicStreamCount max_open_streams) {
+ QUIC_BUG_IF(incoming_stream_count_ > 0)
+ << "non-zero stream count when setting max incoming stream.";
+ QUIC_LOG_IF(WARNING, incoming_initial_max_open_streams_ != max_open_streams)
+ << quiche::QuicheStrCat(
+ unidirectional_ ? "unidirectional " : "bidirectional: ",
+ "incoming stream limit changed from ",
+ incoming_initial_max_open_streams_, " to ", max_open_streams);
+ incoming_actual_max_streams_ = max_open_streams;
+ incoming_advertised_max_streams_ = max_open_streams;
+ incoming_initial_max_open_streams_ = max_open_streams;
CalculateIncomingMaxStreamsWindow();
}
@@ -168,14 +112,6 @@ void QuicStreamIdManager::MaybeSendMaxStreamsFrame() {
}
void QuicStreamIdManager::SendMaxStreamsFrame() {
- if (!is_config_negotiated_) {
- // The config has not yet been negotiated, so we can not send the
- // MAX STREAMS frame yet. Record that we would have sent one and then
- // return. A new frame will be generated once the configuration is
- // received.
- pending_max_streams_ = true;
- return;
- }
incoming_advertised_max_streams_ = incoming_actual_max_streams_;
delegate_->SendMaxStreams(incoming_advertised_max_streams_, unidirectional_);
}
@@ -189,8 +125,7 @@ void QuicStreamIdManager::OnStreamClosed(QuicStreamId stream_id) {
// If the stream is inbound, we can increase the actual stream limit and maybe
// advertise the new limit to the peer. Have to check to make sure that we do
// not exceed the maximum.
- if (incoming_actual_max_streams_ ==
- QuicUtils::GetMaxStreamCount(unidirectional_, perspective())) {
+ if (incoming_actual_max_streams_ == QuicUtils::GetMaxStreamCount()) {
// Reached the maximum stream id value that the implementation
// supports. Nothing can be done here.
return;
@@ -201,94 +136,64 @@ void QuicStreamIdManager::OnStreamClosed(QuicStreamId stream_id) {
}
QuicStreamId QuicStreamIdManager::GetNextOutgoingStreamId() {
- // TODO(fkastenholz): Should we close the connection?
+ // Applications should always consult CanOpenNextOutgoingStream() first.
+ // If they ask for stream ids that violate the limit, it's an implementation
+ // bug.
QUIC_BUG_IF(outgoing_stream_count_ >= outgoing_max_streams_)
<< "Attempt to allocate a new outgoing stream that would exceed the "
"limit ("
<< outgoing_max_streams_ << ")";
QuicStreamId id = next_outgoing_stream_id_;
- next_outgoing_stream_id_ += QuicUtils::StreamIdDelta(transport_version());
+ next_outgoing_stream_id_ += QuicUtils::StreamIdDelta(transport_version_);
outgoing_stream_count_++;
return id;
}
-bool QuicStreamIdManager::CanOpenNextOutgoingStream() {
- DCHECK(VersionHasIetfQuicFrames(transport_version()));
- if (outgoing_stream_count_ < outgoing_max_streams_) {
- return true;
- }
- // Next stream ID would exceed the limit, need to inform the peer.
-
- if (!is_config_negotiated_) {
- // The config is not negotiated, so we can not send the STREAMS_BLOCKED
- // frame yet. Record that we would have sent one, and what the limit was
- // when we were blocked, and return.
- pending_streams_blocked_ = outgoing_max_streams_;
- return false;
- }
- delegate_->SendStreamsBlocked(outgoing_max_streams_, unidirectional_);
- QUIC_CODE_COUNT(quic_reached_outgoing_stream_id_limit);
- return false;
+bool QuicStreamIdManager::CanOpenNextOutgoingStream() const {
+ DCHECK(VersionHasIetfQuicFrames(transport_version_));
+ return outgoing_stream_count_ < outgoing_max_streams_;
}
-// Stream_id is the id of a new incoming stream. Check if it can be
-// created (doesn't violate limits, etc).
bool QuicStreamIdManager::MaybeIncreaseLargestPeerStreamId(
- const QuicStreamId stream_id) {
+ const QuicStreamId stream_id,
+ std::string* error_details) {
// |stream_id| must be an incoming stream of the right directionality.
DCHECK_NE(QuicUtils::IsBidirectionalStreamId(stream_id), unidirectional_);
- DCHECK_NE(
- QuicUtils::IsServerInitiatedStreamId(transport_version(), stream_id),
- perspective() == Perspective::IS_SERVER);
- available_streams_.erase(stream_id);
-
- if (largest_peer_created_stream_id_ !=
- QuicUtils::GetInvalidStreamId(transport_version()) &&
- stream_id <= largest_peer_created_stream_id_) {
+ DCHECK_NE(QuicUtils::IsServerInitiatedStreamId(transport_version_, stream_id),
+ perspective() == Perspective::IS_SERVER);
+ if (available_streams_.erase(stream_id) == 1) {
+ // stream_id is available.
return true;
}
- QuicStreamCount stream_count_increment;
if (largest_peer_created_stream_id_ !=
- QuicUtils::GetInvalidStreamId(transport_version())) {
- stream_count_increment = (stream_id - largest_peer_created_stream_id_) /
- QuicUtils::StreamIdDelta(transport_version());
- } else {
- // Largest_peer_created_stream_id is the invalid ID,
- // which means that the peer has not created any stream IDs.
- // The "+1" is because the first stream ID has not yet
- // been used. For example, if the FirstIncoming ID is 1
- // and stream_id is 1, then we want the increment to be 1.
- stream_count_increment = ((stream_id - GetFirstIncomingStreamId()) /
- QuicUtils::StreamIdDelta(transport_version())) +
- 1;
+ QuicUtils::GetInvalidStreamId(transport_version_)) {
+ DCHECK_GT(stream_id, largest_peer_created_stream_id_);
}
- // If already at, or over, the limit, close the connection/etc.
- if (((incoming_stream_count_ + stream_count_increment) >
- incoming_advertised_max_streams_) ||
- ((incoming_stream_count_ + stream_count_increment) <
- incoming_stream_count_)) {
- // This stream would exceed the limit. do not increase.
+ // Calculate increment of incoming_stream_count_ by creating stream_id.
+ const QuicStreamCount delta = QuicUtils::StreamIdDelta(transport_version_);
+ const QuicStreamId least_new_stream_id =
+ largest_peer_created_stream_id_ ==
+ QuicUtils::GetInvalidStreamId(transport_version_)
+ ? GetFirstIncomingStreamId()
+ : largest_peer_created_stream_id_ + delta;
+ const QuicStreamCount stream_count_increment =
+ (stream_id - least_new_stream_id) / delta + 1;
+
+ if (incoming_stream_count_ + stream_count_increment >
+ incoming_advertised_max_streams_) {
QUIC_DLOG(INFO) << ENDPOINT
<< "Failed to create a new incoming stream with id:"
<< stream_id << ", reaching MAX_STREAMS limit: "
<< incoming_advertised_max_streams_ << ".";
- delegate_->OnError(
- QUIC_INVALID_STREAM_ID,
- QuicStrCat("Stream id ", stream_id, " would exceed stream count limit ",
- incoming_advertised_max_streams_));
+ *error_details = quiche::QuicheStrCat("Stream id ", stream_id,
+ " would exceed stream count limit ",
+ incoming_advertised_max_streams_);
return false;
}
- QuicStreamId id = GetFirstIncomingStreamId();
- if (largest_peer_created_stream_id_ !=
- QuicUtils::GetInvalidStreamId(transport_version())) {
- id = largest_peer_created_stream_id_ +
- QuicUtils::StreamIdDelta(transport_version());
- }
-
- for (; id < stream_id; id += QuicUtils::StreamIdDelta(transport_version())) {
+ for (QuicStreamId id = least_new_stream_id; id < stream_id; id += delta) {
available_streams_.insert(id);
}
incoming_stream_count_ += stream_count_increment;
@@ -305,7 +210,7 @@ bool QuicStreamIdManager::IsAvailableStream(QuicStreamId id) const {
}
// For peer created streams, we also need to consider available streams.
return largest_peer_created_stream_id_ ==
- QuicUtils::GetInvalidStreamId(transport_version()) ||
+ QuicUtils::GetInvalidStreamId(transport_version_) ||
id > largest_peer_created_stream_id_ ||
QuicContainsKey(available_streams_, id);
}
@@ -322,16 +227,16 @@ bool QuicStreamIdManager::IsIncomingStream(QuicStreamId id) const {
QuicStreamId QuicStreamIdManager::GetFirstOutgoingStreamId() const {
return (unidirectional_) ? QuicUtils::GetFirstUnidirectionalStreamId(
- transport_version(), perspective())
+ transport_version_, perspective())
: QuicUtils::GetFirstBidirectionalStreamId(
- transport_version(), perspective());
+ transport_version_, perspective());
}
QuicStreamId QuicStreamIdManager::GetFirstIncomingStreamId() const {
return (unidirectional_) ? QuicUtils::GetFirstUnidirectionalStreamId(
- transport_version(), peer_perspective())
+ transport_version_, peer_perspective())
: QuicUtils::GetFirstBidirectionalStreamId(
- transport_version(), peer_perspective());
+ transport_version_, peer_perspective());
}
Perspective QuicStreamIdManager::perspective() const {
@@ -342,11 +247,7 @@ Perspective QuicStreamIdManager::peer_perspective() const {
return QuicUtils::InvertPerspective(perspective());
}
-QuicTransportVersion QuicStreamIdManager::transport_version() const {
- return transport_version_;
-}
-
-size_t QuicStreamIdManager::available_incoming_streams() {
+QuicStreamCount QuicStreamIdManager::available_incoming_streams() {
return incoming_advertised_max_streams_ - incoming_stream_count_;
}
@@ -357,25 +258,4 @@ void QuicStreamIdManager::CalculateIncomingMaxStreamsWindow() {
}
}
-void QuicStreamIdManager::OnConfigNegotiated() {
- is_config_negotiated_ = true;
- // If a STREAMS_BLOCKED or MAX_STREAMS is pending, send it and clear
- // the pending state.
- if (pending_streams_blocked_ !=
- QuicUtils::GetInvalidStreamId(transport_version())) {
- if (pending_streams_blocked_ >= outgoing_max_streams_) {
- // There is a pending STREAMS_BLOCKED frame and the current limit does not
- // let new streams be formed. Regenerate and send the frame.
- delegate_->SendStreamsBlocked(outgoing_max_streams_, unidirectional_);
- }
- pending_streams_blocked_ =
- QuicUtils::GetInvalidStreamId(transport_version());
- }
- if (pending_max_streams_) {
- // Generate a MAX_STREAMS using the current stream limits.
- SendMaxStreamsFrame();
- pending_max_streams_ = false;
- }
-}
-
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.h b/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.h
index e39e14fcf85..fa4b1a06b47 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.h
@@ -8,7 +8,7 @@
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
namespace quic {
@@ -33,32 +33,15 @@ class QUIC_EXPORT_PRIVATE QuicStreamIdManager {
public:
virtual ~DelegateInterface() = default;
- // Called when new outgoing streams are available to be opened. This occurs
- // when an extant, open, stream is moved to draining or closed.
- // |unidirectional| indicates whether unidirectional or bidirectional
- // streams are now available. If both become available at the same time then
- // there will be two calls to this method, one with unidirectional==true,
- // the other with it ==false.
- virtual void OnCanCreateNewOutgoingStream(bool unidirectional) = 0;
-
- // Closes the connection when an error is encountered.
- virtual void OnError(QuicErrorCode error_code,
- std::string error_details) = 0;
-
// Send a MAX_STREAMS frame.
virtual void SendMaxStreams(QuicStreamCount stream_count,
bool unidirectional) = 0;
-
- // Send a STREAMS_BLOCKED frame.
- virtual void SendStreamsBlocked(QuicStreamCount stream_count,
- bool unidirectional) = 0;
};
QuicStreamIdManager(DelegateInterface* delegate,
bool unidirectional,
Perspective perspective,
QuicTransportVersion transport_version,
- QuicStreamCount num_expected_static_streams,
QuicStreamCount max_allowed_outgoing_streams,
QuicStreamCount max_allowed_incoming_streams);
@@ -67,13 +50,12 @@ class QUIC_EXPORT_PRIVATE QuicStreamIdManager {
// Generate a string suitable for sending to the log/etc to show current state
// of the stream ID manager.
std::string DebugString() const {
- return QuicStrCat(
+ return quiche::QuicheStrCat(
" { unidirectional_: ", unidirectional_,
", perspective: ", perspective(),
", outgoing_max_streams_: ", outgoing_max_streams_,
", next_outgoing_stream_id_: ", next_outgoing_stream_id_,
", outgoing_stream_count_: ", outgoing_stream_count_,
- ", using_default_max_streams_: ", using_default_max_streams_,
", incoming_actual_max_streams_: ", incoming_actual_max_streams_,
", incoming_advertised_max_streams_: ",
incoming_advertised_max_streams_,
@@ -83,20 +65,13 @@ class QUIC_EXPORT_PRIVATE QuicStreamIdManager {
", max_streams_window_: ", max_streams_window_, " }");
}
- // Processes the MAX_STREAMS frame, invoked from
- // QuicSession::OnMaxStreamsFrame. It has the same semantics as the
- // QuicFramerVisitorInterface, returning true if the framer should continue
- // processing the packet, false if not.
- bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame);
-
- // Processes the STREAMS_BLOCKED frame, invoked from
- // QuicSession::OnStreamsBlockedFrame. It has the same semantics as the
- // QuicFramerVisitorInterface, returning true if the framer should continue
- // processing the packet, false if not.
- bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame);
+ // Processes the STREAMS_BLOCKED frame. If error is encountered, populates
+ // |error_details| and returns false.
+ bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame,
+ std::string* error_details);
// Indicates whether the next outgoing stream ID can be allocated or not.
- bool CanOpenNextOutgoingStream();
+ bool CanOpenNextOutgoingStream() const;
// Generate and send a MAX_STREAMS frame.
void SendMaxStreamsFrame();
@@ -112,22 +87,21 @@ class QUIC_EXPORT_PRIVATE QuicStreamIdManager {
// allocates a stream ID past the peer specified limit.
QuicStreamId GetNextOutgoingStreamId();
- void SetMaxOpenIncomingStreams(size_t max_open_streams);
+ void SetMaxOpenIncomingStreams(QuicStreamCount max_open_streams);
- // Sets the maximum number of outgoing streams to max_open_streams.
- // Used when configuration has been done and we have an initial
- // maximum stream count from the peer. Note that if the stream count is such
- // that it would result in stream ID values that are greater than the
- // implementation limit, it pegs the count at the implementation limit.
- bool SetMaxOpenOutgoingStreams(size_t max_open_streams);
+ // Called on |max_open_streams| outgoing streams can be created because of 1)
+ // config negotiated or 2) MAX_STREAMS received. Returns true if new
+ // streams can be created.
+ bool MaybeAllowNewOutgoingStreams(QuicStreamCount max_open_streams);
// Checks if the incoming stream ID exceeds the MAX_STREAMS limit. If the
- // limit is exceeded, closes the connection and returns false. Uses the
+ // limit is exceeded, populates |error_detials| and returns false. Uses the
// actual maximium, not the most recently advertised value, in order to
// enforce the Google-QUIC number of open streams behavior.
// This method should be called exactly once for each incoming stream
// creation.
- bool MaybeIncreaseLargestPeerStreamId(const QuicStreamId stream_id);
+ bool MaybeIncreaseLargestPeerStreamId(const QuicStreamId stream_id,
+ std::string* error_details);
// Returns true if |id| is still available.
bool IsAvailableStream(QuicStreamId id) const;
@@ -135,7 +109,7 @@ class QUIC_EXPORT_PRIVATE QuicStreamIdManager {
// Return true if given stream is peer initiated.
bool IsIncomingStream(QuicStreamId id) const;
- size_t incoming_initial_max_open_streams() const {
+ QuicStreamCount incoming_initial_max_open_streams() const {
return incoming_initial_max_open_streams_;
}
@@ -146,12 +120,7 @@ class QUIC_EXPORT_PRIVATE QuicStreamIdManager {
}
// Number of streams that the peer believes that it can still create.
- size_t available_incoming_streams();
-
- void set_largest_peer_created_stream_id(
- QuicStreamId largest_peer_created_stream_id) {
- largest_peer_created_stream_id_ = largest_peer_created_stream_id;
- }
+ QuicStreamCount available_incoming_streams();
QuicStreamId largest_peer_created_stream_id() const {
return largest_peer_created_stream_id_;
@@ -177,12 +146,6 @@ class QUIC_EXPORT_PRIVATE QuicStreamIdManager {
Perspective perspective() const;
Perspective peer_perspective() const;
- QuicTransportVersion transport_version() const;
-
- // Called when session has been configured. Causes the Stream ID manager to
- // send out any pending MAX_STREAMS and STREAMS_BLOCKED frames.
- void OnConfigNegotiated();
-
private:
friend class test::QuicSessionPeer;
friend class test::QuicStreamIdManagerPeer;
@@ -213,12 +176,6 @@ class QUIC_EXPORT_PRIVATE QuicStreamIdManager {
// Transport version used for this manager.
const QuicTransportVersion transport_version_;
- // Number of expected static streams.
- const QuicStreamCount num_expected_static_streams_;
-
- // True if the config has been negotiated_;
- bool is_config_negotiated_;
-
// This is the number of streams that this node can initiate.
// This limit is:
// - Initiated to a value specified in the constructor
@@ -234,17 +191,6 @@ class QUIC_EXPORT_PRIVATE QuicStreamIdManager {
// outgoing_max_streams_.
QuicStreamCount outgoing_stream_count_;
- // Set to true while the default (from the constructor) outgoing stream limit
- // is in use. It is set to false when either a MAX STREAMS frame is received
- // or the transport negotiation completes and sets the stream limit (this is
- // equivalent to a MAX_STREAMS frame).
- // Necessary because outgoing_max_streams_ is a "best guess"
- // until we receive an authoritative value from the peer.
- // outgoing_max_streams_ is initialized in the constructor
- // to some hard-coded value, which may or may not be consistent
- // with what the peer wants.
- bool using_default_max_streams_;
-
// FOR INCOMING STREAMS
// The maximum number of streams that can be opened by the peer.
@@ -272,13 +218,6 @@ class QUIC_EXPORT_PRIVATE QuicStreamIdManager {
// max_streams_window_ is set to 1/2 of the initial number of incoming streams
// that are allowed (as set in the constructor).
QuicStreamId max_streams_window_;
-
- // MAX_STREAMS and STREAMS_BLOCKED frames are not sent before the session has
- // been configured. Instead, the relevant information is stored in
- // |pending_max_streams_| and |pending_streams_blocked_| and sent when
- // OnConfigNegotiated() is invoked.
- bool pending_max_streams_;
- QuicStreamId pending_streams_blocked_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager_test.cc
index 2ff55be857c..3207e59558b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager_test.cc
@@ -7,10 +7,13 @@
#include <string>
#include <utility>
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_stream_id_manager_peer.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
using testing::_;
using testing::StrictMock;
@@ -21,36 +24,42 @@ namespace {
class MockDelegate : public QuicStreamIdManager::DelegateInterface {
public:
- MOCK_METHOD1(OnCanCreateNewOutgoingStream, void(bool unidirectional));
- MOCK_METHOD2(OnError,
- void(QuicErrorCode error_code, std::string error_details));
MOCK_METHOD2(SendMaxStreams,
void(QuicStreamCount stream_count, bool unidirectional));
- MOCK_METHOD2(SendStreamsBlocked,
- void(QuicStreamCount stream_count, bool unidirectional));
};
struct TestParams {
- TestParams(Perspective perspective, bool is_unidirectional)
- : perspective(perspective), is_unidirectional(is_unidirectional) {}
-
+ TestParams(ParsedQuicVersion version,
+ Perspective perspective,
+ bool is_unidirectional)
+ : version(version),
+ perspective(perspective),
+ is_unidirectional(is_unidirectional) {}
+
+ ParsedQuicVersion version;
Perspective perspective;
bool is_unidirectional;
};
// Used by ::testing::PrintToStringParamName().
std::string PrintToString(const TestParams& p) {
- return QuicStrCat(
+ return quiche::QuicheStrCat(
+ ParsedQuicVersionToString(p.version), "_",
(p.perspective == Perspective::IS_CLIENT ? "Client" : "Server"),
(p.is_unidirectional ? "Unidirectional" : "Bidirectional"));
}
std::vector<TestParams> GetTestParams() {
std::vector<TestParams> params;
- for (Perspective perspective :
- {Perspective::IS_CLIENT, Perspective::IS_SERVER}) {
- for (bool is_unidirectional : {true, false}) {
- params.push_back(TestParams(perspective, is_unidirectional));
+ for (const ParsedQuicVersion& version : AllSupportedVersions()) {
+ if (!version.HasIetfQuicFrames()) {
+ continue;
+ }
+ for (Perspective perspective :
+ {Perspective::IS_CLIENT, Perspective::IS_SERVER}) {
+ for (bool is_unidirectional : {true, false}) {
+ params.push_back(TestParams(version, perspective, is_unidirectional));
+ }
}
}
return params;
@@ -64,12 +73,13 @@ class QuicStreamIdManagerTest : public QuicTestWithParam<TestParams> {
perspective(),
transport_version(),
0,
- kDefaultMaxStreamsPerConnection,
kDefaultMaxStreamsPerConnection) {
DCHECK(VersionHasIetfQuicFrames(transport_version()));
}
- QuicTransportVersion transport_version() const { return QUIC_VERSION_99; }
+ QuicTransportVersion transport_version() const {
+ return GetParam().version.transport_version;
+ }
// Returns the stream ID for the Nth incoming stream (created by the peer)
// of the corresponding directionality of this manager.
@@ -97,8 +107,7 @@ INSTANTIATE_TEST_SUITE_P(Tests,
::testing::PrintToStringParamName());
TEST_P(QuicStreamIdManagerTest, Initialization) {
- EXPECT_EQ(kDefaultMaxStreamsPerConnection,
- stream_id_manager_.outgoing_max_streams());
+ EXPECT_EQ(0u, stream_id_manager_.outgoing_max_streams());
EXPECT_EQ(kDefaultMaxStreamsPerConnection,
stream_id_manager_.incoming_actual_max_streams());
@@ -123,62 +132,26 @@ TEST_P(QuicStreamIdManagerTest, CheckMaxStreamsWindowForSingleStream) {
}
TEST_P(QuicStreamIdManagerTest, CheckMaxStreamsBadValuesOverMaxFailsOutgoing) {
- QuicStreamCount implementation_max =
- QuicUtils::GetMaxStreamCount(IsUnidirectional(), perspective());
+ QuicStreamCount implementation_max = QuicUtils::GetMaxStreamCount();
// Ensure that the limit is less than the implementation maximum.
EXPECT_LT(stream_id_manager_.outgoing_max_streams(), implementation_max);
- EXPECT_CALL(delegate_, OnCanCreateNewOutgoingStream(IsUnidirectional()));
- stream_id_manager_.SetMaxOpenOutgoingStreams(implementation_max + 1);
+ EXPECT_TRUE(
+ stream_id_manager_.MaybeAllowNewOutgoingStreams(implementation_max + 1));
// Should be pegged at the max.
EXPECT_EQ(implementation_max, stream_id_manager_.outgoing_max_streams());
}
-// Now do the same for the incoming streams
-TEST_P(QuicStreamIdManagerTest, CheckMaxStreamsBadValuesIncoming) {
- QuicStreamCount implementation_max =
- QuicUtils::GetMaxStreamCount(IsUnidirectional(), perspective());
- stream_id_manager_.SetMaxOpenIncomingStreams(implementation_max - 1u);
- EXPECT_EQ(implementation_max - 1u,
- stream_id_manager_.incoming_initial_max_open_streams());
- EXPECT_EQ(implementation_max - 1u,
- stream_id_manager_.incoming_actual_max_streams());
- EXPECT_EQ((implementation_max - 1u) / 2u,
- stream_id_manager_.max_streams_window());
-
- stream_id_manager_.SetMaxOpenIncomingStreams(implementation_max);
- EXPECT_EQ(implementation_max,
- stream_id_manager_.incoming_initial_max_open_streams());
- EXPECT_EQ(implementation_max,
- stream_id_manager_.incoming_actual_max_streams());
- EXPECT_EQ(implementation_max / 2, stream_id_manager_.max_streams_window());
-
- // Reset to 1 so that we can detect the change.
- stream_id_manager_.SetMaxOpenIncomingStreams(1u);
- EXPECT_EQ(1u, stream_id_manager_.incoming_initial_max_open_streams());
- EXPECT_EQ(1u, stream_id_manager_.incoming_actual_max_streams());
- EXPECT_EQ(1u, stream_id_manager_.max_streams_window());
- // Now try to exceed the max, without wrapping.
- stream_id_manager_.SetMaxOpenIncomingStreams(implementation_max + 1);
- EXPECT_EQ(implementation_max,
- stream_id_manager_.incoming_initial_max_open_streams());
- EXPECT_EQ(implementation_max,
- stream_id_manager_.incoming_actual_max_streams());
- EXPECT_EQ(implementation_max / 2u, stream_id_manager_.max_streams_window());
-}
-
// Check the case of the stream count in a STREAMS_BLOCKED frame is less than
// the count most recently advertised in a MAX_STREAMS frame. This should cause
// a MAX_STREAMS frame with the most recently advertised count to be sent.
TEST_P(QuicStreamIdManagerTest, ProcessStreamsBlockedOk) {
- // Set the config negotiated so that the MAX_STREAMS is transmitted.
- stream_id_manager_.OnConfigNegotiated();
-
QuicStreamCount stream_count =
stream_id_manager_.incoming_initial_max_open_streams();
QuicStreamsBlockedFrame frame(0, stream_count - 1, IsUnidirectional());
EXPECT_CALL(delegate_, SendMaxStreams(stream_count, IsUnidirectional()));
- stream_id_manager_.OnStreamsBlockedFrame(frame);
+ std::string error_details;
+ EXPECT_TRUE(stream_id_manager_.OnStreamsBlockedFrame(frame, &error_details));
}
// Check the case of the stream count in a STREAMS_BLOCKED frame is equal to the
@@ -195,13 +168,15 @@ TEST_P(QuicStreamIdManagerTest, ProcessStreamsBlockedNoOp) {
// the count most recently advertised in a MAX_STREAMS frame. Expect a
// connection close with an error.
TEST_P(QuicStreamIdManagerTest, ProcessStreamsBlockedTooBig) {
- EXPECT_CALL(delegate_, OnError(QUIC_STREAMS_BLOCKED_ERROR, _));
EXPECT_CALL(delegate_, SendMaxStreams(_, _)).Times(0);
- EXPECT_CALL(delegate_, SendStreamsBlocked(_, _)).Times(0);
QuicStreamCount stream_count =
stream_id_manager_.incoming_initial_max_open_streams() + 1;
QuicStreamsBlockedFrame frame(0, stream_count, IsUnidirectional());
- stream_id_manager_.OnStreamsBlockedFrame(frame);
+ std::string error_details;
+ EXPECT_FALSE(stream_id_manager_.OnStreamsBlockedFrame(frame, &error_details));
+ EXPECT_EQ(
+ error_details,
+ "StreamsBlockedFrame's stream count 101 exceeds incoming max stream 100");
}
// Same basic tests as above, but calls
@@ -213,68 +188,28 @@ TEST_P(QuicStreamIdManagerTest, ProcessStreamsBlockedTooBig) {
TEST_P(QuicStreamIdManagerTest, IsIncomingStreamIdValidBelowLimit) {
QuicStreamId stream_id = GetNthIncomingStreamId(
stream_id_manager_.incoming_actual_max_streams() - 2);
- EXPECT_CALL(delegate_, OnError(_, _)).Times(0);
- EXPECT_TRUE(stream_id_manager_.MaybeIncreaseLargestPeerStreamId(stream_id));
+ EXPECT_TRUE(
+ stream_id_manager_.MaybeIncreaseLargestPeerStreamId(stream_id, nullptr));
}
// Accept a stream with an ID that equals the limit.
TEST_P(QuicStreamIdManagerTest, IsIncomingStreamIdValidAtLimit) {
QuicStreamId stream_id = GetNthIncomingStreamId(
stream_id_manager_.incoming_actual_max_streams() - 1);
- EXPECT_CALL(delegate_, OnError(_, _)).Times(0);
- EXPECT_TRUE(stream_id_manager_.MaybeIncreaseLargestPeerStreamId(stream_id));
+ EXPECT_TRUE(
+ stream_id_manager_.MaybeIncreaseLargestPeerStreamId(stream_id, nullptr));
}
// Close the connection if the id exceeds the limit.
TEST_P(QuicStreamIdManagerTest, IsIncomingStreamIdInValidAboveLimit) {
QuicStreamId stream_id =
GetNthIncomingStreamId(stream_id_manager_.incoming_actual_max_streams());
- std::string error_details = QuicStrCat(
- "Stream id ", stream_id, " would exceed stream count limit 100");
- EXPECT_CALL(delegate_, OnError(QUIC_INVALID_STREAM_ID, error_details));
- EXPECT_FALSE(stream_id_manager_.MaybeIncreaseLargestPeerStreamId(stream_id));
-}
-
-TEST_P(QuicStreamIdManagerTest, OnMaxStreamsFrame) {
- // Get the current maximum allowed outgoing stream count.
- QuicStreamCount initial_stream_count =
- // need to know the number of request/response streams.
- // This is the total number of outgoing streams (which includes both
- // req/resp and statics).
- stream_id_manager_.outgoing_max_streams();
-
- QuicMaxStreamsFrame frame;
-
- // Even though the stream count in the frame is < the initial maximum,
- // it shouldn't be ignored since the initial max was set via
- // the constructor (an educated guess) but the MAX STREAMS frame
- // is authoritative.
- frame.stream_count = initial_stream_count - 1;
-
- frame.unidirectional = IsUnidirectional();
- EXPECT_CALL(delegate_, OnCanCreateNewOutgoingStream(IsUnidirectional()));
- EXPECT_TRUE(stream_id_manager_.OnMaxStreamsFrame(frame));
- EXPECT_EQ(initial_stream_count - 1u,
- stream_id_manager_.outgoing_max_streams());
-
- QuicStreamCount save_outgoing_max_streams =
- stream_id_manager_.outgoing_max_streams();
- // Now that there has been one MAX STREAMS frame, we should not
- // accept a MAX_STREAMS that reduces the limit...
- frame.stream_count = initial_stream_count - 2;
- frame.unidirectional = IsUnidirectional();
- EXPECT_TRUE(stream_id_manager_.OnMaxStreamsFrame(frame));
- // should not change from previous setting.
- EXPECT_EQ(save_outgoing_max_streams,
- stream_id_manager_.outgoing_max_streams());
-
- // A stream count greater than the current limit should increase the limit.
- frame.stream_count = initial_stream_count + 1;
- EXPECT_CALL(delegate_, OnCanCreateNewOutgoingStream(IsUnidirectional()));
- EXPECT_TRUE(stream_id_manager_.OnMaxStreamsFrame(frame));
-
- EXPECT_EQ(initial_stream_count + 1u,
- stream_id_manager_.outgoing_max_streams());
+ std::string error_details;
+ EXPECT_FALSE(stream_id_manager_.MaybeIncreaseLargestPeerStreamId(
+ stream_id, &error_details));
+ EXPECT_EQ(error_details,
+ quiche::QuicheStrCat("Stream id ", stream_id,
+ " would exceed stream count limit 100"));
}
TEST_P(QuicStreamIdManagerTest, OnStreamsBlockedFrame) {
@@ -282,9 +217,6 @@ TEST_P(QuicStreamIdManagerTest, OnStreamsBlockedFrame) {
QuicStreamCount advertised_stream_count =
stream_id_manager_.incoming_advertised_max_streams();
- // Set the config negotiated to allow frame transmission.
- stream_id_manager_.OnConfigNegotiated();
-
QuicStreamsBlockedFrame frame;
frame.unidirectional = IsUnidirectional();
@@ -292,14 +224,16 @@ TEST_P(QuicStreamIdManagerTest, OnStreamsBlockedFrame) {
// If the peer is saying it's blocked on the stream count that
// we've advertised, it's a noop since the peer has the correct information.
frame.stream_count = advertised_stream_count;
- EXPECT_CALL(delegate_, SendStreamsBlocked(_, _)).Times(0);
- EXPECT_TRUE(stream_id_manager_.OnStreamsBlockedFrame(frame));
+ std::string error_details;
+ EXPECT_TRUE(stream_id_manager_.OnStreamsBlockedFrame(frame, &error_details));
// If the peer is saying it's blocked on a stream count that is larger
// than what we've advertised, the connection should get closed.
frame.stream_count = advertised_stream_count + 1;
- EXPECT_CALL(delegate_, OnError(QUIC_STREAMS_BLOCKED_ERROR, _));
- EXPECT_FALSE(stream_id_manager_.OnStreamsBlockedFrame(frame));
+ EXPECT_FALSE(stream_id_manager_.OnStreamsBlockedFrame(frame, &error_details));
+ EXPECT_EQ(
+ error_details,
+ "StreamsBlockedFrame's stream count 101 exceeds incoming max stream 100");
// If the peer is saying it's blocked on a count that is less than
// our actual count, we send a MAX_STREAMS frame and update
@@ -331,7 +265,7 @@ TEST_P(QuicStreamIdManagerTest, OnStreamsBlockedFrame) {
SendMaxStreams(stream_id_manager_.incoming_actual_max_streams(),
IsUnidirectional()));
- EXPECT_TRUE(stream_id_manager_.OnStreamsBlockedFrame(frame));
+ EXPECT_TRUE(stream_id_manager_.OnStreamsBlockedFrame(frame, &error_details));
// Check that the saved frame is correct.
EXPECT_EQ(stream_id_manager_.incoming_actual_max_streams(),
stream_id_manager_.incoming_advertised_max_streams());
@@ -342,10 +276,8 @@ TEST_P(QuicStreamIdManagerTest, GetNextOutgoingStream) {
// opening...
size_t number_of_streams = kDefaultMaxStreamsPerConnection;
- EXPECT_CALL(delegate_, OnCanCreateNewOutgoingStream(IsUnidirectional()));
- stream_id_manager_.SetMaxOpenOutgoingStreams(100);
-
- stream_id_manager_.OnConfigNegotiated();
+ EXPECT_TRUE(
+ stream_id_manager_.MaybeAllowNewOutgoingStreams(number_of_streams));
QuicStreamId stream_id =
IsUnidirectional()
@@ -363,9 +295,7 @@ TEST_P(QuicStreamIdManagerTest, GetNextOutgoingStream) {
}
// If we try to check that the next outgoing stream id is available it should
- // A) fail and B) generate a STREAMS_BLOCKED frame.
- EXPECT_CALL(delegate_, SendStreamsBlocked(kDefaultMaxStreamsPerConnection,
- IsUnidirectional()));
+ // fail.
EXPECT_FALSE(stream_id_manager_.CanOpenNextOutgoingStream());
// If we try to get the next id (above the limit), it should cause a quic-bug.
@@ -377,22 +307,23 @@ TEST_P(QuicStreamIdManagerTest, GetNextOutgoingStream) {
TEST_P(QuicStreamIdManagerTest, MaybeIncreaseLargestPeerStreamId) {
QuicStreamId max_stream_id = GetNthIncomingStreamId(
stream_id_manager_.incoming_actual_max_streams() - 1);
- EXPECT_TRUE(
- stream_id_manager_.MaybeIncreaseLargestPeerStreamId(max_stream_id));
+ EXPECT_TRUE(stream_id_manager_.MaybeIncreaseLargestPeerStreamId(max_stream_id,
+ nullptr));
QuicStreamId first_stream_id = GetNthIncomingStreamId(0);
- EXPECT_TRUE(
- stream_id_manager_.MaybeIncreaseLargestPeerStreamId(first_stream_id));
+ EXPECT_TRUE(stream_id_manager_.MaybeIncreaseLargestPeerStreamId(
+ first_stream_id, nullptr));
// A bad stream ID results in a closed connection.
- EXPECT_CALL(delegate_, OnError(QUIC_INVALID_STREAM_ID, _));
+ std::string error_details;
EXPECT_FALSE(stream_id_manager_.MaybeIncreaseLargestPeerStreamId(
- max_stream_id + kV99StreamIdIncrement));
+ max_stream_id + kV99StreamIdIncrement, &error_details));
+ EXPECT_EQ(
+ error_details,
+ quiche::QuicheStrCat("Stream id ", max_stream_id + kV99StreamIdIncrement,
+ " would exceed stream count limit 100"));
}
TEST_P(QuicStreamIdManagerTest, MaxStreamsWindow) {
- // Set the config negotiated to allow frame transmission.
- stream_id_manager_.OnConfigNegotiated();
-
// Test that a MAX_STREAMS frame is generated when the peer has less than
// |max_streams_window_| streams left that it can initiate.
@@ -405,7 +336,6 @@ TEST_P(QuicStreamIdManagerTest, MaxStreamsWindow) {
// Should not get a control-frame transmission since the peer should have
// "plenty" of stream IDs to use.
- EXPECT_CALL(delegate_, SendStreamsBlocked(_, _)).Times(0);
EXPECT_CALL(delegate_, SendMaxStreams(_, _)).Times(0);
// Get the first incoming stream ID to try and allocate.
@@ -413,7 +343,8 @@ TEST_P(QuicStreamIdManagerTest, MaxStreamsWindow) {
size_t old_available_incoming_streams =
stream_id_manager_.available_incoming_streams();
while (stream_count) {
- EXPECT_TRUE(stream_id_manager_.MaybeIncreaseLargestPeerStreamId(stream_id));
+ EXPECT_TRUE(stream_id_manager_.MaybeIncreaseLargestPeerStreamId(stream_id,
+ nullptr));
// This node should think that the peer believes it has one fewer
// stream it can create.
@@ -454,104 +385,35 @@ TEST_P(QuicStreamIdManagerTest, MaxStreamsWindow) {
// SendMaxStreams(stream_id_manager_.incoming_actual_max_streams(),
// IsUnidirectional()));
EXPECT_CALL(delegate_, SendMaxStreams(_, IsUnidirectional()));
- EXPECT_TRUE(stream_id_manager_.MaybeIncreaseLargestPeerStreamId(stream_id));
+ EXPECT_TRUE(
+ stream_id_manager_.MaybeIncreaseLargestPeerStreamId(stream_id, nullptr));
stream_id_manager_.OnStreamClosed(stream_id);
}
TEST_P(QuicStreamIdManagerTest, StreamsBlockedEdgeConditions) {
- // Set the config negotiated to allow frame transmission.
- stream_id_manager_.OnConfigNegotiated();
-
QuicStreamsBlockedFrame frame;
frame.unidirectional = IsUnidirectional();
// Check that receipt of a STREAMS BLOCKED with stream-count = 0 does nothing
// when max_allowed_incoming_streams is 0.
EXPECT_CALL(delegate_, SendMaxStreams(_, _)).Times(0);
- EXPECT_CALL(delegate_, SendStreamsBlocked(_, _)).Times(0);
stream_id_manager_.SetMaxOpenIncomingStreams(0);
frame.stream_count = 0;
- stream_id_manager_.OnStreamsBlockedFrame(frame);
+ std::string error_details;
+ EXPECT_TRUE(stream_id_manager_.OnStreamsBlockedFrame(frame, &error_details));
// Check that receipt of a STREAMS BLOCKED with stream-count = 0 invokes a
// MAX STREAMS, count = 123, when the MaxOpen... is set to 123.
EXPECT_CALL(delegate_, SendMaxStreams(123u, IsUnidirectional()));
- EXPECT_CALL(delegate_, SendStreamsBlocked(_, _)).Times(0);
stream_id_manager_.SetMaxOpenIncomingStreams(123);
frame.stream_count = 0;
- stream_id_manager_.OnStreamsBlockedFrame(frame);
-}
-
-TEST_P(QuicStreamIdManagerTest, HoldMaxStreamsFrame) {
- // The config has not been negotiated so the MAX_STREAMS frame will not be
- // sent.
- EXPECT_CALL(delegate_, SendMaxStreams(_, _)).Times(0);
-
- QuicStreamsBlockedFrame frame(1u, 0u, IsUnidirectional());
- // Should cause change in pending_max_streams.
- stream_id_manager_.OnStreamsBlockedFrame(frame);
-
- EXPECT_CALL(delegate_, SendMaxStreams(_, IsUnidirectional()));
-
- // MAX_STREAMS will be sent now that the config has been negotiated.
- stream_id_manager_.OnConfigNegotiated();
-}
-
-TEST_P(QuicStreamIdManagerTest, HoldStreamsBlockedFrameXmit) {
- // set outgoing limit to 0, will cause the CanOpenNext... to fail
- // leading to a STREAMS_BLOCKED.
- EXPECT_CALL(delegate_, OnCanCreateNewOutgoingStream(IsUnidirectional()));
- stream_id_manager_.SetMaxOpenOutgoingStreams(0);
-
- // We should not see a STREAMS_BLOCKED frame because we're not configured..
- EXPECT_CALL(delegate_, SendStreamsBlocked(_, _)).Times(0);
-
- // Since the stream limit is 0 and no sreams can be created this should return
- // false and have forced a STREAMS_BLOCKED to be queued up, with the
- // blocked stream id == 0.
- EXPECT_FALSE(stream_id_manager_.CanOpenNextOutgoingStream());
-
- // Since the steam limit has not been increased when the config was negotiated
- // a STREAMS_BLOCKED frame should be sent.
- EXPECT_CALL(delegate_, SendStreamsBlocked(_, IsUnidirectional()));
- stream_id_manager_.OnConfigNegotiated();
-}
-
-TEST_P(QuicStreamIdManagerTest, HoldStreamsBlockedFrameNoXmit) {
- // Set outgoing limit to 0, will cause the CanOpenNext... to fail
- // leading to a STREAMS_BLOCKED.
- EXPECT_CALL(delegate_, OnCanCreateNewOutgoingStream(IsUnidirectional()));
- stream_id_manager_.SetMaxOpenOutgoingStreams(0);
-
- // We should not see a STREAMS_BLOCKED frame because we're not configured..
- EXPECT_CALL(delegate_, SendStreamsBlocked(_, IsUnidirectional())).Times(0);
-
- // Since the stream limit is 0 and no sreams can be created this should return
- // false and have forced a STREAMS_BLOCKED to be queued up, with the
- // blocked stream id == 0.
- EXPECT_FALSE(stream_id_manager_.CanOpenNextOutgoingStream());
-
- EXPECT_CALL(delegate_, OnCanCreateNewOutgoingStream(IsUnidirectional()));
- stream_id_manager_.SetMaxOpenOutgoingStreams(10);
- // Since the stream limit has been increase which allows streams to be created
- // no STREAMS_BLOCKED should be send.
- stream_id_manager_.OnConfigNegotiated();
-}
-
-TEST_P(QuicStreamIdManagerTest, CheckMaxAllowedOutgoingInitialization) {
- const size_t kIncomingStreamCount = 123;
- EXPECT_CALL(delegate_, OnCanCreateNewOutgoingStream(IsUnidirectional()));
- stream_id_manager_.SetMaxOpenOutgoingStreams(kIncomingStreamCount);
- EXPECT_EQ(kIncomingStreamCount, stream_id_manager_.outgoing_max_streams());
+ EXPECT_TRUE(stream_id_manager_.OnStreamsBlockedFrame(frame, &error_details));
}
// Test that a MAX_STREAMS frame is generated when half the stream ids become
// available. This has a useful side effect of testing that when streams are
// closed, the number of available stream ids increases.
TEST_P(QuicStreamIdManagerTest, MaxStreamsSlidingWindow) {
- // Simulate config being negotiated, causing the limits all to be initialized.
- stream_id_manager_.OnConfigNegotiated();
-
QuicStreamCount first_advert =
stream_id_manager_.incoming_advertised_max_streams();
@@ -569,7 +431,8 @@ TEST_P(QuicStreamIdManagerTest, MaxStreamsSlidingWindow) {
SendMaxStreams(first_advert + stream_id_manager_.max_streams_window(),
IsUnidirectional()));
while (i) {
- EXPECT_TRUE(stream_id_manager_.MaybeIncreaseLargestPeerStreamId(id));
+ EXPECT_TRUE(
+ stream_id_manager_.MaybeIncreaseLargestPeerStreamId(id, nullptr));
stream_id_manager_.OnStreamClosed(id);
i--;
id += kV99StreamIdIncrement;
@@ -577,9 +440,7 @@ TEST_P(QuicStreamIdManagerTest, MaxStreamsSlidingWindow) {
}
TEST_P(QuicStreamIdManagerTest, NewStreamDoesNotExceedLimit) {
- EXPECT_CALL(delegate_, OnCanCreateNewOutgoingStream(IsUnidirectional()));
- stream_id_manager_.SetMaxOpenOutgoingStreams(100);
- stream_id_manager_.OnConfigNegotiated();
+ EXPECT_TRUE(stream_id_manager_.MaybeAllowNewOutgoingStreams(100));
size_t stream_count = stream_id_manager_.outgoing_max_streams();
EXPECT_NE(0u, stream_count);
@@ -592,15 +453,13 @@ TEST_P(QuicStreamIdManagerTest, NewStreamDoesNotExceedLimit) {
EXPECT_EQ(stream_id_manager_.outgoing_stream_count(),
stream_id_manager_.outgoing_max_streams());
- // Create another, it should fail. Should also send a STREAMS_BLOCKED
- // control frame.
- EXPECT_CALL(delegate_, SendStreamsBlocked(_, IsUnidirectional()));
+ // Create another, it should fail.
EXPECT_FALSE(stream_id_manager_.CanOpenNextOutgoingStream());
}
TEST_P(QuicStreamIdManagerTest, AvailableStreams) {
- stream_id_manager_.MaybeIncreaseLargestPeerStreamId(
- GetNthIncomingStreamId(3));
+ stream_id_manager_.MaybeIncreaseLargestPeerStreamId(GetNthIncomingStreamId(3),
+ nullptr);
EXPECT_TRUE(stream_id_manager_.IsAvailableStream(GetNthIncomingStreamId(1)));
EXPECT_TRUE(stream_id_manager_.IsAvailableStream(GetNthIncomingStreamId(2)));
@@ -614,12 +473,13 @@ TEST_P(QuicStreamIdManagerTest, AvailableStreams) {
TEST_P(QuicStreamIdManagerTest, ExtremeMaybeIncreaseLargestPeerStreamId) {
QuicStreamId too_big_stream_id = GetNthIncomingStreamId(
stream_id_manager_.incoming_actual_max_streams() + 20);
- std::string error_details = QuicStrCat(
- "Stream id ", too_big_stream_id, " would exceed stream count limit 100");
- EXPECT_CALL(delegate_, OnError(QUIC_INVALID_STREAM_ID, error_details));
- EXPECT_FALSE(
- stream_id_manager_.MaybeIncreaseLargestPeerStreamId(too_big_stream_id));
+ std::string error_details;
+ EXPECT_FALSE(stream_id_manager_.MaybeIncreaseLargestPeerStreamId(
+ too_big_stream_id, &error_details));
+ EXPECT_EQ(error_details,
+ quiche::QuicheStrCat("Stream id ", too_big_stream_id,
+ " would exceed stream count limit 100"));
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.cc b/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.cc
index 158afd80f63..7b8a23b86c4 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.cc
@@ -9,7 +9,6 @@
#include "net/third_party/quiche/src/quic/core/quic_stream_send_buffer.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
@@ -35,13 +34,19 @@ BufferedSlice& BufferedSlice::operator=(BufferedSlice&& other) = default;
BufferedSlice::~BufferedSlice() {}
+QuicInterval<std::size_t> BufferedSlice::interval() const {
+ const std::size_t length = slice.length();
+ return QuicInterval<std::size_t>(offset, offset + length);
+}
+
bool StreamPendingRetransmission::operator==(
const StreamPendingRetransmission& other) const {
return offset == other.offset && length == other.length;
}
QuicStreamSendBuffer::QuicStreamSendBuffer(QuicBufferAllocator* allocator)
- : stream_offset_(0),
+ : current_end_offset_(0),
+ stream_offset_(0),
allocator_(allocator),
stream_bytes_written_(0),
stream_bytes_outstanding_(0),
@@ -59,10 +64,10 @@ void QuicStreamSendBuffer::SaveStreamData(const struct iovec* iov,
GetQuicFlag(FLAGS_quic_send_buffer_max_data_slice_size);
while (data_length > 0) {
size_t slice_len = std::min(data_length, max_data_slice_size);
- QuicMemSlice slice(allocator_, slice_len);
+ QuicUniqueBufferPtr buffer = MakeUniqueBuffer(allocator_, slice_len);
QuicUtils::CopyToBuffer(iov, iov_count, iov_offset, slice_len,
- const_cast<char*>(slice.data()));
- SaveMemSlice(std::move(slice));
+ buffer.get());
+ SaveMemSlice(QuicMemSlice(std::move(buffer), slice_len));
data_length -= slice_len;
iov_offset += slice_len;
}
@@ -76,10 +81,13 @@ void QuicStreamSendBuffer::SaveMemSlice(QuicMemSlice slice) {
return;
}
size_t length = slice.length();
- buffered_slices_.emplace_back(std::move(slice), stream_offset_);
- if (write_index_ == -1) {
- write_index_ = buffered_slices_.size() - 1;
+ // Need to start the offsets at the right interval.
+ if (interval_deque_.Empty()) {
+ const QuicStreamOffset end = stream_offset_ + length;
+ current_end_offset_ = std::max(current_end_offset_, end);
}
+ BufferedSlice bs = BufferedSlice(std::move(slice), stream_offset_);
+ interval_deque_.PushBack(std::move(bs));
stream_offset_ += length;
}
@@ -96,35 +104,18 @@ void QuicStreamSendBuffer::OnStreamDataConsumed(size_t bytes_consumed) {
bool QuicStreamSendBuffer::WriteStreamData(QuicStreamOffset offset,
QuicByteCount data_length,
QuicDataWriter* writer) {
- // TODO(renjietang): Remove this variable once quic_coalesce_stream_frames_2
- // is deprecated.
- bool write_index_hit = false;
- QuicDeque<BufferedSlice>::iterator slice_it =
- write_index_ == -1
- ? buffered_slices_.begin()
- // Assume with write_index, write mostly starts from indexed slice.
- : buffered_slices_.begin() + write_index_;
- if (write_index_ != -1) {
- if (offset >= slice_it->offset + slice_it->slice.length()) {
- QUIC_BUG << "Tried to write data out of sequence.";
- return false;
- }
- // Determine if write actually happens at indexed slice.
- if (offset >= slice_it->offset) {
- write_index_hit = true;
- } else {
- // Write index missed, move iterator to the beginning.
- slice_it = buffered_slices_.begin();
- }
- }
-
- for (; slice_it != buffered_slices_.end(); ++slice_it) {
+ QUIC_BUG_IF(current_end_offset_ < offset)
+ << "Tried to write data out of sequence. last_offset_end:"
+ << current_end_offset_ << ", offset:" << offset;
+ // The iterator returned from |interval_deque_| will automatically advance
+ // the internal write index for the QuicIntervalDeque. The incrementing is
+ // done in operator++.
+ for (auto slice_it = interval_deque_.DataAt(offset);
+ slice_it != interval_deque_.DataEnd(); ++slice_it) {
if (data_length == 0 || offset < slice_it->offset) {
break;
}
- if (offset >= slice_it->offset + slice_it->slice.length()) {
- continue;
- }
+
QuicByteCount slice_offset = offset - slice_it->offset;
QuicByteCount available_bytes_in_slice =
slice_it->slice.length() - slice_offset;
@@ -136,39 +127,10 @@ bool QuicStreamSendBuffer::WriteStreamData(QuicStreamOffset offset,
}
offset += copy_length;
data_length -= copy_length;
-
- if (GetQuicRestartFlag(quic_coalesce_stream_frames_2)) {
- QUIC_RESTART_FLAG_COUNT_N(quic_coalesce_stream_frames_2, 2, 3);
- if (write_index_ != -1) {
- QuicDeque<BufferedSlice>::const_iterator index_slice =
- buffered_slices_.begin() + write_index_;
- if (index_slice->offset == slice_it->offset &&
- copy_length == available_bytes_in_slice) {
- // The slice pointed by write_index has been fully written, advance
- // write index.
- ++write_index_;
- }
- }
- } else if (write_index_hit && copy_length == available_bytes_in_slice) {
- // Finished writing all data in current slice, advance write index for
- // next write.
- ++write_index_;
- }
- }
-
- if (GetQuicRestartFlag(quic_coalesce_stream_frames_2)) {
- QUIC_RESTART_FLAG_COUNT_N(quic_coalesce_stream_frames_2, 3, 3);
- if (write_index_ != -1 &&
- static_cast<size_t>(write_index_) == buffered_slices_.size()) {
- write_index_ = -1;
- }
- } else if (write_index_hit &&
- static_cast<size_t>(write_index_) == buffered_slices_.size()) {
- // Already write to the end off buffer.
- QUIC_DVLOG(2) << "Finish writing out all buffered data.";
- write_index_ = -1;
+ const QuicStreamOffset new_end =
+ slice_it->offset + slice_it->slice.length();
+ current_end_offset_ = std::max(current_end_offset_, new_end);
}
-
return data_length == 0;
}
@@ -187,7 +149,7 @@ bool QuicStreamSendBuffer::OnStreamDataAcked(
if (stream_bytes_outstanding_ < data_length) {
return false;
}
- bytes_acked_.Add(offset, offset + data_length);
+ bytes_acked_.AddOptimizedForAppend(offset, offset + data_length);
*newly_acked_length = data_length;
stream_bytes_outstanding_ -= data_length;
pending_retransmissions_.Difference(offset, offset + data_length);
@@ -264,27 +226,26 @@ StreamPendingRetransmission QuicStreamSendBuffer::NextPendingRetransmission()
bool QuicStreamSendBuffer::FreeMemSlices(QuicStreamOffset start,
QuicStreamOffset end) {
- auto it = buffered_slices_.begin();
- // Find it, such that buffered_slices_[it - 1].end < start <=
- // buffered_slices_[it].end.
- if (it == buffered_slices_.end() || it->slice.empty()) {
+ auto it = interval_deque_.DataBegin();
+ if (it == interval_deque_.DataEnd() || it->slice.empty()) {
QUIC_BUG << "Trying to ack stream data [" << start << ", " << end << "), "
- << (it == buffered_slices_.end()
+ << (it == interval_deque_.DataEnd()
? "and there is no outstanding data."
: "and the first slice is empty.");
return false;
}
- if (start >= it->offset + it->slice.length() || start < it->offset) {
+ if (!it->interval().Contains(start)) {
// Slow path that not the earliest outstanding data gets acked.
- it = std::lower_bound(buffered_slices_.begin(), buffered_slices_.end(),
- start, CompareOffset());
+ it = std::lower_bound(interval_deque_.DataBegin(),
+ interval_deque_.DataEnd(), start, CompareOffset());
}
- if (it == buffered_slices_.end() || it->slice.empty()) {
- QUIC_BUG << "Offset " << start
- << " does not exist or it has already been acked.";
+ if (it == interval_deque_.DataEnd() || it->slice.empty()) {
+ QUIC_BUG << "Offset " << start << " with iterator offset: " << it->offset
+ << (it == interval_deque_.DataEnd() ? " does not exist."
+ : " has already been acked.");
return false;
}
- for (; it != buffered_slices_.end(); ++it) {
+ for (; it != interval_deque_.DataEnd(); ++it) {
if (it->offset >= end) {
break;
}
@@ -297,21 +258,14 @@ bool QuicStreamSendBuffer::FreeMemSlices(QuicStreamOffset start,
}
void QuicStreamSendBuffer::CleanUpBufferedSlices() {
- while (!buffered_slices_.empty() && buffered_slices_.front().slice.empty()) {
- // Remove data which stops waiting for acks. Please note, mem slices can
- // be released out of order, but send buffer is cleaned up in order.
- QUIC_BUG_IF(write_index_ == 0)
- << "Fail to advance current_write_slice_. It points to the slice "
- "whose data has all be written and ACK'ed or ignored. "
- "current_write_slice_ offset "
- << buffered_slices_[write_index_].offset << " length "
- << buffered_slices_[write_index_].slice.length();
- if (write_index_ > 0) {
- // If write index is pointing to any slice, reduce the index as the
- // slices are all shifted to the left by one.
- --write_index_;
- }
- buffered_slices_.pop_front();
+ while (!interval_deque_.Empty() &&
+ interval_deque_.DataBegin()->slice.empty()) {
+ QUIC_BUG_IF(interval_deque_.DataBegin()->offset > current_end_offset_)
+ << "Fail to pop front from interval_deque_. Front element contained "
+ "a slice whose data has not all be written. Front offset "
+ << interval_deque_.DataBegin()->offset << " length "
+ << interval_deque_.DataBegin()->slice.length();
+ interval_deque_.PopFront();
}
}
@@ -323,7 +277,7 @@ bool QuicStreamSendBuffer::IsStreamDataOutstanding(
}
size_t QuicStreamSendBuffer::size() const {
- return buffered_slices_.size();
+ return interval_deque_.Size();
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.h b/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.h
index 51a10e9f325..71448944521 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.h
@@ -6,9 +6,10 @@
#define QUICHE_QUIC_CORE_QUIC_STREAM_SEND_BUFFER_H_
#include "net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_circular_deque.h"
+#include "net/third_party/quiche/src/quic/core/quic_interval_deque.h"
#include "net/third_party/quiche/src/quic/core/quic_interval_set.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_iovec.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice_span.h"
@@ -35,6 +36,9 @@ struct QUIC_EXPORT_PRIVATE BufferedSlice {
BufferedSlice& operator=(const BufferedSlice& other) = delete;
~BufferedSlice();
+ // Return an interval representing the offset and length.
+ QuicInterval<std::size_t> interval() const;
+
// Stream data of this data slice.
QuicMemSlice slice;
// Location of this data slice in the stream.
@@ -141,7 +145,10 @@ class QUIC_EXPORT_PRIVATE QuicStreamSendBuffer {
// Cleanup empty slices in order from buffered_slices_.
void CleanUpBufferedSlices();
- QuicDeque<BufferedSlice> buffered_slices_;
+ // |current_end_offset_| stores the end offset of the current slice to ensure
+ // data isn't being written out of order when using the |interval_deque_|.
+ QuicStreamOffset current_end_offset_;
+ QuicIntervalDeque<BufferedSlice> interval_deque_;
// Offset of next inserted byte.
QuicStreamOffset stream_offset_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer_test.cc
index 90fcd6eb104..6232887d678 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer_test.cc
@@ -15,12 +15,13 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_test_mem_slice_vector.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_stream_send_buffer_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
namespace {
-struct iovec MakeIovec(QuicStringPiece data) {
+struct iovec MakeIovec(quiche::QuicheStringPiece data) {
struct iovec iov = {const_cast<char*>(data.data()),
static_cast<size_t>(data.size())};
return iov;
@@ -35,17 +36,18 @@ class QuicStreamSendBufferTest : public QuicTest {
std::string data1(1536, 'a');
std::string data2 = std::string(256, 'b') + std::string(256, 'c');
struct iovec iov[2];
- iov[0] = MakeIovec(QuicStringPiece(data1));
- iov[1] = MakeIovec(QuicStringPiece(data2));
+ iov[0] = MakeIovec(quiche::QuicheStringPiece(data1));
+ iov[1] = MakeIovec(quiche::QuicheStringPiece(data2));
- QuicMemSlice slice1(&allocator_, 1024);
- memset(const_cast<char*>(slice1.data()), 'c', 1024);
- QuicMemSlice slice2(&allocator_, 768);
- memset(const_cast<char*>(slice2.data()), 'd', 768);
+ QuicUniqueBufferPtr buffer1 = MakeUniqueBuffer(&allocator_, 1024);
+ memset(buffer1.get(), 'c', 1024);
+ QuicMemSlice slice1(std::move(buffer1), 1024);
+ QuicUniqueBufferPtr buffer2 = MakeUniqueBuffer(&allocator_, 768);
+ memset(buffer2.get(), 'd', 768);
+ QuicMemSlice slice2(std::move(buffer2), 768);
- // Index starts from not pointing to any slice.
- EXPECT_EQ(nullptr,
- QuicStreamSendBufferPeer::CurrentWriteSlice(&send_buffer_));
+ // The stream offset should be 0 since nothing is written.
+ EXPECT_EQ(0u, QuicStreamSendBufferPeer::EndOffset(&send_buffer_));
// Save all data.
SetQuicFlag(FLAGS_quic_send_buffer_max_data_slice_size, 1024);
@@ -86,23 +88,23 @@ TEST_F(QuicStreamSendBufferTest, CopyDataToBuffer) {
std::string copy4(768, 'd');
ASSERT_TRUE(send_buffer_.WriteStreamData(0, 1024, &writer));
- EXPECT_EQ(copy1, QuicStringPiece(buf, 1024));
+ EXPECT_EQ(copy1, quiche::QuicheStringPiece(buf, 1024));
ASSERT_TRUE(send_buffer_.WriteStreamData(1024, 1024, &writer));
- EXPECT_EQ(copy2, QuicStringPiece(buf + 1024, 1024));
+ EXPECT_EQ(copy2, quiche::QuicheStringPiece(buf + 1024, 1024));
ASSERT_TRUE(send_buffer_.WriteStreamData(2048, 1024, &writer));
- EXPECT_EQ(copy3, QuicStringPiece(buf + 2048, 1024));
+ EXPECT_EQ(copy3, quiche::QuicheStringPiece(buf + 2048, 1024));
ASSERT_TRUE(send_buffer_.WriteStreamData(3072, 768, &writer));
- EXPECT_EQ(copy4, QuicStringPiece(buf + 3072, 768));
+ EXPECT_EQ(copy4, quiche::QuicheStringPiece(buf + 3072, 768));
// Test data piece across boundries.
QuicDataWriter writer2(4000, buf, quiche::HOST_BYTE_ORDER);
std::string copy5 =
std::string(536, 'a') + std::string(256, 'b') + std::string(232, 'c');
ASSERT_TRUE(send_buffer_.WriteStreamData(1000, 1024, &writer2));
- EXPECT_EQ(copy5, QuicStringPiece(buf, 1024));
+ EXPECT_EQ(copy5, quiche::QuicheStringPiece(buf, 1024));
ASSERT_TRUE(send_buffer_.WriteStreamData(2500, 1024, &writer2));
std::string copy6 = std::string(572, 'c') + std::string(452, 'd');
- EXPECT_EQ(copy6, QuicStringPiece(buf + 1024, 1024));
+ EXPECT_EQ(copy6, quiche::QuicheStringPiece(buf + 1024, 1024));
// Invalid data copy.
QuicDataWriter writer3(4000, buf, quiche::HOST_BYTE_ORDER);
@@ -127,27 +129,22 @@ TEST_F(QuicStreamSendBufferTest,
// Write more than one slice.
EXPECT_EQ(0, QuicStreamSendBufferPeer::write_index(&send_buffer_));
ASSERT_TRUE(send_buffer_.WriteStreamData(0, 1024, &writer));
- EXPECT_EQ(copy1, QuicStringPiece(buf, 1024));
+ EXPECT_EQ(copy1, quiche::QuicheStringPiece(buf, 1024));
EXPECT_EQ(1, QuicStreamSendBufferPeer::write_index(&send_buffer_));
// Retransmit the first frame and also send new data.
ASSERT_TRUE(send_buffer_.WriteStreamData(0, 2048, &writer));
- EXPECT_EQ(copy1 + copy2, QuicStringPiece(buf + 1024, 2048));
+ EXPECT_EQ(copy1 + copy2, quiche::QuicheStringPiece(buf + 1024, 2048));
// Write new data.
- if (!GetQuicRestartFlag(quic_coalesce_stream_frames_2)) {
- EXPECT_EQ(1, QuicStreamSendBufferPeer::write_index(&send_buffer_));
- EXPECT_QUIC_DEBUG_DEATH(send_buffer_.WriteStreamData(2048, 50, &writer),
- "Tried to write data out of sequence.");
- } else {
- EXPECT_EQ(2, QuicStreamSendBufferPeer::write_index(&send_buffer_));
- ASSERT_TRUE(send_buffer_.WriteStreamData(2048, 50, &writer));
- EXPECT_EQ(std::string(50, 'c'), QuicStringPiece(buf + 1024 + 2048, 50));
- EXPECT_EQ(2, QuicStreamSendBufferPeer::write_index(&send_buffer_));
- ASSERT_TRUE(send_buffer_.WriteStreamData(2048, 1124, &writer));
- EXPECT_EQ(copy3, QuicStringPiece(buf + 1024 + 2048 + 50, 1124));
- EXPECT_EQ(3, QuicStreamSendBufferPeer::write_index(&send_buffer_));
- }
+ EXPECT_EQ(2048u, QuicStreamSendBufferPeer::EndOffset(&send_buffer_));
+ ASSERT_TRUE(send_buffer_.WriteStreamData(2048, 50, &writer));
+ EXPECT_EQ(std::string(50, 'c'),
+ quiche::QuicheStringPiece(buf + 1024 + 2048, 50));
+ EXPECT_EQ(3072u, QuicStreamSendBufferPeer::EndOffset(&send_buffer_));
+ ASSERT_TRUE(send_buffer_.WriteStreamData(2048, 1124, &writer));
+ EXPECT_EQ(copy3, quiche::QuicheStringPiece(buf + 1024 + 2048 + 50, 1124));
+ EXPECT_EQ(3840u, QuicStreamSendBufferPeer::EndOffset(&send_buffer_));
}
TEST_F(QuicStreamSendBufferTest, RemoveStreamFrame) {
@@ -288,39 +285,37 @@ TEST_F(QuicStreamSendBufferTest, PendingRetransmission) {
EXPECT_TRUE(send_buffer_.IsStreamDataOutstanding(400, 800));
}
-TEST_F(QuicStreamSendBufferTest, CurrentWriteIndex) {
+TEST_F(QuicStreamSendBufferTest, EndOffset) {
char buf[4000];
QuicDataWriter writer(4000, buf, quiche::HOST_BYTE_ORDER);
- // With data buffered, index points to the 1st slice of data.
- EXPECT_EQ(0u,
- QuicStreamSendBufferPeer::CurrentWriteSlice(&send_buffer_)->offset);
+
+ EXPECT_EQ(1024u, QuicStreamSendBufferPeer::EndOffset(&send_buffer_));
ASSERT_TRUE(send_buffer_.WriteStreamData(0, 1024, &writer));
- // Wrote all data on 1st slice, index points to next slice.
- EXPECT_EQ(1024u,
- QuicStreamSendBufferPeer::CurrentWriteSlice(&send_buffer_)->offset);
+ // Last offset we've seen is 1024
+ EXPECT_EQ(1024u, QuicStreamSendBufferPeer::EndOffset(&send_buffer_));
+
ASSERT_TRUE(send_buffer_.WriteStreamData(1024, 512, &writer));
- // Last write didn't finish a whole slice. Index remains.
- EXPECT_EQ(1024u,
- QuicStreamSendBufferPeer::CurrentWriteSlice(&send_buffer_)->offset);
+ // Last offset is now 2048 as that's the end of the next slice.
+ EXPECT_EQ(2048u, QuicStreamSendBufferPeer::EndOffset(&send_buffer_));
send_buffer_.OnStreamDataConsumed(1024);
// If data in 1st slice gets ACK'ed, it shouldn't change the indexed slice
QuicByteCount newly_acked_length;
EXPECT_TRUE(send_buffer_.OnStreamDataAcked(0, 1024, &newly_acked_length));
- EXPECT_EQ(1024u,
- QuicStreamSendBufferPeer::CurrentWriteSlice(&send_buffer_)->offset);
+ // Last offset is still 2048.
+ EXPECT_EQ(2048u, QuicStreamSendBufferPeer::EndOffset(&send_buffer_));
ASSERT_TRUE(
send_buffer_.WriteStreamData(1024 + 512, 3840 - 1024 - 512, &writer));
- // After writing all buffered data, index become invalid again.
- EXPECT_EQ(nullptr,
- QuicStreamSendBufferPeer::CurrentWriteSlice(&send_buffer_));
- QuicMemSlice slice(&allocator_, 60);
- memset(const_cast<char*>(slice.data()), 'e', 60);
+
+ // Last offset is end offset of last slice.
+ EXPECT_EQ(3840u, QuicStreamSendBufferPeer::EndOffset(&send_buffer_));
+ QuicUniqueBufferPtr buffer = MakeUniqueBuffer(&allocator_, 60);
+ memset(buffer.get(), 'e', 60);
+ QuicMemSlice slice(std::move(buffer), 60);
send_buffer_.SaveMemSlice(std::move(slice));
- // With new data, index points to the new data.
- EXPECT_EQ(3840u,
- QuicStreamSendBufferPeer::CurrentWriteSlice(&send_buffer_)->offset);
+
+ EXPECT_EQ(3840u, QuicStreamSendBufferPeer::EndOffset(&send_buffer_));
}
TEST_F(QuicStreamSendBufferTest, SaveMemSliceSpan) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer.cc b/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer.cc
index d7976689331..0dfc8f7c103 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer.cc
@@ -5,22 +5,24 @@
#include "net/third_party/quiche/src/quic/core/quic_stream_sequencer.h"
#include <algorithm>
+#include <cstddef>
#include <limits>
#include <string>
#include <utility>
+#include "net/third_party/quiche/src/quic/core/quic_clock.h"
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -33,15 +35,7 @@ QuicStreamSequencer::QuicStreamSequencer(StreamInterface* quic_stream)
num_frames_received_(0),
num_duplicate_frames_received_(0),
ignore_read_data_(false),
- level_triggered_(false),
- stop_reading_when_level_triggered_(
- GetQuicReloadableFlag(quic_stop_reading_when_level_triggered)),
- close_connection_and_discard_data_on_wrong_offset_(GetQuicReloadableFlag(
- quic_close_connection_and_discard_data_on_wrong_offset)) {
- if (stop_reading_when_level_triggered_) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_stop_reading_when_level_triggered);
- }
-}
+ level_triggered_(false) {}
QuicStreamSequencer::~QuicStreamSequencer() {}
@@ -51,18 +45,9 @@ void QuicStreamSequencer::OnStreamFrame(const QuicStreamFrame& frame) {
const QuicStreamOffset byte_offset = frame.offset;
const size_t data_len = frame.data_length;
- if (frame.fin) {
- bool should_process_data = CloseStreamAtOffset(frame.offset + data_len);
- if (data_len == 0) {
- return;
- }
- if (close_connection_and_discard_data_on_wrong_offset_) {
- QUIC_RELOADABLE_FLAG_COUNT_N(
- quic_close_connection_and_discard_data_on_wrong_offset, 1, 3);
- if (!should_process_data) {
- return;
- }
- }
+ if (frame.fin &&
+ (!CloseStreamAtOffset(frame.offset + data_len) || data_len == 0)) {
+ return;
}
OnFrameData(byte_offset, data_len, frame.data_buffer);
}
@@ -80,16 +65,15 @@ void QuicStreamSequencer::OnFrameData(QuicStreamOffset byte_offset,
size_t bytes_written;
std::string error_details;
QuicErrorCode result = buffered_frames_.OnStreamData(
- byte_offset, QuicStringPiece(data_buffer, data_len), &bytes_written,
- &error_details);
+ byte_offset, quiche::QuicheStringPiece(data_buffer, data_len),
+ &bytes_written, &error_details);
if (result != QUIC_NO_ERROR) {
- std::string details = QuicStrCat(
- "Stream ", stream_->id(), ": ", QuicErrorCodeToString(result), ": ",
- error_details,
- "\nPeer Address: ", stream_->PeerAddressOfLatestPacket().ToString());
+ std::string details = quiche::QuicheStrCat("Stream ", stream_->id(), ": ",
+ QuicErrorCodeToString(result),
+ ": ", error_details);
QUIC_LOG_FIRST_N(WARNING, 50) << QuicErrorCodeToString(result);
QUIC_LOG_FIRST_N(WARNING, 50) << details;
- stream_->CloseConnectionWithDetails(result, details);
+ stream_->OnUnrecoverableError(result, details);
return;
}
@@ -107,8 +91,7 @@ void QuicStreamSequencer::OnFrameData(QuicStreamOffset byte_offset,
if (buffered_frames_.ReadableBytes() > previous_readable_bytes) {
// Readable bytes has changed, let stream decide if to inform application
// or not.
- if (stop_reading_when_level_triggered_ && ignore_read_data_) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_stop_reading_when_level_triggered);
+ if (ignore_read_data_) {
FlushBufferedFrames();
} else {
stream_->OnDataAvailable();
@@ -133,29 +116,20 @@ bool QuicStreamSequencer::CloseStreamAtOffset(QuicStreamOffset offset) {
// If there is a scheduled close, the new offset should match it.
if (close_offset_ != kMaxOffset && offset != close_offset_) {
- if (!close_connection_and_discard_data_on_wrong_offset_) {
- stream_->Reset(QUIC_MULTIPLE_TERMINATION_OFFSETS);
- return false;
- }
- QUIC_RELOADABLE_FLAG_COUNT_N(
- quic_close_connection_and_discard_data_on_wrong_offset, 2, 3);
- stream_->CloseConnectionWithDetails(
+ stream_->OnUnrecoverableError(
QUIC_STREAM_SEQUENCER_INVALID_STATE,
- QuicStrCat("Stream ", stream_->id(),
- " received new final offset: ", offset,
- ", which is different from close offset: ", close_offset_));
+ quiche::QuicheStrCat(
+ "Stream ", stream_->id(), " received new final offset: ", offset,
+ ", which is different from close offset: ", close_offset_));
return false;
}
// The final offset should be no less than the highest offset that is
// received.
- if (close_connection_and_discard_data_on_wrong_offset_ &&
- offset < highest_offset_) {
- QUIC_RELOADABLE_FLAG_COUNT_N(
- quic_close_connection_and_discard_data_on_wrong_offset, 3, 3);
- stream_->CloseConnectionWithDetails(
+ if (offset < highest_offset_) {
+ stream_->OnUnrecoverableError(
QUIC_STREAM_SEQUENCER_INVALID_STATE,
- QuicStrCat(
+ quiche::QuicheStrCat(
"Stream ", stream_->id(), " received fin with offset: ", offset,
", which reduces current highest offset: ", highest_offset_));
return false;
@@ -213,7 +187,7 @@ void QuicStreamSequencer::Read(std::string* buffer) {
Readv(&iov, 1);
}
-int QuicStreamSequencer::Readv(const struct iovec* iov, size_t iov_len) {
+size_t QuicStreamSequencer::Readv(const struct iovec* iov, size_t iov_len) {
DCHECK(!blocked_);
std::string error_details;
size_t bytes_read;
@@ -221,13 +195,13 @@ int QuicStreamSequencer::Readv(const struct iovec* iov, size_t iov_len) {
buffered_frames_.Readv(iov, iov_len, &bytes_read, &error_details);
if (read_error != QUIC_NO_ERROR) {
std::string details =
- QuicStrCat("Stream ", stream_->id(), ": ", error_details);
- stream_->CloseConnectionWithDetails(read_error, details);
- return static_cast<int>(bytes_read);
+ quiche::QuicheStrCat("Stream ", stream_->id(), ": ", error_details);
+ stream_->OnUnrecoverableError(read_error, details);
+ return bytes_read;
}
stream_->AddBytesConsumed(bytes_read);
- return static_cast<int>(bytes_read);
+ return bytes_read;
}
bool QuicStreamSequencer::HasBytesToRead() const {
@@ -304,7 +278,7 @@ QuicStreamOffset QuicStreamSequencer::NumBytesConsumed() const {
const std::string QuicStreamSequencer::DebugString() const {
// clang-format off
- return QuicStrCat("QuicStreamSequencer:",
+ return quiche::QuicheStrCat("QuicStreamSequencer:",
"\n bytes buffered: ", NumBytesBuffered(),
"\n bytes consumed: ", NumBytesConsumed(),
"\n has bytes to read: ", HasBytesToRead() ? "true" : "false",
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer.h b/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer.h
index 878acb04307..50b5b68eaed 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer.h
@@ -35,20 +35,15 @@ class QUIC_EXPORT_PRIVATE QuicStreamSequencer {
virtual void OnFinRead() = 0;
// Called when bytes have been consumed from the sequencer.
virtual void AddBytesConsumed(QuicByteCount bytes) = 0;
- // TODO(rch): Clean up this interface via OnUnrecoverableError and
- // remove PeerAddressOfLatestPacket().
// Called when an error has occurred which should result in the stream
// being reset.
virtual void Reset(QuicRstStreamErrorCode error) = 0;
// Called when an error has occurred which should result in the connection
// being closed.
- virtual void CloseConnectionWithDetails(QuicErrorCode error,
- const std::string& details) = 0;
-
+ virtual void OnUnrecoverableError(QuicErrorCode error,
+ const std::string& details) = 0;
// Returns the stream id of this stream.
virtual QuicStreamId id() const = 0;
- // Returns the peer address of the last packet received for this stream.
- virtual const QuicSocketAddress& PeerAddressOfLatestPacket() const = 0;
};
explicit QuicStreamSequencer(StreamInterface* quic_stream);
@@ -91,7 +86,7 @@ class QUIC_EXPORT_PRIVATE QuicStreamSequencer {
// bytes read. Any buffered data no longer in use will be released.
// TODO(rch): remove this method and instead implement it as a helper method
// based on GetReadableRegions and MarkConsumed.
- int Readv(const struct iovec* iov, size_t iov_len);
+ size_t Readv(const struct iovec* iov, size_t iov_len);
// Consumes |num_bytes| data. Used in conjunction with |GetReadableRegions|
// to do zero-copy reads.
@@ -206,16 +201,6 @@ class QUIC_EXPORT_PRIVATE QuicStreamSequencer {
// If false, only call OnDataAvailable() when it becomes newly unblocked.
// Otherwise, call OnDataAvailable() when number of readable bytes changes.
bool level_triggered_;
-
- // Latched value of quic_stop_reading_when_level_triggered flag. When true,
- // the sequencer will discard incoming data (but not FIN bits) after
- // StopReading is called, even in level_triggered_ mode.
- const bool stop_reading_when_level_triggered_;
-
- // Latched value of quic_close_connection_and_discard_data_on_wrong_offset.
- // When true, the sequencer will inform the stream to close connection when
- // wrong offset is received. And the stream frame's data will be discarded.
- const bool close_connection_and_discard_data_on_wrong_offset_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.cc b/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.cc
index 89a6ad750f3..8a26521a4da 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.cc
@@ -12,7 +12,8 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace {
@@ -54,20 +55,20 @@ void QuicStreamSequencerBuffer::Clear() {
bytes_received_.Add(0, total_bytes_read_);
}
-bool QuicStreamSequencerBuffer::RetireBlock(size_t idx) {
- if (blocks_[idx] == nullptr) {
+bool QuicStreamSequencerBuffer::RetireBlock(size_t index) {
+ if (blocks_[index] == nullptr) {
QUIC_BUG << "Try to retire block twice";
return false;
}
- delete blocks_[idx];
- blocks_[idx] = nullptr;
- QUIC_DVLOG(1) << "Retired block with index: " << idx;
+ delete blocks_[index];
+ blocks_[index] = nullptr;
+ QUIC_DVLOG(1) << "Retired block with index: " << index;
return true;
}
QuicErrorCode QuicStreamSequencerBuffer::OnStreamData(
QuicStreamOffset starting_offset,
- QuicStringPiece data,
+ quiche::QuicheStringPiece data,
size_t* const bytes_buffered,
std::string* error_details) {
*bytes_buffered = 0;
@@ -134,7 +135,7 @@ QuicErrorCode QuicStreamSequencerBuffer::OnStreamData(
}
bool QuicStreamSequencerBuffer::CopyStreamData(QuicStreamOffset offset,
- QuicStringPiece data,
+ quiche::QuicheStringPiece data,
size_t* bytes_copy,
std::string* error_details) {
*bytes_copy = 0;
@@ -168,7 +169,7 @@ bool QuicStreamSequencerBuffer::CopyStreamData(QuicStreamOffset offset,
}
if (write_block_num >= blocks_count_) {
- *error_details = QuicStrCat(
+ *error_details = quiche::QuicheStrCat(
"QuicStreamSequencerBuffer error: OnStreamData() exceed array bounds."
"write offset = ",
offset, " write_block_num = ", write_block_num,
@@ -193,12 +194,12 @@ bool QuicStreamSequencerBuffer::CopyStreamData(QuicStreamOffset offset,
<< " length: " << bytes_to_copy;
if (dest == nullptr || source == nullptr) {
- *error_details = QuicStrCat(
+ *error_details = quiche::QuicheStrCat(
"QuicStreamSequencerBuffer error: OnStreamData()"
" dest == nullptr: ",
(dest == nullptr), " source == nullptr: ", (source == nullptr),
- " Writing at offset ", offset, " Gaps: ", GapsDebugString(),
- " Remaining frames: ", ReceivedFramesDebugString(),
+ " Writing at offset ", offset,
+ " Received frames: ", ReceivedFramesDebugString(),
" total_bytes_read_ = ", total_bytes_read_);
return false;
}
@@ -230,13 +231,12 @@ QuicErrorCode QuicStreamSequencerBuffer::Readv(const iovec* dest_iov,
std::min<size_t>(bytes_available_in_block, dest_remaining);
DCHECK_GT(bytes_to_copy, 0u);
if (blocks_[block_idx] == nullptr || dest == nullptr) {
- *error_details = QuicStrCat(
+ *error_details = quiche::QuicheStrCat(
"QuicStreamSequencerBuffer error:"
" Readv() dest == nullptr: ",
(dest == nullptr), " blocks_[", block_idx,
"] == nullptr: ", (blocks_[block_idx] == nullptr),
- " Gaps: ", GapsDebugString(),
- " Remaining frames: ", ReceivedFramesDebugString(),
+ " Received frames: ", ReceivedFramesDebugString(),
" total_bytes_read_ = ", total_bytes_read_);
return QUIC_STREAM_SEQUENCER_INVALID_STATE;
}
@@ -255,11 +255,12 @@ QuicErrorCode QuicStreamSequencerBuffer::Readv(const iovec* dest_iov,
if (bytes_to_copy == bytes_available_in_block) {
bool retire_successfully = RetireBlockIfEmpty(block_idx);
if (!retire_successfully) {
- *error_details = QuicStrCat(
+ *error_details = quiche::QuicheStrCat(
"QuicStreamSequencerBuffer error: fail to retire block ",
block_idx,
" as the block is already released, total_bytes_read_ = ",
- total_bytes_read_, " Gaps: ", GapsDebugString());
+ total_bytes_read_,
+ " Received frames: ", ReceivedFramesDebugString());
return QUIC_STREAM_SEQUENCER_INVALID_STATE;
}
}
@@ -270,9 +271,9 @@ QuicErrorCode QuicStreamSequencerBuffer::Readv(const iovec* dest_iov,
}
int QuicStreamSequencerBuffer::GetReadableRegions(struct iovec* iov,
- int iov_count) const {
+ int iov_len) const {
DCHECK(iov != nullptr);
- DCHECK_GT(iov_count, 0);
+ DCHECK_GT(iov_len, 0);
if (ReadableBytes() == 0) {
iov[0].iov_base = nullptr;
@@ -307,7 +308,7 @@ int QuicStreamSequencerBuffer::GetReadableRegions(struct iovec* iov,
// a region.
int iov_used = 1;
size_t block_idx = (start_block_idx + iov_used) % blocks_count_;
- while (block_idx != end_block_idx && iov_used < iov_count) {
+ while (block_idx != end_block_idx && iov_used < iov_len) {
DCHECK(nullptr != blocks_[block_idx]);
iov[iov_used].iov_base = blocks_[block_idx]->buffer;
iov[iov_used].iov_len = GetBlockCapacity(block_idx);
@@ -317,7 +318,7 @@ int QuicStreamSequencerBuffer::GetReadableRegions(struct iovec* iov,
}
// Deal with last block if |iov| can hold more.
- if (iov_used < iov_count) {
+ if (iov_used < iov_len) {
DCHECK(nullptr != blocks_[block_idx]);
iov[iov_used].iov_base = blocks_[end_block_idx]->buffer;
iov[iov_used].iov_len = end_block_offset + 1;
@@ -363,11 +364,11 @@ bool QuicStreamSequencerBuffer::PeekRegion(QuicStreamOffset offset,
return true;
}
-bool QuicStreamSequencerBuffer::MarkConsumed(size_t bytes_used) {
- if (bytes_used > ReadableBytes()) {
+bool QuicStreamSequencerBuffer::MarkConsumed(size_t bytes_consumed) {
+ if (bytes_consumed > ReadableBytes()) {
return false;
}
- size_t bytes_to_consume = bytes_used;
+ size_t bytes_to_consume = bytes_consumed;
while (bytes_to_consume > 0) {
size_t block_idx = NextBlockToRead();
size_t offset_in_block = ReadOffset();
@@ -482,11 +483,6 @@ size_t QuicStreamSequencerBuffer::GetBlockCapacity(size_t block_index) const {
}
}
-std::string QuicStreamSequencerBuffer::GapsDebugString() const {
- // TODO(vasilvv): this should return the complement of |bytes_received_|.
- return bytes_received_.ToString();
-}
-
std::string QuicStreamSequencerBuffer::ReceivedFramesDebugString() const {
return bytes_received_.ToString();
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.h b/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.h
index 406cd92edc3..356b62fccc9 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.h
@@ -28,11 +28,11 @@
// Expected Use:
// QuicStreamSequencerBuffer buffer(2.5 * 8 * 1024);
// std::string source(1024, 'a');
-// QuicStringPiece string_piece(source.data(), source.size());
+// quiche::QuicheStringPiece string_piece(source.data(), source.size());
// size_t written = 0;
// buffer.OnStreamData(800, string_piece, GetEpollClockNow(), &written);
// source = std::string{800, 'b'};
-// QuicStringPiece string_piece1(source.data(), 800);
+// quiche::QuicheStringPiece string_piece1(source.data(), 800);
// // Try to write to [1, 801), but should fail due to overlapping,
// // res should be QUIC_INVALID_STREAM_DATA
// auto res = buffer.OnStreamData(1, string_piece1, &written));
@@ -69,7 +69,7 @@
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_iovec.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -106,7 +106,7 @@ class QUIC_EXPORT_PRIVATE QuicStreamSequencerBuffer {
// successfully buffered, returns QUIC_NO_ERROR and stores the number of
// bytes buffered in |bytes_buffered|. Returns an error otherwise.
QuicErrorCode OnStreamData(QuicStreamOffset offset,
- QuicStringPiece data,
+ quiche::QuicheStringPiece data,
size_t* bytes_buffered,
std::string* error_details);
@@ -137,10 +137,10 @@ class QUIC_EXPORT_PRIVATE QuicStreamSequencerBuffer {
// Does not consume data.
bool PeekRegion(QuicStreamOffset offset, iovec* iov) const;
- // Called after GetReadableRegions() to free up |bytes_used| space if these
- // bytes are processed.
- // Pre-requisite: bytes_used <= available bytes to read.
- bool MarkConsumed(size_t bytes_buffered);
+ // Called after GetReadableRegions() to free up |bytes_consumed| space if
+ // these bytes are processed.
+ // Pre-requisite: bytes_consumed <= available bytes to read.
+ bool MarkConsumed(size_t bytes_consumed);
// Deletes and records as consumed any buffered data and clear the buffer.
// (To be called only after sequencer's StopReading has been called.)
@@ -167,7 +167,7 @@ class QUIC_EXPORT_PRIVATE QuicStreamSequencerBuffer {
// Copies |data| to blocks_, sets |bytes_copy|. Returns true if the copy is
// successful. Otherwise, sets |error_details| and returns false.
bool CopyStreamData(QuicStreamOffset offset,
- QuicStringPiece data,
+ quiche::QuicheStringPiece data,
size_t* bytes_copy,
std::string* error_details);
@@ -208,10 +208,7 @@ class QUIC_EXPORT_PRIVATE QuicStreamSequencerBuffer {
// Returns offset of highest received byte + 1.
QuicStreamOffset NextExpectedByte() const;
- // Return |gaps_| as a string: [1024, 1500) [1800, 2048)... for debugging.
- std::string GapsDebugString() const;
-
- // Return all received frames as a string in same format as GapsDebugString();
+ // Return all received frames as a string.
std::string ReceivedFramesDebugString() const;
// The maximum total capacity of this buffer in byte, as constructed.
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer_test.cc
index b17dcc498fa..7341983d4a5 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer_test.cc
@@ -12,18 +12,19 @@
#include <utility>
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_stream_sequencer_buffer_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
-QuicStringPiece IovecToStringPiece(iovec iov) {
- return QuicStringPiece(reinterpret_cast<const char*>(iov.iov_base),
- iov.iov_len);
+quiche::QuicheStringPiece IovecToStringPiece(iovec iov) {
+ return quiche::QuicheStringPiece(reinterpret_cast<const char*>(iov.iov_base),
+ iov.iov_len);
}
char GetCharFromIOVecs(size_t offset, iovec iov[], size_t count) {
@@ -158,11 +159,11 @@ TEST_F(QuicStreamSequencerBufferTest, Move) {
TEST_F(QuicStreamSequencerBufferTest, OnStreamDataInvalidSource) {
// Pass in an invalid source, expects to return error.
- QuicStringPiece source;
- source = QuicStringPiece(nullptr, 1024);
+ quiche::QuicheStringPiece source;
+ source = quiche::QuicheStringPiece(nullptr, 1024);
EXPECT_THAT(buffer_->OnStreamData(800, source, &written_, &error_details_),
IsError(QUIC_STREAM_SEQUENCER_INVALID_STATE));
- EXPECT_EQ(0u, error_details_.find(QuicStrCat(
+ EXPECT_EQ(0u, error_details_.find(quiche::QuicheStrCat(
"QuicStreamSequencerBuffer error: OnStreamData() "
"dest == nullptr: ",
false, " source == nullptr: ", true)));
@@ -319,7 +320,7 @@ TEST_F(QuicStreamSequencerBufferTest, Readv100Bytes) {
QUIC_LOG(ERROR) << error_details_;
EXPECT_EQ(100u, read);
EXPECT_EQ(100u, buffer_->BytesConsumed());
- EXPECT_EQ(source, QuicStringPiece(dest, read));
+ EXPECT_EQ(source, quiche::QuicheStringPiece(dest, read));
// The first block should be released as its data has been read out.
EXPECT_EQ(nullptr, helper_->GetBlock(0));
EXPECT_TRUE(helper_->CheckBufferInvariants());
@@ -609,7 +610,8 @@ TEST_F(QuicStreamSequencerBufferTest, PeekSingleBlock) {
// Peek at a different offset.
EXPECT_TRUE(buffer_->PeekRegion(100, &iov));
- EXPECT_EQ(QuicStringPiece(source).substr(100), IovecToStringPiece(iov));
+ EXPECT_EQ(quiche::QuicheStringPiece(source).substr(100),
+ IovecToStringPiece(iov));
// Peeking at or after FirstMissingByte() returns false.
EXPECT_FALSE(buffer_->PeekRegion(kBlockSizeBytes, &iov));
@@ -636,15 +638,15 @@ TEST_F(QuicStreamSequencerBufferTest, PeekTwoWritesInSingleBlock) {
// Peek with an offset inside the first write.
const QuicStreamOffset offset1 = 500;
EXPECT_TRUE(buffer_->PeekRegion(offset1, &iov));
- EXPECT_EQ(QuicStringPiece(source1).substr(offset1),
+ EXPECT_EQ(quiche::QuicheStringPiece(source1).substr(offset1),
IovecToStringPiece(iov).substr(0, length1 - offset1));
- EXPECT_EQ(QuicStringPiece(source2),
+ EXPECT_EQ(quiche::QuicheStringPiece(source2),
IovecToStringPiece(iov).substr(length1 - offset1));
// Peek with an offset inside the second write.
const QuicStreamOffset offset2 = 1500;
EXPECT_TRUE(buffer_->PeekRegion(offset2, &iov));
- EXPECT_EQ(QuicStringPiece(source2).substr(offset2 - length1),
+ EXPECT_EQ(quiche::QuicheStringPiece(source2).substr(offset2 - length1),
IovecToStringPiece(iov));
// Peeking at or after FirstMissingByte() returns false.
@@ -669,16 +671,19 @@ TEST_F(QuicStreamSequencerBufferTest, PeekBufferWithMultipleBlocks) {
EXPECT_TRUE(buffer_->PeekRegion(0, &iov));
EXPECT_EQ(kBlockSizeBytes, iov.iov_len);
EXPECT_EQ(source1, IovecToStringPiece(iov).substr(0, length1));
- EXPECT_EQ(QuicStringPiece(source2).substr(0, kBlockSizeBytes - length1),
- IovecToStringPiece(iov).substr(length1));
+ EXPECT_EQ(
+ quiche::QuicheStringPiece(source2).substr(0, kBlockSizeBytes - length1),
+ IovecToStringPiece(iov).substr(length1));
EXPECT_TRUE(buffer_->PeekRegion(length1, &iov));
- EXPECT_EQ(QuicStringPiece(source2).substr(0, kBlockSizeBytes - length1),
- IovecToStringPiece(iov));
+ EXPECT_EQ(
+ quiche::QuicheStringPiece(source2).substr(0, kBlockSizeBytes - length1),
+ IovecToStringPiece(iov));
EXPECT_TRUE(buffer_->PeekRegion(kBlockSizeBytes, &iov));
- EXPECT_EQ(QuicStringPiece(source2).substr(kBlockSizeBytes - length1),
- IovecToStringPiece(iov));
+ EXPECT_EQ(
+ quiche::QuicheStringPiece(source2).substr(kBlockSizeBytes - length1),
+ IovecToStringPiece(iov));
// Peeking at or after FirstMissingByte() returns false.
EXPECT_FALSE(buffer_->PeekRegion(length1 + length2, &iov));
@@ -701,10 +706,12 @@ TEST_F(QuicStreamSequencerBufferTest, PeekAfterConsumed) {
EXPECT_FALSE(buffer_->PeekRegion(512, &iov));
EXPECT_TRUE(buffer_->PeekRegion(1024, &iov));
- EXPECT_EQ(QuicStringPiece(source1).substr(1024), IovecToStringPiece(iov));
+ EXPECT_EQ(quiche::QuicheStringPiece(source1).substr(1024),
+ IovecToStringPiece(iov));
EXPECT_TRUE(buffer_->PeekRegion(1500, &iov));
- EXPECT_EQ(QuicStringPiece(source1).substr(1500), IovecToStringPiece(iov));
+ EXPECT_EQ(quiche::QuicheStringPiece(source1).substr(1500),
+ IovecToStringPiece(iov));
// Consume rest of block.
EXPECT_TRUE(buffer_->MarkConsumed(kBlockSizeBytes - 1024));
@@ -718,7 +725,8 @@ TEST_F(QuicStreamSequencerBufferTest, PeekAfterConsumed) {
EXPECT_EQ(source2, IovecToStringPiece(iov));
EXPECT_TRUE(buffer_->PeekRegion(kBlockSizeBytes + 128, &iov));
- EXPECT_EQ(QuicStringPiece(source2).substr(128), IovecToStringPiece(iov));
+ EXPECT_EQ(quiche::QuicheStringPiece(source2).substr(128),
+ IovecToStringPiece(iov));
// Peeking into consumed data still fails.
EXPECT_FALSE(buffer_->PeekRegion(0, &iov));
@@ -925,7 +933,7 @@ class QuicStreamSequencerBufferRandomIOTest
for (size_t i = 0; i < num_to_write; ++i) {
write_buf[i] = (offset + i) % 256;
}
- QuicStringPiece string_piece_w(write_buf.get(), num_to_write);
+ quiche::QuicheStringPiece string_piece_w(write_buf.get(), num_to_write);
auto result = buffer_->OnStreamData(offset, string_piece_w, &written_,
&error_details_);
if (result == QUIC_NO_ERROR) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_test.cc
index cb6fb936cf6..188eb86f6fe 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_test.cc
@@ -13,14 +13,14 @@
#include "net/third_party/quiche/src/quic/core/quic_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_stream_sequencer_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
using testing::_;
using testing::AnyNumber;
@@ -33,21 +33,13 @@ class MockStream : public QuicStreamSequencer::StreamInterface {
public:
MOCK_METHOD0(OnFinRead, void());
MOCK_METHOD0(OnDataAvailable, void());
- MOCK_METHOD2(CloseConnectionWithDetails,
+ MOCK_METHOD2(OnUnrecoverableError,
void(QuicErrorCode error, const std::string& details));
MOCK_METHOD1(Reset, void(QuicRstStreamErrorCode error));
MOCK_METHOD0(OnCanWrite, void());
MOCK_METHOD1(AddBytesConsumed, void(QuicByteCount bytes));
QuicStreamId id() const override { return 1; }
-
- const QuicSocketAddress& PeerAddressOfLatestPacket() const override {
- return peer_address_;
- }
-
- protected:
- QuicSocketAddress peer_address_ =
- QuicSocketAddress(QuicIpAddress::Any4(), 65535);
};
namespace {
@@ -59,11 +51,11 @@ class QuicStreamSequencerTest : public QuicTest {
public:
void ConsumeData(size_t num_bytes) {
char buffer[1024];
- ASSERT_GT(QUIC_ARRAYSIZE(buffer), num_bytes);
+ ASSERT_GT(QUICHE_ARRAYSIZE(buffer), num_bytes);
struct iovec iov;
iov.iov_base = buffer;
iov.iov_len = num_bytes;
- ASSERT_EQ(static_cast<int>(num_bytes), sequencer_->Readv(&iov, 1));
+ ASSERT_EQ(num_bytes, sequencer_->Readv(&iov, 1));
}
protected:
@@ -103,7 +95,7 @@ class QuicStreamSequencerTest : public QuicTest {
const std::vector<std::string>& expected) {
iovec iovecs[5];
size_t num_iovecs =
- sequencer.GetReadableRegions(iovecs, QUIC_ARRAYSIZE(iovecs));
+ sequencer.GetReadableRegions(iovecs, QUICHE_ARRAYSIZE(iovecs));
return VerifyReadableRegion(sequencer, expected) &&
VerifyIovecs(sequencer, iovecs, num_iovecs, expected);
}
@@ -123,7 +115,7 @@ class QuicStreamSequencerTest : public QuicTest {
return true;
}
- bool VerifyIovec(const iovec& iovec, QuicStringPiece expected) {
+ bool VerifyIovec(const iovec& iovec, quiche::QuicheStringPiece expected) {
if (iovec.iov_len != expected.length()) {
QUIC_LOG(ERROR) << "Invalid length: " << iovec.iov_len << " vs "
<< expected.length();
@@ -250,8 +242,7 @@ TEST_F(QuicStreamSequencerTest, BlockedThenFullFrameAndFinConsumed) {
}
TEST_F(QuicStreamSequencerTest, EmptyFrame) {
- EXPECT_CALL(stream_,
- CloseConnectionWithDetails(QUIC_EMPTY_STREAM_FRAME_NO_FIN, _));
+ EXPECT_CALL(stream_, OnUnrecoverableError(QUIC_EMPTY_STREAM_FRAME_NO_FIN, _));
OnFrame(0, "");
EXPECT_EQ(0u, NumBufferedBytes());
EXPECT_EQ(0u, sequencer_->NumBytesConsumed());
@@ -375,15 +366,10 @@ TEST_F(QuicStreamSequencerTest, MultipleOffsets) {
OnFinFrame(3, "");
EXPECT_EQ(3u, QuicStreamSequencerPeer::GetCloseOffset(sequencer_.get()));
- if (!GetQuicReloadableFlag(
- quic_close_connection_and_discard_data_on_wrong_offset)) {
- EXPECT_CALL(stream_, Reset(QUIC_MULTIPLE_TERMINATION_OFFSETS));
- } else {
- EXPECT_CALL(stream_, CloseConnectionWithDetails(
- QUIC_STREAM_SEQUENCER_INVALID_STATE,
- "Stream 1 received new final offset: 1, which is "
- "different from close offset: 3"));
- }
+ EXPECT_CALL(stream_, OnUnrecoverableError(
+ QUIC_STREAM_SEQUENCER_INVALID_STATE,
+ "Stream 1 received new final offset: 1, which is "
+ "different from close offset: 3"));
OnFinFrame(1, "");
}
@@ -393,7 +379,7 @@ class QuicSequencerRandomTest : public QuicStreamSequencerTest {
typedef std::vector<Frame> FrameList;
void CreateFrames() {
- int payload_size = QUIC_ARRAYSIZE(kPayload) - 1;
+ int payload_size = QUICHE_ARRAYSIZE(kPayload) - 1;
int remaining_payload = payload_size;
while (remaining_payload != 0) {
int size = std::min(OneToN(6), remaining_payload);
@@ -416,10 +402,10 @@ class QuicSequencerRandomTest : public QuicStreamSequencerTest {
void ReadAvailableData() {
// Read all available data
- char output[QUIC_ARRAYSIZE(kPayload) + 1];
+ char output[QUICHE_ARRAYSIZE(kPayload) + 1];
iovec iov;
iov.iov_base = output;
- iov.iov_len = QUIC_ARRAYSIZE(output);
+ iov.iov_len = QUICHE_ARRAYSIZE(output);
int bytes_read = sequencer_->Readv(&iov, 1);
EXPECT_NE(0, bytes_read);
output_.append(output, bytes_read);
@@ -455,9 +441,9 @@ TEST_F(QuicSequencerRandomTest, RandomFramesNoDroppingNoBackup) {
list_.erase(list_.begin() + index);
}
- ASSERT_EQ(QUIC_ARRAYSIZE(kPayload) - 1, output_.size());
+ ASSERT_EQ(QUICHE_ARRAYSIZE(kPayload) - 1, output_.size());
EXPECT_EQ(kPayload, output_);
- EXPECT_EQ(QUIC_ARRAYSIZE(kPayload) - 1, total_bytes_consumed);
+ EXPECT_EQ(QUICHE_ARRAYSIZE(kPayload) - 1, total_bytes_consumed);
}
TEST_F(QuicSequencerRandomTest, RandomFramesNoDroppingBackup) {
@@ -477,7 +463,7 @@ TEST_F(QuicSequencerRandomTest, RandomFramesNoDroppingBackup) {
total_bytes_consumed += bytes;
}));
- while (output_.size() != QUIC_ARRAYSIZE(kPayload) - 1) {
+ while (output_.size() != QUICHE_ARRAYSIZE(kPayload) - 1) {
if (!list_.empty() && OneToN(2) == 1) { // Send data
int index = OneToN(list_.size()) - 1;
OnFrame(list_[index].first, list_[index].second.data());
@@ -493,7 +479,7 @@ TEST_F(QuicSequencerRandomTest, RandomFramesNoDroppingBackup) {
ASSERT_EQ(0, iovs_peeked);
ASSERT_FALSE(sequencer_->GetReadableRegion(peek_iov));
}
- int total_bytes_to_peek = QUIC_ARRAYSIZE(buffer);
+ int total_bytes_to_peek = QUICHE_ARRAYSIZE(buffer);
for (int i = 0; i < iovs_peeked; ++i) {
int bytes_to_peek =
std::min<int>(peek_iov[i].iov_len, total_bytes_to_peek);
@@ -510,7 +496,7 @@ TEST_F(QuicSequencerRandomTest, RandomFramesNoDroppingBackup) {
}
EXPECT_EQ(std::string(kPayload), output_);
EXPECT_EQ(std::string(kPayload), peeked_);
- EXPECT_EQ(QUIC_ARRAYSIZE(kPayload) - 1, total_bytes_consumed);
+ EXPECT_EQ(QUICHE_ARRAYSIZE(kPayload) - 1, total_bytes_consumed);
}
// Same as above, just using a different method for reading.
@@ -613,12 +599,11 @@ TEST_F(QuicStreamSequencerTest, OverlappingFramesReceived) {
// overlapping byte ranges - if they do, we close the connection.
QuicStreamId id = 1;
- QuicStreamFrame frame1(id, false, 1, QuicStringPiece("hello"));
+ QuicStreamFrame frame1(id, false, 1, quiche::QuicheStringPiece("hello"));
sequencer_->OnStreamFrame(frame1);
- QuicStreamFrame frame2(id, false, 2, QuicStringPiece("hello"));
- EXPECT_CALL(stream_,
- CloseConnectionWithDetails(QUIC_OVERLAPPING_STREAM_DATA, _))
+ QuicStreamFrame frame2(id, false, 2, quiche::QuicheStringPiece("hello"));
+ EXPECT_CALL(stream_, OnUnrecoverableError(QUIC_OVERLAPPING_STREAM_DATA, _))
.Times(0);
sequencer_->OnStreamFrame(frame2);
}
@@ -649,7 +634,7 @@ TEST_F(QuicStreamSequencerTest, DataAvailableOnOverlappingFrames) {
EXPECT_EQ(0u, sequencer_->NumBytesBuffered());
// Received [1498, 1503).
- QuicStreamFrame frame3(id, false, 1498, QuicStringPiece("hello"));
+ QuicStreamFrame frame3(id, false, 1498, quiche::QuicheStringPiece("hello"));
EXPECT_CALL(stream_, OnDataAvailable());
sequencer_->OnStreamFrame(frame3);
EXPECT_CALL(stream_, AddBytesConsumed(3));
@@ -658,7 +643,7 @@ TEST_F(QuicStreamSequencerTest, DataAvailableOnOverlappingFrames) {
EXPECT_EQ(0u, sequencer_->NumBytesBuffered());
// Received [1000, 1005).
- QuicStreamFrame frame4(id, false, 1000, QuicStringPiece("hello"));
+ QuicStreamFrame frame4(id, false, 1000, quiche::QuicheStringPiece("hello"));
EXPECT_CALL(stream_, OnDataAvailable()).Times(0);
sequencer_->OnStreamFrame(frame4);
EXPECT_EQ(1503u, sequencer_->NumBytesConsumed());
@@ -741,15 +726,10 @@ TEST_F(QuicStreamSequencerTest, StopReading) {
}
TEST_F(QuicStreamSequencerTest, StopReadingWithLevelTriggered) {
- if (GetQuicReloadableFlag(quic_stop_reading_when_level_triggered)) {
- EXPECT_CALL(stream_, AddBytesConsumed(0));
- EXPECT_CALL(stream_, AddBytesConsumed(3)).Times(3);
- EXPECT_CALL(stream_, OnDataAvailable()).Times(0);
- EXPECT_CALL(stream_, OnFinRead());
- } else {
- EXPECT_CALL(stream_, AddBytesConsumed(0));
- EXPECT_CALL(stream_, OnDataAvailable()).Times(3);
- }
+ EXPECT_CALL(stream_, AddBytesConsumed(0));
+ EXPECT_CALL(stream_, AddBytesConsumed(3)).Times(3);
+ EXPECT_CALL(stream_, OnDataAvailable()).Times(0);
+ EXPECT_CALL(stream_, OnFinRead());
sequencer_->set_level_triggered(true);
sequencer_->StopReading();
@@ -761,11 +741,7 @@ TEST_F(QuicStreamSequencerTest, StopReadingWithLevelTriggered) {
// Regression test for https://crbug.com/992486.
TEST_F(QuicStreamSequencerTest, CorruptFinFrames) {
- if (!GetQuicReloadableFlag(
- quic_close_connection_and_discard_data_on_wrong_offset)) {
- return;
- }
- EXPECT_CALL(stream_, CloseConnectionWithDetails(
+ EXPECT_CALL(stream_, OnUnrecoverableError(
QUIC_STREAM_SEQUENCER_INVALID_STATE,
"Stream 1 received new final offset: 1, which is "
"different from close offset: 2"));
@@ -777,12 +753,8 @@ TEST_F(QuicStreamSequencerTest, CorruptFinFrames) {
// Regression test for crbug.com/1015693
TEST_F(QuicStreamSequencerTest, ReceiveFinLessThanHighestOffset) {
- if (!GetQuicReloadableFlag(
- quic_close_connection_and_discard_data_on_wrong_offset)) {
- return;
- }
EXPECT_CALL(stream_, OnDataAvailable()).Times(1);
- EXPECT_CALL(stream_, CloseConnectionWithDetails(
+ EXPECT_CALL(stream_, OnUnrecoverableError(
QUIC_STREAM_SEQUENCER_INVALID_STATE,
"Stream 1 received fin with offset: 0, which "
"reduces current highest offset: 3"));
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_stream_test.cc
index 673c7a7405c..eea7b15113e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_test.cc
@@ -16,7 +16,6 @@
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
@@ -31,6 +30,9 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_stream_sequencer_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_optional.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
using testing::_;
using testing::AnyNumber;
@@ -98,8 +100,7 @@ class QuicStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
session_->config(), kMinimumFlowControlSendWindow);
QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesOutgoingBidirectional(
session_->config(), kMinimumFlowControlSendWindow);
- QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams(
- session_->config(), 10);
+ QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(session_->config(), 10);
session_->OnConfigNegotiated();
stream_ = new StrictMock<TestStream>(kTestStreamId, session_.get(),
@@ -122,11 +123,13 @@ class QuicStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
write_blocked_list_->HasWriteBlockedDataStreams();
}
- QuicConsumedData CloseStreamOnWriteError(QuicStream* /*stream*/,
- QuicStreamId id,
- size_t /*write_length*/,
- QuicStreamOffset /*offset*/,
- StreamSendingState /*state*/) {
+ QuicConsumedData CloseStreamOnWriteError(
+ QuicStreamId id,
+ size_t /*write_length*/,
+ QuicStreamOffset /*offset*/,
+ StreamSendingState /*state*/,
+ TransmissionType /*type*/,
+ quiche::QuicheOptional<EncryptionLevel> /*level*/) {
session_->CloseStream(id);
return QuicConsumedData(1, false);
}
@@ -277,8 +280,8 @@ TEST_P(QuicStreamTest, WriteAllData) {
VARIABLE_LENGTH_INTEGER_LENGTH_0, 0u);
connection_->SetMaxPacketLength(length);
- EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _))
- .WillOnce(Invoke(&(MockQuicSession::ConsumeData)));
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
+ .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
stream_->WriteOrBufferData(kData1, false, nullptr);
EXPECT_FALSE(HasWriteBlockedStreams());
}
@@ -288,8 +291,9 @@ TEST_P(QuicStreamTest, NoBlockingIfNoDataOrFin) {
// Write no data and no fin. If we consume nothing we should not be write
// blocked.
- EXPECT_QUIC_BUG(stream_->WriteOrBufferData(QuicStringPiece(), false, nullptr),
- "");
+ EXPECT_QUIC_BUG(
+ stream_->WriteOrBufferData(quiche::QuicheStringPiece(), false, nullptr),
+ "");
EXPECT_FALSE(HasWriteBlockedStreams());
}
@@ -298,12 +302,13 @@ TEST_P(QuicStreamTest, BlockIfOnlySomeDataConsumed) {
// Write some data and no fin. If we consume some but not all of the data,
// we should be write blocked a not all the data was consumed.
- EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
.WillOnce(InvokeWithoutArgs([this]() {
- return MockQuicSession::ConsumeData(stream_, stream_->id(), 1u, 0u,
- NO_FIN);
+ return session_->ConsumeData(stream_->id(), 1u, 0u, NO_FIN,
+ NOT_RETRANSMISSION, QuicheNullOpt);
}));
- stream_->WriteOrBufferData(QuicStringPiece(kData1, 2), false, nullptr);
+ stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 2), false,
+ nullptr);
EXPECT_TRUE(session_->HasUnackedStreamData());
ASSERT_EQ(1u, write_blocked_list_->NumBlockedStreams());
EXPECT_EQ(1u, stream_->BufferedDataBytes());
@@ -316,12 +321,13 @@ TEST_P(QuicStreamTest, BlockIfFinNotConsumedWithData) {
// we should be write blocked because the fin was not consumed.
// (This should never actually happen as the fin should be sent out with the
// last data)
- EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
.WillOnce(InvokeWithoutArgs([this]() {
- return MockQuicSession::ConsumeData(stream_, stream_->id(), 2u, 0u,
- NO_FIN);
+ return session_->ConsumeData(stream_->id(), 2u, 0u, NO_FIN,
+ NOT_RETRANSMISSION, QuicheNullOpt);
}));
- stream_->WriteOrBufferData(QuicStringPiece(kData1, 2), true, nullptr);
+ stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 2), true,
+ nullptr);
EXPECT_TRUE(session_->HasUnackedStreamData());
ASSERT_EQ(1u, write_blocked_list_->NumBlockedStreams());
}
@@ -331,9 +337,9 @@ TEST_P(QuicStreamTest, BlockIfSoloFinNotConsumed) {
// Write no data and a fin. If we consume nothing we should be write blocked,
// as the fin was not consumed.
- EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
.WillOnce(Return(QuicConsumedData(0, false)));
- stream_->WriteOrBufferData(QuicStringPiece(), true, nullptr);
+ stream_->WriteOrBufferData(quiche::QuicheStringPiece(), true, nullptr);
ASSERT_EQ(1u, write_blocked_list_->NumBlockedStreams());
}
@@ -343,9 +349,10 @@ TEST_P(QuicStreamTest, CloseOnPartialWrite) {
// Write some data and no fin. However, while writing the data
// close the stream and verify that MarkConnectionLevelWriteBlocked does not
// crash with an unknown stream.
- EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
.WillOnce(Invoke(this, &QuicStreamTest::CloseStreamOnWriteError));
- stream_->WriteOrBufferData(QuicStringPiece(kData1, 2), false, nullptr);
+ stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 2), false,
+ nullptr);
ASSERT_EQ(0u, write_blocked_list_->NumBlockedStreams());
}
@@ -362,10 +369,10 @@ TEST_P(QuicStreamTest, WriteOrBufferData) {
VARIABLE_LENGTH_INTEGER_LENGTH_0, 0u);
connection_->SetMaxPacketLength(length);
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
.WillOnce(InvokeWithoutArgs([this]() {
- return MockQuicSession::ConsumeData(stream_, stream_->id(),
- kDataLen - 1, 0u, NO_FIN);
+ return session_->ConsumeData(stream_->id(), kDataLen - 1, 0u, NO_FIN,
+ NOT_RETRANSMISSION, QuicheNullOpt);
}));
stream_->WriteOrBufferData(kData1, false, nullptr);
@@ -378,20 +385,20 @@ TEST_P(QuicStreamTest, WriteOrBufferData) {
EXPECT_EQ(10u, stream_->BufferedDataBytes());
// Make sure we get the tail of the first write followed by the bytes_consumed
InSequence s;
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
.WillOnce(InvokeWithoutArgs([this]() {
- return MockQuicSession::ConsumeData(stream_, stream_->id(),
- kDataLen - 1, kDataLen - 1, NO_FIN);
+ return session_->ConsumeData(stream_->id(), kDataLen - 1, kDataLen - 1,
+ NO_FIN, NOT_RETRANSMISSION, QuicheNullOpt);
}));
EXPECT_CALL(*stream_, OnCanWriteNewData());
stream_->OnCanWrite();
EXPECT_TRUE(session_->HasUnackedStreamData());
// And finally the end of the bytes_consumed.
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
.WillOnce(InvokeWithoutArgs([this]() {
- return MockQuicSession::ConsumeData(stream_, stream_->id(), 2u,
- 2 * kDataLen - 2, NO_FIN);
+ return session_->ConsumeData(stream_->id(), 2u, 2 * kDataLen - 2,
+ NO_FIN, NOT_RETRANSMISSION, QuicheNullOpt);
}));
EXPECT_CALL(*stream_, OnCanWriteNewData());
stream_->OnCanWrite();
@@ -403,8 +410,8 @@ TEST_P(QuicStreamTest, WriteOrBufferDataReachStreamLimit) {
std::string data("aaaaa");
QuicStreamPeer::SetStreamBytesWritten(kMaxStreamLength - data.length(),
stream_);
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .WillOnce(Invoke(&(MockQuicSession::ConsumeData)));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
stream_->WriteOrBufferData(data, false, nullptr);
EXPECT_TRUE(session_->HasUnackedStreamData());
EXPECT_CALL(*connection_, CloseConnection(QUIC_STREAM_LENGTH_OVERFLOW, _, _));
@@ -435,12 +442,13 @@ TEST_P(QuicStreamTest, RstAlwaysSentIfNoFinSent) {
EXPECT_FALSE(rst_sent());
// Write some data, with no FIN.
- EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
.WillOnce(InvokeWithoutArgs([this]() {
- return MockQuicSession::ConsumeData(stream_, stream_->id(), 1u, 0u,
- NO_FIN);
+ return session_->ConsumeData(stream_->id(), 1u, 0u, NO_FIN,
+ NOT_RETRANSMISSION, QuicheNullOpt);
}));
- stream_->WriteOrBufferData(QuicStringPiece(kData1, 1), false, nullptr);
+ stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 1), false,
+ nullptr);
EXPECT_TRUE(session_->HasUnackedStreamData());
EXPECT_FALSE(fin_sent());
EXPECT_FALSE(rst_sent());
@@ -463,12 +471,13 @@ TEST_P(QuicStreamTest, RstNotSentIfFinSent) {
EXPECT_FALSE(rst_sent());
// Write some data, with FIN.
- EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
.WillOnce(InvokeWithoutArgs([this]() {
- return MockQuicSession::ConsumeData(stream_, stream_->id(), 1u, 0u,
- FIN);
+ return session_->ConsumeData(stream_->id(), 1u, 0u, FIN,
+ NOT_RETRANSMISSION, QuicheNullOpt);
}));
- stream_->WriteOrBufferData(QuicStringPiece(kData1, 1), true, nullptr);
+ stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 1), true,
+ nullptr);
EXPECT_TRUE(fin_sent());
EXPECT_FALSE(rst_sent());
@@ -574,7 +583,6 @@ TEST_P(QuicStreamTest, StreamSequencerNeverSeesPacketsViolatingFlowControl) {
// Verify that after the consumer calls StopReading(), the stream still sends
// flow control updates.
TEST_P(QuicStreamTest, StopReadingSendsFlowControl) {
- SetQuicReloadableFlag(quic_stop_reading_when_level_triggered, true);
Initialize();
stream_->StopReading();
@@ -659,7 +667,7 @@ TEST_P(QuicStreamTest, FinalByteOffsetFromZeroLengthStreamFrame) {
current_connection_flow_control_offset);
QuicStreamFrame zero_length_stream_frame_with_fin(
stream_->id(), /*fin=*/true, kByteOffsetExceedingFlowControlWindow,
- QuicStringPiece());
+ quiche::QuicheStringPiece());
EXPECT_EQ(0, zero_length_stream_frame_with_fin.data_length);
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
@@ -708,9 +716,10 @@ TEST_P(QuicStreamTest, StreamTooLong) {
EXPECT_CALL(*connection_, CloseConnection(QUIC_STREAM_LENGTH_OVERFLOW, _, _))
.Times(1);
QuicStreamFrame stream_frame(stream_->id(), false, kMaxStreamLength, ".");
- EXPECT_QUIC_PEER_BUG(stream_->OnStreamFrame(stream_frame),
- QuicStrCat("Receive stream frame on stream ",
- stream_->id(), " reaches max stream length"));
+ EXPECT_QUIC_PEER_BUG(
+ stream_->OnStreamFrame(stream_frame),
+ quiche::QuicheStrCat("Receive stream frame on stream ", stream_->id(),
+ " reaches max stream length"));
}
TEST_P(QuicStreamTest, SetDrainingIncomingOutgoing) {
@@ -728,12 +737,13 @@ TEST_P(QuicStreamTest, SetDrainingIncomingOutgoing) {
EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams());
// Outgoing data with FIN.
- EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
.WillOnce(InvokeWithoutArgs([this]() {
- return MockQuicSession::ConsumeData(stream_, stream_->id(), 2u, 0u,
- FIN);
+ return session_->ConsumeData(stream_->id(), 2u, 0u, FIN,
+ NOT_RETRANSMISSION, QuicheNullOpt);
}));
- stream_->WriteOrBufferData(QuicStringPiece(kData1, 2), true, nullptr);
+ stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 2), true,
+ nullptr);
EXPECT_TRUE(stream_->write_side_closed());
EXPECT_EQ(1u, QuicSessionPeer::GetDrainingStreams(session_.get())
@@ -746,12 +756,13 @@ TEST_P(QuicStreamTest, SetDrainingOutgoingIncoming) {
Initialize();
// Outgoing data with FIN.
- EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _))
+ EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
.WillOnce(InvokeWithoutArgs([this]() {
- return MockQuicSession::ConsumeData(stream_, stream_->id(), 2u, 0u,
- FIN);
+ return session_->ConsumeData(stream_->id(), 2u, 0u, FIN,
+ NOT_RETRANSMISSION, QuicheNullOpt);
}));
- stream_->WriteOrBufferData(QuicStringPiece(kData1, 2), true, nullptr);
+ stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 2), true,
+ nullptr);
EXPECT_TRUE(stream_->write_side_closed());
EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams());
@@ -775,8 +786,8 @@ TEST_P(QuicStreamTest, EarlyResponseFinHandling) {
Initialize();
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData));
// Receive data for the request.
EXPECT_CALL(*stream_, OnDataAvailable()).Times(1);
@@ -797,8 +808,8 @@ TEST_P(QuicStreamTest, EarlyResponseFinHandling) {
TEST_P(QuicStreamTest, StreamWaitsForAcks) {
Initialize();
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData));
// Stream is not waiting for acks initially.
EXPECT_FALSE(stream_->IsWaitingForAcks());
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
@@ -811,6 +822,7 @@ TEST_P(QuicStreamTest, StreamWaitsForAcks) {
EXPECT_TRUE(stream_->IsWaitingForAcks());
QuicByteCount newly_acked_length = 0;
EXPECT_TRUE(stream_->OnStreamFrameAcked(0, 9, false, QuicTime::Delta::Zero(),
+ QuicTime::Zero(),
&newly_acked_length));
EXPECT_EQ(9u, newly_acked_length);
// Stream is not waiting for acks as all sent data is acked.
@@ -833,6 +845,7 @@ TEST_P(QuicStreamTest, StreamWaitsForAcks) {
// kData2 is acked.
EXPECT_TRUE(stream_->OnStreamFrameAcked(9, 9, false, QuicTime::Delta::Zero(),
+ QuicTime::Zero(),
&newly_acked_length));
EXPECT_EQ(9u, newly_acked_length);
// Stream is waiting for acks as FIN is not acked.
@@ -842,6 +855,7 @@ TEST_P(QuicStreamTest, StreamWaitsForAcks) {
// FIN is acked.
EXPECT_TRUE(stream_->OnStreamFrameAcked(18, 0, true, QuicTime::Delta::Zero(),
+ QuicTime::Zero(),
&newly_acked_length));
EXPECT_EQ(0u, newly_acked_length);
EXPECT_FALSE(stream_->IsWaitingForAcks());
@@ -851,8 +865,8 @@ TEST_P(QuicStreamTest, StreamWaitsForAcks) {
TEST_P(QuicStreamTest, StreamDataGetAckedOutOfOrder) {
Initialize();
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData));
// Send data.
stream_->WriteOrBufferData(kData1, false, nullptr);
stream_->WriteOrBufferData(kData1, false, nullptr);
@@ -863,16 +877,19 @@ TEST_P(QuicStreamTest, StreamDataGetAckedOutOfOrder) {
EXPECT_TRUE(session_->HasUnackedStreamData());
QuicByteCount newly_acked_length = 0;
EXPECT_TRUE(stream_->OnStreamFrameAcked(9, 9, false, QuicTime::Delta::Zero(),
+ QuicTime::Zero(),
&newly_acked_length));
EXPECT_TRUE(session_->HasUnackedStreamData());
EXPECT_EQ(9u, newly_acked_length);
EXPECT_EQ(3u, QuicStreamPeer::SendBuffer(stream_).size());
EXPECT_TRUE(stream_->OnStreamFrameAcked(18, 9, false, QuicTime::Delta::Zero(),
+ QuicTime::Zero(),
&newly_acked_length));
EXPECT_TRUE(session_->HasUnackedStreamData());
EXPECT_EQ(9u, newly_acked_length);
EXPECT_EQ(3u, QuicStreamPeer::SendBuffer(stream_).size());
EXPECT_TRUE(stream_->OnStreamFrameAcked(0, 9, false, QuicTime::Delta::Zero(),
+ QuicTime::Zero(),
&newly_acked_length));
EXPECT_TRUE(session_->HasUnackedStreamData());
EXPECT_EQ(9u, newly_acked_length);
@@ -881,6 +898,7 @@ TEST_P(QuicStreamTest, StreamDataGetAckedOutOfOrder) {
EXPECT_TRUE(stream_->IsWaitingForAcks());
EXPECT_TRUE(session_->HasUnackedStreamData());
EXPECT_TRUE(stream_->OnStreamFrameAcked(27, 0, true, QuicTime::Delta::Zero(),
+ QuicTime::Zero(),
&newly_acked_length));
EXPECT_EQ(0u, newly_acked_length);
EXPECT_FALSE(stream_->IsWaitingForAcks());
@@ -889,8 +907,8 @@ TEST_P(QuicStreamTest, StreamDataGetAckedOutOfOrder) {
TEST_P(QuicStreamTest, CancelStream) {
Initialize();
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData));
EXPECT_FALSE(stream_->IsWaitingForAcks());
EXPECT_FALSE(session_->HasUnackedStreamData());
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
@@ -931,8 +949,8 @@ TEST_P(QuicStreamTest, RstFrameReceivedStreamNotFinishSending) {
}
Initialize();
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData));
EXPECT_FALSE(stream_->IsWaitingForAcks());
EXPECT_FALSE(session_->HasUnackedStreamData());
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
@@ -957,8 +975,8 @@ TEST_P(QuicStreamTest, RstFrameReceivedStreamNotFinishSending) {
TEST_P(QuicStreamTest, RstFrameReceivedStreamFinishSending) {
Initialize();
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData));
EXPECT_FALSE(stream_->IsWaitingForAcks());
EXPECT_FALSE(session_->HasUnackedStreamData());
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
@@ -980,8 +998,8 @@ TEST_P(QuicStreamTest, RstFrameReceivedStreamFinishSending) {
TEST_P(QuicStreamTest, ConnectionClosed) {
Initialize();
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData));
EXPECT_FALSE(stream_->IsWaitingForAcks());
EXPECT_FALSE(session_->HasUnackedStreamData());
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
@@ -1015,10 +1033,10 @@ TEST_P(QuicStreamTest, WriteBufferedData) {
EXPECT_TRUE(stream_->CanWriteNewData());
// Testing WriteOrBufferData.
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
.WillOnce(InvokeWithoutArgs([this]() {
- return MockQuicSession::ConsumeData(stream_, stream_->id(), 100u, 0u,
- NO_FIN);
+ return session_->ConsumeData(stream_->id(), 100u, 0u, NO_FIN,
+ NOT_RETRANSMISSION, QuicheNullOpt);
}));
stream_->WriteOrBufferData(data, false, nullptr);
stream_->WriteOrBufferData(data, false, nullptr);
@@ -1028,10 +1046,10 @@ TEST_P(QuicStreamTest, WriteBufferedData) {
// Verify all data is saved.
EXPECT_EQ(3 * data.length() - 100, stream_->BufferedDataBytes());
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
.WillOnce(InvokeWithoutArgs([this]() {
- return MockQuicSession::ConsumeData(stream_, stream_->id(), 100, 100u,
- NO_FIN);
+ return session_->ConsumeData(stream_->id(), 100, 100u, NO_FIN,
+ NOT_RETRANSMISSION, QuicheNullOpt);
}));
// Buffered data size > threshold, do not ask upper layer for more data.
EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(0);
@@ -1042,10 +1060,10 @@ TEST_P(QuicStreamTest, WriteBufferedData) {
// Send buffered data to make buffered data size < threshold.
size_t data_to_write = 3 * data.length() - 200 -
GetQuicFlag(FLAGS_quic_buffered_data_threshold) + 1;
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
.WillOnce(InvokeWithoutArgs([this, data_to_write]() {
- return MockQuicSession::ConsumeData(stream_, stream_->id(),
- data_to_write, 200u, NO_FIN);
+ return session_->ConsumeData(stream_->id(), data_to_write, 200u, NO_FIN,
+ NOT_RETRANSMISSION, QuicheNullOpt);
}));
// Buffered data size < threshold, ask upper layer for more data.
EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1);
@@ -1056,8 +1074,8 @@ TEST_P(QuicStreamTest, WriteBufferedData) {
EXPECT_TRUE(stream_->CanWriteNewData());
// Flush all buffered data.
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .WillOnce(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1);
stream_->OnCanWrite();
EXPECT_EQ(0u, stream_->BufferedDataBytes());
@@ -1065,7 +1083,7 @@ TEST_P(QuicStreamTest, WriteBufferedData) {
EXPECT_TRUE(stream_->CanWriteNewData());
// Testing Writev.
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
.WillOnce(Return(QuicConsumedData(0, false)));
struct iovec iov = {const_cast<char*>(data.data()), data.length()};
QuicMemSliceStorage storage(
@@ -1080,7 +1098,7 @@ TEST_P(QuicStreamTest, WriteBufferedData) {
EXPECT_EQ(data.length(), stream_->BufferedDataBytes());
EXPECT_FALSE(stream_->CanWriteNewData());
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(0);
QuicMemSliceStorage storage2(
&iov, 1, session_->connection()->helper()->GetStreamSendBufferAllocator(),
1024);
@@ -1092,10 +1110,10 @@ TEST_P(QuicStreamTest, WriteBufferedData) {
data_to_write =
data.length() - GetQuicFlag(FLAGS_quic_buffered_data_threshold) + 1;
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
.WillOnce(InvokeWithoutArgs([this, data_to_write]() {
- return MockQuicSession::ConsumeData(stream_, stream_->id(),
- data_to_write, 0u, NO_FIN);
+ return session_->ConsumeData(stream_->id(), data_to_write, 0u, NO_FIN,
+ NOT_RETRANSMISSION, QuicheNullOpt);
}));
EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1);
@@ -1105,7 +1123,7 @@ TEST_P(QuicStreamTest, WriteBufferedData) {
stream_->BufferedDataBytes());
EXPECT_TRUE(stream_->CanWriteNewData());
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(0);
// All data can be consumed as buffered data is below upper limit.
QuicMemSliceStorage storage3(
&iov, 1, session_->connection()->helper()->GetStreamSendBufferAllocator(),
@@ -1123,8 +1141,8 @@ TEST_P(QuicStreamTest, WritevDataReachStreamLimit) {
std::string data("aaaaa");
QuicStreamPeer::SetStreamBytesWritten(kMaxStreamLength - data.length(),
stream_);
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .WillOnce(Invoke(&(MockQuicSession::ConsumeData)));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
struct iovec iov = {const_cast<char*>(data.data()), 5u};
QuicMemSliceStorage storage(
&iov, 1, session_->connection()->helper()->GetStreamSendBufferAllocator(),
@@ -1147,39 +1165,39 @@ TEST_P(QuicStreamTest, WriteMemSlices) {
Initialize();
char data[1024];
std::vector<std::pair<char*, size_t>> buffers;
- buffers.push_back(std::make_pair(data, QUIC_ARRAYSIZE(data)));
- buffers.push_back(std::make_pair(data, QUIC_ARRAYSIZE(data)));
+ buffers.push_back(std::make_pair(data, QUICHE_ARRAYSIZE(data)));
+ buffers.push_back(std::make_pair(data, QUICHE_ARRAYSIZE(data)));
QuicTestMemSliceVector vector1(buffers);
QuicTestMemSliceVector vector2(buffers);
QuicMemSliceSpan span1 = vector1.span();
QuicMemSliceSpan span2 = vector2.span();
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
.WillOnce(InvokeWithoutArgs([this]() {
- return MockQuicSession::ConsumeData(stream_, stream_->id(), 100u, 0u,
- NO_FIN);
+ return session_->ConsumeData(stream_->id(), 100u, 0u, NO_FIN,
+ NOT_RETRANSMISSION, QuicheNullOpt);
}));
// There is no buffered data before, all data should be consumed.
QuicConsumedData consumed = stream_->WriteMemSlices(span1, false);
EXPECT_EQ(2048u, consumed.bytes_consumed);
EXPECT_FALSE(consumed.fin_consumed);
- EXPECT_EQ(2 * QUIC_ARRAYSIZE(data) - 100, stream_->BufferedDataBytes());
+ EXPECT_EQ(2 * QUICHE_ARRAYSIZE(data) - 100, stream_->BufferedDataBytes());
EXPECT_FALSE(stream_->fin_buffered());
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(0);
// No Data can be consumed as buffered data is beyond upper limit.
consumed = stream_->WriteMemSlices(span2, true);
EXPECT_EQ(0u, consumed.bytes_consumed);
EXPECT_FALSE(consumed.fin_consumed);
- EXPECT_EQ(2 * QUIC_ARRAYSIZE(data) - 100, stream_->BufferedDataBytes());
+ EXPECT_EQ(2 * QUICHE_ARRAYSIZE(data) - 100, stream_->BufferedDataBytes());
EXPECT_FALSE(stream_->fin_buffered());
- size_t data_to_write = 2 * QUIC_ARRAYSIZE(data) - 100 -
+ size_t data_to_write = 2 * QUICHE_ARRAYSIZE(data) - 100 -
GetQuicFlag(FLAGS_quic_buffered_data_threshold) + 1;
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
.WillOnce(InvokeWithoutArgs([this, data_to_write]() {
- return MockQuicSession::ConsumeData(stream_, stream_->id(),
- data_to_write, 100u, NO_FIN);
+ return session_->ConsumeData(stream_->id(), data_to_write, 100u, NO_FIN,
+ NOT_RETRANSMISSION, QuicheNullOpt);
}));
EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1);
stream_->OnCanWrite();
@@ -1187,18 +1205,18 @@ TEST_P(QuicStreamTest, WriteMemSlices) {
GetQuicFlag(FLAGS_quic_buffered_data_threshold) - 1),
stream_->BufferedDataBytes());
// Try to write slices2 again.
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(0);
consumed = stream_->WriteMemSlices(span2, true);
EXPECT_EQ(2048u, consumed.bytes_consumed);
EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_EQ(2 * QUIC_ARRAYSIZE(data) +
+ EXPECT_EQ(2 * QUICHE_ARRAYSIZE(data) +
GetQuicFlag(FLAGS_quic_buffered_data_threshold) - 1,
stream_->BufferedDataBytes());
EXPECT_TRUE(stream_->fin_buffered());
// Flush all buffered data.
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .WillOnce(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
stream_->OnCanWrite();
EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(0);
EXPECT_FALSE(stream_->HasBufferedData());
@@ -1210,13 +1228,13 @@ TEST_P(QuicStreamTest, WriteMemSlicesReachStreamLimit) {
QuicStreamPeer::SetStreamBytesWritten(kMaxStreamLength - 5u, stream_);
char data[5];
std::vector<std::pair<char*, size_t>> buffers;
- buffers.push_back(std::make_pair(data, QUIC_ARRAYSIZE(data)));
+ buffers.push_back(std::make_pair(data, QUICHE_ARRAYSIZE(data)));
QuicTestMemSliceVector vector1(buffers);
QuicMemSliceSpan span1 = vector1.span();
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
.WillOnce(InvokeWithoutArgs([this]() {
- return MockQuicSession::ConsumeData(stream_, stream_->id(), 5u, 0u,
- NO_FIN);
+ return session_->ConsumeData(stream_->id(), 5u, 0u, NO_FIN,
+ NOT_RETRANSMISSION, QuicheNullOpt);
}));
// There is no buffered data before, all data should be consumed.
QuicConsumedData consumed = stream_->WriteMemSlices(span1, false);
@@ -1233,8 +1251,8 @@ TEST_P(QuicStreamTest, WriteMemSlicesReachStreamLimit) {
TEST_P(QuicStreamTest, StreamDataGetAckedMultipleTimes) {
Initialize();
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData));
EXPECT_FALSE(stream_->IsWaitingForAcks());
EXPECT_FALSE(session_->HasUnackedStreamData());
@@ -1249,16 +1267,19 @@ TEST_P(QuicStreamTest, StreamDataGetAckedMultipleTimes) {
// Verify [0, 9) 9 bytes are acked.
QuicByteCount newly_acked_length = 0;
EXPECT_TRUE(stream_->OnStreamFrameAcked(0, 9, false, QuicTime::Delta::Zero(),
+ QuicTime::Zero(),
&newly_acked_length));
EXPECT_EQ(9u, newly_acked_length);
EXPECT_EQ(2u, QuicStreamPeer::SendBuffer(stream_).size());
// Verify [9, 22) 13 bytes are acked.
EXPECT_TRUE(stream_->OnStreamFrameAcked(5, 17, false, QuicTime::Delta::Zero(),
+ QuicTime::Zero(),
&newly_acked_length));
EXPECT_EQ(13u, newly_acked_length);
EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
// Verify [22, 26) 4 bytes are acked.
EXPECT_TRUE(stream_->OnStreamFrameAcked(18, 8, false, QuicTime::Delta::Zero(),
+ QuicTime::Zero(),
&newly_acked_length));
EXPECT_EQ(4u, newly_acked_length);
EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
@@ -1267,6 +1288,7 @@ TEST_P(QuicStreamTest, StreamDataGetAckedMultipleTimes) {
// Ack [0, 27). Verify [26, 27) 1 byte is acked.
EXPECT_TRUE(stream_->OnStreamFrameAcked(26, 1, false, QuicTime::Delta::Zero(),
+ QuicTime::Zero(),
&newly_acked_length));
EXPECT_EQ(1u, newly_acked_length);
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
@@ -1275,6 +1297,7 @@ TEST_P(QuicStreamTest, StreamDataGetAckedMultipleTimes) {
// Ack Fin.
EXPECT_TRUE(stream_->OnStreamFrameAcked(27, 0, true, QuicTime::Delta::Zero(),
+ QuicTime::Zero(),
&newly_acked_length));
EXPECT_EQ(0u, newly_acked_length);
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
@@ -1282,8 +1305,9 @@ TEST_P(QuicStreamTest, StreamDataGetAckedMultipleTimes) {
EXPECT_FALSE(session_->HasUnackedStreamData());
// Ack [10, 27) and fin. No new data is acked.
- EXPECT_FALSE(stream_->OnStreamFrameAcked(
- 10, 17, true, QuicTime::Delta::Zero(), &newly_acked_length));
+ EXPECT_FALSE(
+ stream_->OnStreamFrameAcked(10, 17, true, QuicTime::Delta::Zero(),
+ QuicTime::Zero(), &newly_acked_length));
EXPECT_EQ(0u, newly_acked_length);
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
EXPECT_FALSE(stream_->IsWaitingForAcks());
@@ -1294,14 +1318,14 @@ TEST_P(QuicStreamTest, OnStreamFrameLost) {
Initialize();
// Send [0, 9).
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .WillOnce(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
stream_->WriteOrBufferData(kData1, false, nullptr);
EXPECT_FALSE(stream_->HasBufferedData());
EXPECT_TRUE(stream_->IsStreamFrameOutstanding(0, 9, false));
// Try to send [9, 27), but connection is blocked.
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
.WillOnce(Return(QuicConsumedData(0, false)));
stream_->WriteOrBufferData(kData2, false, nullptr);
stream_->WriteOrBufferData(kData2, false, nullptr);
@@ -1312,22 +1336,22 @@ TEST_P(QuicStreamTest, OnStreamFrameLost) {
// transmitted.
stream_->OnStreamFrameLost(0, 9, false);
EXPECT_TRUE(stream_->HasPendingRetransmission());
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .WillOnce(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1);
stream_->OnCanWrite();
EXPECT_FALSE(stream_->HasPendingRetransmission());
EXPECT_TRUE(stream_->HasBufferedData());
// This OnCanWrite causes [9, 27) to be sent.
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .WillOnce(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
stream_->OnCanWrite();
EXPECT_FALSE(stream_->HasBufferedData());
// Send a fin only frame.
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .WillOnce(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
stream_->WriteOrBufferData("", true, nullptr);
// Lost [9, 27) and fin.
@@ -1338,16 +1362,17 @@ TEST_P(QuicStreamTest, OnStreamFrameLost) {
// Ack [9, 18).
QuicByteCount newly_acked_length = 0;
EXPECT_TRUE(stream_->OnStreamFrameAcked(9, 9, false, QuicTime::Delta::Zero(),
+ QuicTime::Zero(),
&newly_acked_length));
EXPECT_EQ(9u, newly_acked_length);
EXPECT_FALSE(stream_->IsStreamFrameOutstanding(9, 3, false));
EXPECT_TRUE(stream_->HasPendingRetransmission());
// This OnCanWrite causes [18, 27) and fin to be retransmitted. Verify fin can
// be bundled with data.
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
.WillOnce(InvokeWithoutArgs([this]() {
- return MockQuicSession::ConsumeData(stream_, stream_->id(), 9u, 18u,
- FIN);
+ return session_->ConsumeData(stream_->id(), 9u, 18u, FIN,
+ NOT_RETRANSMISSION, QuicheNullOpt);
}));
stream_->OnCanWrite();
EXPECT_FALSE(stream_->HasPendingRetransmission());
@@ -1362,8 +1387,8 @@ TEST_P(QuicStreamTest, CannotBundleLostFin) {
Initialize();
// Send [0, 18) and fin.
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData));
stream_->WriteOrBufferData(kData1, false, nullptr);
stream_->WriteOrBufferData(kData2, true, nullptr);
@@ -1374,12 +1399,12 @@ TEST_P(QuicStreamTest, CannotBundleLostFin) {
// Retransmit lost data. Verify [0, 9) and fin are retransmitted in two
// frames.
InSequence s;
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
.WillOnce(InvokeWithoutArgs([this]() {
- return MockQuicSession::ConsumeData(stream_, stream_->id(), 9u, 0u,
- NO_FIN);
+ return session_->ConsumeData(stream_->id(), 9u, 0u, NO_FIN,
+ NOT_RETRANSMISSION, QuicheNullOpt);
}));
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
.WillOnce(Return(QuicConsumedData(0, true)));
stream_->OnCanWrite();
}
@@ -1398,8 +1423,8 @@ TEST_P(QuicStreamTest, MarkConnectionLevelWriteBlockedOnWindowUpdateFrame) {
session_.get(), BIDIRECTIONAL);
session_->ActivateStream(QuicWrapUnique(stream));
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData));
EXPECT_CALL(*connection_, SendControlFrame(_))
.WillOnce(Invoke(&ClearControlFrame));
std::string data(1024, '.');
@@ -1432,8 +1457,8 @@ TEST_P(QuicStreamTest,
session_->ActivateStream(QuicWrapUnique(stream));
std::string data(100, '.');
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
+ .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData));
EXPECT_CALL(*connection_, SendControlFrame(_))
.WillOnce(Invoke(&ClearControlFrame));
stream->WriteOrBufferData(data, false, nullptr);
@@ -1452,44 +1477,44 @@ TEST_P(QuicStreamTest, RetransmitStreamData) {
InSequence s;
// Send [0, 18) with fin.
- EXPECT_CALL(*session_, WritevData(_, stream_->id(), _, _, _))
+ EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _))
.Times(2)
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+ .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData));
stream_->WriteOrBufferData(kData1, false, nullptr);
stream_->WriteOrBufferData(kData1, true, nullptr);
// Ack [10, 13).
QuicByteCount newly_acked_length = 0;
stream_->OnStreamFrameAcked(10, 3, false, QuicTime::Delta::Zero(),
- &newly_acked_length);
+ QuicTime::Zero(), &newly_acked_length);
EXPECT_EQ(3u, newly_acked_length);
// Retransmit [0, 18) with fin, and only [0, 8) is consumed.
- EXPECT_CALL(*session_, WritevData(_, stream_->id(), 10, 0, NO_FIN))
+ EXPECT_CALL(*session_, WritevData(stream_->id(), 10, 0, NO_FIN, _, _))
.WillOnce(InvokeWithoutArgs([this]() {
- return MockQuicSession::ConsumeData(stream_, stream_->id(), 8, 0u,
- NO_FIN);
+ return session_->ConsumeData(stream_->id(), 8, 0u, NO_FIN,
+ NOT_RETRANSMISSION, QuicheNullOpt);
}));
- EXPECT_FALSE(stream_->RetransmitStreamData(0, 18, true));
+ EXPECT_FALSE(stream_->RetransmitStreamData(0, 18, true, PTO_RETRANSMISSION));
// Retransmit [0, 18) with fin, and all is consumed.
- EXPECT_CALL(*session_, WritevData(_, stream_->id(), 10, 0, NO_FIN))
- .WillOnce(Invoke(MockQuicSession::ConsumeData));
- EXPECT_CALL(*session_, WritevData(_, stream_->id(), 5, 13, FIN))
- .WillOnce(Invoke(MockQuicSession::ConsumeData));
- EXPECT_TRUE(stream_->RetransmitStreamData(0, 18, true));
+ EXPECT_CALL(*session_, WritevData(stream_->id(), 10, 0, NO_FIN, _, _))
+ .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
+ EXPECT_CALL(*session_, WritevData(stream_->id(), 5, 13, FIN, _, _))
+ .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
+ EXPECT_TRUE(stream_->RetransmitStreamData(0, 18, true, PTO_RETRANSMISSION));
// Retransmit [0, 8) with fin, and all is consumed.
- EXPECT_CALL(*session_, WritevData(_, stream_->id(), 8, 0, NO_FIN))
- .WillOnce(Invoke(MockQuicSession::ConsumeData));
- EXPECT_CALL(*session_, WritevData(_, stream_->id(), 0, 18, FIN))
- .WillOnce(Invoke(MockQuicSession::ConsumeData));
- EXPECT_TRUE(stream_->RetransmitStreamData(0, 8, true));
+ EXPECT_CALL(*session_, WritevData(stream_->id(), 8, 0, NO_FIN, _, _))
+ .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
+ EXPECT_CALL(*session_, WritevData(stream_->id(), 0, 18, FIN, _, _))
+ .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
+ EXPECT_TRUE(stream_->RetransmitStreamData(0, 8, true, PTO_RETRANSMISSION));
}
TEST_P(QuicStreamTest, ResetStreamOnTtlExpiresRetransmitLostData) {
Initialize();
- EXPECT_CALL(*session_, WritevData(_, stream_->id(), 200, 0, FIN))
- .WillOnce(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(*session_, WritevData(stream_->id(), 200, 0, FIN, _, _))
+ .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
std::string body(200, 'a');
stream_->WriteOrBufferData(body, true, nullptr);
@@ -1497,9 +1522,9 @@ TEST_P(QuicStreamTest, ResetStreamOnTtlExpiresRetransmitLostData) {
QuicTime::Delta ttl = QuicTime::Delta::FromSeconds(1);
ASSERT_TRUE(stream_->MaybeSetTtl(ttl));
// Verify data gets retransmitted because TTL does not expire.
- EXPECT_CALL(*session_, WritevData(_, stream_->id(), 100, 0, NO_FIN))
- .WillOnce(Invoke(MockQuicSession::ConsumeData));
- EXPECT_TRUE(stream_->RetransmitStreamData(0, 100, false));
+ EXPECT_CALL(*session_, WritevData(stream_->id(), 100, 0, NO_FIN, _, _))
+ .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
+ EXPECT_TRUE(stream_->RetransmitStreamData(0, 100, false, PTO_RETRANSMISSION));
stream_->OnStreamFrameLost(100, 100, true);
EXPECT_TRUE(stream_->HasPendingRetransmission());
@@ -1512,8 +1537,8 @@ TEST_P(QuicStreamTest, ResetStreamOnTtlExpiresRetransmitLostData) {
TEST_P(QuicStreamTest, ResetStreamOnTtlExpiresEarlyRetransmitData) {
Initialize();
- EXPECT_CALL(*session_, WritevData(_, stream_->id(), 200, 0, FIN))
- .WillOnce(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(*session_, WritevData(stream_->id(), 200, 0, FIN, _, _))
+ .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
std::string body(200, 'a');
stream_->WriteOrBufferData(body, true, nullptr);
@@ -1524,7 +1549,7 @@ TEST_P(QuicStreamTest, ResetStreamOnTtlExpiresEarlyRetransmitData) {
connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
// Verify stream gets reset because TTL expires.
EXPECT_CALL(*session_, SendRstStream(_, QUIC_STREAM_TTL_EXPIRED, _)).Times(1);
- stream_->RetransmitStreamData(0, 100, false);
+ stream_->RetransmitStreamData(0, 100, false, PTO_RETRANSMISSION);
}
// Test that QuicStream::StopSending A) is a no-op if the connection is not in
@@ -1589,7 +1614,6 @@ TEST_P(QuicStreamTest, WindowUpdateForReadOnlyStream) {
}
TEST_P(QuicStreamTest, RstStreamFrameChangesCloseOffset) {
- SetQuicReloadableFlag(quic_close_connection_on_wrong_offset, true);
Initialize();
QuicStreamFrame stream_frame(stream_->id(), true, 0, "abc");
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_tag.cc b/chromium/net/third_party/quiche/src/quic/core/quic_tag.cc
index 3b6ba0d4ab2..270383d27ae 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_tag.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_tag.cc
@@ -7,10 +7,10 @@
#include <algorithm>
#include <string>
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
@@ -43,10 +43,10 @@ std::string QuicTagToString(QuicTag tag) {
bool ascii = true;
const QuicTag orig_tag = tag;
- for (size_t i = 0; i < QUIC_ARRAYSIZE(chars); i++) {
+ for (size_t i = 0; i < QUICHE_ARRAYSIZE(chars); i++) {
chars[i] = static_cast<char>(tag);
if ((chars[i] == 0 || chars[i] == '\xff') &&
- i == QUIC_ARRAYSIZE(chars) - 1) {
+ i == QUICHE_ARRAYSIZE(chars) - 1) {
chars[i] = ' ';
}
if (!isprint(static_cast<unsigned char>(chars[i]))) {
@@ -60,8 +60,8 @@ std::string QuicTagToString(QuicTag tag) {
return std::string(chars, sizeof(chars));
}
- return QuicTextUtils::HexEncode(reinterpret_cast<const char*>(&orig_tag),
- sizeof(orig_tag));
+ return quiche::QuicheTextUtils::HexEncode(
+ reinterpret_cast<const char*>(&orig_tag), sizeof(orig_tag));
}
uint32_t MakeQuicTag(char a, char b, char c, char d) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_time.cc b/chromium/net/third_party/quiche/src/quic/core/quic_time.cc
index ffc59dadf9b..b7a12fe8923 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_time.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_time.cc
@@ -9,7 +9,7 @@
#include <limits>
#include <string>
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
namespace quic {
@@ -22,12 +22,12 @@ std::string QuicTime::Delta::ToDebuggingValue() const {
// For debugging purposes, always display the value with the highest precision
// available.
if (absolute_value > one_s && absolute_value % one_s == 0) {
- return QuicStringPrintf("%" PRId64 "s", time_offset_ / one_s);
+ return quiche::QuicheStringPrintf("%" PRId64 "s", time_offset_ / one_s);
}
if (absolute_value > one_ms && absolute_value % one_ms == 0) {
- return QuicStringPrintf("%" PRId64 "ms", time_offset_ / one_ms);
+ return quiche::QuicheStringPrintf("%" PRId64 "ms", time_offset_ / one_ms);
}
- return QuicStringPrintf("%" PRId64 "us", time_offset_);
+ return quiche::QuicheStringPrintf("%" PRId64 "us", time_offset_);
}
uint64_t QuicWallTime::ToUNIXSeconds() const {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.cc b/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.cc
index 705856345ac..2b0c267f626 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.cc
@@ -12,17 +12,18 @@
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
+#include "net/third_party/quiche/src/quic/core/quic_clock.h"
#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
#include "net/third_party/quiche/src/quic/core/quic_framer.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
@@ -220,7 +221,7 @@ void QuicTimeWaitListManager::SendVersionNegotiationPacket(
<< (ietf_quic ? "" : "!") << "ietf_quic, "
<< (use_length_prefix ? "" : "!")
<< "use_length_prefix:" << std::endl
- << QuicTextUtils::HexDump(QuicStringPiece(
+ << quiche::QuicheTextUtils::HexDump(quiche::QuicheStringPiece(
version_packet->data(), version_packet->length()));
SendOrQueuePacket(std::make_unique<QueuedPacket>(self_address, peer_address,
std::move(version_packet)),
@@ -244,9 +245,9 @@ void QuicTimeWaitListManager::SendPublicReset(
BuildIetfStatelessResetPacket(connection_id);
QUIC_DVLOG(2) << "Dispatcher sending IETF reset packet for "
<< connection_id << std::endl
- << QuicTextUtils::HexDump(
- QuicStringPiece(ietf_reset_packet->data(),
- ietf_reset_packet->length()));
+ << quiche::QuicheTextUtils::HexDump(quiche::QuicheStringPiece(
+ ietf_reset_packet->data(),
+ ietf_reset_packet->length()));
SendOrQueuePacket(
std::make_unique<QueuedPacket>(self_address, peer_address,
std::move(ietf_reset_packet)),
@@ -264,7 +265,7 @@ void QuicTimeWaitListManager::SendPublicReset(
std::unique_ptr<QuicEncryptedPacket> reset_packet = BuildPublicReset(packet);
QUIC_DVLOG(2) << "Dispatcher sending reset packet for " << connection_id
<< std::endl
- << QuicTextUtils::HexDump(QuicStringPiece(
+ << quiche::QuicheTextUtils::HexDump(quiche::QuicheStringPiece(
reset_packet->data(), reset_packet->length()));
SendOrQueuePacket(std::make_unique<QueuedPacket>(self_address, peer_address,
std::move(reset_packet)),
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h b/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h
index 5c7553565b4..c9a5261d62f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h
@@ -193,8 +193,8 @@ class QUIC_NO_EXPORT QuicTimeWaitListManager
virtual bool SendOrQueuePacket(std::unique_ptr<QueuedPacket> packet,
const QuicPerPacketContext* packet_context);
- const QuicDeque<std::unique_ptr<QueuedPacket>>& pending_packets_queue()
- const {
+ const QuicCircularDeque<std::unique_ptr<QueuedPacket>>&
+ pending_packets_queue() const {
return pending_packets_queue_;
}
@@ -260,7 +260,7 @@ class QUIC_NO_EXPORT QuicTimeWaitListManager
// Pending termination packets that need to be sent out to the peer when we
// are given a chance to write by the dispatcher.
- QuicDeque<std::unique_ptr<QueuedPacket>> pending_packets_queue_;
+ QuicCircularDeque<std::unique_ptr<QueuedPacket>> pending_packets_queue_;
// Time period for which connection_ids should remain in time wait state.
const QuicTime::Delta time_wait_period_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor.cc b/chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor.cc
index 50974853345..edbce0c709c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor.cc
@@ -6,6 +6,7 @@
#include <string>
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
namespace quic {
@@ -62,6 +63,7 @@ void QuicTraceVisitor::OnPacketSent(const SerializedPacket& serialized_packet,
case WINDOW_UPDATE_FRAME:
case BLOCKED_FRAME:
case PING_FRAME:
+ case HANDSHAKE_DONE_FRAME:
PopulateFrameInfo(frame, event->add_frames());
break;
@@ -193,6 +195,7 @@ void QuicTraceVisitor::PopulateFrameInfo(const QuicFrame& frame,
case PING_FRAME:
case MTU_DISCOVERY_FRAME:
+ case HANDSHAKE_DONE_FRAME:
frame_record->set_frame_type(quic_trace::PING);
break;
@@ -225,6 +228,7 @@ void QuicTraceVisitor::PopulateFrameInfo(const QuicFrame& frame,
void QuicTraceVisitor::OnIncomingAck(
QuicPacketNumber /*ack_packet_number*/,
+ EncryptionLevel ack_decrypted_level,
const QuicAckFrame& ack_frame,
QuicTime ack_receive_time,
QuicPacketNumber /*largest_observed*/,
@@ -234,6 +238,7 @@ void QuicTraceVisitor::OnIncomingAck(
event->set_time_us(ConvertTimestampToRecordedFormat(ack_receive_time));
event->set_packet_number(connection_->GetLargestReceivedPacket().ToUint64());
event->set_event_type(quic_trace::PACKET_RECEIVED);
+ event->set_encryption_level(EncryptionLevelToProto(ack_decrypted_level));
// TODO(vasilvv): consider removing this copy.
QuicAckFrame copy_of_ack = ack_frame;
@@ -242,6 +247,7 @@ void QuicTraceVisitor::OnIncomingAck(
}
void QuicTraceVisitor::OnPacketLoss(QuicPacketNumber lost_packet_number,
+ EncryptionLevel encryption_level,
TransmissionType /*transmission_type*/,
QuicTime detection_time) {
quic_trace::Event* event = trace_.add_events();
@@ -249,6 +255,7 @@ void QuicTraceVisitor::OnPacketLoss(QuicPacketNumber lost_packet_number,
event->set_event_type(quic_trace::PACKET_LOST);
event->set_packet_number(lost_packet_number.ToUint64());
PopulateTransportState(event->mutable_transport_state());
+ event->set_encryption_level(EncryptionLevelToProto(encryption_level));
}
void QuicTraceVisitor::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame,
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor.h b/chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor.h
index 86d7198ebe7..c9732cf423c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor.h
@@ -23,6 +23,7 @@ class QUIC_NO_EXPORT QuicTraceVisitor : public QuicConnectionDebugVisitor {
QuicTime sent_time) override;
void OnIncomingAck(QuicPacketNumber ack_packet_number,
+ EncryptionLevel ack_decrypted_level,
const QuicAckFrame& ack_frame,
QuicTime ack_receive_time,
QuicPacketNumber largest_observed,
@@ -30,6 +31,7 @@ class QUIC_NO_EXPORT QuicTraceVisitor : public QuicConnectionDebugVisitor {
QuicPacketNumber least_unacked_sent_packet) override;
void OnPacketLoss(QuicPacketNumber lost_packet_number,
+ EncryptionLevel encryption_level,
TransmissionType transmission_type,
QuicTime detection_time) override;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor_test.cc
index 5e771336d9c..07bc4f2ea37 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor_test.cc
@@ -81,7 +81,7 @@ TEST_F(QuicTraceVisitorTest, ConnectionId) {
TEST_F(QuicTraceVisitorTest, Version) {
std::string version = trace_.protocol_version();
ASSERT_EQ(4u, version.size());
- EXPECT_EQ('Q', version[0]);
+ EXPECT_NE(0, version[0]);
}
// Check that basic metadata about sent packets is recorded.
@@ -162,5 +162,21 @@ TEST_F(QuicTraceVisitorTest, TransportState) {
acks.rbegin()->transport_state().min_rtt_us());
}
+TEST_F(QuicTraceVisitorTest, EncryptionLevels) {
+ for (const auto& event : trace_.events()) {
+ switch (event.event_type()) {
+ case quic_trace::PACKET_SENT:
+ case quic_trace::PACKET_RECEIVED:
+ case quic_trace::PACKET_LOST:
+ ASSERT_TRUE(event.has_encryption_level());
+ ASSERT_NE(event.encryption_level(), quic_trace::ENCRYPTION_UNKNOWN);
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
} // namespace
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_types.cc b/chromium/net/third_party/quiche/src/quic/core/quic_types.cc
index ca12e76725b..ce24d57113d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_types.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_types.cc
@@ -6,8 +6,9 @@
#include <cstdint>
+#include "third_party/boringssl/src/include/openssl/ssl.h"
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
namespace quic {
@@ -56,10 +57,16 @@ std::string HistogramEnumString(WriteStatus enum_value) {
case WRITE_STATUS_NUM_VALUES:
return "NUM_VALUES";
}
- QUIC_DLOG(ERROR) << "Invalid WriteStatus value: " << enum_value;
+ QUIC_DLOG(ERROR) << "Invalid WriteStatus value: "
+ << static_cast<int16_t>(enum_value);
return "<invalid>";
}
+std::ostream& operator<<(std::ostream& os, const WriteStatus& status) {
+ os << HistogramEnumString(status);
+ return os;
+}
+
std::ostream& operator<<(std::ostream& os, const WriteResult& s) {
os << "{ status: " << s.status;
if (s.status == WRITE_STATUS_OK) {
@@ -79,8 +86,16 @@ MessageResult::MessageResult(MessageStatus status, QuicMessageId message_id)
return #x;
std::string QuicIetfTransportErrorCodeString(QuicIetfTransportErrorCodes c) {
- if (static_cast<uint16_t>(c) >= 0xff00u) {
- return QuicStrCat("Private value: ", static_cast<uint16_t>(c));
+ if (static_cast<uint64_t>(c) >= 0xff00u) {
+ return quiche::QuicheStrCat("Private(", static_cast<uint64_t>(c), ")");
+ }
+ if (c >= CRYPTO_ERROR_FIRST && c <= CRYPTO_ERROR_LAST) {
+ const int tls_error = static_cast<int>(c - CRYPTO_ERROR_FIRST);
+ const char* tls_error_description = SSL_alert_desc_string_long(tls_error);
+ if (strcmp("unknown", tls_error_description) != 0) {
+ return quiche::QuicheStrCat("CRYPTO_ERROR(", tls_error_description, ")");
+ }
+ return quiche::QuicheStrCat("CRYPTO_ERROR(unknown(", tls_error, "))");
}
switch (c) {
@@ -93,13 +108,19 @@ std::string QuicIetfTransportErrorCodeString(QuicIetfTransportErrorCodes c) {
RETURN_STRING_LITERAL(FINAL_SIZE_ERROR);
RETURN_STRING_LITERAL(FRAME_ENCODING_ERROR);
RETURN_STRING_LITERAL(TRANSPORT_PARAMETER_ERROR);
- RETURN_STRING_LITERAL(VERSION_NEGOTIATION_ERROR);
+ RETURN_STRING_LITERAL(CONNECTION_ID_LIMIT_ERROR);
RETURN_STRING_LITERAL(PROTOCOL_VIOLATION);
- RETURN_STRING_LITERAL(INVALID_MIGRATION);
- default:
- return QuicStrCat("Unknown Transport Error Code Value: ",
- static_cast<uint16_t>(c));
+ RETURN_STRING_LITERAL(INVALID_TOKEN);
+ RETURN_STRING_LITERAL(CRYPTO_BUFFER_EXCEEDED);
+ // CRYPTO_ERROR is handled in the if before this switch, these cases do not
+ // change behavior and are only here to make the compiler happy.
+ case CRYPTO_ERROR_FIRST:
+ case CRYPTO_ERROR_LAST:
+ DCHECK(false) << "Unexpected error " << static_cast<uint64_t>(c);
+ break;
}
+
+ return quiche::QuicheStrCat("Unknown(", static_cast<uint64_t>(c), ")");
}
std::ostream& operator<<(std::ostream& os,
@@ -425,6 +446,97 @@ QuicErrorCodeToIetfMapping QuicErrorCodeToTransportErrorCode(
{static_cast<uint64_t>(QUIC_STREAM_DATA_BEYOND_CLOSE_OFFSET)}};
case QUIC_STREAM_MULTIPLE_OFFSET:
return {true, {static_cast<uint64_t>(QUIC_STREAM_MULTIPLE_OFFSET)}};
+ case QUIC_HTTP_FRAME_TOO_LARGE:
+ return {false,
+ {static_cast<uint64_t>(
+ QuicHttp3ErrorCode::IETF_QUIC_HTTP3_EXCESSIVE_LOAD)}};
+ case QUIC_HTTP_FRAME_ERROR:
+ return {false,
+ {static_cast<uint64_t>(
+ QuicHttp3ErrorCode::IETF_QUIC_HTTP3_FRAME_ERROR)}};
+ case QUIC_HTTP_FRAME_UNEXPECTED_ON_SPDY_STREAM:
+ return {false,
+ {static_cast<uint64_t>(
+ QuicHttp3ErrorCode::IETF_QUIC_HTTP3_FRAME_UNEXPECTED)}};
+ case QUIC_HTTP_FRAME_UNEXPECTED_ON_CONTROL_STREAM:
+ return {false,
+ {static_cast<uint64_t>(
+ QuicHttp3ErrorCode::IETF_QUIC_HTTP3_FRAME_UNEXPECTED)}};
+ case QUIC_HTTP_INVALID_FRAME_SEQUENCE_ON_SPDY_STREAM:
+ return {false,
+ {static_cast<uint64_t>(
+ QuicHttp3ErrorCode::IETF_QUIC_HTTP3_FRAME_UNEXPECTED)}};
+ case QUIC_HTTP_INVALID_FRAME_SEQUENCE_ON_CONTROL_STREAM:
+ return {false,
+ {static_cast<uint64_t>(
+ QuicHttp3ErrorCode::IETF_QUIC_HTTP3_FRAME_UNEXPECTED)}};
+ case QUIC_HTTP_DUPLICATE_UNIDIRECTIONAL_STREAM:
+ return {false,
+ {static_cast<uint64_t>(
+ QuicHttp3ErrorCode::IETF_QUIC_HTTP3_STREAM_CREATION_ERROR)}};
+ case QUIC_HTTP_SERVER_INITIATED_BIDIRECTIONAL_STREAM:
+ return {false,
+ {static_cast<uint64_t>(
+ QuicHttp3ErrorCode::IETF_QUIC_HTTP3_STREAM_CREATION_ERROR)}};
+ case QUIC_HTTP_STREAM_WRONG_DIRECTION:
+ return {true, {static_cast<uint64_t>(STREAM_STATE_ERROR)}};
+ case QUIC_HTTP_CLOSED_CRITICAL_STREAM:
+ return {false,
+ {static_cast<uint64_t>(
+ QuicHttp3ErrorCode::IETF_QUIC_HTTP3_CLOSED_CRITICAL_STREAM)}};
+ case QUIC_HTTP_MISSING_SETTINGS_FRAME:
+ return {false,
+ {static_cast<uint64_t>(
+ QuicHttp3ErrorCode::IETF_QUIC_HTTP3_MISSING_SETTINGS)}};
+ case QUIC_HTTP_DUPLICATE_SETTING_IDENTIFIER:
+ return {false,
+ {static_cast<uint64_t>(
+ QuicHttp3ErrorCode::IETF_QUIC_HTTP3_SETTINGS_ERROR)}};
+ case QUIC_HPACK_INDEX_VARINT_ERROR:
+ return {false, {static_cast<uint64_t>(QUIC_HPACK_INDEX_VARINT_ERROR)}};
+ case QUIC_HPACK_NAME_LENGTH_VARINT_ERROR:
+ return {false,
+ {static_cast<uint64_t>(QUIC_HPACK_NAME_LENGTH_VARINT_ERROR)}};
+ case QUIC_HPACK_VALUE_LENGTH_VARINT_ERROR:
+ return {false,
+ {static_cast<uint64_t>(QUIC_HPACK_VALUE_LENGTH_VARINT_ERROR)}};
+ case QUIC_HPACK_NAME_TOO_LONG:
+ return {false, {static_cast<uint64_t>(QUIC_HPACK_NAME_TOO_LONG)}};
+ case QUIC_HPACK_VALUE_TOO_LONG:
+ return {false, {static_cast<uint64_t>(QUIC_HPACK_VALUE_TOO_LONG)}};
+ case QUIC_HPACK_NAME_HUFFMAN_ERROR:
+ return {false, {static_cast<uint64_t>(QUIC_HPACK_NAME_HUFFMAN_ERROR)}};
+ case QUIC_HPACK_VALUE_HUFFMAN_ERROR:
+ return {false, {static_cast<uint64_t>(QUIC_HPACK_VALUE_HUFFMAN_ERROR)}};
+ case QUIC_HPACK_MISSING_DYNAMIC_TABLE_SIZE_UPDATE:
+ return {false,
+ {static_cast<uint64_t>(
+ QUIC_HPACK_MISSING_DYNAMIC_TABLE_SIZE_UPDATE)}};
+ case QUIC_HPACK_INVALID_INDEX:
+ return {false, {static_cast<uint64_t>(QUIC_HPACK_INVALID_INDEX)}};
+ case QUIC_HPACK_INVALID_NAME_INDEX:
+ return {false, {static_cast<uint64_t>(QUIC_HPACK_INVALID_NAME_INDEX)}};
+ case QUIC_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_NOT_ALLOWED:
+ return {false,
+ {static_cast<uint64_t>(
+ QUIC_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_NOT_ALLOWED)}};
+ case QUIC_HPACK_INITIAL_TABLE_SIZE_UPDATE_IS_ABOVE_LOW_WATER_MARK:
+ return {
+ false,
+ {static_cast<uint64_t>(
+ QUIC_HPACK_INITIAL_TABLE_SIZE_UPDATE_IS_ABOVE_LOW_WATER_MARK)}};
+ case QUIC_HPACK_TABLE_SIZE_UPDATE_IS_ABOVE_ACKNOWLEDGED_SETTING:
+ return {false,
+ {static_cast<uint64_t>(
+ QUIC_HPACK_TABLE_SIZE_UPDATE_IS_ABOVE_ACKNOWLEDGED_SETTING)}};
+ case QUIC_HPACK_TRUNCATED_BLOCK:
+ return {false, {static_cast<uint64_t>(QUIC_HPACK_TRUNCATED_BLOCK)}};
+ case QUIC_HPACK_FRAGMENT_TOO_LONG:
+ return {false, {static_cast<uint64_t>(QUIC_HPACK_FRAGMENT_TOO_LONG)}};
+ case QUIC_HPACK_COMPRESSED_HEADER_SIZE_EXCEEDS_LIMIT:
+ return {false,
+ {static_cast<uint64_t>(
+ QUIC_HPACK_COMPRESSED_HEADER_SIZE_EXCEEDS_LIMIT)}};
case QUIC_LAST_ERROR:
return {false, {static_cast<uint64_t>(QUIC_LAST_ERROR)}};
}
@@ -450,8 +562,8 @@ std::string QuicIetfFrameTypeString(QuicIetfFrameType t) {
RETURN_STRING_LITERAL(IETF_MAX_STREAM_DATA);
RETURN_STRING_LITERAL(IETF_MAX_STREAMS_BIDIRECTIONAL);
RETURN_STRING_LITERAL(IETF_MAX_STREAMS_UNIDIRECTIONAL);
- RETURN_STRING_LITERAL(IETF_BLOCKED);
- RETURN_STRING_LITERAL(IETF_STREAM_BLOCKED);
+ RETURN_STRING_LITERAL(IETF_DATA_BLOCKED);
+ RETURN_STRING_LITERAL(IETF_STREAM_DATA_BLOCKED);
RETURN_STRING_LITERAL(IETF_STREAMS_BLOCKED_BIDIRECTIONAL);
RETURN_STRING_LITERAL(IETF_STREAMS_BLOCKED_UNIDIRECTIONAL);
RETURN_STRING_LITERAL(IETF_NEW_CONNECTION_ID);
@@ -465,7 +577,7 @@ std::string QuicIetfFrameTypeString(QuicIetfFrameType t) {
RETURN_STRING_LITERAL(IETF_EXTENSION_MESSAGE_NO_LENGTH_V99);
RETURN_STRING_LITERAL(IETF_EXTENSION_MESSAGE_V99);
default:
- return QuicStrCat("Private value (", t, ")");
+ return quiche::QuicheStrCat("Private value (", t, ")");
}
}
std::ostream& operator<<(std::ostream& os, const QuicIetfFrameType& c) {
@@ -489,7 +601,8 @@ std::string TransmissionTypeToString(TransmissionType transmission_type) {
if (transmission_type == LAST_TRANSMISSION_TYPE + 1) {
return "INVALID_TRANSMISSION_TYPE";
}
- return QuicStrCat("Unknown(", static_cast<int>(transmission_type), ")");
+ return quiche::QuicheStrCat("Unknown(",
+ static_cast<int>(transmission_type), ")");
break;
}
}
@@ -500,7 +613,7 @@ std::string PacketHeaderFormatToString(PacketHeaderFormat format) {
RETURN_STRING_LITERAL(IETF_QUIC_SHORT_HEADER_PACKET);
RETURN_STRING_LITERAL(GOOGLE_QUIC_PACKET);
default:
- return QuicStrCat("Unknown (", static_cast<int>(format), ")");
+ return quiche::QuicheStrCat("Unknown (", static_cast<int>(format), ")");
}
}
@@ -513,7 +626,7 @@ std::string QuicLongHeaderTypeToString(QuicLongHeaderType type) {
RETURN_STRING_LITERAL(RETRY);
RETURN_STRING_LITERAL(INVALID_PACKET_TYPE);
default:
- return QuicStrCat("Unknown (", static_cast<int>(type), ")");
+ return quiche::QuicheStrCat("Unknown (", static_cast<int>(type), ")");
}
}
@@ -526,17 +639,19 @@ std::string MessageStatusToString(MessageStatus message_status) {
RETURN_STRING_LITERAL(MESSAGE_STATUS_TOO_LARGE);
RETURN_STRING_LITERAL(MESSAGE_STATUS_INTERNAL_ERROR);
default:
- return QuicStrCat("Unknown(", static_cast<int>(message_status), ")");
+ return quiche::QuicheStrCat("Unknown(", static_cast<int>(message_status),
+ ")");
break;
}
}
std::string MessageResultToString(MessageResult message_result) {
if (message_result.status != MESSAGE_STATUS_SUCCESS) {
- return QuicStrCat("{", MessageStatusToString(message_result.status), "}");
+ return quiche::QuicheStrCat(
+ "{", MessageStatusToString(message_result.status), "}");
}
- return QuicStrCat("{MESSAGE_STATUS_SUCCESS,id=", message_result.message_id,
- "}");
+ return quiche::QuicheStrCat(
+ "{MESSAGE_STATUS_SUCCESS,id=", message_result.message_id, "}");
}
std::ostream& operator<<(std::ostream& os, const MessageResult& mr) {
@@ -550,7 +665,8 @@ std::string PacketNumberSpaceToString(PacketNumberSpace packet_number_space) {
RETURN_STRING_LITERAL(HANDSHAKE_DATA);
RETURN_STRING_LITERAL(APPLICATION_DATA);
default:
- return QuicStrCat("Unknown(", static_cast<int>(packet_number_space), ")");
+ return quiche::QuicheStrCat("Unknown(",
+ static_cast<int>(packet_number_space), ")");
break;
}
}
@@ -562,7 +678,7 @@ std::string SerializedPacketFateToString(SerializedPacketFate fate) {
RETURN_STRING_LITERAL(SEND_TO_WRITER);
RETURN_STRING_LITERAL(FAILED_TO_WRITE_COALESCED_PACKET);
default:
- return QuicStrCat("Unknown(", static_cast<int>(fate), ")");
+ return quiche::QuicheStrCat("Unknown(", static_cast<int>(fate), ")");
}
}
@@ -573,7 +689,7 @@ std::string EncryptionLevelToString(EncryptionLevel level) {
RETURN_STRING_LITERAL(ENCRYPTION_ZERO_RTT);
RETURN_STRING_LITERAL(ENCRYPTION_FORWARD_SECURE);
default:
- return QuicStrCat("Unknown(", static_cast<int>(level), ")");
+ return quiche::QuicheStrCat("Unknown(", static_cast<int>(level), ")");
break;
}
}
@@ -584,13 +700,34 @@ std::string QuicConnectionCloseTypeString(QuicConnectionCloseType type) {
RETURN_STRING_LITERAL(IETF_QUIC_TRANSPORT_CONNECTION_CLOSE);
RETURN_STRING_LITERAL(IETF_QUIC_APPLICATION_CONNECTION_CLOSE);
default:
- return QuicStrCat("Unknown(", static_cast<int>(type), ")");
+ return quiche::QuicheStrCat("Unknown(", static_cast<int>(type), ")");
break;
}
}
+
std::ostream& operator<<(std::ostream& os, const QuicConnectionCloseType type) {
os << QuicConnectionCloseTypeString(type);
return os;
}
+std::string AddressChangeTypeToString(AddressChangeType type) {
+ using IntType = typename std::underlying_type<AddressChangeType>::type;
+ switch (type) {
+ RETURN_STRING_LITERAL(NO_CHANGE);
+ RETURN_STRING_LITERAL(PORT_CHANGE);
+ RETURN_STRING_LITERAL(IPV4_SUBNET_CHANGE);
+ RETURN_STRING_LITERAL(IPV4_TO_IPV4_CHANGE);
+ RETURN_STRING_LITERAL(IPV4_TO_IPV6_CHANGE);
+ RETURN_STRING_LITERAL(IPV6_TO_IPV4_CHANGE);
+ RETURN_STRING_LITERAL(IPV6_TO_IPV6_CHANGE);
+ default:
+ return quiche::QuicheStrCat("Unknown(", static_cast<IntType>(type), ")");
+ }
+}
+
+std::ostream& operator<<(std::ostream& os, AddressChangeType type) {
+ os << AddressChangeTypeToString(type);
+ return os;
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_types.h b/chromium/net/third_party/quiche/src/quic/core/quic_types.h
index 23cbe7a4eb4..76d3bab90cc 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_types.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_types.h
@@ -17,6 +17,7 @@
#include "net/third_party/quiche/src/quic/core/quic_time.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
namespace quic {
@@ -26,7 +27,6 @@ typedef uint32_t QuicHeaderId;
typedef uint32_t QuicMessageId;
typedef uint64_t QuicDatagramFlowId;
-// TODO(fkastenholz): Should update this to 64 bits for V99.
typedef uint32_t QuicStreamId;
// Count of stream IDs. Used in MAX_STREAMS and STREAMS_BLOCKED
@@ -86,7 +86,7 @@ enum QuicAsyncStatus {
};
// TODO(wtc): see if WriteStatus can be replaced by QuicAsyncStatus.
-enum WriteStatus {
+enum WriteStatus : int16_t {
WRITE_STATUS_OK,
// Write is blocked, caller needs to retry.
WRITE_STATUS_BLOCKED,
@@ -102,6 +102,8 @@ enum WriteStatus {
};
std::string HistogramEnumString(WriteStatus enum_value);
+QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
+ const WriteStatus& status);
inline std::string HistogramEnumDescription(WriteStatus /*dummy*/) {
return "status";
@@ -143,6 +145,12 @@ struct QUIC_EXPORT_PRIVATE WriteResult {
const WriteResult& s);
WriteStatus status;
+ // Number of packets dropped as a result of this write.
+ // Only used by batch writers. Otherwise always 0.
+ uint16_t dropped_packets = 0;
+ // TODO(wub): In some cases, WRITE_STATUS_ERROR may set an error_code and
+ // WRITE_STATUS_BLOCKED_DATA_BUFFERED may set bytes_written. This may need
+ // some cleaning up so that perhaps both values can be set and valid.
union {
int bytes_written; // only valid when status is WRITE_STATUS_OK
int error_code; // only valid when status is WRITE_STATUS_ERROR
@@ -220,6 +228,7 @@ enum QuicFrameType : uint8_t {
MESSAGE_FRAME,
NEW_TOKEN_FRAME,
RETIRE_CONNECTION_ID_FRAME,
+ HANDSHAKE_DONE_FRAME,
NUM_FRAME_TYPES
};
@@ -256,10 +265,8 @@ enum QuicIetfFrameType : uint8_t {
IETF_MAX_STREAM_DATA = 0x11,
IETF_MAX_STREAMS_BIDIRECTIONAL = 0x12,
IETF_MAX_STREAMS_UNIDIRECTIONAL = 0x13,
- IETF_BLOCKED = 0x14, // TODO(fkastenholz): Should, eventually, be renamed to
- // IETF_DATA_BLOCKED
- IETF_STREAM_BLOCKED = 0x15, // TODO(fkastenholz): Should, eventually, be
- // renamed to IETF_STREAM_DATA_BLOCKED
+ IETF_DATA_BLOCKED = 0x14,
+ IETF_STREAM_DATA_BLOCKED = 0x15,
IETF_STREAMS_BLOCKED_BIDIRECTIONAL = 0x16,
IETF_STREAMS_BLOCKED_UNIDIRECTIONAL = 0x17,
IETF_NEW_CONNECTION_ID = 0x18,
@@ -272,6 +279,8 @@ enum QuicIetfFrameType : uint8_t {
IETF_CONNECTION_CLOSE = 0x1c,
IETF_APPLICATION_CLOSE = 0x1d,
+ IETF_HANDSHAKE_DONE = 0x1e,
+
// The MESSAGE frame type has not yet been fully standardized.
// QUIC versions starting with 46 and before 99 use 0x20-0x21.
// IETF QUIC (v99) uses 0x30-0x31, see draft-pauly-quic-datagram.
@@ -396,14 +405,6 @@ enum CongestionControlType {
kBBRv2,
};
-enum LossDetectionType : uint8_t {
- kNack, // Used to mimic TCP's loss detection.
- kTime, // Time based loss detection.
- kAdaptiveTime, // Adaptive time based loss detection.
- kLazyFack, // Nack based but with FACK disabled for the first ack.
- kIetfLossDetection, // IETF style loss detection.
-};
-
// EncryptionLevel enumerates the stages of encryption that a QUIC connection
// progresses through. When retransmitting a packet, the encryption level needs
// to be specified so that it is retransmitted at a level which the peer can
@@ -423,6 +424,15 @@ inline bool EncryptionLevelIsValid(EncryptionLevel level) {
QUIC_EXPORT_PRIVATE std::string EncryptionLevelToString(EncryptionLevel level);
+// Enumeration of whether a server endpoint will request a client certificate,
+// and whether that endpoint requires a valid client certificate to establish a
+// connection.
+enum class ClientCertMode {
+ kNone, // Do not request a client certificate. Default server behavior.
+ kRequest, // Request a certificate, but allow unauthenticated connections.
+ kRequire, // Require clients to provide a valid certificate.
+};
+
enum AddressChangeType : uint8_t {
// IP address and port remain unchanged.
NO_CHANGE,
@@ -440,6 +450,12 @@ enum AddressChangeType : uint8_t {
IPV6_TO_IPV6_CHANGE,
};
+QUIC_EXPORT_PRIVATE std::string AddressChangeTypeToString(
+ AddressChangeType type);
+
+QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
+ AddressChangeType type);
+
enum StreamSendingState {
// Sender has more data to send on this stream.
NO_FIN,
@@ -542,9 +558,12 @@ enum QuicIetfTransportErrorCodes : uint64_t {
FINAL_SIZE_ERROR = 0x6,
FRAME_ENCODING_ERROR = 0x7,
TRANSPORT_PARAMETER_ERROR = 0x8,
- VERSION_NEGOTIATION_ERROR = 0x9,
+ CONNECTION_ID_LIMIT_ERROR = 0x9,
PROTOCOL_VIOLATION = 0xA,
- INVALID_MIGRATION = 0xC,
+ INVALID_TOKEN = 0xB,
+ CRYPTO_BUFFER_EXCEEDED = 0xD,
+ CRYPTO_ERROR_FIRST = 0x100,
+ CRYPTO_ERROR_LAST = 0x1FF,
};
QUIC_EXPORT_PRIVATE std::string QuicIetfTransportErrorCodeString(
QuicIetfTransportErrorCodes c);
@@ -710,6 +729,27 @@ QUIC_EXPORT_PRIVATE std::ostream& operator<<(
QUIC_EXPORT_PRIVATE std::string QuicConnectionCloseTypeString(
QuicConnectionCloseType type);
+// Indicate handshake state of a connection.
+enum HandshakeState {
+ // Initial state.
+ HANDSHAKE_START,
+ // Only used in IETF QUIC with TLS handshake. State proceeds to
+ // HANDSHAKE_PROCESSED after a packet of HANDSHAKE packet number space
+ // gets successfully processed, and the initial key can be dropped.
+ HANDSHAKE_PROCESSED,
+ // In QUIC crypto, state proceeds to HANDSHAKE_COMPLETE if client receives
+ // SHLO or server successfully processes an ENCRYPTION_FORWARD_SECURE
+ // packet, such that the handshake packets can be neutered. In IETF QUIC
+ // with TLS handshake, state proceeds to HANDSHAKE_COMPLETE once the client
+ // has both 1-RTT send and receive keys.
+ HANDSHAKE_COMPLETE,
+ // Only used in IETF QUIC with TLS handshake. State proceeds to
+ // HANDSHAKE_CONFIRMED if 1) a client receives HANDSHAKE_DONE frame or
+ // acknowledgment for 1-RTT packet or 2) server has
+ // 1-RTT send and receive keys.
+ HANDSHAKE_CONFIRMED,
+};
+
} // namespace quic
#endif // QUICHE_QUIC_CORE_QUIC_TYPES_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_types_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_types_test.cc
index c7e4316a218..dc37c43e24e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_types_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_types_test.cc
@@ -6,7 +6,8 @@
#include <cstdint>
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
+#include "third_party/boringssl/src/include/openssl/ssl.h"
+#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
namespace quic {
@@ -16,19 +17,43 @@ namespace {
class QuicTypesTest : public QuicTest {};
TEST_F(QuicTypesTest, QuicIetfTransportErrorCodeString) {
- // QuicIetfTransportErrorCode out of bound.
- for (quic::QuicErrorCode error = quic::QUIC_ENCRYPTION_FAILURE;
- error < quic::QUIC_LAST_ERROR;
- error = static_cast<quic::QuicErrorCode>(error + 1)) {
- QuicErrorCodeToIetfMapping mapping =
- QuicErrorCodeToTransportErrorCode(error);
- if (mapping.is_transport_close_) {
- EXPECT_EQ(
- QuicIetfTransportErrorCodeString(mapping.transport_error_code_),
- QuicStrCat("Unknown Transport Error Code Value: ",
- static_cast<uint16_t>(mapping.transport_error_code_)));
- }
- }
+ EXPECT_EQ("Private(65280)",
+ QuicIetfTransportErrorCodeString(
+ static_cast<quic::QuicIetfTransportErrorCodes>(0xff00u)));
+
+ EXPECT_EQ("CRYPTO_ERROR(missing extension)",
+ QuicIetfTransportErrorCodeString(
+ static_cast<quic::QuicIetfTransportErrorCodes>(
+ CRYPTO_ERROR_FIRST + SSL_AD_MISSING_EXTENSION)));
+
+ EXPECT_EQ("NO_IETF_QUIC_ERROR",
+ QuicIetfTransportErrorCodeString(NO_IETF_QUIC_ERROR));
+ EXPECT_EQ("INTERNAL_ERROR", QuicIetfTransportErrorCodeString(INTERNAL_ERROR));
+ EXPECT_EQ("SERVER_BUSY_ERROR",
+ QuicIetfTransportErrorCodeString(SERVER_BUSY_ERROR));
+ EXPECT_EQ("FLOW_CONTROL_ERROR",
+ QuicIetfTransportErrorCodeString(FLOW_CONTROL_ERROR));
+ EXPECT_EQ("STREAM_LIMIT_ERROR",
+ QuicIetfTransportErrorCodeString(STREAM_LIMIT_ERROR));
+ EXPECT_EQ("STREAM_STATE_ERROR",
+ QuicIetfTransportErrorCodeString(STREAM_STATE_ERROR));
+ EXPECT_EQ("FINAL_SIZE_ERROR",
+ QuicIetfTransportErrorCodeString(FINAL_SIZE_ERROR));
+ EXPECT_EQ("FRAME_ENCODING_ERROR",
+ QuicIetfTransportErrorCodeString(FRAME_ENCODING_ERROR));
+ EXPECT_EQ("TRANSPORT_PARAMETER_ERROR",
+ QuicIetfTransportErrorCodeString(TRANSPORT_PARAMETER_ERROR));
+ EXPECT_EQ("CONNECTION_ID_LIMIT_ERROR",
+ QuicIetfTransportErrorCodeString(CONNECTION_ID_LIMIT_ERROR));
+ EXPECT_EQ("PROTOCOL_VIOLATION",
+ QuicIetfTransportErrorCodeString(PROTOCOL_VIOLATION));
+ EXPECT_EQ("INVALID_TOKEN", QuicIetfTransportErrorCodeString(INVALID_TOKEN));
+ EXPECT_EQ("CRYPTO_BUFFER_EXCEEDED",
+ QuicIetfTransportErrorCodeString(CRYPTO_BUFFER_EXCEEDED));
+
+ EXPECT_EQ("Unknown(1024)",
+ QuicIetfTransportErrorCodeString(
+ static_cast<quic::QuicIetfTransportErrorCodes>(0x400)));
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_udp_socket.h b/chromium/net/third_party/quiche/src/quic/core/quic_udp_socket.h
new file mode 100644
index 00000000000..04f84357dab
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_udp_socket.h
@@ -0,0 +1,248 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_CORE_QUIC_UDP_SOCKET_H_
+#define QUICHE_QUIC_CORE_QUIC_UDP_SOCKET_H_
+
+#include <cstddef>
+#include <cstdint>
+
+#include <type_traits>
+
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_ip_address.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
+
+namespace quic {
+
+#if defined(_WIN32)
+using QuicUdpSocketFd = SOCKET;
+const QuicUdpSocketFd kQuicInvalidSocketFd = INVALID_SOCKET;
+#else
+using QuicUdpSocketFd = int;
+const QuicUdpSocketFd kQuicInvalidSocketFd = -1;
+#endif
+
+const size_t kDefaultUdpPacketControlBufferSize = 512;
+
+enum class QuicUdpPacketInfoBit : uint8_t {
+ DROPPED_PACKETS = 0, // Read
+ V4_SELF_IP, // Read
+ V6_SELF_IP, // Read
+ PEER_ADDRESS, // Read & Write
+ RECV_TIMESTAMP, // Read
+ TTL, // Read & Write
+ GOOGLE_PACKET_HEADER, // Read
+ NUM_BITS,
+};
+static_assert(static_cast<size_t>(QuicUdpPacketInfoBit::NUM_BITS) <=
+ BitMask64::NumBits(),
+ "BitMask64 not wide enough to hold all bits.");
+
+// BufferSpan points to an unowned buffer, copying this structure only copies
+// the pointer and length, not the buffer itself.
+struct QUIC_EXPORT_PRIVATE BufferSpan {
+ BufferSpan(char* buffer, size_t buffer_len)
+ : buffer(buffer), buffer_len(buffer_len) {}
+
+ BufferSpan() = default;
+ BufferSpan(const BufferSpan& other) = default;
+ BufferSpan& operator=(const BufferSpan& other) = default;
+
+ char* buffer = nullptr;
+ size_t buffer_len = 0;
+};
+
+// QuicUdpPacketInfo contains per-packet information used for sending and
+// receiving.
+class QUIC_EXPORT_PRIVATE QuicUdpPacketInfo {
+ public:
+ BitMask64 bitmask() const { return bitmask_; }
+
+ void Reset() { bitmask_.ClearAll(); }
+
+ bool HasValue(QuicUdpPacketInfoBit bit) const { return bitmask_.IsSet(bit); }
+
+ QuicPacketCount dropped_packets() const {
+ DCHECK(HasValue(QuicUdpPacketInfoBit::DROPPED_PACKETS));
+ return dropped_packets_;
+ }
+
+ void SetDroppedPackets(QuicPacketCount dropped_packets) {
+ dropped_packets_ = dropped_packets;
+ bitmask_.Set(QuicUdpPacketInfoBit::DROPPED_PACKETS);
+ }
+
+ const QuicIpAddress& self_v4_ip() const {
+ DCHECK(HasValue(QuicUdpPacketInfoBit::V4_SELF_IP));
+ return self_v4_ip_;
+ }
+
+ void SetSelfV4Ip(QuicIpAddress self_v4_ip) {
+ self_v4_ip_ = self_v4_ip;
+ bitmask_.Set(QuicUdpPacketInfoBit::V4_SELF_IP);
+ }
+
+ const QuicIpAddress& self_v6_ip() const {
+ DCHECK(HasValue(QuicUdpPacketInfoBit::V6_SELF_IP));
+ return self_v6_ip_;
+ }
+
+ void SetSelfV6Ip(QuicIpAddress self_v6_ip) {
+ self_v6_ip_ = self_v6_ip;
+ bitmask_.Set(QuicUdpPacketInfoBit::V6_SELF_IP);
+ }
+
+ void SetSelfIp(QuicIpAddress self_ip) {
+ if (self_ip.IsIPv4()) {
+ SetSelfV4Ip(self_ip);
+ } else {
+ SetSelfV6Ip(self_ip);
+ }
+ }
+
+ const QuicSocketAddress& peer_address() const {
+ DCHECK(HasValue(QuicUdpPacketInfoBit::PEER_ADDRESS));
+ return peer_address_;
+ }
+
+ void SetPeerAddress(QuicSocketAddress peer_address) {
+ peer_address_ = peer_address;
+ bitmask_.Set(QuicUdpPacketInfoBit::PEER_ADDRESS);
+ }
+
+ QuicWallTime receive_timestamp() const {
+ DCHECK(HasValue(QuicUdpPacketInfoBit::RECV_TIMESTAMP));
+ return receive_timestamp_;
+ }
+
+ void SetReceiveTimestamp(QuicWallTime receive_timestamp) {
+ receive_timestamp_ = receive_timestamp;
+ bitmask_.Set(QuicUdpPacketInfoBit::RECV_TIMESTAMP);
+ }
+
+ int ttl() const {
+ DCHECK(HasValue(QuicUdpPacketInfoBit::TTL));
+ return ttl_;
+ }
+
+ void SetTtl(int ttl) {
+ ttl_ = ttl;
+ bitmask_.Set(QuicUdpPacketInfoBit::TTL);
+ }
+
+ BufferSpan google_packet_headers() const {
+ DCHECK(HasValue(QuicUdpPacketInfoBit::GOOGLE_PACKET_HEADER));
+ return google_packet_headers_;
+ }
+
+ void SetGooglePacketHeaders(BufferSpan google_packet_headers) {
+ google_packet_headers_ = google_packet_headers;
+ bitmask_.Set(QuicUdpPacketInfoBit::GOOGLE_PACKET_HEADER);
+ }
+
+ private:
+ BitMask64 bitmask_;
+ QuicPacketCount dropped_packets_;
+ QuicIpAddress self_v4_ip_;
+ QuicIpAddress self_v6_ip_;
+ QuicSocketAddress peer_address_;
+ QuicWallTime receive_timestamp_ = QuicWallTime::Zero();
+ int ttl_;
+ BufferSpan google_packet_headers_;
+};
+
+// QuicUdpSocketApi provides a minimal set of apis for sending and receiving
+// udp packets. The low level udp socket apis differ between kernels and kernel
+// versions, the goal of QuicUdpSocketApi is to hide such differences.
+// We use non-static functions because it is easier to be mocked in tests when
+// needed.
+class QUIC_EXPORT_PRIVATE QuicUdpSocketApi {
+ public:
+ // Creates a non-blocking udp socket, sets the receive/send buffer and enable
+ // receiving of self ip addresses on read.
+ // Return kQuicInvalidSocketFd if failed.
+ QuicUdpSocketFd Create(int address_family,
+ int receive_buffer_size,
+ int send_buffer_size);
+
+ // Closes |fd|. No-op if |fd| equals to kQuicInvalidSocketFd.
+ void Destroy(QuicUdpSocketFd fd);
+
+ // Bind |fd| to |address|. If |address|'s port number is 0, kernel will choose
+ // a random port to bind to. Caller can use QuicSocketAddress::FromSocket(fd)
+ // to get the bound random port.
+ bool Bind(QuicUdpSocketFd fd, QuicSocketAddress address);
+
+ // Enable receiving of various per-packet information. Return true if the
+ // corresponding information can be received on read.
+ bool EnableDroppedPacketCount(QuicUdpSocketFd fd);
+ bool EnableReceiveTimestamp(QuicUdpSocketFd fd);
+ bool EnableReceiveTtlForV4(QuicUdpSocketFd fd);
+ bool EnableReceiveTtlForV6(QuicUdpSocketFd fd);
+
+ // Wait for |fd| to become readable, up to |timeout|.
+ // Return true if |fd| is readable upon return.
+ bool WaitUntilReadable(QuicUdpSocketFd fd, QuicTime::Delta timeout);
+
+ struct QUIC_EXPORT_PRIVATE ReadPacketResult {
+ bool ok = false;
+ QuicUdpPacketInfo packet_info;
+ BufferSpan packet_buffer;
+ BufferSpan control_buffer;
+
+ void Reset(size_t packet_buffer_length) {
+ ok = false;
+ packet_info.Reset();
+ packet_buffer.buffer_len = packet_buffer_length;
+ }
+ };
+ // Read a packet from |fd|:
+ // packet_info_interested: Bitmask indicating what information caller wants to
+ // receive into |result->packet_info|.
+ // result->packet_info: Received per packet information.
+ // result->packet_buffer: The packet buffer, to be filled with packet data.
+ // |result->packet_buffer.buffer_len| is set to the
+ // packet length on a successful return.
+ // result->control_buffer: The control buffer, used by ReadPacket internally.
+ // It is recommended to be
+ // |kDefaultUdpPacketControlBufferSize| bytes.
+ // result->ok: True iff a packet is successfully received.
+ //
+ // If |*result| is reused for subsequent ReadPacket() calls, caller needs to
+ // call result->Reset() before each ReadPacket().
+ void ReadPacket(QuicUdpSocketFd fd,
+ BitMask64 packet_info_interested,
+ ReadPacketResult* result);
+
+ using ReadPacketResults = std::vector<ReadPacketResult>;
+ // Read up to |results->size()| packets from |fd|. The meaning of each element
+ // in |*results| has been documented on top of |ReadPacket|.
+ // Return the number of elements populated into |*results|, note it is
+ // possible for some of the populated elements to have ok=false.
+ size_t ReadMultiplePackets(QuicUdpSocketFd fd,
+ BitMask64 packet_info_interested,
+ ReadPacketResults* results);
+
+ // Write a packet to |fd|.
+ // packet_buffer, packet_buffer_len: The packet buffer to write.
+ // packet_info: The per packet information to set.
+ WriteResult WritePacket(QuicUdpSocketFd fd,
+ const char* packet_buffer,
+ size_t packet_buffer_len,
+ const QuicUdpPacketInfo& packet_info);
+
+ protected:
+ bool SetupSocket(QuicUdpSocketFd fd,
+ int address_family,
+ int receive_buffer_size,
+ int send_buffer_size);
+ bool EnableReceiveSelfIpAddressForV4(QuicUdpSocketFd fd);
+ bool EnableReceiveSelfIpAddressForV6(QuicUdpSocketFd fd);
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_QUIC_UDP_SOCKET_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_udp_socket_posix.cc b/chromium/net/third_party/quiche/src/quic/core/quic_udp_socket_posix.cc
new file mode 100644
index 00000000000..b6c58cdb1d3
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_udp_socket_posix.cc
@@ -0,0 +1,633 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/quic_udp_socket.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_udp_socket_platform_api.h"
+
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#if defined(__APPLE__) && !defined(__APPLE_USE_RFC_3542)
+#error "__APPLE_USE_RFC_3542 needs to be defined."
+#endif
+
+#if defined(__linux__)
+#include <alloca.h>
+// For SO_TIMESTAMPING.
+#include <linux/net_tstamp.h>
+#endif
+
+#if defined(__linux__) && !defined(__ANDROID__)
+#define QUIC_UDP_SOCKET_SUPPORT_TTL 1
+#endif
+
+namespace quic {
+namespace {
+
+#if defined(__linux__) && (!defined(__ANDROID_API__) || __ANDROID_API__ >= 21)
+#define QUIC_UDP_SOCKET_SUPPORT_LINUX_TIMESTAMPING 1
+// This is the structure that SO_TIMESTAMPING fills into the cmsg header.
+// It is well-defined, but does not have a definition in a public header.
+// See https://www.kernel.org/doc/Documentation/networking/timestamping.txt
+// for more information.
+struct LinuxSoTimestamping {
+ // The converted system time of the timestamp.
+ struct timespec systime;
+ // Deprecated; serves only as padding.
+ struct timespec hwtimetrans;
+ // The raw hardware timestamp.
+ struct timespec hwtimeraw;
+};
+const size_t kCmsgSpaceForRecvTimestamp =
+ CMSG_SPACE(sizeof(LinuxSoTimestamping));
+#else
+const size_t kCmsgSpaceForRecvTimestamp = 0;
+#endif
+
+const size_t kMinCmsgSpaceForRead =
+ CMSG_SPACE(sizeof(uint32_t)) // Dropped packet count
+ + CMSG_SPACE(sizeof(in_pktinfo)) // V4 Self IP
+ + CMSG_SPACE(sizeof(in6_pktinfo)) // V6 Self IP
+ + kCmsgSpaceForRecvTimestamp + CMSG_SPACE(sizeof(int)) // TTL
+ + kCmsgSpaceForGooglePacketHeader;
+
+QuicUdpSocketFd CreateNonblockingSocket(int address_family) {
+#if defined(__linux__) && defined(SOCK_NONBLOCK)
+
+ // Create a nonblocking socket directly.
+ int fd = socket(address_family, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
+ if (fd < 0) {
+ QUIC_LOG_FIRST_N(ERROR, 100)
+ << "socket() failed with address_family=" << address_family << ": "
+ << strerror(errno);
+ return kQuicInvalidSocketFd;
+ }
+
+ return fd;
+
+#else
+
+ // Create a socket and use fcntl to set it to nonblocking.
+ // This implementation is used when building for iOS, OSX and old versions of
+ // Linux (< 2.6.27) and old versions of Android (< API 21).
+ int fd = socket(address_family, SOCK_DGRAM, IPPROTO_UDP);
+ if (fd < 0) {
+ QUIC_LOG_FIRST_N(ERROR, 100)
+ << "socket() failed with address_family=" << address_family << ": "
+ << strerror(errno);
+ return kQuicInvalidSocketFd;
+ }
+ int current_flags = fcntl(fd, F_GETFL, 0);
+ if (current_flags == -1) {
+ QUIC_LOG_FIRST_N(ERROR, 100)
+ << "failed to get current socket flags: " << strerror(errno);
+ close(fd);
+ return kQuicInvalidSocketFd;
+ }
+
+ int rc = fcntl(fd, F_SETFL, current_flags | O_NONBLOCK);
+ if (rc == -1) {
+ QUIC_LOG_FIRST_N(ERROR, 100)
+ << "failed to set socket to non-blocking: " << strerror(errno);
+ close(fd);
+ return kQuicInvalidSocketFd;
+ }
+
+ return fd;
+
+#endif
+} // End CreateNonblockingSocket
+
+void SetV4SelfIpInControlMessage(const QuicIpAddress& self_address,
+ cmsghdr* cmsg) {
+ DCHECK(self_address.IsIPv4());
+ in_pktinfo* pktinfo = reinterpret_cast<in_pktinfo*>(CMSG_DATA(cmsg));
+ memset(pktinfo, 0, sizeof(in_pktinfo));
+ pktinfo->ipi_ifindex = 0;
+ std::string address_string = self_address.ToPackedString();
+ memcpy(&pktinfo->ipi_spec_dst, address_string.c_str(),
+ address_string.length());
+}
+
+void SetV6SelfIpInControlMessage(const QuicIpAddress& self_address,
+ cmsghdr* cmsg) {
+ DCHECK(self_address.IsIPv6());
+ in6_pktinfo* pktinfo = reinterpret_cast<in6_pktinfo*>(CMSG_DATA(cmsg));
+ memset(pktinfo, 0, sizeof(in6_pktinfo));
+ std::string address_string = self_address.ToPackedString();
+ memcpy(&pktinfo->ipi6_addr, address_string.c_str(), address_string.length());
+}
+
+void PopulatePacketInfoFromControlMessage(struct cmsghdr* cmsg,
+ QuicUdpPacketInfo* packet_info,
+ BitMask64 packet_info_interested) {
+#if defined(__linux__) && defined(SO_RXQ_OVFL)
+ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL) {
+ if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::DROPPED_PACKETS)) {
+ packet_info->SetDroppedPackets(
+ *(reinterpret_cast<uint32_t*> CMSG_DATA(cmsg)));
+ }
+ return;
+ }
+#endif
+
+#if defined(QUIC_UDP_SOCKET_SUPPORT_LINUX_TIMESTAMPING)
+ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMPING) {
+ if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::RECV_TIMESTAMP)) {
+ LinuxSoTimestamping* linux_ts =
+ reinterpret_cast<LinuxSoTimestamping*>(CMSG_DATA(cmsg));
+ timespec* ts = &linux_ts->systime;
+ int64_t usec = (static_cast<int64_t>(ts->tv_sec) * 1000 * 1000) +
+ (static_cast<int64_t>(ts->tv_nsec) / 1000);
+ packet_info->SetReceiveTimestamp(
+ QuicWallTime::FromUNIXMicroseconds(usec));
+ }
+ return;
+ }
+#endif
+
+ if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
+ if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::V6_SELF_IP)) {
+ const in6_pktinfo* info = reinterpret_cast<in6_pktinfo*>(CMSG_DATA(cmsg));
+ const char* addr_data = reinterpret_cast<const char*>(&info->ipi6_addr);
+ int addr_len = sizeof(in6_addr);
+ QuicIpAddress self_v6_ip;
+ if (self_v6_ip.FromPackedString(addr_data, addr_len)) {
+ packet_info->SetSelfV6Ip(self_v6_ip);
+ } else {
+ QUIC_BUG << "QuicIpAddress::FromPackedString failed";
+ }
+ }
+ return;
+ }
+
+ if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
+ if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::V4_SELF_IP)) {
+ const in_pktinfo* info = reinterpret_cast<in_pktinfo*>(CMSG_DATA(cmsg));
+ const char* addr_data = reinterpret_cast<const char*>(&info->ipi_addr);
+ int addr_len = sizeof(in_addr);
+ QuicIpAddress self_v4_ip;
+ if (self_v4_ip.FromPackedString(addr_data, addr_len)) {
+ packet_info->SetSelfV4Ip(self_v4_ip);
+ } else {
+ QUIC_BUG << "QuicIpAddress::FromPackedString failed";
+ }
+ }
+ return;
+ }
+
+ if ((cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_TTL) ||
+ (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_HOPLIMIT)) {
+ if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::TTL)) {
+ packet_info->SetTtl(*(reinterpret_cast<int*>(CMSG_DATA(cmsg))));
+ }
+ return;
+ }
+
+ if (packet_info_interested.IsSet(
+ QuicUdpPacketInfoBit::GOOGLE_PACKET_HEADER)) {
+ BufferSpan google_packet_headers;
+ if (GetGooglePacketHeadersFromControlMessage(
+ cmsg, &google_packet_headers.buffer,
+ &google_packet_headers.buffer_len)) {
+ packet_info->SetGooglePacketHeaders(google_packet_headers);
+ }
+ }
+}
+
+bool NextCmsg(msghdr* hdr,
+ char* control_buffer,
+ size_t control_buffer_len,
+ int cmsg_level,
+ int cmsg_type,
+ size_t data_size,
+ cmsghdr** cmsg /*in, out*/) {
+ // msg_controllen needs to be increased first, otherwise CMSG_NXTHDR will
+ // return nullptr.
+ hdr->msg_controllen += CMSG_SPACE(data_size);
+ if (hdr->msg_controllen > control_buffer_len) {
+ return false;
+ }
+
+ if ((*cmsg) == nullptr) {
+ DCHECK_EQ(nullptr, hdr->msg_control);
+ memset(control_buffer, 0, control_buffer_len);
+ hdr->msg_control = control_buffer;
+ (*cmsg) = CMSG_FIRSTHDR(hdr);
+ } else {
+ DCHECK_NE(nullptr, hdr->msg_control);
+ (*cmsg) = CMSG_NXTHDR(hdr, (*cmsg));
+ }
+
+ if (nullptr == (*cmsg)) {
+ return false;
+ }
+
+ (*cmsg)->cmsg_len = CMSG_LEN(data_size);
+ (*cmsg)->cmsg_level = cmsg_level;
+ (*cmsg)->cmsg_type = cmsg_type;
+
+ return true;
+}
+} // namespace
+
+QuicUdpSocketFd QuicUdpSocketApi::Create(int address_family,
+ int receive_buffer_size,
+ int send_buffer_size) {
+ // DCHECK here so the program exits early(before reading packets) in debug
+ // mode. This should have been a static_assert, however it can't be done on
+ // ios/osx because CMSG_SPACE isn't a constant expression there.
+ DCHECK_GE(kDefaultUdpPacketControlBufferSize, kMinCmsgSpaceForRead);
+ QuicUdpSocketFd fd = CreateNonblockingSocket(address_family);
+
+ if (fd == kQuicInvalidSocketFd) {
+ return kQuicInvalidSocketFd;
+ }
+
+ if (!SetupSocket(fd, address_family, receive_buffer_size, send_buffer_size)) {
+ Destroy(fd);
+ return kQuicInvalidSocketFd;
+ }
+
+ return fd;
+}
+
+bool QuicUdpSocketApi::SetupSocket(QuicUdpSocketFd fd,
+ int address_family,
+ int receive_buffer_size,
+ int send_buffer_size) {
+ // Receive buffer size.
+ if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &receive_buffer_size,
+ sizeof(receive_buffer_size)) != 0) {
+ QUIC_LOG_FIRST_N(ERROR, 100) << "Failed to set socket recv size";
+ return false;
+ }
+
+ // Send buffer size.
+ if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &send_buffer_size,
+ sizeof(send_buffer_size)) != 0) {
+ QUIC_LOG_FIRST_N(ERROR, 100) << "Failed to set socket send size";
+ return false;
+ }
+
+ if (!EnableReceiveSelfIpAddressForV4(fd)) {
+ QUIC_LOG_FIRST_N(ERROR, 100) << "Failed to enable receiving of self v4 ip";
+ return false;
+ }
+
+ if (address_family == AF_INET6 && !EnableReceiveSelfIpAddressForV6(fd)) {
+ QUIC_LOG_FIRST_N(ERROR, 100) << "Failed to enable receiving of self v6 ip";
+ return false;
+ }
+
+ return true;
+}
+
+void QuicUdpSocketApi::Destroy(QuicUdpSocketFd fd) {
+ if (fd != kQuicInvalidSocketFd) {
+ close(fd);
+ }
+}
+
+bool QuicUdpSocketApi::Bind(QuicUdpSocketFd fd, QuicSocketAddress address) {
+ sockaddr_storage addr = address.generic_address();
+ int addr_len =
+ address.host().IsIPv4() ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
+ return 0 == bind(fd, reinterpret_cast<sockaddr*>(&addr), addr_len);
+}
+
+bool QuicUdpSocketApi::EnableDroppedPacketCount(QuicUdpSocketFd fd) {
+#if defined(__linux__) && defined(SO_RXQ_OVFL)
+ int get_overflow = 1;
+ return 0 == setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow,
+ sizeof(get_overflow));
+#else
+ (void)fd;
+ return false;
+#endif
+}
+
+bool QuicUdpSocketApi::EnableReceiveSelfIpAddressForV4(QuicUdpSocketFd fd) {
+ int get_self_ip = 1;
+ return 0 == setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &get_self_ip,
+ sizeof(get_self_ip));
+}
+
+bool QuicUdpSocketApi::EnableReceiveSelfIpAddressForV6(QuicUdpSocketFd fd) {
+ int get_self_ip = 1;
+ return 0 == setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &get_self_ip,
+ sizeof(get_self_ip));
+}
+
+bool QuicUdpSocketApi::EnableReceiveTimestamp(QuicUdpSocketFd fd) {
+#if defined(__linux__) && (!defined(__ANDROID_API__) || __ANDROID_API__ >= 21)
+ int timestamping = SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE;
+ return 0 == setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, &timestamping,
+ sizeof(timestamping));
+#else
+ (void)fd;
+ return false;
+#endif
+}
+
+bool QuicUdpSocketApi::EnableReceiveTtlForV4(QuicUdpSocketFd fd) {
+#if defined(QUIC_UDP_SOCKET_SUPPORT_TTL)
+ int get_ttl = 1;
+ return 0 == setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &get_ttl, sizeof(get_ttl));
+#else
+ (void)fd;
+ return false;
+#endif
+}
+
+bool QuicUdpSocketApi::EnableReceiveTtlForV6(QuicUdpSocketFd fd) {
+#if defined(QUIC_UDP_SOCKET_SUPPORT_TTL)
+ int get_ttl = 1;
+ return 0 == setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &get_ttl,
+ sizeof(get_ttl));
+#else
+ (void)fd;
+ return false;
+#endif
+}
+
+bool QuicUdpSocketApi::WaitUntilReadable(QuicUdpSocketFd fd,
+ QuicTime::Delta timeout) {
+ fd_set read_fds;
+ FD_ZERO(&read_fds);
+ FD_SET(fd, &read_fds);
+
+ timeval select_timeout;
+ select_timeout.tv_sec = timeout.ToSeconds();
+ select_timeout.tv_usec = timeout.ToMicroseconds() % 1000000;
+
+ return 1 == select(1 + fd, &read_fds, nullptr, nullptr, &select_timeout);
+}
+
+void QuicUdpSocketApi::ReadPacket(QuicUdpSocketFd fd,
+ BitMask64 packet_info_interested,
+ ReadPacketResult* result) {
+ result->ok = false;
+ BufferSpan& packet_buffer = result->packet_buffer;
+ BufferSpan& control_buffer = result->control_buffer;
+ QuicUdpPacketInfo* packet_info = &result->packet_info;
+
+ DCHECK_GE(control_buffer.buffer_len, kMinCmsgSpaceForRead);
+
+ struct iovec iov = {packet_buffer.buffer, packet_buffer.buffer_len};
+ struct sockaddr_storage raw_peer_address;
+
+ if (control_buffer.buffer_len > 0) {
+ reinterpret_cast<struct cmsghdr*>(control_buffer.buffer)->cmsg_len =
+ control_buffer.buffer_len;
+ }
+
+ msghdr hdr;
+ hdr.msg_name = &raw_peer_address;
+ hdr.msg_namelen = sizeof(raw_peer_address);
+ hdr.msg_iov = &iov;
+ hdr.msg_iovlen = 1;
+ hdr.msg_flags = 0;
+ hdr.msg_control = control_buffer.buffer;
+ hdr.msg_controllen = control_buffer.buffer_len;
+
+#if defined(__linux__)
+ // If MSG_TRUNC is set on Linux, recvmsg will return the real packet size even
+ // if |packet_buffer| is too small to receive it.
+ int flags = MSG_TRUNC;
+#else
+ int flags = 0;
+#endif
+
+ int bytes_read = recvmsg(fd, &hdr, flags);
+ if (bytes_read < 0) {
+ const int error_num = errno;
+ if (error_num != EAGAIN) {
+ QUIC_LOG_FIRST_N(ERROR, 100)
+ << "Error reading packet: " << strerror(error_num);
+ }
+ return;
+ }
+
+ if (QUIC_PREDICT_FALSE(hdr.msg_flags & MSG_CTRUNC)) {
+ QUIC_BUG << "Control buffer too small. size:" << control_buffer.buffer_len;
+ return;
+ }
+
+ if (QUIC_PREDICT_FALSE(hdr.msg_flags & MSG_TRUNC) ||
+ // Normally "bytes_read > packet_buffer.buffer_len" implies the MSG_TRUNC
+ // bit is set, but it is not the case if tested with config=android_arm64.
+ static_cast<size_t>(bytes_read) > packet_buffer.buffer_len) {
+ QUIC_LOG_FIRST_N(WARNING, 100)
+ << "Received truncated QUIC packet: buffer size:"
+ << packet_buffer.buffer_len << " packet size:" << bytes_read;
+ return;
+ }
+
+ packet_buffer.buffer_len = bytes_read;
+ if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::PEER_ADDRESS)) {
+ packet_info->SetPeerAddress(QuicSocketAddress(raw_peer_address));
+ }
+
+ if (hdr.msg_controllen > 0) {
+ for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr); cmsg != nullptr;
+ cmsg = CMSG_NXTHDR(&hdr, cmsg)) {
+ BitMask64 prior_bitmask = packet_info->bitmask();
+ PopulatePacketInfoFromControlMessage(cmsg, packet_info,
+ packet_info_interested);
+ if (packet_info->bitmask() == prior_bitmask) {
+ QUIC_DLOG(INFO) << "Ignored cmsg_level:" << cmsg->cmsg_level
+ << ", cmsg_type:" << cmsg->cmsg_type;
+ }
+ }
+ }
+
+ result->ok = true;
+}
+
+size_t QuicUdpSocketApi::ReadMultiplePackets(QuicUdpSocketFd fd,
+ BitMask64 packet_info_interested,
+ ReadPacketResults* results) {
+#if defined(__linux__) && !defined(__ANDROID__)
+ // Use recvmmsg.
+ size_t hdrs_size = sizeof(mmsghdr) * results->size();
+ mmsghdr* hdrs = static_cast<mmsghdr*>(alloca(hdrs_size));
+ memset(hdrs, 0, hdrs_size);
+
+ struct TempPerPacketData {
+ iovec iov;
+ sockaddr_storage raw_peer_address;
+ };
+ TempPerPacketData* packet_data_array = static_cast<TempPerPacketData*>(
+ alloca(sizeof(TempPerPacketData) * results->size()));
+
+ for (size_t i = 0; i < results->size(); ++i) {
+ (*results)[i].ok = false;
+
+ msghdr* hdr = &hdrs[i].msg_hdr;
+ TempPerPacketData* packet_data = &packet_data_array[i];
+ packet_data->iov.iov_base = (*results)[i].packet_buffer.buffer;
+ packet_data->iov.iov_len = (*results)[i].packet_buffer.buffer_len;
+
+ hdr->msg_name = &packet_data->raw_peer_address;
+ hdr->msg_namelen = sizeof(sockaddr_storage);
+ hdr->msg_iov = &packet_data->iov;
+ hdr->msg_iovlen = 1;
+ hdr->msg_flags = 0;
+ hdr->msg_control = (*results)[i].control_buffer.buffer;
+ hdr->msg_controllen = (*results)[i].control_buffer.buffer_len;
+
+ DCHECK_GE(hdr->msg_controllen, kMinCmsgSpaceForRead);
+ }
+ // If MSG_TRUNC is set on Linux, recvmmsg will return the real packet size in
+ // |hdrs[i].msg_len| even if packet buffer is too small to receive it.
+ int packets_read = recvmmsg(fd, hdrs, results->size(), MSG_TRUNC, nullptr);
+ if (packets_read <= 0) {
+ const int error_num = errno;
+ if (error_num != EAGAIN) {
+ QUIC_LOG_FIRST_N(ERROR, 100)
+ << "Error reading packets: " << strerror(error_num);
+ }
+ return 0;
+ }
+
+ for (int i = 0; i < packets_read; ++i) {
+ if (hdrs[i].msg_len == 0) {
+ continue;
+ }
+
+ msghdr& hdr = hdrs[i].msg_hdr;
+ if (QUIC_PREDICT_FALSE(hdr.msg_flags & MSG_CTRUNC)) {
+ QUIC_BUG << "Control buffer too small. size:"
+ << (*results)[i].control_buffer.buffer_len
+ << ", need:" << hdr.msg_controllen;
+ continue;
+ }
+
+ if (QUIC_PREDICT_FALSE(hdr.msg_flags & MSG_TRUNC)) {
+ QUIC_LOG_FIRST_N(WARNING, 100)
+ << "Received truncated QUIC packet: buffer size:"
+ << (*results)[i].packet_buffer.buffer_len
+ << " packet size:" << hdrs[i].msg_len;
+ continue;
+ }
+
+ (*results)[i].ok = true;
+ (*results)[i].packet_buffer.buffer_len = hdrs[i].msg_len;
+
+ QuicUdpPacketInfo* packet_info = &(*results)[i].packet_info;
+ if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::PEER_ADDRESS)) {
+ packet_info->SetPeerAddress(
+ QuicSocketAddress(packet_data_array[i].raw_peer_address));
+ }
+
+ if (hdr.msg_controllen > 0) {
+ for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr); cmsg != nullptr;
+ cmsg = CMSG_NXTHDR(&hdr, cmsg)) {
+ PopulatePacketInfoFromControlMessage(cmsg, packet_info,
+ packet_info_interested);
+ }
+ }
+ }
+ return packets_read;
+#else
+ size_t num_packets = 0;
+ for (ReadPacketResult& result : *results) {
+ result.ok = false;
+ }
+ for (ReadPacketResult& result : *results) {
+ errno = 0;
+ ReadPacket(fd, packet_info_interested, &result);
+ if (!result.ok && errno == EAGAIN) {
+ break;
+ }
+ ++num_packets;
+ }
+ return num_packets;
+#endif
+}
+
+WriteResult QuicUdpSocketApi::WritePacket(
+ QuicUdpSocketFd fd,
+ const char* packet_buffer,
+ size_t packet_buffer_len,
+ const QuicUdpPacketInfo& packet_info) {
+ if (!packet_info.HasValue(QuicUdpPacketInfoBit::PEER_ADDRESS)) {
+ return WriteResult(WRITE_STATUS_ERROR, EINVAL);
+ }
+
+ char control_buffer[512];
+ sockaddr_storage raw_peer_address =
+ packet_info.peer_address().generic_address();
+ iovec iov = {const_cast<char*>(packet_buffer), packet_buffer_len};
+
+ msghdr hdr;
+ hdr.msg_name = &raw_peer_address;
+ hdr.msg_namelen = packet_info.peer_address().host().IsIPv4()
+ ? sizeof(sockaddr_in)
+ : sizeof(sockaddr_in6);
+ hdr.msg_iov = &iov;
+ hdr.msg_iovlen = 1;
+ hdr.msg_flags = 0;
+ hdr.msg_control = nullptr;
+ hdr.msg_controllen = 0;
+
+ cmsghdr* cmsg = nullptr;
+
+ // Set self IP.
+ if (packet_info.HasValue(QuicUdpPacketInfoBit::V4_SELF_IP) &&
+ packet_info.self_v4_ip().IsInitialized()) {
+ if (!NextCmsg(&hdr, control_buffer, sizeof(control_buffer), IPPROTO_IP,
+ IP_PKTINFO, sizeof(in_pktinfo), &cmsg)) {
+ QUIC_LOG_FIRST_N(ERROR, 100)
+ << "Not enough buffer to set self v4 ip address.";
+ return WriteResult(WRITE_STATUS_ERROR, EINVAL);
+ }
+ SetV4SelfIpInControlMessage(packet_info.self_v4_ip(), cmsg);
+ } else if (packet_info.HasValue(QuicUdpPacketInfoBit::V6_SELF_IP) &&
+ packet_info.self_v6_ip().IsInitialized()) {
+ if (!NextCmsg(&hdr, control_buffer, sizeof(control_buffer), IPPROTO_IPV6,
+ IPV6_PKTINFO, sizeof(in6_pktinfo), &cmsg)) {
+ QUIC_LOG_FIRST_N(ERROR, 100)
+ << "Not enough buffer to set self v6 ip address.";
+ return WriteResult(WRITE_STATUS_ERROR, EINVAL);
+ }
+ SetV6SelfIpInControlMessage(packet_info.self_v6_ip(), cmsg);
+ }
+
+#if defined(QUIC_UDP_SOCKET_SUPPORT_TTL)
+ // Set ttl.
+ if (packet_info.HasValue(QuicUdpPacketInfoBit::TTL)) {
+ int cmsg_level =
+ packet_info.peer_address().host().IsIPv4() ? IPPROTO_IP : IPPROTO_IPV6;
+ int cmsg_type =
+ packet_info.peer_address().host().IsIPv4() ? IP_TTL : IPV6_HOPLIMIT;
+ if (!NextCmsg(&hdr, control_buffer, sizeof(control_buffer), cmsg_level,
+ cmsg_type, sizeof(int), &cmsg)) {
+ QUIC_LOG_FIRST_N(ERROR, 100) << "Not enough buffer to set ttl.";
+ return WriteResult(WRITE_STATUS_ERROR, EINVAL);
+ }
+ *reinterpret_cast<int*>(CMSG_DATA(cmsg)) = packet_info.ttl();
+ }
+#endif
+
+ int rc;
+ do {
+ rc = sendmsg(fd, &hdr, 0);
+ } while (rc < 0 && errno == EINTR);
+ if (rc >= 0) {
+ return WriteResult(WRITE_STATUS_OK, rc);
+ }
+ return WriteResult((errno == EAGAIN || errno == EWOULDBLOCK)
+ ? WRITE_STATUS_BLOCKED
+ : WRITE_STATUS_ERROR,
+ errno);
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_udp_socket_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_udp_socket_test.cc
new file mode 100644
index 00000000000..e43fb10c40b
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_udp_socket_test.cc
@@ -0,0 +1,403 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/quic_udp_socket.h"
+
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+
+namespace quic {
+namespace test {
+namespace {
+// Used by ReadMultiplePackets tests.
+struct ReadBuffers {
+ char control_buffer[512];
+ char packet_buffer[1536];
+};
+} // namespace
+
+class QuicUdpSocketTest : public QuicTest {
+ protected:
+ void SetUp() override {
+ // Try creating AF_INET socket, if it fails because of unsupported address
+ // family then tests are being run under IPv6-only environment, initialize
+ // address family to use for running the test under as AF_INET6 otherwise
+ // initialize it as AF_INET.
+ address_family_ = AF_INET;
+ fd_client_ =
+ api_.Create(address_family_,
+ /*receive_buffer_size =*/kDefaultSocketReceiveBuffer,
+ /*send_buffer_size =*/kDefaultSocketReceiveBuffer);
+ if (fd_client_ == kQuicInvalidSocketFd) {
+ address_family_ = AF_INET6;
+ fd_client_ =
+ api_.Create(address_family_,
+ /*receive_buffer_size =*/kDefaultSocketReceiveBuffer,
+ /*send_buffer_size =*/kDefaultSocketReceiveBuffer);
+ }
+ ASSERT_NE(fd_client_, kQuicInvalidSocketFd);
+
+ fd_server_ =
+ api_.Create(address_family_,
+ /*receive_buffer_size =*/kDefaultSocketReceiveBuffer,
+ /*send_buffer_size =*/kDefaultSocketReceiveBuffer);
+ ASSERT_NE(fd_server_, kQuicInvalidSocketFd);
+
+ ASSERT_TRUE(
+ api_.Bind(fd_server_, QuicSocketAddress(Loopback(), /*port=*/0)));
+
+ ASSERT_EQ(0, server_address_.FromSocket(fd_server_));
+
+ QUIC_LOG(INFO) << "Testing under IP"
+ << std::string((address_family_ == AF_INET) ? "v4" : "v6");
+ }
+
+ ~QuicUdpSocketTest() {
+ api_.Destroy(fd_client_);
+ api_.Destroy(fd_server_);
+ }
+
+ QuicIpAddress Loopback() const {
+ return (address_family_ == AF_INET) ? QuicIpAddress::Loopback4()
+ : QuicIpAddress::Loopback6();
+ }
+
+ // Client sends the first |packet_size| bytes in |client_packet_buffer_| to
+ // server.
+ WriteResult SendPacketFromClient(size_t packet_size) {
+ EXPECT_LE(packet_size, sizeof(client_packet_buffer_));
+ QuicUdpPacketInfo packet_info;
+ packet_info.SetPeerAddress(server_address_);
+ return api_.WritePacket(fd_client_, client_packet_buffer_, packet_size,
+ packet_info);
+ }
+
+ WriteResult SendPacketFromClientWithTtl(size_t packet_size, int ttl) {
+ EXPECT_LE(packet_size, sizeof(client_packet_buffer_));
+ QuicUdpPacketInfo packet_info;
+ packet_info.SetPeerAddress(server_address_);
+ packet_info.SetTtl(ttl);
+ return api_.WritePacket(fd_client_, client_packet_buffer_, packet_size,
+ packet_info);
+ }
+
+ // Server waits for an incoming packet and reads it into
+ // |server_packet_buffer_|.
+ QuicUdpSocketApi::ReadPacketResult ReadPacketFromServer(
+ BitMask64 packet_info_interested) {
+ EXPECT_TRUE(
+ api_.WaitUntilReadable(fd_server_, QuicTime::Delta::FromSeconds(5)));
+ memset(server_packet_buffer_, 0, sizeof(server_packet_buffer_));
+ QuicUdpSocketApi::ReadPacketResult result;
+ result.packet_buffer = {server_packet_buffer_,
+ sizeof(server_packet_buffer_)};
+ result.control_buffer = {server_control_buffer_,
+ sizeof(server_control_buffer_)};
+ api_.ReadPacket(fd_server_, packet_info_interested, &result);
+ return result;
+ }
+
+ int ComparePacketBuffers(size_t packet_size) {
+ return memcmp(client_packet_buffer_, server_packet_buffer_, packet_size);
+ }
+
+ bool VerifyBufferIsFilledWith(const char* buffer,
+ size_t buffer_length,
+ char c) {
+ for (size_t i = 0; i < buffer_length; ++i) {
+ if (buffer[i] != c) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ QuicUdpSocketApi api_;
+ QuicUdpSocketFd fd_client_;
+ QuicUdpSocketFd fd_server_;
+ QuicSocketAddress server_address_;
+ int address_family_;
+ char client_packet_buffer_[kEthernetMTU] = {0};
+ char server_packet_buffer_[kDefaultMaxPacketSize] = {0};
+ char server_control_buffer_[512] = {0};
+};
+
+TEST_F(QuicUdpSocketTest, ReadPacketResultReset) {
+ QuicUdpSocketApi::ReadPacketResult result;
+ result.packet_info.SetDroppedPackets(100);
+ result.packet_buffer.buffer_len = 100;
+ result.ok = true;
+
+ result.Reset(/*packet_buffer_length=*/200);
+
+ EXPECT_FALSE(result.ok);
+ EXPECT_FALSE(
+ result.packet_info.HasValue(QuicUdpPacketInfoBit::DROPPED_PACKETS));
+ EXPECT_EQ(200u, result.packet_buffer.buffer_len);
+}
+
+TEST_F(QuicUdpSocketTest, ReadPacketOnly) {
+ const size_t kPacketSize = 512;
+ memset(client_packet_buffer_, '-', kPacketSize);
+ ASSERT_EQ(WriteResult(WRITE_STATUS_OK, kPacketSize),
+ SendPacketFromClient(kPacketSize));
+
+ QuicUdpSocketApi::ReadPacketResult read_result =
+ ReadPacketFromServer(/*packet_info_interested=*/BitMask64());
+ ASSERT_TRUE(read_result.ok);
+ ASSERT_EQ(kPacketSize, read_result.packet_buffer.buffer_len);
+ ASSERT_EQ(0, ComparePacketBuffers(kPacketSize));
+}
+
+TEST_F(QuicUdpSocketTest, ReadTruncated) {
+ const size_t kPacketSize = kDefaultMaxPacketSize + 1;
+ memset(client_packet_buffer_, '*', kPacketSize);
+ ASSERT_EQ(WriteResult(WRITE_STATUS_OK, kPacketSize),
+ SendPacketFromClient(kPacketSize));
+
+ QuicUdpSocketApi::ReadPacketResult read_result =
+ ReadPacketFromServer(/*packet_info_interested=*/BitMask64());
+ ASSERT_FALSE(read_result.ok);
+}
+
+TEST_F(QuicUdpSocketTest, ReadDroppedPackets) {
+ const size_t kPacketSize = kDefaultMaxPacketSize;
+ memset(client_packet_buffer_, '-', kPacketSize);
+ ASSERT_EQ(WriteResult(WRITE_STATUS_OK, kPacketSize),
+ SendPacketFromClient(kPacketSize));
+ ASSERT_EQ(WriteResult(WRITE_STATUS_OK, kPacketSize),
+ SendPacketFromClient(kPacketSize));
+
+ // Read the first packet without enabling DROPPED_PACKETS.
+ QuicUdpSocketApi::ReadPacketResult read_result =
+ ReadPacketFromServer(BitMask64(QuicUdpPacketInfoBit::DROPPED_PACKETS));
+ ASSERT_TRUE(read_result.ok);
+ ASSERT_EQ(kPacketSize, read_result.packet_buffer.buffer_len);
+ ASSERT_EQ(0, ComparePacketBuffers(kPacketSize));
+ ASSERT_FALSE(
+ read_result.packet_info.HasValue(QuicUdpPacketInfoBit::DROPPED_PACKETS));
+
+ // Enable DROPPED_PACKETS and read the second packet.
+ if (!api_.EnableDroppedPacketCount(fd_server_)) {
+ QUIC_LOG(INFO) << "DROPPED_PACKETS is not supported";
+ return;
+ }
+ read_result =
+ ReadPacketFromServer(BitMask64(QuicUdpPacketInfoBit::DROPPED_PACKETS));
+ ASSERT_TRUE(read_result.ok);
+ ASSERT_EQ(kPacketSize, read_result.packet_buffer.buffer_len);
+ ASSERT_EQ(0, ComparePacketBuffers(kPacketSize));
+ if (read_result.packet_info.HasValue(QuicUdpPacketInfoBit::DROPPED_PACKETS)) {
+ EXPECT_EQ(0u, read_result.packet_info.dropped_packets());
+ }
+}
+
+TEST_F(QuicUdpSocketTest, ReadSelfIp) {
+ const QuicUdpPacketInfoBit self_ip_bit =
+ (address_family_ == AF_INET) ? QuicUdpPacketInfoBit::V4_SELF_IP
+ : QuicUdpPacketInfoBit::V6_SELF_IP;
+
+ const size_t kPacketSize = 512;
+ memset(client_packet_buffer_, '&', kPacketSize);
+ ASSERT_EQ(WriteResult(WRITE_STATUS_OK, kPacketSize),
+ SendPacketFromClient(kPacketSize));
+
+ QuicUdpSocketApi::ReadPacketResult read_result =
+ ReadPacketFromServer(BitMask64(self_ip_bit));
+ ASSERT_TRUE(read_result.ok);
+ ASSERT_EQ(kPacketSize, read_result.packet_buffer.buffer_len);
+ ASSERT_EQ(0, ComparePacketBuffers(kPacketSize));
+ ASSERT_TRUE(read_result.packet_info.HasValue(self_ip_bit));
+ EXPECT_EQ(Loopback(), (address_family_ == AF_INET)
+ ? read_result.packet_info.self_v4_ip()
+ : read_result.packet_info.self_v6_ip());
+}
+
+TEST_F(QuicUdpSocketTest, ReadReceiveTimestamp) {
+ const size_t kPacketSize = kDefaultMaxPacketSize;
+ memset(client_packet_buffer_, '-', kPacketSize);
+ ASSERT_EQ(WriteResult(WRITE_STATUS_OK, kPacketSize),
+ SendPacketFromClient(kPacketSize));
+ ASSERT_EQ(WriteResult(WRITE_STATUS_OK, kPacketSize),
+ SendPacketFromClient(kPacketSize));
+
+ // Read the first packet without enabling RECV_TIMESTAMP.
+ QuicUdpSocketApi::ReadPacketResult read_result =
+ ReadPacketFromServer(BitMask64(QuicUdpPacketInfoBit::RECV_TIMESTAMP));
+ ASSERT_TRUE(read_result.ok);
+ ASSERT_EQ(kPacketSize, read_result.packet_buffer.buffer_len);
+ ASSERT_EQ(0, ComparePacketBuffers(kPacketSize));
+ ASSERT_FALSE(
+ read_result.packet_info.HasValue(QuicUdpPacketInfoBit::RECV_TIMESTAMP));
+
+ // Enable RECV_TIMESTAMP and read the second packet.
+ if (!api_.EnableReceiveTimestamp(fd_server_)) {
+ QUIC_LOG(INFO) << "RECV_TIMESTAMP is not supported";
+ return;
+ }
+ read_result =
+ ReadPacketFromServer(BitMask64(QuicUdpPacketInfoBit::RECV_TIMESTAMP));
+ ASSERT_TRUE(read_result.ok);
+ ASSERT_EQ(kPacketSize, read_result.packet_buffer.buffer_len);
+ ASSERT_EQ(0, ComparePacketBuffers(kPacketSize));
+ ASSERT_TRUE(
+ read_result.packet_info.HasValue(QuicUdpPacketInfoBit::RECV_TIMESTAMP));
+ QuicWallTime recv_timestamp = read_result.packet_info.receive_timestamp();
+ // 1577836800 is the unix seconds for 2020-01-01
+ EXPECT_TRUE(
+ QuicWallTime::FromUNIXSeconds(1577836800).IsBefore(recv_timestamp));
+}
+
+TEST_F(QuicUdpSocketTest, Ttl) {
+ const size_t kPacketSize = 512;
+ memset(client_packet_buffer_, '$', kPacketSize);
+ ASSERT_EQ(WriteResult(WRITE_STATUS_OK, kPacketSize),
+ SendPacketFromClientWithTtl(kPacketSize, 13));
+ ASSERT_EQ(WriteResult(WRITE_STATUS_OK, kPacketSize),
+ SendPacketFromClientWithTtl(kPacketSize, 13));
+
+ // Read the first packet without enabling ttl reporting.
+ QuicUdpSocketApi::ReadPacketResult read_result =
+ ReadPacketFromServer(BitMask64(QuicUdpPacketInfoBit::TTL));
+ ASSERT_TRUE(read_result.ok);
+ ASSERT_EQ(kPacketSize, read_result.packet_buffer.buffer_len);
+ ASSERT_EQ(0, ComparePacketBuffers(kPacketSize));
+ ASSERT_FALSE(read_result.packet_info.HasValue(QuicUdpPacketInfoBit::TTL));
+
+ // Enable ttl reporting and read the second packet.
+ if (!((address_family_ == AF_INET)
+ ? api_.EnableReceiveTtlForV4(fd_server_)
+ : api_.EnableReceiveTtlForV6(fd_server_))) {
+ QUIC_LOG(INFO) << "TTL is not supported for address family "
+ << address_family_;
+ return;
+ }
+
+ read_result = ReadPacketFromServer(BitMask64(QuicUdpPacketInfoBit::TTL));
+ ASSERT_TRUE(read_result.ok);
+ ASSERT_EQ(kPacketSize, read_result.packet_buffer.buffer_len);
+ ASSERT_EQ(0, ComparePacketBuffers(kPacketSize));
+ ASSERT_TRUE(read_result.packet_info.HasValue(QuicUdpPacketInfoBit::TTL));
+ EXPECT_EQ(13, read_result.packet_info.ttl());
+}
+
+TEST_F(QuicUdpSocketTest, ReadMultiplePackets) {
+ const QuicUdpPacketInfoBit self_ip_bit =
+ (address_family_ == AF_INET) ? QuicUdpPacketInfoBit::V4_SELF_IP
+ : QuicUdpPacketInfoBit::V6_SELF_IP;
+ const size_t kPacketSize = kDefaultMaxPacketSize;
+ const size_t kNumPackets = 90;
+ for (size_t i = 0; i < kNumPackets; ++i) {
+ memset(client_packet_buffer_, ' ' + i, kPacketSize);
+ ASSERT_EQ(WriteResult(WRITE_STATUS_OK, kPacketSize),
+ SendPacketFromClient(kPacketSize));
+ }
+
+ const size_t kNumPacketsPerRead = 16;
+ size_t total_packets_read = 0;
+ while (total_packets_read < kNumPackets) {
+ std::unique_ptr<ReadBuffers[]> read_buffers =
+ std::make_unique<ReadBuffers[]>(kNumPacketsPerRead);
+ QuicUdpSocketApi::ReadPacketResults results(kNumPacketsPerRead);
+ for (size_t i = 0; i < kNumPacketsPerRead; ++i) {
+ results[i].packet_buffer.buffer = read_buffers[i].packet_buffer;
+ results[i].packet_buffer.buffer_len =
+ sizeof(read_buffers[i].packet_buffer);
+
+ results[i].control_buffer.buffer = read_buffers[i].control_buffer;
+ results[i].control_buffer.buffer_len =
+ sizeof(read_buffers[i].control_buffer);
+ }
+ size_t packets_read =
+ api_.ReadMultiplePackets(fd_server_, BitMask64(self_ip_bit), &results);
+ if (packets_read == 0) {
+ ASSERT_TRUE(
+ api_.WaitUntilReadable(fd_server_, QuicTime::Delta::FromSeconds(5)));
+ packets_read = api_.ReadMultiplePackets(fd_server_,
+ BitMask64(self_ip_bit), &results);
+ ASSERT_GT(packets_read, 0u);
+ }
+
+ for (size_t i = 0; i < packets_read; ++i) {
+ const auto& result = results[i];
+ ASSERT_TRUE(result.ok);
+ ASSERT_EQ(kPacketSize, result.packet_buffer.buffer_len);
+ ASSERT_TRUE(VerifyBufferIsFilledWith(result.packet_buffer.buffer,
+ result.packet_buffer.buffer_len,
+ ' ' + total_packets_read));
+ ASSERT_TRUE(result.packet_info.HasValue(self_ip_bit));
+ EXPECT_EQ(Loopback(), (address_family_ == AF_INET)
+ ? result.packet_info.self_v4_ip()
+ : result.packet_info.self_v6_ip());
+ total_packets_read++;
+ }
+ }
+}
+
+TEST_F(QuicUdpSocketTest, ReadMultiplePacketsSomeTruncated) {
+ const QuicUdpPacketInfoBit self_ip_bit =
+ (address_family_ == AF_INET) ? QuicUdpPacketInfoBit::V4_SELF_IP
+ : QuicUdpPacketInfoBit::V6_SELF_IP;
+ const size_t kPacketSize = kDefaultMaxPacketSize;
+ const size_t kNumPackets = 90;
+ for (size_t i = 0; i < kNumPackets; ++i) {
+ memset(client_packet_buffer_, ' ' + i, kPacketSize);
+ ASSERT_EQ(WriteResult(WRITE_STATUS_OK, kPacketSize),
+ SendPacketFromClient(kPacketSize));
+ }
+
+ const size_t kNumPacketsPerRead = 16;
+ size_t total_packets_read = 0; // Including truncated packets.
+ while (total_packets_read < kNumPackets) {
+ std::unique_ptr<ReadBuffers[]> read_buffers =
+ std::make_unique<ReadBuffers[]>(kNumPacketsPerRead);
+ QuicUdpSocketApi::ReadPacketResults results(kNumPacketsPerRead);
+ // Use small packet buffer for all even-numbered packets and expect them to
+ // be truncated.
+ auto is_truncated = [total_packets_read](size_t i) {
+ return ((total_packets_read + i) % 2) == 1;
+ };
+
+ for (size_t i = 0; i < kNumPacketsPerRead; ++i) {
+ results[i].packet_buffer.buffer = read_buffers[i].packet_buffer;
+ results[i].packet_buffer.buffer_len =
+ is_truncated(i) ? kPacketSize - 1
+ : sizeof(read_buffers[i].packet_buffer);
+
+ results[i].control_buffer.buffer = read_buffers[i].control_buffer;
+ results[i].control_buffer.buffer_len =
+ sizeof(read_buffers[i].control_buffer);
+ }
+ size_t packets_read =
+ api_.ReadMultiplePackets(fd_server_, BitMask64(self_ip_bit), &results);
+ if (packets_read == 0) {
+ ASSERT_TRUE(
+ api_.WaitUntilReadable(fd_server_, QuicTime::Delta::FromSeconds(5)));
+ packets_read = api_.ReadMultiplePackets(fd_server_,
+ BitMask64(self_ip_bit), &results);
+ ASSERT_GT(packets_read, 0u);
+ }
+
+ for (size_t i = 0; i < packets_read; ++i) {
+ const auto& result = results[i];
+ if (is_truncated(i)) {
+ ASSERT_FALSE(result.ok);
+ } else {
+ ASSERT_TRUE(result.ok);
+ ASSERT_EQ(kPacketSize, result.packet_buffer.buffer_len);
+ ASSERT_TRUE(VerifyBufferIsFilledWith(result.packet_buffer.buffer,
+ result.packet_buffer.buffer_len,
+ ' ' + total_packets_read));
+ ASSERT_TRUE(result.packet_info.HasValue(self_ip_bit));
+ EXPECT_EQ(Loopback(), (address_family_ == AF_INET)
+ ? result.packet_info.self_v4_ip()
+ : result.packet_info.self_v6_ip());
+ }
+ total_packets_read++;
+ }
+ }
+}
+
+} // namespace test
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.cc b/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.cc
index d8beb435967..8276f1c287c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.cc
@@ -30,6 +30,9 @@ QuicUnackedPacketMap::QuicUnackedPacketMap(Perspective perspective)
bytes_in_flight_(0),
packets_in_flight_(0),
last_inflight_packet_sent_time_(QuicTime::Zero()),
+ last_inflight_packets_sent_time_{{QuicTime::Zero()},
+ {QuicTime::Zero()},
+ {QuicTime::Zero()}},
last_crypto_packet_sent_time_(QuicTime::Zero()),
session_notifier_(nullptr),
supports_multiple_packet_number_spaces_(false) {}
@@ -65,19 +68,15 @@ void QuicUnackedPacketMap::AddSentPacket(SerializedPacket* packet,
largest_sent_largest_acked_.UpdateMax(packet->largest_acked);
largest_sent_packet_ = packet_number;
- if (supports_multiple_packet_number_spaces_) {
- largest_sent_packets_[GetPacketNumberSpace(packet->encryption_level)] =
- packet_number;
- }
if (set_in_flight) {
+ const PacketNumberSpace packet_number_space =
+ GetPacketNumberSpace(info.encryption_level);
bytes_in_flight_ += bytes_sent;
++packets_in_flight_;
info.in_flight = true;
- largest_sent_retransmittable_packets_[GetPacketNumberSpace(
- info.encryption_level)] = packet_number;
- // TODO(ianswett): Should this field be per packet number space or should
- // GetInFlightPacketSentTime() use largest_sent_retransmittable_packets_?
+ largest_sent_retransmittable_packets_[packet_number_space] = packet_number;
last_inflight_packet_sent_time_ = sent_time;
+ last_inflight_packets_sent_time_[packet_number_space] = sent_time;
}
unacked_packets_.push_back(info);
// Swap the retransmittable frames to avoid allocations.
@@ -208,6 +207,58 @@ void QuicUnackedPacketMap::RemoveFromInFlight(QuicPacketNumber packet_number) {
RemoveFromInFlight(info);
}
+QuicInlinedVector<QuicPacketNumber, 2>
+QuicUnackedPacketMap::NeuterUnencryptedPackets() {
+ QuicInlinedVector<QuicPacketNumber, 2> neutered_packets;
+ QuicPacketNumber packet_number = GetLeastUnacked();
+ for (QuicUnackedPacketMap::iterator it = unacked_packets_.begin();
+ it != unacked_packets_.end(); ++it, ++packet_number) {
+ if (!it->retransmittable_frames.empty() &&
+ it->encryption_level == ENCRYPTION_INITIAL) {
+ QUIC_DVLOG(2) << "Neutering unencrypted packet " << packet_number;
+ // Once the connection swithes to forward secure, no unencrypted packets
+ // will be sent. The data has been abandoned in the cryto stream. Remove
+ // it from in flight.
+ RemoveFromInFlight(packet_number);
+ it->state = NEUTERED;
+ neutered_packets.push_back(packet_number);
+ // Notify session that the data has been delivered (but do not notify
+ // send algorithm).
+ // TODO(b/148868195): use NotifyFramesNeutered.
+ NotifyFramesAcked(*it, QuicTime::Delta::Zero(), QuicTime::Zero());
+ DCHECK(!HasRetransmittableFrames(*it));
+ }
+ }
+ if (supports_multiple_packet_number_spaces_) {
+ last_inflight_packets_sent_time_[INITIAL_DATA] = QuicTime::Zero();
+ }
+ return neutered_packets;
+}
+
+QuicInlinedVector<QuicPacketNumber, 2>
+QuicUnackedPacketMap::NeuterHandshakePackets() {
+ QuicInlinedVector<QuicPacketNumber, 2> neutered_packets;
+ QuicPacketNumber packet_number = GetLeastUnacked();
+ for (QuicUnackedPacketMap::iterator it = unacked_packets_.begin();
+ it != unacked_packets_.end(); ++it, ++packet_number) {
+ if (!it->retransmittable_frames.empty() &&
+ GetPacketNumberSpace(it->encryption_level) == HANDSHAKE_DATA) {
+ QUIC_DVLOG(2) << "Neutering handshake packet " << packet_number;
+ RemoveFromInFlight(packet_number);
+ // Notify session that the data has been delivered (but do not notify
+ // send algorithm).
+ it->state = NEUTERED;
+ neutered_packets.push_back(packet_number);
+ // TODO(b/148868195): use NotifyFramesNeutered.
+ NotifyFramesAcked(*it, QuicTime::Delta::Zero(), QuicTime::Zero());
+ }
+ }
+ if (supports_multiple_packet_number_spaces()) {
+ last_inflight_packets_sent_time_[HANDSHAKE_DATA] = QuicTime::Zero();
+ }
+ return neutered_packets;
+}
+
bool QuicUnackedPacketMap::HasInFlightPackets() const {
return bytes_in_flight_ > 0;
}
@@ -401,6 +452,15 @@ QuicPacketNumber QuicUnackedPacketMap::GetLargestAckedOfPacketNumberSpace(
return largest_acked_packets_[packet_number_space];
}
+QuicTime QuicUnackedPacketMap::GetLastInFlightPacketSentTime(
+ PacketNumberSpace packet_number_space) const {
+ if (packet_number_space >= NUM_PACKET_NUMBER_SPACES) {
+ QUIC_BUG << "Invalid packet number space: " << packet_number_space;
+ return QuicTime::Zero();
+ }
+ return last_inflight_packets_sent_time_[packet_number_space];
+}
+
QuicPacketNumber
QuicUnackedPacketMap::GetLargestSentRetransmittableOfPacketNumberSpace(
PacketNumberSpace packet_number_space) const {
@@ -411,6 +471,32 @@ QuicUnackedPacketMap::GetLargestSentRetransmittableOfPacketNumberSpace(
return largest_sent_retransmittable_packets_[packet_number_space];
}
+const QuicTransmissionInfo*
+QuicUnackedPacketMap::GetFirstInFlightTransmissionInfo() const {
+ DCHECK(HasInFlightPackets());
+ for (auto it = unacked_packets_.begin(); it != unacked_packets_.end(); ++it) {
+ if (it->in_flight) {
+ return &(*it);
+ }
+ }
+ DCHECK(false);
+ return nullptr;
+}
+
+const QuicTransmissionInfo*
+QuicUnackedPacketMap::GetFirstInFlightTransmissionInfoOfSpace(
+ PacketNumberSpace packet_number_space) const {
+ // TODO(fayang): Optimize this part if arm 1st PTO with first in flight sent
+ // time works.
+ for (auto it = unacked_packets_.begin(); it != unacked_packets_.end(); ++it) {
+ if (it->in_flight &&
+ GetPacketNumberSpace(it->encryption_level) == packet_number_space) {
+ return &(*it);
+ }
+ }
+ return nullptr;
+}
+
void QuicUnackedPacketMap::EnableMultiplePacketNumberSpacesSupport() {
if (supports_multiple_packet_number_spaces_) {
QUIC_BUG << "Multiple packet number spaces has already been enabled";
@@ -425,10 +511,4 @@ void QuicUnackedPacketMap::EnableMultiplePacketNumberSpacesSupport() {
supports_multiple_packet_number_spaces_ = true;
}
-QuicPacketNumber QuicUnackedPacketMap::GetLargestSentPacketOfPacketNumberSpace(
- EncryptionLevel encryption_level) const {
- DCHECK(supports_multiple_packet_number_spaces_);
- return largest_sent_packets_[GetPacketNumberSpace(encryption_level)];
-}
-
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.h b/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.h
index fd6510a6c77..bcf5061927a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.h
@@ -65,6 +65,15 @@ class QUIC_EXPORT_PRIVATE QuicUnackedPacketMap {
// Marks |packet_number| as no longer in flight.
void RemoveFromInFlight(QuicPacketNumber packet_number);
+ // Called to neuter all unencrypted packets to ensure they do not get
+ // retransmitted. Returns a vector of neutered packet numbers.
+ QuicInlinedVector<QuicPacketNumber, 2> NeuterUnencryptedPackets();
+
+ // Called to neuter packets in handshake packet number space to ensure they do
+ // not get retransmitted. Returns a vector of neutered packet numbers.
+ // TODO(fayang): Consider to combine this with NeuterUnencryptedPackets.
+ QuicInlinedVector<QuicPacketNumber, 2> NeuterHandshakePackets();
+
// Returns true if |packet_number| has retransmittable frames. This will
// return false if all frames of this packet are either non-retransmittable or
// have been acked.
@@ -100,7 +109,7 @@ class QUIC_EXPORT_PRIVATE QuicUnackedPacketMap {
// been acked by the peer. If there are no unacked packets, returns 0.
QuicPacketNumber GetLeastUnacked() const;
- // This can not be a QuicDeque since pointers into this are
+ // This can not be a QuicCircularDeque since pointers into this are
// assumed to be stable.
typedef std::deque<QuicTransmissionInfo> UnackedPacketMap;
@@ -203,6 +212,18 @@ class QUIC_EXPORT_PRIVATE QuicUnackedPacketMap {
QuicPacketNumber GetLargestSentPacketOfPacketNumberSpace(
EncryptionLevel encryption_level) const;
+ // Returns last in flight packet sent time of |packet_number_space|.
+ QuicTime GetLastInFlightPacketSentTime(
+ PacketNumberSpace packet_number_space) const;
+
+ // Returns TransmissionInfo of the first in flight packet.
+ const QuicTransmissionInfo* GetFirstInFlightTransmissionInfo() const;
+
+ // Returns TransmissionInfo of first in flight packet in
+ // |packet_number_space|.
+ const QuicTransmissionInfo* GetFirstInFlightTransmissionInfoOfSpace(
+ PacketNumberSpace packet_number_space) const;
+
void SetSessionNotifier(SessionNotifierInterface* session_notifier);
void EnableMultiplePacketNumberSpacesSupport();
@@ -236,8 +257,6 @@ class QUIC_EXPORT_PRIVATE QuicUnackedPacketMap {
const Perspective perspective_;
QuicPacketNumber largest_sent_packet_;
- // Only used when supports_multiple_packet_number_spaces_ is true.
- QuicPacketNumber largest_sent_packets_[NUM_PACKET_NUMBER_SPACES];
// The largest sent packet we expect to receive an ack for per packet number
// space.
QuicPacketNumber
@@ -266,6 +285,8 @@ class QUIC_EXPORT_PRIVATE QuicUnackedPacketMap {
// Time that the last inflight packet was sent.
QuicTime last_inflight_packet_sent_time_;
+ // Time that the last in flight packet was sent per packet number space.
+ QuicTime last_inflight_packets_sent_time_[NUM_PACKET_NUMBER_SPACES];
// Time that the last unacked crypto packet was sent.
QuicTime last_crypto_packet_sent_time_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map_test.cc
index 92e61e3bb02..560b8cb0d01 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map_test.cc
@@ -8,10 +8,10 @@
#include "net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h"
#include "net/third_party/quiche/src/quic/core/quic_transmission_info.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_unacked_packet_map_peer.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
using testing::_;
using testing::Return;
@@ -172,7 +172,7 @@ TEST_P(QuicUnackedPacketMapTest, RttOnly) {
unacked_packets_.AddSentPacket(&packet, NOT_RETRANSMISSION, now_, false);
uint64_t unacked[] = {1};
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ VerifyUnackedPackets(unacked, QUICHE_ARRAYSIZE(unacked));
VerifyInFlightPackets(nullptr, 0);
VerifyRetransmittablePackets(nullptr, 0);
@@ -188,18 +188,18 @@ TEST_P(QuicUnackedPacketMapTest, RetransmittableInflightAndRtt) {
unacked_packets_.AddSentPacket(&packet, NOT_RETRANSMISSION, now_, true);
uint64_t unacked[] = {1};
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
- VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
- VerifyRetransmittablePackets(unacked, QUIC_ARRAYSIZE(unacked));
+ VerifyUnackedPackets(unacked, QUICHE_ARRAYSIZE(unacked));
+ VerifyInFlightPackets(unacked, QUICHE_ARRAYSIZE(unacked));
+ VerifyRetransmittablePackets(unacked, QUICHE_ARRAYSIZE(unacked));
unacked_packets_.RemoveRetransmittability(QuicPacketNumber(1));
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
- VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ VerifyUnackedPackets(unacked, QUICHE_ARRAYSIZE(unacked));
+ VerifyInFlightPackets(unacked, QUICHE_ARRAYSIZE(unacked));
VerifyRetransmittablePackets(nullptr, 0);
unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(1));
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
- VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ VerifyUnackedPackets(unacked, QUICHE_ARRAYSIZE(unacked));
+ VerifyInFlightPackets(unacked, QUICHE_ARRAYSIZE(unacked));
VerifyRetransmittablePackets(nullptr, 0);
unacked_packets_.RemoveFromInFlight(QuicPacketNumber(1));
@@ -214,15 +214,15 @@ TEST_P(QuicUnackedPacketMapTest, StopRetransmission) {
unacked_packets_.AddSentPacket(&packet, NOT_RETRANSMISSION, now_, true);
uint64_t unacked[] = {1};
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
- VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ VerifyUnackedPackets(unacked, QUICHE_ARRAYSIZE(unacked));
+ VerifyInFlightPackets(unacked, QUICHE_ARRAYSIZE(unacked));
uint64_t retransmittable[] = {1};
VerifyRetransmittablePackets(retransmittable,
- QUIC_ARRAYSIZE(retransmittable));
+ QUICHE_ARRAYSIZE(retransmittable));
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
- VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ VerifyUnackedPackets(unacked, QUICHE_ARRAYSIZE(unacked));
+ VerifyInFlightPackets(unacked, QUICHE_ARRAYSIZE(unacked));
VerifyRetransmittablePackets(nullptr, 0);
}
@@ -232,16 +232,16 @@ TEST_P(QuicUnackedPacketMapTest, StopRetransmissionOnOtherStream) {
unacked_packets_.AddSentPacket(&packet, NOT_RETRANSMISSION, now_, true);
uint64_t unacked[] = {1};
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
- VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ VerifyUnackedPackets(unacked, QUICHE_ARRAYSIZE(unacked));
+ VerifyInFlightPackets(unacked, QUICHE_ARRAYSIZE(unacked));
uint64_t retransmittable[] = {1};
VerifyRetransmittablePackets(retransmittable,
- QUIC_ARRAYSIZE(retransmittable));
+ QUICHE_ARRAYSIZE(retransmittable));
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
- VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ VerifyUnackedPackets(unacked, QUICHE_ARRAYSIZE(unacked));
+ VerifyInFlightPackets(unacked, QUICHE_ARRAYSIZE(unacked));
VerifyRetransmittablePackets(retransmittable,
- QUIC_ARRAYSIZE(retransmittable));
+ QUICHE_ARRAYSIZE(retransmittable));
}
TEST_P(QuicUnackedPacketMapTest, StopRetransmissionAfterRetransmission) {
@@ -251,14 +251,14 @@ TEST_P(QuicUnackedPacketMapTest, StopRetransmissionAfterRetransmission) {
RetransmitAndSendPacket(1, 2, LOSS_RETRANSMISSION);
uint64_t unacked[] = {1, 2};
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
- VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ VerifyUnackedPackets(unacked, QUICHE_ARRAYSIZE(unacked));
+ VerifyInFlightPackets(unacked, QUICHE_ARRAYSIZE(unacked));
std::vector<uint64_t> retransmittable = {1, 2};
VerifyRetransmittablePackets(&retransmittable[0], retransmittable.size());
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
- VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ VerifyUnackedPackets(unacked, QUICHE_ARRAYSIZE(unacked));
+ VerifyInFlightPackets(unacked, QUICHE_ARRAYSIZE(unacked));
VerifyRetransmittablePackets(nullptr, 0);
}
@@ -270,26 +270,26 @@ TEST_P(QuicUnackedPacketMapTest, RetransmittedPacket) {
RetransmitAndSendPacket(1, 2, LOSS_RETRANSMISSION);
uint64_t unacked[] = {1, 2};
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
- VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ VerifyUnackedPackets(unacked, QUICHE_ARRAYSIZE(unacked));
+ VerifyInFlightPackets(unacked, QUICHE_ARRAYSIZE(unacked));
std::vector<uint64_t> retransmittable = {1, 2};
VerifyRetransmittablePackets(&retransmittable[0], retransmittable.size());
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
unacked_packets_.RemoveRetransmittability(QuicPacketNumber(1));
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
- VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ VerifyUnackedPackets(unacked, QUICHE_ARRAYSIZE(unacked));
+ VerifyInFlightPackets(unacked, QUICHE_ARRAYSIZE(unacked));
VerifyRetransmittablePackets(nullptr, 0);
unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(2));
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
- VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ VerifyUnackedPackets(unacked, QUICHE_ARRAYSIZE(unacked));
+ VerifyInFlightPackets(unacked, QUICHE_ARRAYSIZE(unacked));
VerifyRetransmittablePackets(nullptr, 0);
unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2));
uint64_t unacked2[] = {1};
- VerifyUnackedPackets(unacked2, QUIC_ARRAYSIZE(unacked2));
- VerifyInFlightPackets(unacked2, QUIC_ARRAYSIZE(unacked2));
+ VerifyUnackedPackets(unacked2, QUICHE_ARRAYSIZE(unacked2));
+ VerifyInFlightPackets(unacked2, QUICHE_ARRAYSIZE(unacked2));
VerifyRetransmittablePackets(nullptr, 0);
unacked_packets_.RemoveFromInFlight(QuicPacketNumber(1));
@@ -306,11 +306,11 @@ TEST_P(QuicUnackedPacketMapTest, RetransmitThreeTimes) {
unacked_packets_.AddSentPacket(&packet2, NOT_RETRANSMISSION, now_, true);
uint64_t unacked[] = {1, 2};
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
- VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ VerifyUnackedPackets(unacked, QUICHE_ARRAYSIZE(unacked));
+ VerifyInFlightPackets(unacked, QUICHE_ARRAYSIZE(unacked));
uint64_t retransmittable[] = {1, 2};
VerifyRetransmittablePackets(retransmittable,
- QUIC_ARRAYSIZE(retransmittable));
+ QUICHE_ARRAYSIZE(retransmittable));
// Early retransmit 1 as 3 and send new data as 4.
unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(2));
@@ -322,9 +322,9 @@ TEST_P(QuicUnackedPacketMapTest, RetransmitThreeTimes) {
unacked_packets_.AddSentPacket(&packet4, NOT_RETRANSMISSION, now_, true);
uint64_t unacked2[] = {1, 3, 4};
- VerifyUnackedPackets(unacked2, QUIC_ARRAYSIZE(unacked2));
+ VerifyUnackedPackets(unacked2, QUICHE_ARRAYSIZE(unacked2));
uint64_t pending2[] = {3, 4};
- VerifyInFlightPackets(pending2, QUIC_ARRAYSIZE(pending2));
+ VerifyInFlightPackets(pending2, QUICHE_ARRAYSIZE(pending2));
std::vector<uint64_t> retransmittable2 = {1, 3, 4};
VerifyRetransmittablePackets(&retransmittable2[0], retransmittable2.size());
@@ -341,7 +341,7 @@ TEST_P(QuicUnackedPacketMapTest, RetransmitThreeTimes) {
VerifyUnackedPackets(&unacked3[0], unacked3.size());
VerifyRetransmittablePackets(&retransmittable3[0], retransmittable3.size());
uint64_t pending3[] = {3, 5, 6};
- VerifyInFlightPackets(pending3, QUIC_ARRAYSIZE(pending3));
+ VerifyInFlightPackets(pending3, QUICHE_ARRAYSIZE(pending3));
// Early retransmit 5 as 7 and ensure in flight packet 3 is not removed.
unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(6));
@@ -354,13 +354,13 @@ TEST_P(QuicUnackedPacketMapTest, RetransmitThreeTimes) {
VerifyUnackedPackets(&unacked4[0], unacked4.size());
VerifyRetransmittablePackets(&retransmittable4[0], retransmittable4.size());
uint64_t pending4[] = {3, 5, 7};
- VerifyInFlightPackets(pending4, QUIC_ARRAYSIZE(pending4));
+ VerifyInFlightPackets(pending4, QUICHE_ARRAYSIZE(pending4));
// Remove the older two transmissions from in flight.
unacked_packets_.RemoveFromInFlight(QuicPacketNumber(3));
unacked_packets_.RemoveFromInFlight(QuicPacketNumber(5));
uint64_t pending5[] = {7};
- VerifyInFlightPackets(pending5, QUIC_ARRAYSIZE(pending5));
+ VerifyInFlightPackets(pending5, QUICHE_ARRAYSIZE(pending5));
}
TEST_P(QuicUnackedPacketMapTest, RetransmitFourTimes) {
@@ -371,11 +371,11 @@ TEST_P(QuicUnackedPacketMapTest, RetransmitFourTimes) {
unacked_packets_.AddSentPacket(&packet2, NOT_RETRANSMISSION, now_, true);
uint64_t unacked[] = {1, 2};
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
- VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ VerifyUnackedPackets(unacked, QUICHE_ARRAYSIZE(unacked));
+ VerifyInFlightPackets(unacked, QUICHE_ARRAYSIZE(unacked));
uint64_t retransmittable[] = {1, 2};
VerifyRetransmittablePackets(retransmittable,
- QUIC_ARRAYSIZE(retransmittable));
+ QUICHE_ARRAYSIZE(retransmittable));
// Early retransmit 1 as 3.
unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(2));
@@ -385,9 +385,9 @@ TEST_P(QuicUnackedPacketMapTest, RetransmitFourTimes) {
RetransmitAndSendPacket(1, 3, LOSS_RETRANSMISSION);
uint64_t unacked2[] = {1, 3};
- VerifyUnackedPackets(unacked2, QUIC_ARRAYSIZE(unacked2));
+ VerifyUnackedPackets(unacked2, QUICHE_ARRAYSIZE(unacked2));
uint64_t pending2[] = {3};
- VerifyInFlightPackets(pending2, QUIC_ARRAYSIZE(pending2));
+ VerifyInFlightPackets(pending2, QUICHE_ARRAYSIZE(pending2));
std::vector<uint64_t> retransmittable2 = {1, 3};
VerifyRetransmittablePackets(&retransmittable2[0], retransmittable2.size());
@@ -397,9 +397,9 @@ TEST_P(QuicUnackedPacketMapTest, RetransmitFourTimes) {
unacked_packets_.AddSentPacket(&packet5, NOT_RETRANSMISSION, now_, true);
uint64_t unacked3[] = {1, 3, 4, 5};
- VerifyUnackedPackets(unacked3, QUIC_ARRAYSIZE(unacked3));
+ VerifyUnackedPackets(unacked3, QUICHE_ARRAYSIZE(unacked3));
uint64_t pending3[] = {3, 4, 5};
- VerifyInFlightPackets(pending3, QUIC_ARRAYSIZE(pending3));
+ VerifyInFlightPackets(pending3, QUICHE_ARRAYSIZE(pending3));
std::vector<uint64_t> retransmittable3 = {1, 3, 4, 5};
VerifyRetransmittablePackets(&retransmittable3[0], retransmittable3.size());
@@ -414,7 +414,7 @@ TEST_P(QuicUnackedPacketMapTest, RetransmitFourTimes) {
std::vector<uint64_t> unacked4 = {4, 6};
VerifyUnackedPackets(&unacked4[0], unacked4.size());
uint64_t pending4[] = {6};
- VerifyInFlightPackets(pending4, QUIC_ARRAYSIZE(pending4));
+ VerifyInFlightPackets(pending4, QUICHE_ARRAYSIZE(pending4));
std::vector<uint64_t> retransmittable4 = {4, 6};
VerifyRetransmittablePackets(&retransmittable4[0], retransmittable4.size());
}
@@ -564,20 +564,21 @@ TEST_P(QuicUnackedPacketMapTest, CannotAggregateAckedControlFrames) {
TEST_P(QuicUnackedPacketMapTest, LargestSentPacketMultiplePacketNumberSpaces) {
unacked_packets_.EnableMultiplePacketNumberSpacesSupport();
- EXPECT_FALSE(unacked_packets_
- .GetLargestSentPacketOfPacketNumberSpace(ENCRYPTION_INITIAL)
- .IsInitialized());
+ EXPECT_FALSE(
+ unacked_packets_
+ .GetLargestSentRetransmittableOfPacketNumberSpace(INITIAL_DATA)
+ .IsInitialized());
// Send packet 1.
SerializedPacket packet1(CreateRetransmittablePacket(1));
packet1.encryption_level = ENCRYPTION_INITIAL;
unacked_packets_.AddSentPacket(&packet1, NOT_RETRANSMISSION, now_, true);
EXPECT_EQ(QuicPacketNumber(1u), unacked_packets_.largest_sent_packet());
EXPECT_EQ(QuicPacketNumber(1),
- unacked_packets_.GetLargestSentPacketOfPacketNumberSpace(
- ENCRYPTION_INITIAL));
+ unacked_packets_.GetLargestSentRetransmittableOfPacketNumberSpace(
+ INITIAL_DATA));
EXPECT_FALSE(
unacked_packets_
- .GetLargestSentPacketOfPacketNumberSpace(ENCRYPTION_HANDSHAKE)
+ .GetLargestSentRetransmittableOfPacketNumberSpace(HANDSHAKE_DATA)
.IsInitialized());
// Send packet 2.
SerializedPacket packet2(CreateRetransmittablePacket(2));
@@ -585,33 +586,34 @@ TEST_P(QuicUnackedPacketMapTest, LargestSentPacketMultiplePacketNumberSpaces) {
unacked_packets_.AddSentPacket(&packet2, NOT_RETRANSMISSION, now_, true);
EXPECT_EQ(QuicPacketNumber(2u), unacked_packets_.largest_sent_packet());
EXPECT_EQ(QuicPacketNumber(1),
- unacked_packets_.GetLargestSentPacketOfPacketNumberSpace(
- ENCRYPTION_INITIAL));
+ unacked_packets_.GetLargestSentRetransmittableOfPacketNumberSpace(
+ INITIAL_DATA));
EXPECT_EQ(QuicPacketNumber(2),
- unacked_packets_.GetLargestSentPacketOfPacketNumberSpace(
- ENCRYPTION_HANDSHAKE));
- EXPECT_FALSE(unacked_packets_
- .GetLargestSentPacketOfPacketNumberSpace(ENCRYPTION_ZERO_RTT)
- .IsInitialized());
+ unacked_packets_.GetLargestSentRetransmittableOfPacketNumberSpace(
+ HANDSHAKE_DATA));
+ EXPECT_FALSE(
+ unacked_packets_
+ .GetLargestSentRetransmittableOfPacketNumberSpace(APPLICATION_DATA)
+ .IsInitialized());
// Send packet 3.
SerializedPacket packet3(CreateRetransmittablePacket(3));
packet3.encryption_level = ENCRYPTION_ZERO_RTT;
unacked_packets_.AddSentPacket(&packet3, NOT_RETRANSMISSION, now_, true);
EXPECT_EQ(QuicPacketNumber(3u), unacked_packets_.largest_sent_packet());
EXPECT_EQ(QuicPacketNumber(1),
- unacked_packets_.GetLargestSentPacketOfPacketNumberSpace(
- ENCRYPTION_INITIAL));
+ unacked_packets_.GetLargestSentRetransmittableOfPacketNumberSpace(
+ INITIAL_DATA));
EXPECT_EQ(QuicPacketNumber(2),
- unacked_packets_.GetLargestSentPacketOfPacketNumberSpace(
- ENCRYPTION_HANDSHAKE));
+ unacked_packets_.GetLargestSentRetransmittableOfPacketNumberSpace(
+ HANDSHAKE_DATA));
EXPECT_EQ(QuicPacketNumber(3),
- unacked_packets_.GetLargestSentPacketOfPacketNumberSpace(
- ENCRYPTION_ZERO_RTT));
+ unacked_packets_.GetLargestSentRetransmittableOfPacketNumberSpace(
+ APPLICATION_DATA));
// Verify forward secure belongs to the same packet number space as encryption
// zero rtt.
EXPECT_EQ(QuicPacketNumber(3),
- unacked_packets_.GetLargestSentPacketOfPacketNumberSpace(
- ENCRYPTION_FORWARD_SECURE));
+ unacked_packets_.GetLargestSentRetransmittableOfPacketNumberSpace(
+ APPLICATION_DATA));
// Send packet 4.
SerializedPacket packet4(CreateRetransmittablePacket(4));
@@ -619,19 +621,19 @@ TEST_P(QuicUnackedPacketMapTest, LargestSentPacketMultiplePacketNumberSpaces) {
unacked_packets_.AddSentPacket(&packet4, NOT_RETRANSMISSION, now_, true);
EXPECT_EQ(QuicPacketNumber(4u), unacked_packets_.largest_sent_packet());
EXPECT_EQ(QuicPacketNumber(1),
- unacked_packets_.GetLargestSentPacketOfPacketNumberSpace(
- ENCRYPTION_INITIAL));
+ unacked_packets_.GetLargestSentRetransmittableOfPacketNumberSpace(
+ INITIAL_DATA));
EXPECT_EQ(QuicPacketNumber(2),
- unacked_packets_.GetLargestSentPacketOfPacketNumberSpace(
- ENCRYPTION_HANDSHAKE));
+ unacked_packets_.GetLargestSentRetransmittableOfPacketNumberSpace(
+ HANDSHAKE_DATA));
EXPECT_EQ(QuicPacketNumber(4),
- unacked_packets_.GetLargestSentPacketOfPacketNumberSpace(
- ENCRYPTION_ZERO_RTT));
+ unacked_packets_.GetLargestSentRetransmittableOfPacketNumberSpace(
+ APPLICATION_DATA));
// Verify forward secure belongs to the same packet number space as encryption
// zero rtt.
EXPECT_EQ(QuicPacketNumber(4),
- unacked_packets_.GetLargestSentPacketOfPacketNumberSpace(
- ENCRYPTION_FORWARD_SECURE));
+ unacked_packets_.GetLargestSentRetransmittableOfPacketNumberSpace(
+ APPLICATION_DATA));
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_utils.cc b/chromium/net/third_party/quiche/src/quic/core/quic_utils.cc
index a69efcdf822..60354f332fa 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_utils.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_utils.cc
@@ -13,13 +13,14 @@
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_aligned.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_prefetch.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_uint128.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace {
@@ -34,7 +35,8 @@ namespace {
#endif
#ifdef QUIC_UTIL_HAS_UINT128
-QuicUint128 IncrementalHashFast(QuicUint128 uhash, QuicStringPiece data) {
+QuicUint128 IncrementalHashFast(QuicUint128 uhash,
+ quiche::QuicheStringPiece data) {
// This code ends up faster than the naive implementation for 2 reasons:
// 1. QuicUint128 is sufficiently complicated that the compiler
// cannot transform the multiplication by kPrime into a shift-multiply-add;
@@ -57,7 +59,8 @@ QuicUint128 IncrementalHashFast(QuicUint128 uhash, QuicStringPiece data) {
#ifndef QUIC_UTIL_HAS_UINT128
// Slow implementation of IncrementalHash. In practice, only used by Chromium.
-QuicUint128 IncrementalHashSlow(QuicUint128 hash, QuicStringPiece data) {
+QuicUint128 IncrementalHashSlow(QuicUint128 hash,
+ quiche::QuicheStringPiece data) {
// kPrime = 309485009821345068724781371
static const QuicUint128 kPrime = MakeQuicUint128(16777216, 315);
const uint8_t* octets = reinterpret_cast<const uint8_t*>(data.data());
@@ -69,7 +72,7 @@ QuicUint128 IncrementalHashSlow(QuicUint128 hash, QuicStringPiece data) {
}
#endif
-QuicUint128 IncrementalHash(QuicUint128 hash, QuicStringPiece data) {
+QuicUint128 IncrementalHash(QuicUint128 hash, quiche::QuicheStringPiece data) {
#ifdef QUIC_UTIL_HAS_UINT128
return IncrementalHashFast(hash, data);
#else
@@ -80,7 +83,7 @@ QuicUint128 IncrementalHash(QuicUint128 hash, QuicStringPiece data) {
} // namespace
// static
-uint64_t QuicUtils::FNV1a_64_Hash(QuicStringPiece data) {
+uint64_t QuicUtils::FNV1a_64_Hash(quiche::QuicheStringPiece data) {
static const uint64_t kOffset = UINT64_C(14695981039346656037);
static const uint64_t kPrime = UINT64_C(1099511628211);
@@ -97,20 +100,21 @@ uint64_t QuicUtils::FNV1a_64_Hash(QuicStringPiece data) {
}
// static
-QuicUint128 QuicUtils::FNV1a_128_Hash(QuicStringPiece data) {
- return FNV1a_128_Hash_Three(data, QuicStringPiece(), QuicStringPiece());
+QuicUint128 QuicUtils::FNV1a_128_Hash(quiche::QuicheStringPiece data) {
+ return FNV1a_128_Hash_Three(data, quiche::QuicheStringPiece(),
+ quiche::QuicheStringPiece());
}
// static
-QuicUint128 QuicUtils::FNV1a_128_Hash_Two(QuicStringPiece data1,
- QuicStringPiece data2) {
- return FNV1a_128_Hash_Three(data1, data2, QuicStringPiece());
+QuicUint128 QuicUtils::FNV1a_128_Hash_Two(quiche::QuicheStringPiece data1,
+ quiche::QuicheStringPiece data2) {
+ return FNV1a_128_Hash_Three(data1, data2, quiche::QuicheStringPiece());
}
// static
-QuicUint128 QuicUtils::FNV1a_128_Hash_Three(QuicStringPiece data1,
- QuicStringPiece data2,
- QuicStringPiece data3) {
+QuicUint128 QuicUtils::FNV1a_128_Hash_Three(quiche::QuicheStringPiece data1,
+ quiche::QuicheStringPiece data2,
+ quiche::QuicheStringPiece data3) {
// The two constants are defined as part of the hash algorithm.
// see http://www.isthe.com/chongo/tech/comp/fnv/
// kOffset = 144066263297769815596495629667062367629
@@ -281,7 +285,7 @@ void QuicUtils::CopyToBuffer(const struct iovec* iov,
}
// static
-struct iovec QuicUtils::MakeIovec(QuicStringPiece data) {
+struct iovec QuicUtils::MakeIovec(quiche::QuicheStringPiece data) {
struct iovec iov = {const_cast<char*>(data.data()),
static_cast<size_t>(data.size())};
return iov;
@@ -317,6 +321,17 @@ bool QuicUtils::IsHandshakeFrame(const QuicFrame& frame,
}
// static
+bool QuicUtils::ContainsFrameType(const QuicFrames& frames,
+ QuicFrameType type) {
+ for (const QuicFrame& frame : frames) {
+ if (frame.type == type) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// static
SentPacketState QuicUtils::RetransmissionTypeToPacketState(
TransmissionType retransmission_type) {
switch (retransmission_type) {
@@ -478,7 +493,7 @@ QuicStreamId QuicUtils::GetFirstUnidirectionalStreamId(
QuicConnectionId QuicUtils::CreateReplacementConnectionId(
QuicConnectionId connection_id) {
const uint64_t connection_id_hash = FNV1a_64_Hash(
- QuicStringPiece(connection_id.data(), connection_id.length()));
+ quiche::QuicheStringPiece(connection_id.data(), connection_id.length()));
return QuicConnectionId(reinterpret_cast<const char*>(&connection_id_hash),
sizeof(connection_id_hash));
}
@@ -513,21 +528,12 @@ QuicConnectionId QuicUtils::CreateRandomConnectionId(
}
// static
-bool QuicUtils::VariableLengthConnectionIdAllowedForVersion(
- QuicTransportVersion version) {
- // We allow variable length connection IDs for unsupported versions to
- // ensure that IETF version negotiation works when other implementations
- // trigger version negotiation with custom connection ID lengths.
- return version > QUIC_VERSION_46 || version == QUIC_VERSION_UNSUPPORTED;
-}
-
-// static
QuicConnectionId QuicUtils::CreateZeroConnectionId(
QuicTransportVersion version) {
- if (!VariableLengthConnectionIdAllowedForVersion(version)) {
+ if (!VersionAllowsVariableLengthConnectionIds(version)) {
char connection_id_bytes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
return QuicConnectionId(static_cast<char*>(connection_id_bytes),
- QUIC_ARRAYSIZE(connection_id_bytes));
+ QUICHE_ARRAYSIZE(connection_id_bytes));
}
return EmptyQuicConnectionId();
}
@@ -541,10 +547,17 @@ bool QuicUtils::IsConnectionIdLengthValidForVersion(
static_cast<size_t>(std::numeric_limits<uint8_t>::max())) {
return false;
}
+
+ if (transport_version == QUIC_VERSION_UNSUPPORTED ||
+ transport_version == QUIC_VERSION_RESERVED_FOR_NEGOTIATION) {
+ // Unknown versions could allow connection ID lengths up to 255.
+ return true;
+ }
+
const uint8_t connection_id_length8 =
static_cast<uint8_t>(connection_id_length);
// Versions that do not support variable lengths only support length 8.
- if (!VariableLengthConnectionIdAllowedForVersion(transport_version)) {
+ if (!VersionAllowsVariableLengthConnectionIds(transport_version)) {
return connection_id_length8 == kQuicDefaultConnectionIdLength;
}
// Versions that do support variable length but do not have length-prefixed
@@ -569,24 +582,11 @@ bool QuicUtils::IsConnectionIdValidForVersion(
QuicUint128 QuicUtils::GenerateStatelessResetToken(
QuicConnectionId connection_id) {
return FNV1a_128_Hash(
- QuicStringPiece(connection_id.data(), connection_id.length()));
+ quiche::QuicheStringPiece(connection_id.data(), connection_id.length()));
}
-// Returns the maximum value that a stream count may have, taking into account
-// the fact that bidirectional, client initiated, streams have one fewer stream
-// available than the others. This is because the old crypto streams, with ID ==
-// 0 are not included in the count.
-// The version is not included in the call, nor does the method take the version
-// into account, because this is called only from code used for IETF QUIC.
-// TODO(fkastenholz): Remove this method and replace calls to it with direct
-// references to kMaxQuicStreamIdCount when streamid 0 becomes a normal stream
-// id.
// static
-QuicStreamCount QuicUtils::GetMaxStreamCount(bool unidirectional,
- Perspective perspective) {
- if (!unidirectional && perspective == Perspective::IS_CLIENT) {
- return kMaxQuicStreamCount >> 2;
- }
+QuicStreamCount QuicUtils::GetMaxStreamCount() {
return (kMaxQuicStreamCount >> 2) + 1;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_utils.h b/chromium/net/third_party/quiche/src/quic/core/quic_utils.h
index f04dace927d..eec9a5f25df 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_utils.h
@@ -7,7 +7,9 @@
#include <cstddef>
#include <cstdint>
+#include <sstream>
#include <string>
+#include <type_traits>
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
#include "net/third_party/quiche/src/quic/core/frames/quic_frame.h"
@@ -18,8 +20,8 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_iovec.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_uint128.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -29,22 +31,22 @@ class QUIC_EXPORT_PRIVATE QuicUtils {
// Returns the 64 bit FNV1a hash of the data. See
// http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param
- static uint64_t FNV1a_64_Hash(QuicStringPiece data);
+ static uint64_t FNV1a_64_Hash(quiche::QuicheStringPiece data);
// Returns the 128 bit FNV1a hash of the data. See
// http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param
- static QuicUint128 FNV1a_128_Hash(QuicStringPiece data);
+ static QuicUint128 FNV1a_128_Hash(quiche::QuicheStringPiece data);
// Returns the 128 bit FNV1a hash of the two sequences of data. See
// http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param
- static QuicUint128 FNV1a_128_Hash_Two(QuicStringPiece data1,
- QuicStringPiece data2);
+ static QuicUint128 FNV1a_128_Hash_Two(quiche::QuicheStringPiece data1,
+ quiche::QuicheStringPiece data2);
// Returns the 128 bit FNV1a hash of the three sequences of data. See
// http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param
- static QuicUint128 FNV1a_128_Hash_Three(QuicStringPiece data1,
- QuicStringPiece data2,
- QuicStringPiece data3);
+ static QuicUint128 FNV1a_128_Hash_Three(quiche::QuicheStringPiece data1,
+ quiche::QuicheStringPiece data2,
+ quiche::QuicheStringPiece data3);
// SerializeUint128 writes the first 96 bits of |v| in little-endian form
// to |out|.
@@ -78,7 +80,7 @@ class QUIC_EXPORT_PRIVATE QuicUtils {
char* buffer);
// Creates an iovec pointing to the same data as |data|.
- static struct iovec MakeIovec(QuicStringPiece data);
+ static struct iovec MakeIovec(quiche::QuicheStringPiece data);
// Returns the opposite Perspective of the |perspective| passed in.
static constexpr Perspective InvertPerspective(Perspective perspective) {
@@ -99,6 +101,9 @@ class QUIC_EXPORT_PRIVATE QuicUtils {
static bool IsHandshakeFrame(const QuicFrame& frame,
QuicTransportVersion transport_version);
+ // Return true if any frame in |frames| is of |type|.
+ static bool ContainsFrameType(const QuicFrames& frames, QuicFrameType type);
+
// Returns packet state corresponding to |retransmission_type|.
static SentPacketState RetransmissionTypeToPacketState(
TransmissionType retransmission_type);
@@ -184,10 +189,6 @@ class QUIC_EXPORT_PRIVATE QuicUtils {
static QuicConnectionId CreateRandomConnectionId(uint8_t connection_id_length,
QuicRandom* random);
- // Returns true if the QUIC version allows variable length connection IDs.
- static bool VariableLengthConnectionIdAllowedForVersion(
- QuicTransportVersion version);
-
// Returns true if the connection ID length is valid for this QUIC version.
static bool IsConnectionIdLengthValidForVersion(
size_t connection_id_length,
@@ -218,10 +219,68 @@ class QUIC_EXPORT_PRIVATE QuicUtils {
// Get the maximum value for a V99/IETF QUIC stream count. If a count
// exceeds this value, it will result in a stream ID that exceeds the
// implementation limit on stream ID size.
- static QuicStreamCount GetMaxStreamCount(bool unidirectional,
- Perspective perspective);
+ static QuicStreamCount GetMaxStreamCount();
};
+template <typename Mask>
+class QUIC_EXPORT_PRIVATE BitMask {
+ public:
+ // explicit to prevent (incorrect) usage like "BitMask bitmask = 0;".
+ template <typename... Bits>
+ explicit BitMask(Bits... bits) {
+ mask_ = MakeMask(bits...);
+ }
+
+ BitMask() = default;
+ BitMask(const BitMask& other) = default;
+ BitMask& operator=(const BitMask& other) = default;
+
+ template <typename... Bits>
+ void Set(Bits... bits) {
+ mask_ |= MakeMask(bits...);
+ }
+
+ template <typename Bit>
+ bool IsSet(Bit bit) const {
+ return (MakeMask(bit) & mask_) != 0;
+ }
+
+ void ClearAll() { mask_ = 0; }
+
+ static constexpr size_t NumBits() { return 8 * sizeof(Mask); }
+
+ friend bool operator==(const BitMask& lhs, const BitMask& rhs) {
+ return lhs.mask_ == rhs.mask_;
+ }
+
+ std::string DebugString() const {
+ std::ostringstream oss;
+ oss << "0x" << std::hex << mask_;
+ return oss.str();
+ }
+
+ private:
+ template <typename Bit>
+ static std::enable_if_t<std::is_enum<Bit>::value, Mask> MakeMask(Bit bit) {
+ using IntType = typename std::underlying_type<Bit>::type;
+ return Mask(1) << static_cast<IntType>(bit);
+ }
+
+ template <typename Bit>
+ static std::enable_if_t<!std::is_enum<Bit>::value, Mask> MakeMask(Bit bit) {
+ return Mask(1) << bit;
+ }
+
+ template <typename Bit, typename... Bits>
+ static Mask MakeMask(Bit first_bit, Bits... other_bits) {
+ return MakeMask(first_bit) | MakeMask(other_bits...);
+ }
+
+ Mask mask_ = 0;
+};
+
+using BitMask64 = BitMask<uint64_t>;
+
} // namespace quic
#endif // QUICHE_QUIC_CORE_QUIC_UTILS_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_utils_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_utils_test.cc
index 362c766b7de..5b2186acde4 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_utils_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_utils_test.cc
@@ -8,9 +8,10 @@
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
@@ -99,7 +100,7 @@ TEST_F(QuicUtilsTest, ReferenceTest) {
data[i] = i % 255;
}
EXPECT_EQ(IncrementalHashReference(data.data(), data.size()),
- QuicUtils::FNV1a_128_Hash(QuicStringPiece(
+ QuicUtils::FNV1a_128_Hash(quiche::QuicheStringPiece(
reinterpret_cast<const char*>(data.data()), data.size())));
}
@@ -183,7 +184,7 @@ TEST_F(QuicUtilsTest, ReplacementConnectionIdIsDeterministic) {
TEST_F(QuicUtilsTest, ReplacementConnectionIdLengthIsCorrect) {
// Verify that all lengths get replaced by kQuicDefaultConnectionIdLength.
- const char connection_id_bytes[kQuicMaxConnectionIdAllVersionsLength] = {};
+ const char connection_id_bytes[255] = {};
for (uint8_t i = 0; i < sizeof(connection_id_bytes) - 1; ++i) {
QuicConnectionId connection_id(connection_id_bytes, i);
QuicConnectionId replacement_connection_id =
@@ -213,10 +214,10 @@ TEST_F(QuicUtilsTest, RandomConnectionId) {
QuicConnectionId connection_id = QuicUtils::CreateRandomConnectionId(&random);
EXPECT_EQ(connection_id.length(), sizeof(uint64_t));
char connection_id_bytes[sizeof(uint64_t)];
- random.RandBytes(connection_id_bytes, QUIC_ARRAYSIZE(connection_id_bytes));
+ random.RandBytes(connection_id_bytes, QUICHE_ARRAYSIZE(connection_id_bytes));
EXPECT_EQ(connection_id,
QuicConnectionId(static_cast<char*>(connection_id_bytes),
- QUIC_ARRAYSIZE(connection_id_bytes)));
+ QUICHE_ARRAYSIZE(connection_id_bytes)));
EXPECT_NE(connection_id, EmptyQuicConnectionId());
EXPECT_NE(connection_id, TestConnectionId());
EXPECT_NE(connection_id, TestConnectionId(1));
@@ -232,10 +233,10 @@ TEST_F(QuicUtilsTest, RandomConnectionIdVariableLength) {
QuicUtils::CreateRandomConnectionId(connection_id_length, &random);
EXPECT_EQ(connection_id.length(), connection_id_length);
char connection_id_bytes[connection_id_length];
- random.RandBytes(connection_id_bytes, QUIC_ARRAYSIZE(connection_id_bytes));
+ random.RandBytes(connection_id_bytes, QUICHE_ARRAYSIZE(connection_id_bytes));
EXPECT_EQ(connection_id,
QuicConnectionId(static_cast<char*>(connection_id_bytes),
- QUIC_ARRAYSIZE(connection_id_bytes)));
+ QUICHE_ARRAYSIZE(connection_id_bytes)));
EXPECT_NE(connection_id, EmptyQuicConnectionId());
EXPECT_NE(connection_id, TestConnectionId());
EXPECT_NE(connection_id, TestConnectionId(1));
@@ -245,15 +246,14 @@ TEST_F(QuicUtilsTest, RandomConnectionIdVariableLength) {
}
TEST_F(QuicUtilsTest, VariableLengthConnectionId) {
- EXPECT_FALSE(
- QuicUtils::VariableLengthConnectionIdAllowedForVersion(QUIC_VERSION_43));
+ EXPECT_FALSE(VersionAllowsVariableLengthConnectionIds(QUIC_VERSION_43));
EXPECT_TRUE(QuicUtils::IsConnectionIdValidForVersion(
QuicUtils::CreateZeroConnectionId(QUIC_VERSION_43), QUIC_VERSION_43));
EXPECT_TRUE(QuicUtils::IsConnectionIdValidForVersion(
- QuicUtils::CreateZeroConnectionId(QUIC_VERSION_99), QUIC_VERSION_99));
+ QuicUtils::CreateZeroConnectionId(QUIC_VERSION_50), QUIC_VERSION_50));
EXPECT_NE(QuicUtils::CreateZeroConnectionId(QUIC_VERSION_43),
EmptyQuicConnectionId());
- EXPECT_EQ(QuicUtils::CreateZeroConnectionId(QUIC_VERSION_99),
+ EXPECT_EQ(QuicUtils::CreateZeroConnectionId(QUIC_VERSION_50),
EmptyQuicConnectionId());
EXPECT_FALSE(QuicUtils::IsConnectionIdValidForVersion(EmptyQuicConnectionId(),
QUIC_VERSION_43));
@@ -270,6 +270,81 @@ TEST_F(QuicUtilsTest, StatelessResetToken) {
EXPECT_NE(token1a, token2);
}
+enum class TestEnumClassBit : uint8_t {
+ BIT_ZERO = 0,
+ BIT_ONE,
+ BIT_TWO,
+};
+
+enum TestEnumBit {
+ TEST_BIT_0 = 0,
+ TEST_BIT_1,
+ TEST_BIT_2,
+};
+
+TEST(QuicBitMaskTest, EnumClass) {
+ BitMask64 mask(TestEnumClassBit::BIT_ZERO, TestEnumClassBit::BIT_TWO);
+ EXPECT_TRUE(mask.IsSet(TestEnumClassBit::BIT_ZERO));
+ EXPECT_FALSE(mask.IsSet(TestEnumClassBit::BIT_ONE));
+ EXPECT_TRUE(mask.IsSet(TestEnumClassBit::BIT_TWO));
+
+ mask.ClearAll();
+ EXPECT_FALSE(mask.IsSet(TestEnumClassBit::BIT_ZERO));
+ EXPECT_FALSE(mask.IsSet(TestEnumClassBit::BIT_ONE));
+ EXPECT_FALSE(mask.IsSet(TestEnumClassBit::BIT_TWO));
+}
+
+TEST(QuicBitMaskTest, Enum) {
+ BitMask64 mask(TEST_BIT_1, TEST_BIT_2);
+ EXPECT_FALSE(mask.IsSet(TEST_BIT_0));
+ EXPECT_TRUE(mask.IsSet(TEST_BIT_1));
+ EXPECT_TRUE(mask.IsSet(TEST_BIT_2));
+
+ mask.ClearAll();
+ EXPECT_FALSE(mask.IsSet(TEST_BIT_0));
+ EXPECT_FALSE(mask.IsSet(TEST_BIT_1));
+ EXPECT_FALSE(mask.IsSet(TEST_BIT_2));
+}
+
+TEST(QuicBitMaskTest, Integer) {
+ BitMask64 mask(1, 3);
+ mask.Set(3);
+ mask.Set(5, 7, 9);
+ EXPECT_FALSE(mask.IsSet(0));
+ EXPECT_TRUE(mask.IsSet(1));
+ EXPECT_FALSE(mask.IsSet(2));
+ EXPECT_TRUE(mask.IsSet(3));
+ EXPECT_FALSE(mask.IsSet(4));
+ EXPECT_TRUE(mask.IsSet(5));
+ EXPECT_FALSE(mask.IsSet(6));
+ EXPECT_TRUE(mask.IsSet(7));
+ EXPECT_FALSE(mask.IsSet(8));
+ EXPECT_TRUE(mask.IsSet(9));
+}
+
+TEST(QuicBitMaskTest, NumBits) {
+ EXPECT_EQ(64u, BitMask64::NumBits());
+ EXPECT_EQ(32u, BitMask<uint32_t>::NumBits());
+}
+
+TEST(QuicBitMaskTest, Constructor) {
+ BitMask64 empty_mask;
+ for (size_t bit = 0; bit < empty_mask.NumBits(); ++bit) {
+ EXPECT_FALSE(empty_mask.IsSet(bit));
+ }
+
+ BitMask64 mask(1, 3);
+ BitMask64 mask2 = mask;
+ BitMask64 mask3(mask2);
+
+ for (size_t bit = 0; bit < mask.NumBits(); ++bit) {
+ EXPECT_EQ(mask.IsSet(bit), mask2.IsSet(bit));
+ EXPECT_EQ(mask.IsSet(bit), mask3.IsSet(bit));
+ }
+
+ EXPECT_TRUE(std::is_trivially_copyable<BitMask64>::value);
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.cc b/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.cc
index 476bbc7fad3..1dda8881066 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.cc
@@ -4,22 +4,29 @@
#include "net/third_party/quiche/src/quic/core/quic_version_manager.h"
+#include <algorithm>
+
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
-
-#include <algorithm>
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
namespace quic {
QuicVersionManager::QuicVersionManager(
ParsedQuicVersionVector supported_versions)
- : enable_version_99_(GetQuicReloadableFlag(quic_enable_version_99)),
- enable_version_50_(GetQuicReloadableFlag(quic_enable_version_50)),
- enable_tls_(GetQuicReloadableFlag(quic_supports_tls_handshake)),
+ : enable_version_draft_27_(
+ GetQuicReloadableFlag(quic_enable_version_draft_27)),
+ enable_version_draft_25_(
+ GetQuicReloadableFlag(quic_enable_version_draft_25_v3)),
+ disable_version_q050_(GetQuicReloadableFlag(quic_disable_version_q050)),
+ enable_version_t050_(GetQuicReloadableFlag(quic_enable_version_t050)),
+ disable_version_q049_(GetQuicReloadableFlag(quic_disable_version_q049)),
+ disable_version_q048_(GetQuicReloadableFlag(quic_disable_version_q048)),
+ disable_version_q046_(GetQuicReloadableFlag(quic_disable_version_q046)),
+ disable_version_q043_(GetQuicReloadableFlag(quic_disable_version_q043)),
allowed_supported_versions_(std::move(supported_versions)) {
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
+ static_assert(SupportedVersions().size() == 8u,
"Supported versions out of sync");
RefilterSupportedVersions();
}
@@ -38,14 +45,34 @@ const ParsedQuicVersionVector& QuicVersionManager::GetSupportedVersions() {
}
void QuicVersionManager::MaybeRefilterSupportedVersions() {
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
+ static_assert(SupportedVersions().size() == 8u,
"Supported versions out of sync");
- if (enable_version_99_ != GetQuicReloadableFlag(quic_enable_version_99) ||
- enable_version_50_ != GetQuicReloadableFlag(quic_enable_version_50) ||
- enable_tls_ != GetQuicReloadableFlag(quic_supports_tls_handshake)) {
- enable_version_99_ = GetQuicReloadableFlag(quic_enable_version_99);
- enable_version_50_ = GetQuicReloadableFlag(quic_enable_version_50);
- enable_tls_ = GetQuicReloadableFlag(quic_supports_tls_handshake);
+ if (enable_version_draft_27_ !=
+ GetQuicReloadableFlag(quic_enable_version_draft_27) ||
+ enable_version_draft_25_ !=
+ GetQuicReloadableFlag(quic_enable_version_draft_25_v3) ||
+ disable_version_q050_ !=
+ GetQuicReloadableFlag(quic_disable_version_q050) ||
+ enable_version_t050_ != GetQuicReloadableFlag(quic_enable_version_t050) ||
+ disable_version_q049_ !=
+ GetQuicReloadableFlag(quic_disable_version_q049) ||
+ disable_version_q048_ !=
+ GetQuicReloadableFlag(quic_disable_version_q048) ||
+ disable_version_q046_ !=
+ GetQuicReloadableFlag(quic_disable_version_q046) ||
+ disable_version_q043_ !=
+ GetQuicReloadableFlag(quic_disable_version_q043)) {
+ enable_version_draft_27_ =
+ GetQuicReloadableFlag(quic_enable_version_draft_27);
+ enable_version_draft_25_ =
+ GetQuicReloadableFlag(quic_enable_version_draft_25_v3);
+ disable_version_q050_ = GetQuicReloadableFlag(quic_disable_version_q050);
+ enable_version_t050_ = GetQuicReloadableFlag(quic_enable_version_t050);
+ disable_version_q049_ = GetQuicReloadableFlag(quic_disable_version_q049);
+ disable_version_q048_ = GetQuicReloadableFlag(quic_disable_version_q048);
+ disable_version_q046_ = GetQuicReloadableFlag(quic_disable_version_q046);
+ disable_version_q043_ = GetQuicReloadableFlag(quic_disable_version_q043);
+
RefilterSupportedVersions();
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.h b/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.h
index 0851464b857..4d683745bdc 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.h
@@ -41,12 +41,22 @@ class QUIC_EXPORT_PRIVATE QuicVersionManager {
private:
// Cached value of reloadable flags.
- // quic_enable_version_99 flag
- bool enable_version_99_;
- // quic_enable_version_50 flag
- bool enable_version_50_;
- // quic_supports_tls_handshake flag
- bool enable_tls_;
+ // quic_enable_version_draft_27 flag
+ bool enable_version_draft_27_;
+ // quic_enable_version_draft_25_v3 flag
+ bool enable_version_draft_25_;
+ // quic_disable_version_q050 flag
+ bool disable_version_q050_;
+ // quic_enable_version_t050 flag
+ bool enable_version_t050_;
+ // quic_disable_version_q049 flag
+ bool disable_version_q049_;
+ // quic_disable_version_q048 flag
+ bool disable_version_q048_;
+ // quic_disable_version_q046 flag
+ bool disable_version_q046_;
+ // quic_disable_version_q043 flag
+ bool disable_version_q043_;
// The list of versions that may be supported.
ParsedQuicVersionVector allowed_supported_versions_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_version_manager_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_version_manager_test.cc
index 48623a878f3..98dc4a348ec 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_version_manager_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_version_manager_test.cc
@@ -5,9 +5,9 @@
#include "net/third_party/quiche/src/quic/core/quic_version_manager.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
namespace quic {
namespace test {
@@ -16,40 +16,55 @@ namespace {
class QuicVersionManagerTest : public QuicTest {};
TEST_F(QuicVersionManagerTest, QuicVersionManager) {
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
+ static_assert(SupportedVersions().size() == 8u,
"Supported versions out of sync");
- SetQuicReloadableFlag(quic_enable_version_99, false);
- SetQuicReloadableFlag(quic_enable_version_50, false);
+ SetQuicReloadableFlag(quic_enable_version_draft_27, false);
+ SetQuicReloadableFlag(quic_enable_version_draft_25_v3, false);
+ SetQuicReloadableFlag(quic_enable_version_t050, false);
+ SetQuicReloadableFlag(quic_disable_version_q050, false);
+ SetQuicReloadableFlag(quic_disable_version_q049, false);
+ SetQuicReloadableFlag(quic_disable_version_q048, false);
+ SetQuicReloadableFlag(quic_disable_version_q046, false);
+ SetQuicReloadableFlag(quic_disable_version_q043, false);
QuicVersionManager manager(AllSupportedVersions());
- EXPECT_EQ(FilterSupportedTransportVersions(AllSupportedTransportVersions()),
- manager.GetSupportedTransportVersions());
-
- EXPECT_EQ(QuicTransportVersionVector({QUIC_VERSION_49, QUIC_VERSION_48,
- QUIC_VERSION_46, QUIC_VERSION_43}),
- manager.GetSupportedTransportVersions());
-
- SetQuicReloadableFlag(quic_enable_version_50, true);
- EXPECT_EQ(QuicTransportVersionVector({QUIC_VERSION_50, QUIC_VERSION_49,
- QUIC_VERSION_48, QUIC_VERSION_46,
- QUIC_VERSION_43}),
- manager.GetSupportedTransportVersions());
-
- SetQuicReloadableFlag(quic_enable_version_99, true);
- EXPECT_EQ(QuicTransportVersionVector({QUIC_VERSION_99, QUIC_VERSION_50,
- QUIC_VERSION_49, QUIC_VERSION_48,
- QUIC_VERSION_46, QUIC_VERSION_43}),
- manager.GetSupportedTransportVersions());
-
- SetQuicReloadableFlag(quic_enable_version_99, true);
- EXPECT_EQ(QuicTransportVersionVector({QUIC_VERSION_99, QUIC_VERSION_50,
- QUIC_VERSION_49, QUIC_VERSION_48,
- QUIC_VERSION_46, QUIC_VERSION_43}),
- manager.GetSupportedTransportVersions());
-
- // Ensure that all versions are now supported.
- EXPECT_EQ(FilterSupportedTransportVersions(AllSupportedTransportVersions()),
- manager.GetSupportedTransportVersions());
+ ParsedQuicVersionVector expected_parsed_versions;
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50));
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_49));
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48));
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46));
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43));
+
+ EXPECT_EQ(expected_parsed_versions, manager.GetSupportedVersions());
+
+ EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()),
+ manager.GetSupportedVersions());
+
+ SetQuicReloadableFlag(quic_enable_version_draft_27, true);
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_DRAFT_27));
+ EXPECT_EQ(expected_parsed_versions, manager.GetSupportedVersions());
+ EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()),
+ manager.GetSupportedVersions());
+
+ SetQuicReloadableFlag(quic_enable_version_draft_25_v3, true);
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_DRAFT_25));
+ EXPECT_EQ(expected_parsed_versions, manager.GetSupportedVersions());
+ EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()),
+ manager.GetSupportedVersions());
+
+ SetQuicReloadableFlag(quic_enable_version_t050, true);
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_50));
+ EXPECT_EQ(expected_parsed_versions, manager.GetSupportedVersions());
+ EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()),
+ manager.GetSupportedVersions());
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_versions.cc b/chromium/net/third_party/quiche/src/quic/core/quic_versions.cc
index abeb64e7f7f..6dc67d92078 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_versions.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_versions.cc
@@ -9,13 +9,14 @@
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
#include "net/third_party/quiche/src/quic/core/quic_tag.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
namespace {
@@ -40,53 +41,126 @@ QuicVersionLabel CreateRandomVersionLabelForNegotiation() {
} // namespace
+bool ParsedQuicVersion::IsKnown() const {
+ DCHECK(ParsedQuicVersionIsValid(handshake_protocol, transport_version))
+ << QuicVersionToString(transport_version) << " "
+ << HandshakeProtocolToString(handshake_protocol);
+ return transport_version != QUIC_VERSION_UNSUPPORTED;
+}
+
bool ParsedQuicVersion::KnowsWhichDecrypterToUse() const {
+ DCHECK(IsKnown());
return transport_version > QUIC_VERSION_46 ||
handshake_protocol == PROTOCOL_TLS1_3;
}
bool ParsedQuicVersion::UsesInitialObfuscators() const {
+ DCHECK(IsKnown());
return transport_version > QUIC_VERSION_49 ||
handshake_protocol == PROTOCOL_TLS1_3;
}
bool ParsedQuicVersion::AllowsLowFlowControlLimits() const {
- return transport_version == QUIC_VERSION_99 &&
+ DCHECK(IsKnown());
+ return transport_version >= QUIC_VERSION_IETF_DRAFT_25 &&
handshake_protocol == PROTOCOL_TLS1_3;
}
bool ParsedQuicVersion::HasHeaderProtection() const {
+ DCHECK(IsKnown());
return transport_version > QUIC_VERSION_49;
}
bool ParsedQuicVersion::SupportsRetry() const {
+ DCHECK(IsKnown());
return transport_version > QUIC_VERSION_46;
}
+bool ParsedQuicVersion::HasRetryIntegrityTag() const {
+ DCHECK(IsKnown());
+ return handshake_protocol == PROTOCOL_TLS1_3;
+}
+
bool ParsedQuicVersion::SendsVariableLengthPacketNumberInLongHeader() const {
+ DCHECK(IsKnown());
return transport_version > QUIC_VERSION_46;
}
+bool ParsedQuicVersion::AllowsVariableLengthConnectionIds() const {
+ DCHECK(IsKnown());
+ return VersionAllowsVariableLengthConnectionIds(transport_version);
+}
+
bool ParsedQuicVersion::SupportsClientConnectionIds() const {
+ DCHECK(IsKnown());
return transport_version > QUIC_VERSION_48;
}
bool ParsedQuicVersion::HasLengthPrefixedConnectionIds() const {
+ DCHECK(IsKnown());
return VersionHasLengthPrefixedConnectionIds(transport_version);
}
bool ParsedQuicVersion::SupportsAntiAmplificationLimit() const {
- return transport_version == QUIC_VERSION_99 &&
+ DCHECK(IsKnown());
+ return transport_version >= QUIC_VERSION_IETF_DRAFT_25 &&
handshake_protocol == PROTOCOL_TLS1_3;
}
bool ParsedQuicVersion::CanSendCoalescedPackets() const {
+ DCHECK(IsKnown());
return QuicVersionHasLongHeaderLengths(transport_version) &&
handshake_protocol == PROTOCOL_TLS1_3;
}
+bool ParsedQuicVersion::SupportsGoogleAltSvcFormat() const {
+ DCHECK(IsKnown());
+ return VersionSupportsGoogleAltSvcFormat(transport_version);
+}
+
+bool ParsedQuicVersion::HasIetfInvariantHeader() const {
+ DCHECK(IsKnown());
+ return VersionHasIetfInvariantHeader(transport_version);
+}
+
+bool ParsedQuicVersion::SupportsMessageFrames() const {
+ DCHECK(IsKnown());
+ return VersionSupportsMessageFrames(transport_version);
+}
+
+bool ParsedQuicVersion::UsesHttp3() const {
+ DCHECK(IsKnown());
+ return VersionUsesHttp3(transport_version);
+}
+
+bool ParsedQuicVersion::HasLongHeaderLengths() const {
+ DCHECK(IsKnown());
+ return QuicVersionHasLongHeaderLengths(transport_version);
+}
+
+bool ParsedQuicVersion::UsesCryptoFrames() const {
+ DCHECK(IsKnown());
+ return QuicVersionUsesCryptoFrames(transport_version);
+}
+
+bool ParsedQuicVersion::HasIetfQuicFrames() const {
+ DCHECK(IsKnown());
+ return VersionHasIetfQuicFrames(transport_version);
+}
+
+bool ParsedQuicVersion::HasHandshakeDone() const {
+ DCHECK(IsKnown());
+ return HasIetfQuicFrames() && handshake_protocol == PROTOCOL_TLS1_3;
+}
+
+bool ParsedQuicVersion::HasVarIntTransportParams() const {
+ DCHECK(IsKnown());
+ return transport_version >= QUIC_VERSION_IETF_DRAFT_27;
+}
+
bool VersionHasLengthPrefixedConnectionIds(
QuicTransportVersion transport_version) {
+ DCHECK(transport_version != QUIC_VERSION_UNSUPPORTED);
return transport_version > QUIC_VERSION_48;
}
@@ -109,7 +183,7 @@ QuicVersionLabel CreateQuicVersionLabel(ParsedQuicVersion parsed_version) {
<< parsed_version.handshake_protocol;
return 0;
}
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
+ static_assert(SupportedVersions().size() == 8u,
"Supported versions out of sync");
switch (parsed_version.transport_version) {
case QUIC_VERSION_43:
@@ -122,11 +196,18 @@ QuicVersionLabel CreateQuicVersionLabel(ParsedQuicVersion parsed_version) {
return MakeVersionLabel(proto, '0', '4', '9');
case QUIC_VERSION_50:
return MakeVersionLabel(proto, '0', '5', '0');
- case QUIC_VERSION_99:
+ case QUIC_VERSION_IETF_DRAFT_25:
+ if (parsed_version.handshake_protocol == PROTOCOL_TLS1_3) {
+ return MakeVersionLabel(0xff, 0x00, 0x00, 25);
+ }
+ QUIC_BUG << "QUIC_VERSION_IETF_DRAFT_25 requires TLS";
+ return 0;
+ case QUIC_VERSION_IETF_DRAFT_27:
if (parsed_version.handshake_protocol == PROTOCOL_TLS1_3) {
- return MakeVersionLabel(0xff, 0x00, 0x00, kQuicIetfDraftVersion);
+ return MakeVersionLabel(0xff, 0x00, 0x00, 27);
}
- return MakeVersionLabel(proto, '0', '9', '9');
+ QUIC_BUG << "QUIC_VERSION_IETF_DRAFT_27 requires TLS";
+ return 0;
case QUIC_VERSION_RESERVED_FOR_NEGOTIATION:
return CreateRandomVersionLabelForNegotiation();
default:
@@ -148,15 +229,43 @@ QuicVersionLabelVector CreateQuicVersionLabelVector(
return out;
}
+ParsedQuicVersionVector AllSupportedVersionsWithQuicCrypto() {
+ ParsedQuicVersionVector versions;
+ for (const ParsedQuicVersion& version : AllSupportedVersions()) {
+ if (version.handshake_protocol == PROTOCOL_QUIC_CRYPTO) {
+ versions.push_back(version);
+ }
+ }
+ QUIC_BUG_IF(versions.empty()) << "No version with QUIC crypto found.";
+ return versions;
+}
+
+ParsedQuicVersionVector CurrentSupportedVersionsWithQuicCrypto() {
+ ParsedQuicVersionVector versions;
+ for (const ParsedQuicVersion& version : CurrentSupportedVersions()) {
+ if (version.handshake_protocol == PROTOCOL_QUIC_CRYPTO) {
+ versions.push_back(version);
+ }
+ }
+ QUIC_BUG_IF(versions.empty()) << "No version with QUIC crypto found.";
+ return versions;
+}
+
+ParsedQuicVersionVector CurrentSupportedVersionsWithTls() {
+ ParsedQuicVersionVector versions;
+ for (const ParsedQuicVersion& version : CurrentSupportedVersions()) {
+ if (version.handshake_protocol == PROTOCOL_TLS1_3) {
+ versions.push_back(version);
+ }
+ }
+ QUIC_BUG_IF(versions.empty()) << "No version with TLS handshake found.";
+ return versions;
+}
+
ParsedQuicVersion ParseQuicVersionLabel(QuicVersionLabel version_label) {
- std::vector<HandshakeProtocol> protocols = {PROTOCOL_QUIC_CRYPTO,
- PROTOCOL_TLS1_3};
- for (QuicTransportVersion version : kSupportedTransportVersions) {
- for (HandshakeProtocol handshake : protocols) {
- if (version_label ==
- CreateQuicVersionLabel(ParsedQuicVersion(handshake, version))) {
- return ParsedQuicVersion(handshake, version);
- }
+ for (const ParsedQuicVersion& version : AllSupportedVersions()) {
+ if (version_label == CreateQuicVersionLabel(version)) {
+ return version;
}
}
// Reading from the client so this should not be considered an ERROR.
@@ -165,35 +274,37 @@ ParsedQuicVersion ParseQuicVersionLabel(QuicVersionLabel version_label) {
return UnsupportedQuicVersion();
}
-ParsedQuicVersion ParseQuicVersionString(std::string version_string) {
+ParsedQuicVersion ParseQuicVersionString(
+ quiche::QuicheStringPiece version_string) {
if (version_string.empty()) {
return UnsupportedQuicVersion();
}
int quic_version_number = 0;
- if (QuicTextUtils::StringToInt(version_string, &quic_version_number) &&
+ if (quiche::QuicheTextUtils::StringToInt(version_string,
+ &quic_version_number) &&
quic_version_number > 0) {
- return ParsedQuicVersion(
- PROTOCOL_QUIC_CRYPTO,
- static_cast<QuicTransportVersion>(quic_version_number));
- }
-
- std::vector<HandshakeProtocol> protocols = {PROTOCOL_QUIC_CRYPTO};
- if (GetQuicReloadableFlag(quic_supports_tls_handshake)) {
- protocols.push_back(PROTOCOL_TLS1_3);
- }
- for (QuicTransportVersion version : kSupportedTransportVersions) {
- for (HandshakeProtocol handshake : protocols) {
- const ParsedQuicVersion parsed_version =
- ParsedQuicVersion(handshake, version);
- if (version_string == ParsedQuicVersionToString(parsed_version)) {
- return parsed_version;
+ QuicTransportVersion transport_version =
+ static_cast<QuicTransportVersion>(quic_version_number);
+ bool transport_version_is_supported = false;
+ for (QuicTransportVersion transport_vers : SupportedTransportVersions()) {
+ if (transport_vers == transport_version) {
+ transport_version_is_supported = true;
+ break;
}
}
+ if (!transport_version_is_supported ||
+ !ParsedQuicVersionIsValid(PROTOCOL_QUIC_CRYPTO, transport_version)) {
+ return UnsupportedQuicVersion();
+ }
+ return ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, transport_version);
}
- // Still recognize T099 even if flag quic_ietf_draft_version has been changed.
- if (GetQuicReloadableFlag(quic_supports_tls_handshake) &&
- version_string == "T099") {
- return ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99);
+ for (const ParsedQuicVersion& version : AllSupportedVersions()) {
+ if (version_string == ParsedQuicVersionToString(version) ||
+ version_string == AlpnForVersion(version) ||
+ (version.handshake_protocol == PROTOCOL_QUIC_CRYPTO &&
+ version_string == QuicVersionToString(version.transport_version))) {
+ return version;
+ }
}
// Reading from the client so this should not be considered an ERROR.
QUIC_DLOG(INFO) << "Unsupported QUIC version string: \"" << version_string
@@ -201,72 +312,87 @@ ParsedQuicVersion ParseQuicVersionString(std::string version_string) {
return UnsupportedQuicVersion();
}
-QuicTransportVersionVector AllSupportedTransportVersions() {
- QuicTransportVersionVector supported_versions;
- for (QuicTransportVersion version : kSupportedTransportVersions) {
- supported_versions.push_back(version);
+ParsedQuicVersionVector ParseQuicVersionVectorString(
+ quiche::QuicheStringPiece versions_string) {
+ ParsedQuicVersionVector versions;
+ std::vector<quiche::QuicheStringPiece> version_strings =
+ quiche::QuicheTextUtils::Split(versions_string, ',');
+ for (quiche::QuicheStringPiece version_string : version_strings) {
+ quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(
+ &version_string);
+ ParsedQuicVersion version = ParseQuicVersionString(version_string);
+ if (version.transport_version == QUIC_VERSION_UNSUPPORTED ||
+ std::find(versions.begin(), versions.end(), version) !=
+ versions.end()) {
+ continue;
+ }
+ versions.push_back(version);
}
- return supported_versions;
+ return versions;
}
-ParsedQuicVersionVector AllSupportedVersions() {
- ParsedQuicVersionVector supported_versions;
- for (HandshakeProtocol protocol : kSupportedHandshakeProtocols) {
- for (QuicTransportVersion version : kSupportedTransportVersions) {
- if (protocol == PROTOCOL_TLS1_3 &&
- !QuicVersionUsesCryptoFrames(version)) {
- // The TLS handshake is only deployable if CRYPTO frames are also used.
- continue;
- }
- supported_versions.push_back(ParsedQuicVersion(protocol, version));
- }
- }
+QuicTransportVersionVector AllSupportedTransportVersions() {
+ constexpr auto supported_transport_versions = SupportedTransportVersions();
+ QuicTransportVersionVector supported_versions(
+ supported_transport_versions.begin(), supported_transport_versions.end());
return supported_versions;
}
-// TODO(nharper): Remove this function when it is no longer in use.
-QuicTransportVersionVector CurrentSupportedTransportVersions() {
- return FilterSupportedTransportVersions(AllSupportedTransportVersions());
+ParsedQuicVersionVector AllSupportedVersions() {
+ constexpr auto supported_versions = SupportedVersions();
+ return ParsedQuicVersionVector(supported_versions.begin(),
+ supported_versions.end());
}
ParsedQuicVersionVector CurrentSupportedVersions() {
return FilterSupportedVersions(AllSupportedVersions());
}
-// TODO(nharper): Remove this function when it is no longer in use.
-QuicTransportVersionVector FilterSupportedTransportVersions(
- QuicTransportVersionVector versions) {
- ParsedQuicVersionVector parsed_versions;
- for (QuicTransportVersion version : versions) {
- parsed_versions.push_back(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
- }
- ParsedQuicVersionVector filtered_parsed_versions =
- FilterSupportedVersions(parsed_versions);
- QuicTransportVersionVector filtered_versions;
- for (ParsedQuicVersion version : filtered_parsed_versions) {
- filtered_versions.push_back(version.transport_version);
- }
- return filtered_versions;
-}
-
ParsedQuicVersionVector FilterSupportedVersions(
ParsedQuicVersionVector versions) {
ParsedQuicVersionVector filtered_versions;
filtered_versions.reserve(versions.size());
for (ParsedQuicVersion version : versions) {
- if (version.handshake_protocol == PROTOCOL_TLS1_3 &&
- !GetQuicReloadableFlag(quic_supports_tls_handshake)) {
- continue;
- }
- if (version.transport_version == QUIC_VERSION_99) {
- if (GetQuicReloadableFlag(quic_enable_version_99)) {
+ if (version.transport_version == QUIC_VERSION_IETF_DRAFT_27) {
+ QUIC_BUG_IF(version.handshake_protocol != PROTOCOL_TLS1_3);
+ if (GetQuicReloadableFlag(quic_enable_version_draft_27)) {
+ filtered_versions.push_back(version);
+ }
+ } else if (version.transport_version == QUIC_VERSION_IETF_DRAFT_25) {
+ QUIC_BUG_IF(version.handshake_protocol != PROTOCOL_TLS1_3);
+ if (GetQuicReloadableFlag(quic_enable_version_draft_25_v3)) {
filtered_versions.push_back(version);
}
} else if (version.transport_version == QUIC_VERSION_50) {
- if (GetQuicReloadableFlag(quic_enable_version_50)) {
+ if (version.handshake_protocol == PROTOCOL_QUIC_CRYPTO) {
+ if (!GetQuicReloadableFlag(quic_disable_version_q050)) {
+ filtered_versions.push_back(version);
+ }
+ } else {
+ if (GetQuicReloadableFlag(quic_enable_version_t050)) {
+ filtered_versions.push_back(version);
+ }
+ }
+ } else if (version.transport_version == QUIC_VERSION_49) {
+ if (!GetQuicReloadableFlag(quic_disable_version_q049)) {
+ filtered_versions.push_back(version);
+ }
+ } else if (version.transport_version == QUIC_VERSION_48) {
+ if (!GetQuicReloadableFlag(quic_disable_version_q048)) {
+ filtered_versions.push_back(version);
+ }
+ } else if (version.transport_version == QUIC_VERSION_46) {
+ QUIC_BUG_IF(version.handshake_protocol != PROTOCOL_QUIC_CRYPTO);
+ if (!GetQuicReloadableFlag(quic_disable_version_q046)) {
+ filtered_versions.push_back(version);
+ }
+ } else if (version.transport_version == QUIC_VERSION_43) {
+ QUIC_BUG_IF(version.handshake_protocol != PROTOCOL_QUIC_CRYPTO);
+ if (!GetQuicReloadableFlag(quic_disable_version_q043)) {
filtered_versions.push_back(version);
}
} else {
+ QUIC_BUG << "QUIC version " << version << " has no flag protection";
filtered_versions.push_back(version);
}
}
@@ -353,7 +479,7 @@ HandshakeProtocol QuicVersionLabelToHandshakeProtocol(
return #x
std::string QuicVersionToString(QuicTransportVersion transport_version) {
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
+ static_assert(SupportedTransportVersions().size() == 7u,
"Supported versions out of sync");
switch (transport_version) {
RETURN_STRING_LITERAL(QUIC_VERSION_43);
@@ -361,10 +487,23 @@ std::string QuicVersionToString(QuicTransportVersion transport_version) {
RETURN_STRING_LITERAL(QUIC_VERSION_48);
RETURN_STRING_LITERAL(QUIC_VERSION_49);
RETURN_STRING_LITERAL(QUIC_VERSION_50);
- RETURN_STRING_LITERAL(QUIC_VERSION_99);
- default:
- return "QUIC_VERSION_UNSUPPORTED";
+ RETURN_STRING_LITERAL(QUIC_VERSION_IETF_DRAFT_25);
+ RETURN_STRING_LITERAL(QUIC_VERSION_IETF_DRAFT_27);
+ RETURN_STRING_LITERAL(QUIC_VERSION_UNSUPPORTED);
+ RETURN_STRING_LITERAL(QUIC_VERSION_RESERVED_FOR_NEGOTIATION);
}
+ return quiche::QuicheStrCat("QUIC_VERSION_UNKNOWN(",
+ static_cast<int>(transport_version), ")");
+}
+
+std::string HandshakeProtocolToString(HandshakeProtocol handshake_protocol) {
+ switch (handshake_protocol) {
+ RETURN_STRING_LITERAL(PROTOCOL_UNSUPPORTED);
+ RETURN_STRING_LITERAL(PROTOCOL_QUIC_CRYPTO);
+ RETURN_STRING_LITERAL(PROTOCOL_TLS1_3);
+ }
+ return quiche::QuicheStrCat("PROTOCOL_UNKNOWN(",
+ static_cast<int>(handshake_protocol), ")");
}
std::string ParsedQuicVersionToString(ParsedQuicVersion version) {
@@ -408,6 +547,12 @@ bool VersionSupportsGoogleAltSvcFormat(QuicTransportVersion transport_version) {
return transport_version <= QUIC_VERSION_46;
}
+bool VersionAllowsVariableLengthConnectionIds(
+ QuicTransportVersion transport_version) {
+ DCHECK_NE(transport_version, QUIC_VERSION_UNSUPPORTED);
+ return transport_version > QUIC_VERSION_46;
+}
+
bool QuicVersionLabelUses4BitConnectionIdLength(
QuicVersionLabel version_label) {
// As we deprecate old versions, we still need the ability to send valid
@@ -446,29 +591,44 @@ ParsedQuicVersion QuicVersionReservedForNegotiation() {
}
std::string AlpnForVersion(ParsedQuicVersion parsed_version) {
- if (parsed_version.handshake_protocol == PROTOCOL_TLS1_3 &&
- parsed_version.transport_version == QUIC_VERSION_99) {
- return "h3-" + QuicTextUtils::Uint64ToString(kQuicIetfDraftVersion);
+ if (parsed_version.handshake_protocol == PROTOCOL_TLS1_3) {
+ if (parsed_version.transport_version == QUIC_VERSION_IETF_DRAFT_25) {
+ return "h3-25";
+ }
+ if (parsed_version.transport_version == QUIC_VERSION_IETF_DRAFT_27) {
+ return "h3-27";
+ }
}
return "h3-" + ParsedQuicVersionToString(parsed_version);
}
void QuicVersionInitializeSupportForIetfDraft() {
// Enable necessary flags.
- SetQuicReloadableFlag(quic_supports_tls_handshake, true);
}
void QuicEnableVersion(ParsedQuicVersion parsed_version) {
- if (parsed_version.handshake_protocol == PROTOCOL_TLS1_3) {
- SetQuicReloadableFlag(quic_supports_tls_handshake, true);
- }
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
+ static_assert(SupportedVersions().size() == 8u,
"Supported versions out of sync");
- if (parsed_version.transport_version == QUIC_VERSION_99) {
- SetQuicReloadableFlag(quic_enable_version_99, true);
- }
- if (parsed_version.transport_version == QUIC_VERSION_50) {
- SetQuicReloadableFlag(quic_enable_version_50, true);
+ if (parsed_version.transport_version == QUIC_VERSION_IETF_DRAFT_27) {
+ QUIC_BUG_IF(parsed_version.handshake_protocol != PROTOCOL_TLS1_3);
+ SetQuicReloadableFlag(quic_enable_version_draft_27, true);
+ } else if (parsed_version.transport_version == QUIC_VERSION_IETF_DRAFT_25) {
+ QUIC_BUG_IF(parsed_version.handshake_protocol != PROTOCOL_TLS1_3);
+ SetQuicReloadableFlag(quic_enable_version_draft_25_v3, true);
+ } else if (parsed_version.transport_version == QUIC_VERSION_50) {
+ if (parsed_version.handshake_protocol == PROTOCOL_QUIC_CRYPTO) {
+ SetQuicReloadableFlag(quic_disable_version_q050, false);
+ } else {
+ SetQuicReloadableFlag(quic_enable_version_t050, true);
+ }
+ } else if (parsed_version.transport_version == QUIC_VERSION_49) {
+ SetQuicReloadableFlag(quic_disable_version_q049, false);
+ } else if (parsed_version.transport_version == QUIC_VERSION_48) {
+ SetQuicReloadableFlag(quic_disable_version_q048, false);
+ } else if (parsed_version.transport_version == QUIC_VERSION_46) {
+ SetQuicReloadableFlag(quic_disable_version_q046, false);
+ } else if (parsed_version.transport_version == QUIC_VERSION_43) {
+ SetQuicReloadableFlag(quic_disable_version_q043, false);
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_versions.h b/chromium/net/third_party/quiche/src/quic/core/quic_versions.h
index 0a4022e2006..7850b416fc9 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_versions.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_versions.h
@@ -21,6 +21,7 @@
#include "net/third_party/quiche/src/quic/core/quic_tag.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -107,8 +108,11 @@ enum QuicTransportVersion {
QUIC_VERSION_49 = 49, // Client connection IDs, long header lengths, IETF
// header format from draft-ietf-quic-invariants-06.
QUIC_VERSION_50 = 50, // Header protection and initial obfuscators.
- QUIC_VERSION_99 = 99, // Dumping ground for IETF QUIC changes which are not
- // yet ready for production.
+ QUIC_VERSION_IETF_DRAFT_25 = 70, // draft-ietf-quic-transport-25.
+ QUIC_VERSION_IETF_DRAFT_27 = 71, // draft-ietf-quic-transport-27.
+ // Version 99 was a dumping ground for IETF QUIC changes which were not yet
+ // yet ready for production between 2018-02 and 2020-02.
+
// QUIC_VERSION_RESERVED_FOR_NEGOTIATION is sent over the wire as ?a?a?a?a
// which is part of a range reserved by the IETF for version negotiation
// testing (see the "Versions" section of draft-ietf-quic-transport).
@@ -118,8 +122,26 @@ enum QuicTransportVersion {
QUIC_VERSION_RESERVED_FOR_NEGOTIATION = 999,
};
-// IETF draft version most closely approximated by TLS + v99.
-static const int kQuicIetfDraftVersion = 24;
+// This array contains QUIC transport versions which we currently support.
+// This should be ordered such that the highest supported version is the first
+// element, with subsequent elements in descending order (versions can be
+// skipped as necessary).
+//
+// See go/new-quic-version for more details on how to roll out new versions.
+constexpr std::array<QuicTransportVersion, 7> SupportedTransportVersions() {
+ return {QUIC_VERSION_IETF_DRAFT_27,
+ QUIC_VERSION_IETF_DRAFT_25,
+ QUIC_VERSION_50,
+ QUIC_VERSION_49,
+ QUIC_VERSION_48,
+ QUIC_VERSION_46,
+ QUIC_VERSION_43};
+}
+
+// Helper function which translates from a QuicTransportVersion to a string.
+// Returns strings corresponding to enum names (e.g. QUIC_VERSION_6).
+QUIC_EXPORT_PRIVATE std::string QuicVersionToString(
+ QuicTransportVersion transport_version);
// The crypto handshake protocols that can be used with QUIC.
enum HandshakeProtocol {
@@ -128,6 +150,58 @@ enum HandshakeProtocol {
PROTOCOL_TLS1_3,
};
+// Helper function which translates from a HandshakeProtocol to a string.
+QUIC_EXPORT_PRIVATE std::string HandshakeProtocolToString(
+ HandshakeProtocol handshake_protocol);
+
+// Returns whether |transport_version| uses CRYPTO frames for the handshake
+// instead of stream 1.
+QUIC_EXPORT_PRIVATE constexpr bool QuicVersionUsesCryptoFrames(
+ QuicTransportVersion transport_version) {
+ return transport_version >= QUIC_VERSION_48;
+}
+
+// Returns whether this combination of handshake protocol and transport
+// version is allowed. For example, {PROTOCOL_TLS1_3, QUIC_VERSION_43} is NOT
+// allowed as TLS requires crypto frames which v43 does not support. Note that
+// UnsupportedQuicVersion is a valid version.
+QUIC_EXPORT_PRIVATE constexpr bool ParsedQuicVersionIsValid(
+ HandshakeProtocol handshake_protocol,
+ QuicTransportVersion transport_version) {
+ bool transport_version_is_valid =
+ transport_version == QUIC_VERSION_UNSUPPORTED ||
+ transport_version == QUIC_VERSION_RESERVED_FOR_NEGOTIATION;
+ if (!transport_version_is_valid) {
+ // Iterators are not constexpr in C++14 which Chrome uses.
+ constexpr auto supported_transport_versions = SupportedTransportVersions();
+ for (size_t i = 0; i < supported_transport_versions.size(); ++i) {
+ const QuicTransportVersion& trans_vers = supported_transport_versions[i];
+ if (trans_vers == transport_version) {
+ transport_version_is_valid = true;
+ break;
+ }
+ }
+ }
+ if (!transport_version_is_valid) {
+ return false;
+ }
+ switch (handshake_protocol) {
+ case PROTOCOL_UNSUPPORTED:
+ return transport_version == QUIC_VERSION_UNSUPPORTED;
+ case PROTOCOL_QUIC_CRYPTO:
+ return transport_version != QUIC_VERSION_UNSUPPORTED &&
+ transport_version != QUIC_VERSION_IETF_DRAFT_25 &&
+ transport_version != QUIC_VERSION_IETF_DRAFT_27;
+ case PROTOCOL_TLS1_3:
+ // The TLS handshake is only deployable if CRYPTO frames are also used.
+ // We explicitly removed support for T048 and T049 to reduce test load.
+ return transport_version != QUIC_VERSION_UNSUPPORTED &&
+ QuicVersionUsesCryptoFrames(transport_version) &&
+ transport_version > QUIC_VERSION_49;
+ }
+ return false;
+}
+
// A parsed QUIC version label which determines that handshake protocol
// and the transport version.
struct QUIC_EXPORT_PRIVATE ParsedQuicVersion {
@@ -137,13 +211,20 @@ struct QUIC_EXPORT_PRIVATE ParsedQuicVersion {
constexpr ParsedQuicVersion(HandshakeProtocol handshake_protocol,
QuicTransportVersion transport_version)
: handshake_protocol(handshake_protocol),
- transport_version(transport_version) {}
+ transport_version(transport_version) {
+ DCHECK(ParsedQuicVersionIsValid(handshake_protocol, transport_version))
+ << QuicVersionToString(transport_version) << " "
+ << HandshakeProtocolToString(handshake_protocol);
+ }
constexpr ParsedQuicVersion(const ParsedQuicVersion& other)
- : handshake_protocol(other.handshake_protocol),
- transport_version(other.transport_version) {}
+ : ParsedQuicVersion(other.handshake_protocol, other.transport_version) {}
ParsedQuicVersion& operator=(const ParsedQuicVersion& other) {
+ DCHECK(ParsedQuicVersionIsValid(other.handshake_protocol,
+ other.transport_version))
+ << QuicVersionToString(other.transport_version) << " "
+ << HandshakeProtocolToString(other.handshake_protocol);
if (this != &other) {
handshake_protocol = other.handshake_protocol;
transport_version = other.transport_version;
@@ -161,6 +242,12 @@ struct QUIC_EXPORT_PRIVATE ParsedQuicVersion {
transport_version != other.transport_version;
}
+ // Returns whether our codebase understands this version. This should only be
+ // called on valid versions, see ParsedQuicVersionIsValid. Assuming the
+ // version is valid, IsKnown returns whether the version is not
+ // UnsupportedQuicVersion.
+ bool IsKnown() const;
+
bool KnowsWhichDecrypterToUse() const;
// Returns whether this version uses keys derived from the Connection ID for
@@ -177,10 +264,17 @@ struct QUIC_EXPORT_PRIVATE ParsedQuicVersion {
// Returns whether this version supports IETF RETRY packets.
bool SupportsRetry() const;
+ // Returns whether RETRY packets carry the Retry Integrity Tag field.
+ bool HasRetryIntegrityTag() const;
+
// Returns true if this version sends variable length packet number in long
// header.
bool SendsVariableLengthPacketNumberInLongHeader() const;
+ // Returns whether this version allows server connection ID lengths
+ // that are not 64 bits.
+ bool AllowsVariableLengthConnectionIds() const;
+
// Returns whether this version supports client connection ID.
bool SupportsClientConnectionIds() const;
@@ -196,6 +290,46 @@ struct QUIC_EXPORT_PRIVATE ParsedQuicVersion {
// Returns true if this version can send coalesced packets.
bool CanSendCoalescedPackets() const;
+
+ // Returns true if this version supports the old Google-style Alt-Svc
+ // advertisement format.
+ bool SupportsGoogleAltSvcFormat() const;
+
+ // Returns true if |transport_version| uses IETF invariant headers.
+ bool HasIetfInvariantHeader() const;
+
+ // Returns true if |transport_version| supports MESSAGE frames.
+ bool SupportsMessageFrames() const;
+
+ // If true, HTTP/3 instead of gQUIC will be used at the HTTP layer.
+ // Notable changes are:
+ // * Headers stream no longer exists.
+ // * PRIORITY, HEADERS are moved from headers stream to HTTP/3 control stream.
+ // * PUSH_PROMISE is moved to request stream.
+ // * Unidirectional streams will have their first byte as a stream type.
+ // * HEADERS frames are compressed using QPACK.
+ // * DATA frame has frame headers.
+ // * GOAWAY is moved to HTTP layer.
+ bool UsesHttp3() const;
+
+ // Returns whether the transport_version supports the variable length integer
+ // length field as defined by IETF QUIC draft-13 and later.
+ bool HasLongHeaderLengths() const;
+
+ // Returns whether |transport_version| uses CRYPTO frames for the handshake
+ // instead of stream 1.
+ bool UsesCryptoFrames() const;
+
+ // Returns whether |transport_version| makes use of IETF QUIC
+ // frames or not.
+ bool HasIetfQuicFrames() const;
+
+ // Returns true if this parsed version supports handshake done.
+ bool HasHandshakeDone() const;
+
+ // Returns true if this version uses variable-length integers when
+ // encoding transport parameter types and lengths.
+ bool HasVarIntTransportParams() const;
};
QUIC_EXPORT_PRIVATE ParsedQuicVersion UnsupportedQuicVersion();
@@ -212,22 +346,25 @@ using ParsedQuicVersionVector = std::vector<ParsedQuicVersion>;
using QuicVersionLabel = uint32_t;
using QuicVersionLabelVector = std::vector<QuicVersionLabel>;
-// This vector contains QUIC versions which we currently support.
-// This should be ordered such that the highest supported version is the first
-// element, with subsequent elements in descending order (versions can be
-// skipped as necessary).
-//
-// See go/new-quic-version for more details on how to roll out new versions.
-static const QuicTransportVersion kSupportedTransportVersions[] = {
- QUIC_VERSION_99, QUIC_VERSION_50, QUIC_VERSION_49,
- QUIC_VERSION_48, QUIC_VERSION_46, QUIC_VERSION_43,
-};
-
// This vector contains all crypto handshake protocols that are supported.
-static const HandshakeProtocol kSupportedHandshakeProtocols[] = {
- PROTOCOL_QUIC_CRYPTO, PROTOCOL_TLS1_3};
+constexpr std::array<HandshakeProtocol, 2> SupportedHandshakeProtocols() {
+ return {PROTOCOL_QUIC_CRYPTO, PROTOCOL_TLS1_3};
+}
-typedef std::vector<QuicTransportVersion> QuicTransportVersionVector;
+constexpr std::array<ParsedQuicVersion, 8> SupportedVersions() {
+ return {
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50),
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_49),
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48),
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46),
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43),
+ ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_DRAFT_27),
+ ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_DRAFT_25),
+ ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_50),
+ };
+}
+
+using QuicTransportVersionVector = std::vector<QuicTransportVersion>;
// Returns a vector of QUIC versions in kSupportedTransportVersions.
QUIC_EXPORT_PRIVATE QuicTransportVersionVector AllSupportedTransportVersions();
@@ -236,11 +373,6 @@ QUIC_EXPORT_PRIVATE QuicTransportVersionVector AllSupportedTransportVersions();
// kSupportedTransportVersions and kSupportedHandshakeProtocols.
QUIC_EXPORT_PRIVATE ParsedQuicVersionVector AllSupportedVersions();
-// Returns a vector of QUIC versions from kSupportedTransportVersions which
-// exclude any versions which are disabled by flags.
-QUIC_EXPORT_PRIVATE QuicTransportVersionVector
-CurrentSupportedTransportVersions();
-
// Returns a vector of QUIC versions that is the cartesian product of
// kSupportedTransportVersions and kSupportedHandshakeProtocols, with any
// versions disabled by flags excluded.
@@ -248,14 +380,25 @@ QUIC_EXPORT_PRIVATE ParsedQuicVersionVector CurrentSupportedVersions();
// Returns a vector of QUIC versions from |versions| which exclude any versions
// which are disabled by flags.
-QUIC_EXPORT_PRIVATE QuicTransportVersionVector
-FilterSupportedTransportVersions(QuicTransportVersionVector versions);
-
-// Returns a vector of QUIC versions from |versions| which exclude any versions
-// which are disabled by flags.
QUIC_EXPORT_PRIVATE ParsedQuicVersionVector
FilterSupportedVersions(ParsedQuicVersionVector versions);
+// Returns a subset of AllSupportedVersions() with
+// handshake_protocol == PROTOCOL_QUIC_CRYPTO, in the same order.
+// Deprecated; only to be used in components that do not yet support
+// PROTOCOL_TLS1_3.
+QUIC_EXPORT_PRIVATE ParsedQuicVersionVector
+AllSupportedVersionsWithQuicCrypto();
+
+// Returns a subset of CurrentSupportedVersions() with
+// handshake_protocol == PROTOCOL_QUIC_CRYPTO, in the same order.
+QUIC_EXPORT_PRIVATE ParsedQuicVersionVector
+CurrentSupportedVersionsWithQuicCrypto();
+
+// Returns a subset of CurrentSupportedVersions() with handshake_protocol ==
+// PROTOCOL_TLS1_3.
+QUIC_EXPORT_PRIVATE ParsedQuicVersionVector CurrentSupportedVersionsWithTls();
+
// Returns QUIC version of |index| in result of |versions|. Returns
// QUIC_VERSION_UNSUPPORTED if |index| is out of bounds.
QUIC_EXPORT_PRIVATE QuicTransportVersionVector
@@ -280,10 +423,17 @@ ParsedVersionsToTransportVersions(const ParsedQuicVersionVector& versions);
QUIC_EXPORT_PRIVATE ParsedQuicVersion
ParseQuicVersionLabel(QuicVersionLabel version_label);
-// Parses a QUIC version string such as "Q043" or "T099".
-// Also supports parsing numbers such as "44".
+// Parses a QUIC version string such as "Q043" or "T050". Also supports parsing
+// ALPN such as "h3-25" or "h3-Q050". For PROTOCOL_QUIC_CRYPTO versions, also
+// supports parsing numbers such as "46".
QUIC_EXPORT_PRIVATE ParsedQuicVersion
-ParseQuicVersionString(std::string version_string);
+ParseQuicVersionString(quiche::QuicheStringPiece version_string);
+
+// Parses a comma-separated list of QUIC version strings. Supports parsing by
+// label, ALPN and numbers for PROTOCOL_QUIC_CRYPTO. Skips unknown versions.
+// For example: "h3-25,Q050,46".
+QUIC_EXPORT_PRIVATE ParsedQuicVersionVector
+ParseQuicVersionVectorString(quiche::QuicheStringPiece versions_string);
// Constructs a QuicVersionLabel from the provided ParsedQuicVersion.
QUIC_EXPORT_PRIVATE QuicVersionLabel
@@ -331,11 +481,6 @@ QuicVersionLabelToQuicVersion(QuicVersionLabel version_label);
QUIC_EXPORT_PRIVATE HandshakeProtocol
QuicVersionLabelToHandshakeProtocol(QuicVersionLabel version_label);
-// Helper function which translates from a QuicTransportVersion to a string.
-// Returns strings corresponding to enum names (e.g. QUIC_VERSION_6).
-QUIC_EXPORT_PRIVATE std::string QuicVersionToString(
- QuicTransportVersion transport_version);
-
// Helper function which translates from a ParsedQuicVersion to a string.
// Returns strings corresponding to the on-the-wire tag.
QUIC_EXPORT_PRIVATE std::string ParsedQuicVersionToString(
@@ -368,13 +513,13 @@ QUIC_EXPORT_PRIVATE inline std::string ParsedQuicVersionVectorToString(
}
// Returns true if |transport_version| uses IETF invariant headers.
-QUIC_EXPORT_PRIVATE inline bool VersionHasIetfInvariantHeader(
+QUIC_EXPORT_PRIVATE constexpr bool VersionHasIetfInvariantHeader(
QuicTransportVersion transport_version) {
return transport_version > QUIC_VERSION_43;
}
// Returns true if |transport_version| supports MESSAGE frames.
-QUIC_EXPORT_PRIVATE inline bool VersionSupportsMessageFrames(
+QUIC_EXPORT_PRIVATE constexpr bool VersionSupportsMessageFrames(
QuicTransportVersion transport_version) {
return transport_version >= QUIC_VERSION_46;
}
@@ -388,30 +533,23 @@ QUIC_EXPORT_PRIVATE inline bool VersionSupportsMessageFrames(
// * HEADERS frames are compressed using QPACK.
// * DATA frame has frame headers.
// * GOAWAY is moved to HTTP layer.
-QUIC_EXPORT_PRIVATE inline bool VersionUsesHttp3(
+QUIC_EXPORT_PRIVATE constexpr bool VersionUsesHttp3(
QuicTransportVersion transport_version) {
- return transport_version == QUIC_VERSION_99;
+ return transport_version >= QUIC_VERSION_IETF_DRAFT_25;
}
// Returns whether the transport_version supports the variable length integer
// length field as defined by IETF QUIC draft-13 and later.
-QUIC_EXPORT_PRIVATE inline bool QuicVersionHasLongHeaderLengths(
+QUIC_EXPORT_PRIVATE constexpr bool QuicVersionHasLongHeaderLengths(
QuicTransportVersion transport_version) {
return transport_version >= QUIC_VERSION_49;
}
-// Returns whether |transport_version| uses CRYPTO frames for the handshake
-// instead of stream 1.
-QUIC_EXPORT_PRIVATE inline bool QuicVersionUsesCryptoFrames(
- QuicTransportVersion transport_version) {
- return transport_version >= QUIC_VERSION_48;
-}
-
// Returns whether |transport_version| makes use of IETF QUIC
// frames or not.
-QUIC_EXPORT_PRIVATE inline bool VersionHasIetfQuicFrames(
+QUIC_EXPORT_PRIVATE constexpr bool VersionHasIetfQuicFrames(
QuicTransportVersion transport_version) {
- return transport_version >= QUIC_VERSION_99;
+ return transport_version >= QUIC_VERSION_IETF_DRAFT_25;
}
// Returns whether this version supports long header 8-bit encoded
@@ -425,6 +563,11 @@ QUIC_EXPORT_PRIVATE bool VersionHasLengthPrefixedConnectionIds(
QUIC_EXPORT_PRIVATE bool VersionSupportsGoogleAltSvcFormat(
QuicTransportVersion transport_version);
+// Returns whether this version allows server connection ID lengths that are
+// not 64 bits.
+QUIC_EXPORT_PRIVATE bool VersionAllowsVariableLengthConnectionIds(
+ QuicTransportVersion transport_version);
+
// Returns whether this version label supports long header 4-bit encoded
// connection ID lengths as described in draft-ietf-quic-invariants-05 and
// draft-ietf-quic-transport-21.
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_versions_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_versions_test.cc
index 283113fe37f..216b0800bbe 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_versions_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_versions_test.cc
@@ -4,18 +4,20 @@
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_mock_log.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
namespace quic {
namespace test {
namespace {
-using testing::_;
+using ::testing::_;
+using ::testing::ElementsAre;
+using ::testing::IsEmpty;
class QuicVersionsTest : public QuicTest {
protected:
@@ -41,15 +43,44 @@ TEST_F(QuicVersionsTest, QuicVersionToQuicVersionLabel) {
// Loop over all supported versions and make sure that we never hit the
// default case (i.e. all supported versions should be successfully converted
// to valid QuicVersionLabels).
- for (size_t i = 0; i < QUIC_ARRAYSIZE(kSupportedTransportVersions); ++i) {
- QuicTransportVersion version = kSupportedTransportVersions[i];
- EXPECT_LT(0u, QuicVersionToQuicVersionLabel(version));
+ for (QuicTransportVersion transport_version : SupportedTransportVersions()) {
+ if (!ParsedQuicVersionIsValid(PROTOCOL_QUIC_CRYPTO, transport_version)) {
+ continue;
+ }
+ EXPECT_LT(0u, QuicVersionToQuicVersionLabel(transport_version));
}
}
TEST_F(QuicVersionsTest, QuicVersionToQuicVersionLabelUnsupported) {
- EXPECT_QUIC_BUG(QuicVersionToQuicVersionLabel(QUIC_VERSION_UNSUPPORTED),
- "Unsupported QuicTransportVersion: 0");
+ EXPECT_QUIC_BUG(CreateQuicVersionLabel(UnsupportedQuicVersion()),
+ "Invalid HandshakeProtocol: 0");
+}
+
+TEST_F(QuicVersionsTest, KnownAndValid) {
+ for (const ParsedQuicVersion& version : AllSupportedVersions()) {
+ EXPECT_TRUE(version.IsKnown());
+ EXPECT_TRUE(ParsedQuicVersionIsValid(version.handshake_protocol,
+ version.transport_version));
+ }
+ ParsedQuicVersion unsupported = UnsupportedQuicVersion();
+ EXPECT_FALSE(unsupported.IsKnown());
+ EXPECT_TRUE(ParsedQuicVersionIsValid(unsupported.handshake_protocol,
+ unsupported.transport_version));
+ ParsedQuicVersion reserved = QuicVersionReservedForNegotiation();
+ EXPECT_TRUE(reserved.IsKnown());
+ EXPECT_TRUE(ParsedQuicVersionIsValid(reserved.handshake_protocol,
+ reserved.transport_version));
+ // Check that invalid combinations are not valid.
+ EXPECT_FALSE(ParsedQuicVersionIsValid(PROTOCOL_TLS1_3, QUIC_VERSION_43));
+ EXPECT_FALSE(ParsedQuicVersionIsValid(PROTOCOL_QUIC_CRYPTO,
+ QUIC_VERSION_IETF_DRAFT_27));
+ // Check that deprecated versions are not valid.
+ EXPECT_FALSE(ParsedQuicVersionIsValid(PROTOCOL_QUIC_CRYPTO,
+ static_cast<QuicTransportVersion>(33)));
+ EXPECT_FALSE(ParsedQuicVersionIsValid(PROTOCOL_QUIC_CRYPTO,
+ static_cast<QuicTransportVersion>(99)));
+ EXPECT_FALSE(ParsedQuicVersionIsValid(PROTOCOL_TLS1_3,
+ static_cast<QuicTransportVersion>(99)));
}
TEST_F(QuicVersionsTest, QuicVersionLabelToQuicTransportVersion) {
@@ -66,17 +97,20 @@ TEST_F(QuicVersionsTest, QuicVersionLabelToQuicTransportVersion) {
EXPECT_EQ(QUIC_VERSION_43,
QuicVersionLabelToQuicVersion(MakeQuicTag('3', '4', '0', 'Q')));
- for (size_t i = 0; i < QUIC_ARRAYSIZE(kSupportedTransportVersions); ++i) {
- QuicTransportVersion version = kSupportedTransportVersions[i];
+ for (QuicTransportVersion transport_version : SupportedTransportVersions()) {
+ if (!ParsedQuicVersionIsValid(PROTOCOL_QUIC_CRYPTO, transport_version)) {
+ continue;
+ }
// Get the label from the version (we can loop over QuicVersions easily).
- QuicVersionLabel version_label = QuicVersionToQuicVersionLabel(version);
+ QuicVersionLabel version_label =
+ QuicVersionToQuicVersionLabel(transport_version);
EXPECT_LT(0u, version_label);
// Now try converting back.
QuicTransportVersion label_to_transport_version =
QuicVersionLabelToQuicVersion(version_label);
- EXPECT_EQ(version, label_to_transport_version);
+ EXPECT_EQ(transport_version, label_to_transport_version);
EXPECT_NE(QUIC_VERSION_UNSUPPORTED, label_to_transport_version);
}
}
@@ -99,15 +133,18 @@ TEST_F(QuicVersionsTest, QuicVersionLabelToHandshakeProtocol) {
EXPECT_QUIC_LOG_CALL(log).Times(0);
log.StartCapturingLogs();
- for (size_t i = 0; i < QUIC_ARRAYSIZE(kSupportedTransportVersions); ++i) {
+ for (const ParsedQuicVersion& version : AllSupportedVersions()) {
+ if (version.handshake_protocol != PROTOCOL_QUIC_CRYPTO) {
+ continue;
+ }
QuicVersionLabel version_label =
- QuicVersionToQuicVersionLabel(kSupportedTransportVersions[i]);
+ QuicVersionToQuicVersionLabel(version.transport_version);
EXPECT_EQ(PROTOCOL_QUIC_CRYPTO,
QuicVersionLabelToHandshakeProtocol(version_label));
}
// Test a TLS version:
- QuicTag tls_tag = MakeQuicTag('3', '4', '0', 'T');
+ QuicTag tls_tag = MakeQuicTag('0', '5', '0', 'T');
EXPECT_EQ(PROTOCOL_TLS1_3, QuicVersionLabelToHandshakeProtocol(tls_tag));
}
@@ -120,14 +157,6 @@ TEST_F(QuicVersionsTest, ParseQuicVersionLabel) {
ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '4', '8')));
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50),
ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '5', '0')));
-
- // Test TLS versions:
- EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_43),
- ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '3')));
- EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_46),
- ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '6')));
- EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_48),
- ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '8')));
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_50),
ParseQuicVersionLabel(MakeVersionLabel('T', '0', '5', '0')));
}
@@ -136,26 +165,110 @@ TEST_F(QuicVersionsTest, ParseQuicVersionString) {
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43),
ParseQuicVersionString("Q043"));
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46),
+ ParseQuicVersionString("QUIC_VERSION_46"));
+ EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46),
+ ParseQuicVersionString("46"));
+ EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46),
ParseQuicVersionString("Q046"));
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48),
ParseQuicVersionString("Q048"));
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50),
ParseQuicVersionString("Q050"));
+ EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50),
+ ParseQuicVersionString("50"));
+ EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50),
+ ParseQuicVersionString("h3-Q050"));
EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionString(""));
EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionString("Q 46"));
EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionString("Q046 "));
+ EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionString("99"));
+ EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionString("70"));
- // Test a TLS version:
- SetQuicReloadableFlag(quic_supports_tls_handshake, true);
- EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_43),
- ParseQuicVersionString("T043"));
- EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_46),
- ParseQuicVersionString("T046"));
- EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_48),
- ParseQuicVersionString("T048"));
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_50),
ParseQuicVersionString("T050"));
+ EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_50),
+ ParseQuicVersionString("h3-T050"));
+ EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_DRAFT_27),
+ ParseQuicVersionString("ff00001b"));
+ EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_DRAFT_27),
+ ParseQuicVersionString("h3-27"));
+ EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_DRAFT_25),
+ ParseQuicVersionString("ff000019"));
+ EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_DRAFT_25),
+ ParseQuicVersionString("h3-25"));
+}
+
+TEST_F(QuicVersionsTest, ParseQuicVersionVectorString) {
+ ParsedQuicVersion version_q046(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46);
+ ParsedQuicVersion version_q050(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50);
+ ParsedQuicVersion version_t050(PROTOCOL_TLS1_3, QUIC_VERSION_50);
+ ParsedQuicVersion version_draft_25(PROTOCOL_TLS1_3,
+ QUIC_VERSION_IETF_DRAFT_25);
+ ParsedQuicVersion version_draft_27(PROTOCOL_TLS1_3,
+ QUIC_VERSION_IETF_DRAFT_27);
+
+ EXPECT_THAT(ParseQuicVersionVectorString(""), IsEmpty());
+
+ EXPECT_THAT(ParseQuicVersionVectorString("QUIC_VERSION_50"),
+ ElementsAre(version_q050));
+ EXPECT_THAT(ParseQuicVersionVectorString("h3-Q050"),
+ ElementsAre(version_q050));
+ EXPECT_THAT(ParseQuicVersionVectorString("h3-T050"),
+ ElementsAre(version_t050));
+
+ EXPECT_THAT(ParseQuicVersionVectorString("h3-25, h3-27"),
+ ElementsAre(version_draft_25, version_draft_27));
+ EXPECT_THAT(ParseQuicVersionVectorString("h3-25,h3-27"),
+ ElementsAre(version_draft_25, version_draft_27));
+ EXPECT_THAT(ParseQuicVersionVectorString("h3-25,h3-27,h3-25"),
+ ElementsAre(version_draft_25, version_draft_27));
+ EXPECT_THAT(ParseQuicVersionVectorString("h3-25,h3-27, h3-25"),
+ ElementsAre(version_draft_25, version_draft_27));
+ EXPECT_THAT(ParseQuicVersionVectorString("h3-27,h3-25"),
+ ElementsAre(version_draft_27, version_draft_25));
+
+ EXPECT_THAT(ParseQuicVersionVectorString("h3-27,50"),
+ ElementsAre(version_draft_27, version_q050));
+
+ EXPECT_THAT(ParseQuicVersionVectorString("h3-Q050, h3-T050"),
+ ElementsAre(version_q050, version_t050));
+ EXPECT_THAT(ParseQuicVersionVectorString("h3-T050, h3-Q050"),
+ ElementsAre(version_t050, version_q050));
+ EXPECT_THAT(ParseQuicVersionVectorString("QUIC_VERSION_50,h3-T050"),
+ ElementsAre(version_q050, version_t050));
+ EXPECT_THAT(ParseQuicVersionVectorString("h3-T050,QUIC_VERSION_50"),
+ ElementsAre(version_t050, version_q050));
+ EXPECT_THAT(ParseQuicVersionVectorString("QUIC_VERSION_50, h3-T050"),
+ ElementsAre(version_q050, version_t050));
+ EXPECT_THAT(ParseQuicVersionVectorString("h3-T050, QUIC_VERSION_50"),
+ ElementsAre(version_t050, version_q050));
+
+ EXPECT_THAT(ParseQuicVersionVectorString("QUIC_VERSION_50,QUIC_VERSION_46"),
+ ElementsAre(version_q050, version_q046));
+ EXPECT_THAT(ParseQuicVersionVectorString("QUIC_VERSION_46,QUIC_VERSION_50"),
+ ElementsAre(version_q046, version_q050));
+
+ // Regression test for https://crbug.com/1044952.
+ EXPECT_THAT(ParseQuicVersionVectorString("QUIC_VERSION_50, QUIC_VERSION_50"),
+ ElementsAre(version_q050));
+ EXPECT_THAT(ParseQuicVersionVectorString("h3-Q050, h3-Q050"),
+ ElementsAre(version_q050));
+ EXPECT_THAT(ParseQuicVersionVectorString("h3-T050, h3-T050"),
+ ElementsAre(version_t050));
+ EXPECT_THAT(ParseQuicVersionVectorString("h3-Q050, QUIC_VERSION_50"),
+ ElementsAre(version_q050));
+ EXPECT_THAT(ParseQuicVersionVectorString(
+ "QUIC_VERSION_50, h3-Q050, QUIC_VERSION_50, h3-Q050"),
+ ElementsAre(version_q050));
+ EXPECT_THAT(ParseQuicVersionVectorString("QUIC_VERSION_50, h3-T050, h3-Q050"),
+ ElementsAre(version_q050, version_t050));
+
+ EXPECT_THAT(ParseQuicVersionVectorString("99"), IsEmpty());
+ EXPECT_THAT(ParseQuicVersionVectorString("70"), IsEmpty());
+ EXPECT_THAT(ParseQuicVersionVectorString("h3-01"), IsEmpty());
+ EXPECT_THAT(ParseQuicVersionVectorString("h3-01,h3-25"),
+ ElementsAre(version_draft_25));
}
TEST_F(QuicVersionsTest, CreateQuicVersionLabel) {
@@ -173,15 +286,6 @@ TEST_F(QuicVersionsTest, CreateQuicVersionLabel) {
ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50)));
// Test a TLS version:
- EXPECT_EQ(MakeVersionLabel('T', '0', '4', '3'),
- CreateQuicVersionLabel(
- ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_43)));
- EXPECT_EQ(MakeVersionLabel('T', '0', '4', '6'),
- CreateQuicVersionLabel(
- ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_46)));
- EXPECT_EQ(MakeVersionLabel('T', '0', '4', '8'),
- CreateQuicVersionLabel(
- ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_48)));
EXPECT_EQ(MakeVersionLabel('T', '0', '5', '0'),
CreateQuicVersionLabel(
ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_50)));
@@ -222,7 +326,7 @@ TEST_F(QuicVersionsTest, QuicVersionToString) {
QuicTransportVersion single_version[] = {QUIC_VERSION_43};
QuicTransportVersionVector versions_vector;
- for (size_t i = 0; i < QUIC_ARRAYSIZE(single_version); ++i) {
+ for (size_t i = 0; i < QUICHE_ARRAYSIZE(single_version); ++i) {
versions_vector.push_back(single_version[i]);
}
EXPECT_EQ("QUIC_VERSION_43",
@@ -231,16 +335,16 @@ TEST_F(QuicVersionsTest, QuicVersionToString) {
QuicTransportVersion multiple_versions[] = {QUIC_VERSION_UNSUPPORTED,
QUIC_VERSION_43};
versions_vector.clear();
- for (size_t i = 0; i < QUIC_ARRAYSIZE(multiple_versions); ++i) {
+ for (size_t i = 0; i < QUICHE_ARRAYSIZE(multiple_versions); ++i) {
versions_vector.push_back(multiple_versions[i]);
}
EXPECT_EQ("QUIC_VERSION_UNSUPPORTED,QUIC_VERSION_43",
QuicTransportVersionVectorToString(versions_vector));
// Make sure that all supported versions are present in QuicVersionToString.
- for (size_t i = 0; i < QUIC_ARRAYSIZE(kSupportedTransportVersions); ++i) {
- QuicTransportVersion version = kSupportedTransportVersions[i];
- EXPECT_NE("QUIC_VERSION_UNSUPPORTED", QuicVersionToString(version));
+ for (QuicTransportVersion transport_version : SupportedTransportVersions()) {
+ EXPECT_NE("QUIC_VERSION_UNSUPPORTED",
+ QuicVersionToString(transport_version));
}
}
@@ -261,107 +365,104 @@ TEST_F(QuicVersionsTest, ParsedQuicVersionToString) {
// Make sure that all supported versions are present in
// ParsedQuicVersionToString.
- for (QuicTransportVersion transport_version : kSupportedTransportVersions) {
- for (HandshakeProtocol protocol : kSupportedHandshakeProtocols) {
- EXPECT_NE("0", ParsedQuicVersionToString(
- ParsedQuicVersion(protocol, transport_version)));
- }
- }
-}
-TEST_F(QuicVersionsTest, AllSupportedTransportVersions) {
- QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
- ASSERT_EQ(QUIC_ARRAYSIZE(kSupportedTransportVersions), all_versions.size());
- for (size_t i = 0; i < all_versions.size(); ++i) {
- EXPECT_EQ(kSupportedTransportVersions[i], all_versions[i]);
+ for (const ParsedQuicVersion& version : AllSupportedVersions()) {
+ EXPECT_NE("0", ParsedQuicVersionToString(version));
}
}
-TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsAllVersions) {
- QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
+TEST_F(QuicVersionsTest, FilterSupportedVersionsAllVersions) {
+ static_assert(SupportedVersions().size() == 8u,
"Supported versions out of sync");
- SetQuicReloadableFlag(quic_enable_version_50, true);
- SetQuicReloadableFlag(quic_enable_version_99, true);
- ParsedQuicVersionVector parsed_versions;
- for (QuicTransportVersion version : all_versions) {
- parsed_versions.push_back(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
- }
- QuicTransportVersionVector expected_versions = {
- QUIC_VERSION_99, QUIC_VERSION_50, QUIC_VERSION_49,
- QUIC_VERSION_48, QUIC_VERSION_46, QUIC_VERSION_43};
- ParsedQuicVersionVector expected_parsed_versions;
- for (QuicTransportVersion version : expected_versions) {
- expected_parsed_versions.push_back(
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
- }
+ SetQuicReloadableFlag(quic_enable_version_draft_27, true);
+ SetQuicReloadableFlag(quic_enable_version_draft_25_v3, true);
+ SetQuicReloadableFlag(quic_enable_version_t050, true);
+ SetQuicReloadableFlag(quic_disable_version_q050, false);
+ SetQuicReloadableFlag(quic_disable_version_q049, false);
+ SetQuicReloadableFlag(quic_disable_version_q048, false);
+ SetQuicReloadableFlag(quic_disable_version_q046, false);
+ SetQuicReloadableFlag(quic_disable_version_q043, false);
- ASSERT_EQ(expected_versions, FilterSupportedTransportVersions(all_versions));
- ASSERT_EQ(expected_parsed_versions, FilterSupportedVersions(parsed_versions));
+ ParsedQuicVersionVector expected_parsed_versions;
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50));
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_49));
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48));
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46));
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43));
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_DRAFT_27));
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_DRAFT_25));
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_50));
+
+ ASSERT_EQ(expected_parsed_versions,
+ FilterSupportedVersions(AllSupportedVersions()));
+ ASSERT_EQ(expected_parsed_versions, AllSupportedVersions());
}
-TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo99) {
- QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
+TEST_F(QuicVersionsTest, FilterSupportedVersionsNo99) {
+ static_assert(SupportedVersions().size() == 8u,
"Supported versions out of sync");
- SetQuicReloadableFlag(quic_enable_version_50, true);
- SetQuicReloadableFlag(quic_enable_version_99, false);
- ParsedQuicVersionVector parsed_versions;
- for (QuicTransportVersion version : all_versions) {
- parsed_versions.push_back(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
- }
- QuicTransportVersionVector expected_versions = {
- QUIC_VERSION_50, QUIC_VERSION_49, QUIC_VERSION_48, QUIC_VERSION_46,
- QUIC_VERSION_43};
- ParsedQuicVersionVector expected_parsed_versions;
- for (QuicTransportVersion version : expected_versions) {
- expected_parsed_versions.push_back(
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
- }
-
- ASSERT_EQ(expected_versions, FilterSupportedTransportVersions(all_versions));
- ASSERT_EQ(expected_parsed_versions, FilterSupportedVersions(parsed_versions));
-}
+ SetQuicReloadableFlag(quic_enable_version_draft_27, false);
+ SetQuicReloadableFlag(quic_enable_version_draft_25_v3, true);
+ SetQuicReloadableFlag(quic_enable_version_t050, true);
+ SetQuicReloadableFlag(quic_disable_version_q050, false);
+ SetQuicReloadableFlag(quic_disable_version_q049, false);
+ SetQuicReloadableFlag(quic_disable_version_q048, false);
+ SetQuicReloadableFlag(quic_disable_version_q046, false);
+ SetQuicReloadableFlag(quic_disable_version_q043, false);
-TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo50) {
- QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
- SetQuicReloadableFlag(quic_enable_version_50, false);
- SetQuicReloadableFlag(quic_enable_version_99, false);
- ParsedQuicVersionVector parsed_versions;
- for (QuicTransportVersion version : all_versions) {
- parsed_versions.push_back(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
- }
- QuicTransportVersionVector expected_versions = {
- QUIC_VERSION_49, QUIC_VERSION_48, QUIC_VERSION_46, QUIC_VERSION_43};
ParsedQuicVersionVector expected_parsed_versions;
- for (QuicTransportVersion version : expected_versions) {
- expected_parsed_versions.push_back(
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
- }
-
- ASSERT_EQ(expected_versions, FilterSupportedTransportVersions(all_versions));
- ASSERT_EQ(expected_parsed_versions, FilterSupportedVersions(parsed_versions));
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50));
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_49));
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48));
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46));
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43));
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_DRAFT_25));
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_50));
+
+ ASSERT_EQ(expected_parsed_versions,
+ FilterSupportedVersions(AllSupportedVersions()));
}
-TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNoFlags) {
- QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
+TEST_F(QuicVersionsTest, FilterSupportedVersionsNoFlags) {
+ static_assert(SupportedVersions().size() == 8u,
"Supported versions out of sync");
- SetQuicReloadableFlag(quic_enable_version_50, false);
- SetQuicReloadableFlag(quic_enable_version_99, false);
- ParsedQuicVersionVector parsed_versions;
- for (QuicTransportVersion version : all_versions) {
- parsed_versions.push_back(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
- }
- QuicTransportVersionVector expected_versions = {
- QUIC_VERSION_49, QUIC_VERSION_48, QUIC_VERSION_46, QUIC_VERSION_43};
- ParsedQuicVersionVector expected_parsed_versions;
- for (QuicTransportVersion version : expected_versions) {
- expected_parsed_versions.push_back(
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
- }
+ SetQuicReloadableFlag(quic_enable_version_draft_27, false);
+ SetQuicReloadableFlag(quic_enable_version_draft_25_v3, false);
+ SetQuicReloadableFlag(quic_enable_version_t050, false);
+ SetQuicReloadableFlag(quic_disable_version_q050, false);
+ SetQuicReloadableFlag(quic_disable_version_q049, false);
+ SetQuicReloadableFlag(quic_disable_version_q048, false);
+ SetQuicReloadableFlag(quic_disable_version_q046, false);
+ SetQuicReloadableFlag(quic_disable_version_q043, false);
- ASSERT_EQ(expected_versions, FilterSupportedTransportVersions(all_versions));
- ASSERT_EQ(expected_parsed_versions, FilterSupportedVersions(parsed_versions));
+ ParsedQuicVersionVector expected_parsed_versions;
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50));
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_49));
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48));
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46));
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43));
+
+ ASSERT_EQ(expected_parsed_versions,
+ FilterSupportedVersions(AllSupportedVersions()));
}
TEST_F(QuicVersionsTest, LookUpVersionByIndex) {
@@ -402,82 +503,88 @@ TEST_F(QuicVersionsTest, ParsedVersionsToTransportVersions) {
// This test may appear to be so simplistic as to be unnecessary,
// yet a typo was made in doing the #defines and it was caught
// only in some test far removed from here... Better safe than sorry.
-TEST_F(QuicVersionsTest, CheckVersionNumbersForTypos) {
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
+TEST_F(QuicVersionsTest, CheckTransportVersionNumbersForTypos) {
+ static_assert(SupportedTransportVersions().size() == 7u,
"Supported versions out of sync");
EXPECT_EQ(QUIC_VERSION_43, 43);
EXPECT_EQ(QUIC_VERSION_46, 46);
EXPECT_EQ(QUIC_VERSION_48, 48);
EXPECT_EQ(QUIC_VERSION_49, 49);
EXPECT_EQ(QUIC_VERSION_50, 50);
- EXPECT_EQ(QUIC_VERSION_99, 99);
+ EXPECT_EQ(QUIC_VERSION_IETF_DRAFT_25, 70);
+ EXPECT_EQ(QUIC_VERSION_IETF_DRAFT_27, 71);
}
TEST_F(QuicVersionsTest, AlpnForVersion) {
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
+ static_assert(SupportedVersions().size() == 8u,
"Supported versions out of sync");
ParsedQuicVersion parsed_version_q048 =
ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48);
- ParsedQuicVersion parsed_version_t048 =
- ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_48);
ParsedQuicVersion parsed_version_q049 =
ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_49);
- ParsedQuicVersion parsed_version_t049 =
- ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_49);
ParsedQuicVersion parsed_version_q050 =
ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50);
ParsedQuicVersion parsed_version_t050 =
ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_50);
- ParsedQuicVersion parsed_version_t099 =
- ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99);
+ ParsedQuicVersion parsed_version_draft_25 =
+ ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_DRAFT_25);
+ ParsedQuicVersion parsed_version_draft_27 =
+ ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_DRAFT_27);
EXPECT_EQ("h3-Q048", AlpnForVersion(parsed_version_q048));
- EXPECT_EQ("h3-T048", AlpnForVersion(parsed_version_t048));
EXPECT_EQ("h3-Q049", AlpnForVersion(parsed_version_q049));
- EXPECT_EQ("h3-T049", AlpnForVersion(parsed_version_t049));
EXPECT_EQ("h3-Q050", AlpnForVersion(parsed_version_q050));
EXPECT_EQ("h3-T050", AlpnForVersion(parsed_version_t050));
- EXPECT_EQ("h3-24", AlpnForVersion(parsed_version_t099));
- static_assert(kQuicIetfDraftVersion == 24,
- "ALPN does not match draft version");
+ EXPECT_EQ("h3-25", AlpnForVersion(parsed_version_draft_25));
+ EXPECT_EQ("h3-27", AlpnForVersion(parsed_version_draft_27));
}
TEST_F(QuicVersionsTest, QuicEnableVersion) {
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
+ static_assert(SupportedVersions().size() == 8u,
"Supported versions out of sync");
- SetQuicReloadableFlag(quic_supports_tls_handshake, true);
+ ParsedQuicVersion parsed_version_draft_27 =
+ ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_DRAFT_27);
+ ParsedQuicVersion parsed_version_draft_25 =
+ ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_DRAFT_25);
ParsedQuicVersion parsed_version_q050 =
ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50);
ParsedQuicVersion parsed_version_t050 =
ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_50);
- ParsedQuicVersion parsed_version_t099 =
- ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99);
- SetQuicReloadableFlag(quic_supports_tls_handshake, false);
- SetQuicReloadableFlag(quic_enable_version_50, false);
- SetQuicReloadableFlag(quic_enable_version_99, false);
{
QuicFlagSaver flag_saver;
+ SetQuicReloadableFlag(quic_enable_version_draft_27, false);
+ QuicEnableVersion(parsed_version_draft_27);
+ EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_draft_27));
+ }
+
+ {
+ QuicFlagSaver flag_saver;
+ SetQuicReloadableFlag(quic_enable_version_draft_25_v3, false);
+ QuicEnableVersion(parsed_version_draft_25);
+ EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_draft_25_v3));
+ }
+
+ {
+ QuicFlagSaver flag_saver;
+ SetQuicReloadableFlag(quic_disable_version_q050, true);
QuicEnableVersion(parsed_version_q050);
- EXPECT_FALSE(GetQuicReloadableFlag(quic_supports_tls_handshake));
- EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_50));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_99));
+ EXPECT_FALSE(GetQuicReloadableFlag(quic_disable_version_q050));
}
{
QuicFlagSaver flag_saver;
+ SetQuicReloadableFlag(quic_enable_version_t050, false);
QuicEnableVersion(parsed_version_t050);
- EXPECT_TRUE(GetQuicReloadableFlag(quic_supports_tls_handshake));
- EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_50));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_99));
+ EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_t050));
}
{
QuicFlagSaver flag_saver;
- QuicEnableVersion(parsed_version_t099);
- EXPECT_TRUE(GetQuicReloadableFlag(quic_supports_tls_handshake));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_50));
- EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_99));
+ for (const ParsedQuicVersion& version : SupportedVersions()) {
+ QuicEnableVersion(version);
+ }
+ ASSERT_EQ(AllSupportedVersions(), CurrentSupportedVersions());
}
}
@@ -486,9 +593,40 @@ TEST_F(QuicVersionsTest, ReservedForNegotiation) {
QuicVersionReservedForNegotiation().transport_version);
// QUIC_VERSION_RESERVED_FOR_NEGOTIATION MUST NOT be added to
// kSupportedTransportVersions.
- for (size_t i = 0; i < QUIC_ARRAYSIZE(kSupportedTransportVersions); ++i) {
- EXPECT_NE(QUIC_VERSION_RESERVED_FOR_NEGOTIATION,
- kSupportedTransportVersions[i]);
+ for (QuicTransportVersion transport_version : SupportedTransportVersions()) {
+ EXPECT_NE(QUIC_VERSION_RESERVED_FOR_NEGOTIATION, transport_version);
+ }
+}
+
+TEST_F(QuicVersionsTest, SupportedVersionsHasCorrectList) {
+ size_t index = 0;
+ for (HandshakeProtocol handshake_protocol : SupportedHandshakeProtocols()) {
+ for (QuicTransportVersion transport_version :
+ SupportedTransportVersions()) {
+ SCOPED_TRACE(index);
+ if (ParsedQuicVersionIsValid(handshake_protocol, transport_version)) {
+ EXPECT_EQ(SupportedVersions()[index],
+ ParsedQuicVersion(handshake_protocol, transport_version));
+ index++;
+ }
+ }
+ }
+ EXPECT_EQ(SupportedVersions().size(), index);
+}
+
+TEST_F(QuicVersionsTest, SupportedVersionsAllDistinct) {
+ for (size_t index1 = 0; index1 < SupportedVersions().size(); ++index1) {
+ ParsedQuicVersion version1 = SupportedVersions()[index1];
+ for (size_t index2 = index1 + 1; index2 < SupportedVersions().size();
+ ++index2) {
+ ParsedQuicVersion version2 = SupportedVersions()[index2];
+ EXPECT_NE(version1, version2) << version1 << " " << version2;
+ EXPECT_NE(CreateQuicVersionLabel(version1),
+ CreateQuicVersionLabel(version2))
+ << version1 << " " << version2;
+ EXPECT_NE(AlpnForVersion(version1), AlpnForVersion(version2))
+ << version1 << " " << version2;
+ }
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list.h b/chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list.h
index b80eca6e963..c98711292f3 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list.h
@@ -145,8 +145,8 @@ class QUIC_EXPORT_PRIVATE QuicWriteBlockedList {
void RegisterStream(QuicStreamId stream_id,
bool is_static_stream,
const spdy::SpdyStreamPrecedence& precedence) {
- DCHECK(!priority_write_scheduler_->StreamRegistered(stream_id) &&
- PrecedenceMatchesSchedulerType(precedence));
+ DCHECK(!priority_write_scheduler_->StreamRegistered(stream_id));
+ DCHECK(PrecedenceMatchesSchedulerType(precedence));
if (is_static_stream) {
static_stream_collection_.Register(stream_id);
return;
@@ -165,8 +165,8 @@ class QUIC_EXPORT_PRIVATE QuicWriteBlockedList {
void UpdateStreamPriority(QuicStreamId stream_id,
const spdy::SpdyStreamPrecedence& new_precedence) {
- DCHECK(!static_stream_collection_.IsRegistered(stream_id) &&
- PrecedenceMatchesSchedulerType(new_precedence));
+ DCHECK(!static_stream_collection_.IsRegistered(stream_id));
+ DCHECK(PrecedenceMatchesSchedulerType(new_precedence));
priority_write_scheduler_->UpdateStreamPrecedence(stream_id,
new_precedence);
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/stream_delegate_interface.h b/chromium/net/third_party/quiche/src/quic/core/stream_delegate_interface.h
new file mode 100644
index 00000000000..de77badb74a
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/stream_delegate_interface.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_CORE_STREAM_DELEGATE_INTERFACE_H_
+#define QUICHE_QUIC_CORE_STREAM_DELEGATE_INTERFACE_H_
+
+#include <cstddef>
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_optional.h"
+#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
+
+namespace quic {
+
+class QuicStream;
+
+class QUIC_EXPORT_PRIVATE StreamDelegateInterface {
+ public:
+ virtual ~StreamDelegateInterface() {}
+
+ // Called when the stream has encountered errors that it can't handle.
+ virtual void OnStreamError(QuicErrorCode error_code,
+ std::string error_details) = 0;
+ // Called when the stream needs to write data. If |level| is present, the data
+ // will be written at the specified |level|. The data will be written
+ // at specified transmission |type|.
+ virtual QuicConsumedData WritevData(
+ QuicStreamId id,
+ size_t write_length,
+ QuicStreamOffset offset,
+ StreamSendingState state,
+ TransmissionType type,
+ quiche::QuicheOptional<EncryptionLevel> level) = 0;
+ // Called to write crypto data.
+ virtual size_t SendCryptoData(EncryptionLevel level,
+ size_t write_length,
+ QuicStreamOffset offset,
+ TransmissionType type) = 0;
+ // Called on stream creation.
+ virtual void RegisterStreamPriority(
+ QuicStreamId id,
+ bool is_static,
+ const spdy::SpdyStreamPrecedence& precedence) = 0;
+ // Called on stream destruction to clear priority.
+ virtual void UnregisterStreamPriority(QuicStreamId id, bool is_static) = 0;
+ // Called by the stream on SetPriority to update priority.
+ virtual void UpdateStreamPriority(
+ QuicStreamId id,
+ const spdy::SpdyStreamPrecedence& new_precedence) = 0;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_STREAM_DELEGATE_INTERFACE_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.cc b/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.cc
index a65fefc308f..5148e71caf5 100644
--- a/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.cc
@@ -11,7 +11,8 @@
#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/transport_parameters.h"
#include "net/third_party/quiche/src/quic/core/quic_session.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
@@ -49,7 +50,8 @@ TlsClientHandshaker::TlsClientHandshaker(
std::unique_ptr<ProofVerifyContext> verify_context,
QuicCryptoClientConfig* crypto_config,
QuicCryptoClientStream::ProofHandler* proof_handler)
- : TlsHandshaker(stream, session, crypto_config->ssl_ctx()),
+ : TlsHandshaker(stream, session),
+ session_(session),
server_id_(server_id),
proof_verifier_(crypto_config->proof_verifier()),
verify_context_(std::move(verify_context)),
@@ -68,9 +70,10 @@ TlsClientHandshaker::~TlsClientHandshaker() {
bool TlsClientHandshaker::CryptoConnect() {
state_ = STATE_HANDSHAKE_RUNNING;
- // Configure the SSL to be a client.
+ // Set the SNI to send, if any.
SSL_set_connect_state(ssl());
- if (SSL_set_tlsext_host_name(ssl(), server_id_.host().c_str()) != 1) {
+ if (!server_id_.host().empty() &&
+ SSL_set_tlsext_host_name(ssl(), server_id_.host().c_str()) != 1) {
return false;
}
@@ -132,8 +135,8 @@ bool TlsClientHandshaker::SetAlpn() {
success && (SSL_set_alpn_protos(ssl(), alpn, alpn_writer.length()) == 0);
if (!success) {
QUIC_BUG << "Failed to set ALPN: "
- << QuicTextUtils::HexDump(
- QuicStringPiece(alpn_writer.data(), alpn_writer.length()));
+ << quiche::QuicheTextUtils::HexDump(quiche::QuicheStringPiece(
+ alpn_writer.data(), alpn_writer.length()));
return false;
}
QUIC_DLOG(INFO) << "Client using ALPN: '" << alpns[0] << "'";
@@ -164,11 +167,17 @@ bool TlsClientHandshaker::ProcessTransportParameters(
const uint8_t* param_bytes;
size_t param_bytes_len;
SSL_get_peer_quic_transport_params(ssl(), &param_bytes, &param_bytes_len);
- if (param_bytes_len == 0 ||
- !ParseTransportParameters(session()->connection()->version(),
- Perspective::IS_SERVER, param_bytes,
- param_bytes_len, &params)) {
- *error_details = "Unable to parse Transport Parameters";
+ if (param_bytes_len == 0) {
+ *error_details = "Server's transport parameters are missing";
+ return false;
+ }
+ std::string parse_error_details;
+ if (!ParseTransportParameters(
+ session()->connection()->version(), Perspective::IS_SERVER,
+ param_bytes, param_bytes_len, &params, &parse_error_details)) {
+ DCHECK(!parse_error_details.empty());
+ *error_details =
+ "Unable to parse server's transport parameters: " + parse_error_details;
return false;
}
@@ -201,15 +210,25 @@ bool TlsClientHandshaker::ProcessTransportParameters(
}
int TlsClientHandshaker::num_sent_client_hellos() const {
- // TODO(nharper): Return a sensible value here.
return 0;
}
bool TlsClientHandshaker::IsResumption() const {
- QUIC_BUG_IF(!handshake_confirmed_);
+ QUIC_BUG_IF(!one_rtt_keys_available_);
return SSL_session_reused(ssl()) == 1;
}
+bool TlsClientHandshaker::EarlyDataAccepted() const {
+ QUIC_BUG_IF(!one_rtt_keys_available_);
+ return SSL_early_data_accepted(ssl()) == 1;
+}
+
+bool TlsClientHandshaker::ReceivedInchoateReject() const {
+ QUIC_BUG_IF(!one_rtt_keys_available_);
+ // REJ messages are a QUIC crypto feature, so TLS always returns false.
+ return false;
+}
+
int TlsClientHandshaker::num_scup_messages_received() const {
// SCUP messages aren't sent or received when using the TLS handshake.
return 0;
@@ -223,8 +242,8 @@ bool TlsClientHandshaker::encryption_established() const {
return encryption_established_;
}
-bool TlsClientHandshaker::handshake_confirmed() const {
- return handshake_confirmed_;
+bool TlsClientHandshaker::one_rtt_keys_available() const {
+ return one_rtt_keys_available_;
}
const QuicCryptoNegotiatedParameters&
@@ -236,11 +255,58 @@ CryptoMessageParser* TlsClientHandshaker::crypto_message_parser() {
return TlsHandshaker::crypto_message_parser();
}
+HandshakeState TlsClientHandshaker::GetHandshakeState() const {
+ if (handshake_confirmed_) {
+ return HANDSHAKE_CONFIRMED;
+ }
+ if (one_rtt_keys_available_) {
+ return HANDSHAKE_COMPLETE;
+ }
+ if (state_ >= STATE_ENCRYPTION_HANDSHAKE_DATA_SENT) {
+ return HANDSHAKE_PROCESSED;
+ }
+ return HANDSHAKE_START;
+}
+
size_t TlsClientHandshaker::BufferSizeLimitForLevel(
EncryptionLevel level) const {
return TlsHandshaker::BufferSizeLimitForLevel(level);
}
+void TlsClientHandshaker::OnOneRttPacketAcknowledged() {
+ OnHandshakeConfirmed();
+}
+
+void TlsClientHandshaker::OnHandshakeDoneReceived() {
+ if (!one_rtt_keys_available_) {
+ CloseConnection(QUIC_HANDSHAKE_FAILED,
+ "Unexpected handshake done received");
+ return;
+ }
+ OnHandshakeConfirmed();
+}
+
+void TlsClientHandshaker::SetWriteSecret(
+ EncryptionLevel level,
+ const SSL_CIPHER* cipher,
+ const std::vector<uint8_t>& write_secret) {
+ if (GetQuicRestartFlag(quic_send_settings_on_write_key_available) &&
+ level == ENCRYPTION_FORWARD_SECURE) {
+ encryption_established_ = true;
+ }
+ TlsHandshaker::SetWriteSecret(level, cipher, write_secret);
+}
+
+void TlsClientHandshaker::OnHandshakeConfirmed() {
+ DCHECK(one_rtt_keys_available_);
+ if (handshake_confirmed_) {
+ return;
+ }
+ handshake_confirmed_ = true;
+ handshaker_delegate()->DiscardOldEncryptionKey(ENCRYPTION_HANDSHAKE);
+ handshaker_delegate()->DiscardOldDecryptionKey(ENCRYPTION_HANDSHAKE);
+}
+
void TlsClientHandshaker::AdvanceHandshake() {
if (state_ == STATE_CONNECTION_CLOSED) {
QUIC_LOG(INFO)
@@ -291,12 +357,22 @@ void TlsClientHandshaker::CloseConnection(QuicErrorCode error,
const std::string& reason_phrase) {
DCHECK(!reason_phrase.empty());
state_ = STATE_CONNECTION_CLOSED;
- stream()->CloseConnectionWithDetails(error, reason_phrase);
+ stream()->OnUnrecoverableError(error, reason_phrase);
}
void TlsClientHandshaker::FinishHandshake() {
QUIC_LOG(INFO) << "Client: handshake finished";
state_ = STATE_HANDSHAKE_COMPLETE;
+ if (GetQuicRestartFlag(quic_send_settings_on_write_key_available)) {
+ // Fill crypto_negotiated_params_:
+ const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl());
+ if (cipher) {
+ crypto_negotiated_params_->cipher_suite = SSL_CIPHER_get_value(cipher);
+ }
+ crypto_negotiated_params_->key_exchange_group = SSL_get_curve_id(ssl());
+ crypto_negotiated_params_->peer_signature_algorithm =
+ SSL_get_peer_signature_algorithm(ssl());
+ }
std::string error_details;
if (!ProcessTransportParameters(&error_details)) {
@@ -333,21 +409,23 @@ void TlsClientHandshaker::FinishHandshake() {
QUIC_DLOG(INFO) << "Client: server selected ALPN: '" << received_alpn_string
<< "'";
- encryption_established_ = true;
- handshake_confirmed_ = true;
- delegate()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
-
- // Fill crypto_negotiated_params_:
- const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl());
- if (cipher) {
- crypto_negotiated_params_->cipher_suite = SSL_CIPHER_get_value(cipher);
- }
- crypto_negotiated_params_->key_exchange_group = SSL_get_curve_id(ssl());
- crypto_negotiated_params_->peer_signature_algorithm =
- SSL_get_peer_signature_algorithm(ssl());
- // TODO(fayang): Replace this with DiscardOldKeys(ENCRYPTION_HANDSHAKE) when
- // handshake key discarding settles down.
- delegate()->NeuterHandshakeData();
+ if (!GetQuicRestartFlag(quic_send_settings_on_write_key_available)) {
+ encryption_established_ = true;
+ }
+ one_rtt_keys_available_ = true;
+
+ if (!GetQuicRestartFlag(quic_send_settings_on_write_key_available)) {
+ // Fill crypto_negotiated_params_:
+ const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl());
+ if (cipher) {
+ crypto_negotiated_params_->cipher_suite = SSL_CIPHER_get_value(cipher);
+ }
+ crypto_negotiated_params_->key_exchange_group = SSL_get_curve_id(ssl());
+ crypto_negotiated_params_->peer_signature_algorithm =
+ SSL_get_peer_signature_algorithm(ssl());
+ }
+
+ handshaker_delegate()->OnOneRttKeysAvailable();
}
enum ssl_verify_result_t TlsClientHandshaker::VerifyCert(uint8_t* out_alert) {
@@ -414,12 +492,12 @@ void TlsClientHandshaker::InsertSession(bssl::UniquePtr<SSL_SESSION> session) {
}
void TlsClientHandshaker::WriteMessage(EncryptionLevel level,
- QuicStringPiece data) {
+ quiche::QuicheStringPiece data) {
if (level == ENCRYPTION_HANDSHAKE &&
state_ < STATE_ENCRYPTION_HANDSHAKE_DATA_SENT) {
state_ = STATE_ENCRYPTION_HANDSHAKE_DATA_SENT;
- delegate()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
- delegate()->DiscardOldDecryptionKey(ENCRYPTION_INITIAL);
+ handshaker_delegate()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
+ handshaker_delegate()->DiscardOldDecryptionKey(ENCRYPTION_INITIAL);
}
TlsHandshaker::WriteMessage(level, data);
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.h b/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.h
index 319cd1704bc..d9ee7608f6f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.h
+++ b/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.h
@@ -14,14 +14,15 @@
#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
#include "net/third_party/quiche/src/quic/core/tls_handshaker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
-// An implementation of QuicCryptoClientStream::HandshakerDelegate which uses
+// An implementation of QuicCryptoClientStream::HandshakerInterface which uses
// TLS 1.3 for the crypto handshake protocol.
class QUIC_EXPORT_PRIVATE TlsClientHandshaker
: public TlsHandshaker,
- public QuicCryptoClientStream::HandshakerDelegate,
+ public QuicCryptoClientStream::HandshakerInterface,
public TlsClientConnection::Delegate {
public:
TlsClientHandshaker(const QuicServerId& server_id,
@@ -35,23 +36,32 @@ class QUIC_EXPORT_PRIVATE TlsClientHandshaker
~TlsClientHandshaker() override;
- // From QuicCryptoClientStream::HandshakerDelegate
+ // From QuicCryptoClientStream::HandshakerInterface
bool CryptoConnect() override;
int num_sent_client_hellos() const override;
bool IsResumption() const override;
+ bool EarlyDataAccepted() const override;
+ bool ReceivedInchoateReject() const override;
int num_scup_messages_received() const override;
std::string chlo_hash() const override;
- // From QuicCryptoClientStream::HandshakerDelegate and TlsHandshaker
+ // From QuicCryptoClientStream::HandshakerInterface and TlsHandshaker
bool encryption_established() const override;
- bool handshake_confirmed() const override;
+ bool one_rtt_keys_available() const override;
const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
const override;
CryptoMessageParser* crypto_message_parser() override;
+ HandshakeState GetHandshakeState() const override;
size_t BufferSizeLimitForLevel(EncryptionLevel level) const override;
+ void OnOneRttPacketAcknowledged() override;
+ void OnHandshakeDoneReceived() override;
+ void SetWriteSecret(EncryptionLevel level,
+ const SSL_CIPHER* cipher,
+ const std::vector<uint8_t>& write_secret) override;
// Override to drop initial keys if trying to write ENCRYPTION_HANDSHAKE data.
- void WriteMessage(EncryptionLevel level, QuicStringPiece data) override;
+ void WriteMessage(EncryptionLevel level,
+ quiche::QuicheStringPiece data) override;
void AllowEmptyAlpnForTests() { allow_empty_alpn_for_tests_ = true; }
@@ -103,8 +113,15 @@ class QUIC_EXPORT_PRIVATE TlsClientHandshaker
bool ProcessTransportParameters(std::string* error_details);
void FinishHandshake();
+ // Called when server completes handshake (i.e., either handshake done is
+ // received or 1-RTT packet gets acknowledged).
+ void OnHandshakeConfirmed();
+
void InsertSession(bssl::UniquePtr<SSL_SESSION> session) override;
+ QuicSession* session() { return session_; }
+ QuicSession* session_;
+
QuicServerId server_id_;
// Objects used for verifying the server's certificate chain.
@@ -131,6 +148,7 @@ class QUIC_EXPORT_PRIVATE TlsClientHandshaker
std::string cert_verify_error_details_;
bool encryption_established_ = false;
+ bool one_rtt_keys_available_ = false;
bool handshake_confirmed_ = false;
QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters>
crypto_negotiated_params_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/tls_handshaker.cc b/chromium/net/third_party/quiche/src/quic/core/tls_handshaker.cc
index 08b4eb9525c..1b200636a91 100644
--- a/chromium/net/third_party/quiche/src/quic/core/tls_handshaker.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/tls_handshaker.cc
@@ -8,22 +8,20 @@
#include "third_party/boringssl/src/include/openssl/ssl.h"
#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
-TlsHandshaker::TlsHandshaker(QuicCryptoStream* stream,
- QuicSession* session,
- SSL_CTX* /*ssl_ctx*/)
- : stream_(stream), session_(session), delegate_(session) {
- QUIC_BUG_IF(!GetQuicReloadableFlag(quic_supports_tls_handshake))
- << "Attempted to create TLS handshaker when TLS is disabled";
-}
+TlsHandshaker::TlsHandshaker(QuicCryptoStream* stream, QuicSession* session)
+ : stream_(stream), handshaker_delegate_(session) {}
TlsHandshaker::~TlsHandshaker() {}
-bool TlsHandshaker::ProcessInput(QuicStringPiece input, EncryptionLevel level) {
+bool TlsHandshaker::ProcessInput(quiche::QuicheStringPiece input,
+ EncryptionLevel level) {
if (parser_error_ != QUIC_NO_ERROR) {
return false;
}
@@ -59,45 +57,51 @@ size_t TlsHandshaker::BufferSizeLimitForLevel(EncryptionLevel level) const {
ssl(), TlsConnection::BoringEncryptionLevel(level));
}
-const EVP_MD* TlsHandshaker::Prf() {
- return EVP_get_digestbynid(
- SSL_CIPHER_get_prf_nid(SSL_get_pending_cipher(ssl())));
+const EVP_MD* TlsHandshaker::Prf(const SSL_CIPHER* cipher) {
+ return EVP_get_digestbynid(SSL_CIPHER_get_prf_nid(cipher));
}
-void TlsHandshaker::SetEncryptionSecret(
- EncryptionLevel level,
- const std::vector<uint8_t>& read_secret,
- const std::vector<uint8_t>& write_secret) {
+void TlsHandshaker::SetWriteSecret(EncryptionLevel level,
+ const SSL_CIPHER* cipher,
+ const std::vector<uint8_t>& write_secret) {
std::unique_ptr<QuicEncrypter> encrypter =
- QuicEncrypter::CreateFromCipherSuite(
- SSL_CIPHER_get_id(SSL_get_pending_cipher(ssl())));
- CryptoUtils::SetKeyAndIV(Prf(), write_secret, encrypter.get());
+ QuicEncrypter::CreateFromCipherSuite(SSL_CIPHER_get_id(cipher));
+ CryptoUtils::SetKeyAndIV(Prf(cipher), write_secret, encrypter.get());
+ handshaker_delegate_->OnNewEncryptionKeyAvailable(level,
+ std::move(encrypter));
+}
+
+bool TlsHandshaker::SetReadSecret(EncryptionLevel level,
+ const SSL_CIPHER* cipher,
+ const std::vector<uint8_t>& read_secret) {
std::unique_ptr<QuicDecrypter> decrypter =
- QuicDecrypter::CreateFromCipherSuite(
- SSL_CIPHER_get_id(SSL_get_pending_cipher(ssl())));
- CryptoUtils::SetKeyAndIV(Prf(), read_secret, decrypter.get());
- delegate_->OnNewKeysAvailable(level, std::move(decrypter),
- /*set_alternative_decrypter=*/false,
- /*latch_once_used=*/false,
- std::move(encrypter));
+ QuicDecrypter::CreateFromCipherSuite(SSL_CIPHER_get_id(cipher));
+ CryptoUtils::SetKeyAndIV(Prf(cipher), read_secret, decrypter.get());
+ return handshaker_delegate_->OnNewDecryptionKeyAvailable(
+ level, std::move(decrypter),
+ /*set_alternative_decrypter=*/false,
+ /*latch_once_used=*/false);
}
-void TlsHandshaker::WriteMessage(EncryptionLevel level, QuicStringPiece data) {
+void TlsHandshaker::WriteMessage(EncryptionLevel level,
+ quiche::QuicheStringPiece data) {
stream_->WriteCryptoData(level, data);
}
void TlsHandshaker::FlushFlight() {}
-void TlsHandshaker::SendAlert(EncryptionLevel /*level*/, uint8_t desc) {
- // TODO(nharper): Alerts should be sent on the wire as a 16-bit QUIC error
- // code computed to be 0x100 | desc (draft-ietf-quic-tls-14, section 4.8).
+void TlsHandshaker::SendAlert(EncryptionLevel level, uint8_t desc) {
+ // TODO(b/151676147): Alerts should be sent on the wire as a varint QUIC error
+ // code computed to be 0x100 | desc (draft-ietf-quic-tls-27, section 4.9).
// This puts it in the range reserved for CRYPTO_ERROR
- // (draft-ietf-quic-transport-14, section 11.3). However, according to
+ // (draft-ietf-quic-transport-27, section 20). However, according to
// quic_error_codes.h, this QUIC implementation only sends 1-byte error codes
// right now.
- QUIC_DLOG(INFO) << "TLS failing handshake due to alert "
- << static_cast<int>(desc);
- CloseConnection(QUIC_HANDSHAKE_FAILED, "TLS handshake failure");
+ std::string error_details = quiche::QuicheStrCat(
+ "TLS handshake failure (", EncryptionLevelToString(level), ") ",
+ static_cast<int>(desc), ": ", SSL_alert_desc_string_long(desc));
+ QUIC_DLOG(ERROR) << error_details;
+ CloseConnection(QUIC_HANDSHAKE_FAILED, error_details);
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/tls_handshaker.h b/chromium/net/third_party/quiche/src/quic/core/tls_handshaker.h
index 14503cde549..3d5f1e2d26a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/tls_handshaker.h
+++ b/chromium/net/third_party/quiche/src/quic/core/tls_handshaker.h
@@ -14,6 +14,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/tls_connection.h"
#include "net/third_party/quiche/src/quic/core/quic_session.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -28,16 +29,15 @@ class QUIC_EXPORT_PRIVATE TlsHandshaker : public TlsConnection::Delegate,
public:
// TlsHandshaker does not take ownership of any of its arguments; they must
// outlive the TlsHandshaker.
- TlsHandshaker(QuicCryptoStream* stream,
- QuicSession* session,
- SSL_CTX* ssl_ctx);
+ TlsHandshaker(QuicCryptoStream* stream, QuicSession* session);
TlsHandshaker(const TlsHandshaker&) = delete;
TlsHandshaker& operator=(const TlsHandshaker&) = delete;
~TlsHandshaker() override;
// From CryptoMessageParser
- bool ProcessInput(QuicStringPiece input, EncryptionLevel level) override;
+ bool ProcessInput(quiche::QuicheStringPiece input,
+ EncryptionLevel level) override;
size_t InputBytesRemaining() const override { return 0; }
QuicErrorCode error() const override { return parser_error_; }
const std::string& error_detail() const override {
@@ -46,10 +46,11 @@ class QUIC_EXPORT_PRIVATE TlsHandshaker : public TlsConnection::Delegate,
// From QuicCryptoStream
virtual bool encryption_established() const = 0;
- virtual bool handshake_confirmed() const = 0;
+ virtual bool one_rtt_keys_available() const = 0;
virtual const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
const = 0;
virtual CryptoMessageParser* crypto_message_parser() { return this; }
+ virtual HandshakeState GetHandshakeState() const = 0;
size_t BufferSizeLimitForLevel(EncryptionLevel level) const;
protected:
@@ -59,30 +60,39 @@ class QUIC_EXPORT_PRIVATE TlsHandshaker : public TlsConnection::Delegate,
const std::string& reason_phrase) = 0;
// Returns the PRF used by the cipher suite negotiated in the TLS handshake.
- const EVP_MD* Prf();
+ const EVP_MD* Prf(const SSL_CIPHER* cipher);
virtual const TlsConnection* tls_connection() const = 0;
SSL* ssl() const { return tls_connection()->ssl(); }
QuicCryptoStream* stream() { return stream_; }
- QuicSession* session() { return session_; }
- HandshakerDelegateInterface* delegate() { return delegate_; }
-
- // SetEncryptionSecret provides the encryption secret to use at a particular
- // encryption level. The secrets provided here are the ones from the TLS 1.3
- // key schedule (RFC 8446 section 7.1), in particular the handshake traffic
- // secrets and application traffic secrets. For a given secret |secret|,
- // |level| indicates which EncryptionLevel it is to be used at, and |is_write|
- // indicates whether it is used for encryption or decryption.
- void SetEncryptionSecret(EncryptionLevel level,
- const std::vector<uint8_t>& read_secret,
- const std::vector<uint8_t>& write_secret) override;
+ HandshakerDelegateInterface* handshaker_delegate() {
+ return handshaker_delegate_;
+ }
+
+ // SetWriteSecret provides the encryption secret used to encrypt messages at
+ // encryption level |level|. The secret provided here is the one from the TLS
+ // 1.3 key schedule (RFC 8446 section 7.1), in particular the handshake
+ // traffic secrets and application traffic secrets. The provided write secret
+ // must be used with the provided cipher suite |cipher|.
+ void SetWriteSecret(EncryptionLevel level,
+ const SSL_CIPHER* cipher,
+ const std::vector<uint8_t>& write_secret) override;
+
+ // SetReadSecret is similar to SetWriteSecret, except that it is used for
+ // decrypting messages. SetReadSecret at a particular level is always called
+ // after SetWriteSecret for that level, except for ENCRYPTION_ZERO_RTT, where
+ // the EncryptionLevel for SetWriteSecret is ENCRYPTION_FORWARD_SECURE.
+ bool SetReadSecret(EncryptionLevel level,
+ const SSL_CIPHER* cipher,
+ const std::vector<uint8_t>& read_secret) override;
// WriteMessage is called when there is |data| from the TLS stack ready for
// the QUIC stack to write in a crypto frame. The data must be transmitted at
// encryption level |level|.
- void WriteMessage(EncryptionLevel level, QuicStringPiece data) override;
+ void WriteMessage(EncryptionLevel level,
+ quiche::QuicheStringPiece data) override;
// FlushFlight is called to signal that the current flight of
// messages have all been written (via calls to WriteMessage) and can be
@@ -95,8 +105,7 @@ class QUIC_EXPORT_PRIVATE TlsHandshaker : public TlsConnection::Delegate,
private:
QuicCryptoStream* stream_;
- QuicSession* session_;
- HandshakerDelegateInterface* delegate_;
+ HandshakerDelegateInterface* handshaker_delegate_;
QuicErrorCode parser_error_ = QUIC_NO_ERROR;
std::string parser_error_detail_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/tls_handshaker_test.cc b/chromium/net/third_party/quiche/src/quic/core/tls_handshaker_test.cc
index a86b5217bfb..2d332a385bd 100644
--- a/chromium/net/third_party/quiche/src/quic/core/tls_handshaker_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/tls_handshaker_test.cc
@@ -10,13 +10,15 @@
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h"
#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/fake_proof_source.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_quic_session_visitor.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/quic/tools/fake_proof_verifier.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
@@ -26,9 +28,9 @@ using ::testing::_;
using ::testing::ElementsAreArray;
using ::testing::Return;
-class FakeProofVerifier : public ProofVerifier {
+class TestProofVerifier : public ProofVerifier {
public:
- FakeProofVerifier()
+ TestProofVerifier()
: verifier_(crypto_test_utils::ProofVerifierForTesting()) {}
QuicAsyncStatus VerifyProof(
@@ -36,7 +38,7 @@ class FakeProofVerifier : public ProofVerifier {
const uint16_t port,
const std::string& server_config,
QuicTransportVersion quic_version,
- QuicStringPiece chlo_hash,
+ quiche::QuicheStringPiece chlo_hash,
const std::vector<std::string>& certs,
const std::string& cert_sct,
const std::string& signature,
@@ -118,7 +120,7 @@ class FakeProofVerifier : public ProofVerifier {
delegate_(delegate) {}
void Run() {
- // FakeProofVerifier depends on crypto_test_utils::ProofVerifierForTesting
+ // TestProofVerifier depends on crypto_test_utils::ProofVerifierForTesting
// running synchronously. It passes a FailingProofVerifierCallback and
// runs the original callback after asserting that the verification ran
// synchronously.
@@ -160,8 +162,8 @@ class TestQuicCryptoStream : public QuicCryptoStream {
return handshaker()->encryption_established();
}
- bool handshake_confirmed() const override {
- return handshaker()->handshake_confirmed();
+ bool one_rtt_keys_available() const override {
+ return handshaker()->one_rtt_keys_available();
}
const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
@@ -173,11 +175,17 @@ class TestQuicCryptoStream : public QuicCryptoStream {
return handshaker()->crypto_message_parser();
}
- void WriteCryptoData(EncryptionLevel level, QuicStringPiece data) override {
+ void WriteCryptoData(EncryptionLevel level,
+ quiche::QuicheStringPiece data) override {
pending_writes_.push_back(std::make_pair(std::string(data), level));
}
void OnPacketDecrypted(EncryptionLevel /*level*/) override {}
+ void OnOneRttPacketAcknowledged() override {}
+
+ HandshakeState GetHandshakeState() const override {
+ return handshaker()->GetHandshakeState();
+ }
const std::vector<std::pair<std::string, EncryptionLevel>>& pending_writes() {
return pending_writes_;
@@ -199,9 +207,8 @@ class TestQuicCryptoStream : public QuicCryptoStream {
for (size_t i = 0; i < pending_writes_.size(); ++i) {
if (!stream->crypto_message_parser()->ProcessInput(
pending_writes_[i].first, pending_writes_[i].second)) {
- CloseConnectionWithDetails(
- stream->crypto_message_parser()->error(),
- stream->crypto_message_parser()->error_detail());
+ OnUnrecoverableError(stream->crypto_message_parser()->error(),
+ stream->crypto_message_parser()->error_detail());
break;
}
}
@@ -224,11 +231,18 @@ class MockProofHandler : public QuicCryptoClientStream::ProofHandler {
class TestQuicCryptoClientStream : public TestQuicCryptoStream {
public:
explicit TestQuicCryptoClientStream(QuicSession* session)
+ : TestQuicCryptoClientStream(session,
+ QuicServerId("test.example.com", 443),
+ std::make_unique<TestProofVerifier>()) {}
+
+ TestQuicCryptoClientStream(QuicSession* session,
+ const QuicServerId& server_id,
+ std::unique_ptr<ProofVerifier> proof_verifier)
: TestQuicCryptoStream(session),
- crypto_config_(std::make_unique<FakeProofVerifier>(),
+ crypto_config_(std::move(proof_verifier),
/*session_cache*/ nullptr),
handshaker_(new TlsClientHandshaker(
- QuicServerId("test.example.com", 443, false),
+ server_id,
this,
session,
crypto_test_utils::ProofVerifyContextForTesting(),
@@ -240,11 +254,12 @@ class TestQuicCryptoClientStream : public TestQuicCryptoStream {
TlsHandshaker* handshaker() const override { return handshaker_.get(); }
TlsClientHandshaker* client_handshaker() const { return handshaker_.get(); }
const MockProofHandler& proof_handler() { return proof_handler_; }
+ void OnHandshakeDoneReceived() override {}
bool CryptoConnect() { return handshaker_->CryptoConnect(); }
- FakeProofVerifier* GetFakeProofVerifier() const {
- return static_cast<FakeProofVerifier*>(crypto_config_.proof_verifier());
+ TestProofVerifier* GetTestProofVerifier() const {
+ return static_cast<TestProofVerifier*>(crypto_config_.proof_verifier());
}
private:
@@ -253,6 +268,24 @@ class TestQuicCryptoClientStream : public TestQuicCryptoStream {
std::unique_ptr<TlsClientHandshaker> handshaker_;
};
+class TestTlsServerHandshaker : public TlsServerHandshaker {
+ public:
+ TestTlsServerHandshaker(QuicSession* session,
+ SSL_CTX* ssl_ctx,
+ ProofSource* proof_source,
+ TestQuicCryptoStream* test_stream)
+ : TlsServerHandshaker(session, ssl_ctx, proof_source),
+ test_stream_(test_stream) {}
+
+ void WriteCryptoData(EncryptionLevel level,
+ quiche::QuicheStringPiece data) override {
+ test_stream_->WriteCryptoData(level, data);
+ }
+
+ private:
+ TestQuicCryptoStream* test_stream_;
+};
+
class TestQuicCryptoServerStream : public TestQuicCryptoStream {
public:
TestQuicCryptoServerStream(QuicSession* session,
@@ -260,10 +293,10 @@ class TestQuicCryptoServerStream : public TestQuicCryptoStream {
: TestQuicCryptoStream(session),
proof_source_(proof_source),
ssl_ctx_(TlsServerConnection::CreateSslCtx()),
- handshaker_(new TlsServerHandshaker(this,
- session,
- ssl_ctx_.get(),
- proof_source_)) {}
+ handshaker_(new TestTlsServerHandshaker(session,
+ ssl_ctx_.get(),
+ proof_source_,
+ this)) {}
~TestQuicCryptoServerStream() override = default;
@@ -274,6 +307,7 @@ class TestQuicCryptoServerStream : public TestQuicCryptoStream {
void OnPacketDecrypted(EncryptionLevel level) override {
handshaker_->OnPacketDecrypted(level);
}
+ void OnHandshakeDoneReceived() override { DCHECK(false); }
TlsHandshaker* handshaker() const override { return handshaker_.get(); }
@@ -286,7 +320,7 @@ class TestQuicCryptoServerStream : public TestQuicCryptoStream {
};
void ExchangeHandshakeMessages(TestQuicCryptoStream* client,
- TestQuicCryptoStream* server) {
+ TestQuicCryptoServerStream* server) {
while (!client->pending_writes().empty() ||
!server->pending_writes().empty()) {
client->SendCryptoMessagesToPeer(server);
@@ -294,22 +328,20 @@ void ExchangeHandshakeMessages(TestQuicCryptoStream* client,
}
}
-class TlsHandshakerTest : public QuicTest {
+class TlsHandshakerTest : public QuicTestWithParam<ParsedQuicVersion> {
public:
TlsHandshakerTest()
- : client_conn_(new MockQuicConnection(
- &conn_helper_,
- &alarm_factory_,
- Perspective::IS_CLIENT,
- {ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99)})),
- server_conn_(new MockQuicConnection(
- &conn_helper_,
- &alarm_factory_,
- Perspective::IS_SERVER,
- {ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99)})),
+ : version_(GetParam()),
+ client_conn_(new MockQuicConnection(&conn_helper_,
+ &alarm_factory_,
+ Perspective::IS_CLIENT,
+ {version_})),
+ server_conn_(new MockQuicConnection(&conn_helper_,
+ &alarm_factory_,
+ Perspective::IS_SERVER,
+ {version_})),
client_session_(client_conn_, /*create_mock_crypto_stream=*/false),
server_session_(server_conn_, /*create_mock_crypto_stream=*/false) {
- SetQuicReloadableFlag(quic_supports_tls_handshake, true);
client_stream_ = new TestQuicCryptoClientStream(&client_session_);
client_session_.SetCryptoStream(client_stream_);
server_stream_ =
@@ -318,27 +350,28 @@ class TlsHandshakerTest : public QuicTest {
client_session_.Initialize();
server_session_.Initialize();
EXPECT_FALSE(client_stream_->encryption_established());
- EXPECT_FALSE(client_stream_->handshake_confirmed());
+ EXPECT_FALSE(client_stream_->one_rtt_keys_available());
EXPECT_FALSE(server_stream_->encryption_established());
- EXPECT_FALSE(server_stream_->handshake_confirmed());
+ EXPECT_FALSE(server_stream_->one_rtt_keys_available());
const std::string default_alpn =
AlpnForVersion(client_session_.connection()->version());
ON_CALL(client_session_, GetAlpnsToOffer())
.WillByDefault(Return(std::vector<std::string>({default_alpn})));
ON_CALL(server_session_, SelectAlpn(_))
.WillByDefault(
- [default_alpn](const std::vector<QuicStringPiece>& alpns) {
+ [default_alpn](
+ const std::vector<quiche::QuicheStringPiece>& alpns) {
return std::find(alpns.begin(), alpns.end(), default_alpn);
});
}
void ExpectHandshakeSuccessful() {
- EXPECT_TRUE(client_stream_->handshake_confirmed());
+ EXPECT_TRUE(client_stream_->one_rtt_keys_available());
EXPECT_TRUE(client_stream_->encryption_established());
- EXPECT_TRUE(server_stream_->handshake_confirmed());
+ EXPECT_TRUE(server_stream_->one_rtt_keys_available());
EXPECT_TRUE(server_stream_->encryption_established());
- EXPECT_TRUE(client_conn_->IsHandshakeComplete());
- EXPECT_TRUE(server_conn_->IsHandshakeComplete());
+ EXPECT_EQ(HANDSHAKE_COMPLETE, client_stream_->GetHandshakeState());
+ EXPECT_EQ(HANDSHAKE_CONFIRMED, server_stream_->GetHandshakeState());
const auto& client_crypto_params =
client_stream_->crypto_negotiated_params();
@@ -360,6 +393,7 @@ class TlsHandshakerTest : public QuicTest {
EXPECT_EQ(0, server_crypto_params.peer_signature_algorithm);
}
+ ParsedQuicVersion version_;
MockQuicConnectionHelper conn_helper_;
MockAlarmFactory alarm_factory_;
MockQuicConnection* client_conn_;
@@ -372,7 +406,22 @@ class TlsHandshakerTest : public QuicTest {
TestQuicCryptoServerStream* server_stream_;
};
-TEST_F(TlsHandshakerTest, CryptoHandshake) {
+std::vector<ParsedQuicVersion> AllSupportedTlsVersions() {
+ std::vector<ParsedQuicVersion> tls_versions;
+ for (const ParsedQuicVersion& version : AllSupportedVersions()) {
+ if (version.handshake_protocol == PROTOCOL_TLS1_3) {
+ tls_versions.push_back(version);
+ }
+ }
+ return tls_versions;
+}
+
+INSTANTIATE_TEST_SUITE_P(TlsHandshakerTests,
+ TlsHandshakerTest,
+ ::testing::ValuesIn(AllSupportedTlsVersions()),
+ ::testing::PrintToStringParamName());
+
+TEST_P(TlsHandshakerTest, CryptoHandshake) {
EXPECT_FALSE(client_conn_->IsHandshakeComplete());
EXPECT_FALSE(server_conn_->IsHandshakeComplete());
@@ -385,7 +434,7 @@ TEST_F(TlsHandshakerTest, CryptoHandshake) {
ExpectHandshakeSuccessful();
}
-TEST_F(TlsHandshakerTest, HandshakeWithAsyncProofSource) {
+TEST_P(TlsHandshakerTest, HandshakeWithAsyncProofSource) {
EXPECT_CALL(*client_conn_, CloseConnection(_, _, _)).Times(0);
EXPECT_CALL(*server_conn_, CloseConnection(_, _, _)).Times(0);
// Enable FakeProofSource to capture call to ComputeTlsSignature and run it
@@ -405,7 +454,7 @@ TEST_F(TlsHandshakerTest, HandshakeWithAsyncProofSource) {
ExpectHandshakeSuccessful();
}
-TEST_F(TlsHandshakerTest, CancelPendingProofSource) {
+TEST_P(TlsHandshakerTest, CancelPendingProofSource) {
EXPECT_CALL(*client_conn_, CloseConnection(_, _, _)).Times(0);
EXPECT_CALL(*server_conn_, CloseConnection(_, _, _)).Times(0);
// Enable FakeProofSource to capture call to ComputeTlsSignature and run it
@@ -423,12 +472,12 @@ TEST_F(TlsHandshakerTest, CancelPendingProofSource) {
proof_source->InvokePendingCallback(0);
}
-TEST_F(TlsHandshakerTest, HandshakeWithAsyncProofVerifier) {
+TEST_P(TlsHandshakerTest, HandshakeWithAsyncProofVerifier) {
EXPECT_CALL(*client_conn_, CloseConnection(_, _, _)).Times(0);
EXPECT_CALL(*server_conn_, CloseConnection(_, _, _)).Times(0);
- // Enable FakeProofVerifier to capture call to VerifyCertChain and run it
+ // Enable TestProofVerifier to capture call to VerifyCertChain and run it
// asynchronously.
- FakeProofVerifier* proof_verifier = client_stream_->GetFakeProofVerifier();
+ TestProofVerifier* proof_verifier = client_stream_->GetTestProofVerifier();
proof_verifier->Activate();
EXPECT_CALL(client_stream_->proof_handler(), OnProofVerifyDetailsAvailable);
@@ -445,7 +494,35 @@ TEST_F(TlsHandshakerTest, HandshakeWithAsyncProofVerifier) {
ExpectHandshakeSuccessful();
}
-TEST_F(TlsHandshakerTest, ClientConnectionClosedOnTlsError) {
+TEST_P(TlsHandshakerTest, ClientSendsNoSNI) {
+ // Create a new client stream (and handshaker) with an empty server hostname.
+ client_stream_ =
+ new TestQuicCryptoClientStream(&client_session_, QuicServerId("", 443),
+ std::make_unique<FakeProofVerifier>());
+ client_session_.SetCryptoStream(client_stream_);
+
+ EXPECT_CALL(*client_conn_, CloseConnection(_, _, _)).Times(0);
+ EXPECT_CALL(*server_conn_, CloseConnection(_, _, _)).Times(0);
+ EXPECT_CALL(client_stream_->proof_handler(), OnProofVerifyDetailsAvailable);
+ client_stream_->CryptoConnect();
+ ExchangeHandshakeMessages(client_stream_, server_stream_);
+
+ ExpectHandshakeSuccessful();
+ EXPECT_EQ(server_stream_->crypto_negotiated_params().sni, "");
+}
+
+TEST_P(TlsHandshakerTest, ServerExtractSNI) {
+ EXPECT_CALL(*client_conn_, CloseConnection(_, _, _)).Times(0);
+ EXPECT_CALL(*server_conn_, CloseConnection(_, _, _)).Times(0);
+ EXPECT_CALL(client_stream_->proof_handler(), OnProofVerifyDetailsAvailable);
+ client_stream_->CryptoConnect();
+ ExchangeHandshakeMessages(client_stream_, server_stream_);
+ ExpectHandshakeSuccessful();
+
+ EXPECT_EQ(server_stream_->crypto_negotiated_params().sni, "test.example.com");
+}
+
+TEST_P(TlsHandshakerTest, ClientConnectionClosedOnTlsError) {
// Have client send ClientHello.
client_stream_->CryptoConnect();
EXPECT_CALL(*client_conn_, CloseConnection(QUIC_HANDSHAKE_FAILED, _, _));
@@ -458,14 +535,14 @@ TEST_F(TlsHandshakerTest, ClientConnectionClosedOnTlsError) {
};
server_stream_->WriteCryptoData(
ENCRYPTION_INITIAL,
- QuicStringPiece(bogus_handshake_message,
- QUIC_ARRAYSIZE(bogus_handshake_message)));
+ quiche::QuicheStringPiece(bogus_handshake_message,
+ QUICHE_ARRAYSIZE(bogus_handshake_message)));
server_stream_->SendCryptoMessagesToPeer(client_stream_);
- EXPECT_FALSE(client_stream_->handshake_confirmed());
+ EXPECT_FALSE(client_stream_->one_rtt_keys_available());
}
-TEST_F(TlsHandshakerTest, ServerConnectionClosedOnTlsError) {
+TEST_P(TlsHandshakerTest, ServerConnectionClosedOnTlsError) {
EXPECT_CALL(*server_conn_, CloseConnection(QUIC_HANDSHAKE_FAILED, _, _));
// Send a zero-length ClientHello from client to server.
@@ -476,14 +553,14 @@ TEST_F(TlsHandshakerTest, ServerConnectionClosedOnTlsError) {
};
client_stream_->WriteCryptoData(
ENCRYPTION_INITIAL,
- QuicStringPiece(bogus_handshake_message,
- QUIC_ARRAYSIZE(bogus_handshake_message)));
+ quiche::QuicheStringPiece(bogus_handshake_message,
+ QUICHE_ARRAYSIZE(bogus_handshake_message)));
client_stream_->SendCryptoMessagesToPeer(server_stream_);
- EXPECT_FALSE(server_stream_->handshake_confirmed());
+ EXPECT_FALSE(server_stream_->one_rtt_keys_available());
}
-TEST_F(TlsHandshakerTest, ClientNotSendingALPN) {
+TEST_P(TlsHandshakerTest, ClientNotSendingALPN) {
client_stream_->client_handshaker()->AllowEmptyAlpnForTests();
EXPECT_CALL(client_session_, GetAlpnsToOffer())
.WillOnce(Return(std::vector<std::string>()));
@@ -495,13 +572,15 @@ TEST_F(TlsHandshakerTest, ClientNotSendingALPN) {
client_stream_->CryptoConnect();
ExchangeHandshakeMessages(client_stream_, server_stream_);
- EXPECT_FALSE(client_stream_->handshake_confirmed());
- EXPECT_FALSE(client_stream_->encryption_established());
- EXPECT_FALSE(server_stream_->handshake_confirmed());
- EXPECT_FALSE(server_stream_->encryption_established());
+ EXPECT_FALSE(client_stream_->one_rtt_keys_available());
+ EXPECT_EQ(GetQuicRestartFlag(quic_send_settings_on_write_key_available),
+ client_stream_->encryption_established());
+ EXPECT_FALSE(server_stream_->one_rtt_keys_available());
+ EXPECT_EQ(GetQuicRestartFlag(quic_send_settings_on_write_key_available),
+ server_stream_->encryption_established());
}
-TEST_F(TlsHandshakerTest, ClientSendingBadALPN) {
+TEST_P(TlsHandshakerTest, ClientSendingBadALPN) {
const std::string kTestBadClientAlpn = "bad-client-alpn";
EXPECT_CALL(client_session_, GetAlpnsToOffer())
.WillOnce(Return(std::vector<std::string>({kTestBadClientAlpn})));
@@ -513,13 +592,15 @@ TEST_F(TlsHandshakerTest, ClientSendingBadALPN) {
client_stream_->CryptoConnect();
ExchangeHandshakeMessages(client_stream_, server_stream_);
- EXPECT_FALSE(client_stream_->handshake_confirmed());
- EXPECT_FALSE(client_stream_->encryption_established());
- EXPECT_FALSE(server_stream_->handshake_confirmed());
- EXPECT_FALSE(server_stream_->encryption_established());
+ EXPECT_FALSE(client_stream_->one_rtt_keys_available());
+ EXPECT_EQ(GetQuicRestartFlag(quic_send_settings_on_write_key_available),
+ client_stream_->encryption_established());
+ EXPECT_FALSE(server_stream_->one_rtt_keys_available());
+ EXPECT_EQ(GetQuicRestartFlag(quic_send_settings_on_write_key_available),
+ server_stream_->encryption_established());
}
-TEST_F(TlsHandshakerTest, ClientSendingTooManyALPNs) {
+TEST_P(TlsHandshakerTest, ClientSendingTooManyALPNs) {
std::string long_alpn(250, 'A');
EXPECT_CALL(client_session_, GetAlpnsToOffer())
.WillOnce(Return(std::vector<std::string>({
@@ -535,12 +616,13 @@ TEST_F(TlsHandshakerTest, ClientSendingTooManyALPNs) {
EXPECT_QUIC_BUG(client_stream_->CryptoConnect(), "Failed to set ALPN");
}
-TEST_F(TlsHandshakerTest, ServerRequiresCustomALPN) {
+TEST_P(TlsHandshakerTest, ServerRequiresCustomALPN) {
const std::string kTestAlpn = "An ALPN That Client Did Not Offer";
EXPECT_CALL(server_session_, SelectAlpn(_))
- .WillOnce([kTestAlpn](const std::vector<QuicStringPiece>& alpns) {
- return std::find(alpns.cbegin(), alpns.cend(), kTestAlpn);
- });
+ .WillOnce(
+ [kTestAlpn](const std::vector<quiche::QuicheStringPiece>& alpns) {
+ return std::find(alpns.cbegin(), alpns.cend(), kTestAlpn);
+ });
EXPECT_CALL(*client_conn_, CloseConnection(QUIC_HANDSHAKE_FAILED,
"Server did not select ALPN", _));
EXPECT_CALL(*server_conn_,
@@ -549,13 +631,15 @@ TEST_F(TlsHandshakerTest, ServerRequiresCustomALPN) {
client_stream_->CryptoConnect();
ExchangeHandshakeMessages(client_stream_, server_stream_);
- EXPECT_FALSE(client_stream_->handshake_confirmed());
- EXPECT_FALSE(client_stream_->encryption_established());
- EXPECT_FALSE(server_stream_->handshake_confirmed());
- EXPECT_FALSE(server_stream_->encryption_established());
+ EXPECT_FALSE(client_stream_->one_rtt_keys_available());
+ EXPECT_EQ(GetQuicRestartFlag(quic_send_settings_on_write_key_available),
+ client_stream_->encryption_established());
+ EXPECT_FALSE(server_stream_->one_rtt_keys_available());
+ EXPECT_EQ(GetQuicRestartFlag(quic_send_settings_on_write_key_available),
+ server_stream_->encryption_established());
}
-TEST_F(TlsHandshakerTest, CustomALPNNegotiation) {
+TEST_P(TlsHandshakerTest, CustomALPNNegotiation) {
EXPECT_CALL(*client_conn_, CloseConnection(_, _, _)).Times(0);
EXPECT_CALL(*server_conn_, CloseConnection(_, _, _)).Times(0);
@@ -565,13 +649,15 @@ TEST_F(TlsHandshakerTest, CustomALPNNegotiation) {
EXPECT_CALL(client_session_, GetAlpnsToOffer())
.WillRepeatedly(Return(kTestAlpns));
EXPECT_CALL(server_session_, SelectAlpn(_))
- .WillOnce(
- [kTestAlpn, kTestAlpns](const std::vector<QuicStringPiece>& alpns) {
- EXPECT_THAT(alpns, ElementsAreArray(kTestAlpns));
- return std::find(alpns.cbegin(), alpns.cend(), kTestAlpn);
- });
- EXPECT_CALL(client_session_, OnAlpnSelected(QuicStringPiece(kTestAlpn)));
- EXPECT_CALL(server_session_, OnAlpnSelected(QuicStringPiece(kTestAlpn)));
+ .WillOnce([kTestAlpn, kTestAlpns](
+ const std::vector<quiche::QuicheStringPiece>& alpns) {
+ EXPECT_THAT(alpns, ElementsAreArray(kTestAlpns));
+ return std::find(alpns.cbegin(), alpns.cend(), kTestAlpn);
+ });
+ EXPECT_CALL(client_session_,
+ OnAlpnSelected(quiche::QuicheStringPiece(kTestAlpn)));
+ EXPECT_CALL(server_session_,
+ OnAlpnSelected(quiche::QuicheStringPiece(kTestAlpn)));
client_stream_->CryptoConnect();
ExchangeHandshakeMessages(client_stream_, server_stream_);
diff --git a/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.cc b/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.cc
index 24af98daf00..ced2bd4a51c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.cc
@@ -11,7 +11,9 @@
#include "third_party/boringssl/src/include/openssl/ssl.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h"
#include "net/third_party/quiche/src/quic/core/crypto/transport_parameters.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_hostname_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -19,13 +21,16 @@ TlsServerHandshaker::SignatureCallback::SignatureCallback(
TlsServerHandshaker* handshaker)
: handshaker_(handshaker) {}
-void TlsServerHandshaker::SignatureCallback::Run(bool ok,
- std::string signature) {
+void TlsServerHandshaker::SignatureCallback::Run(
+ bool ok,
+ std::string signature,
+ std::unique_ptr<ProofSource::Details> details) {
if (handshaker_ == nullptr) {
return;
}
if (ok) {
handshaker_->cert_verify_sig_ = std::move(signature);
+ handshaker_->proof_source_details_ = std::move(details);
}
State last_state = handshaker_->state_;
handshaker_->state_ = STATE_SIGNATURE_COMPLETE;
@@ -39,11 +44,11 @@ void TlsServerHandshaker::SignatureCallback::Cancel() {
handshaker_ = nullptr;
}
-TlsServerHandshaker::TlsServerHandshaker(QuicCryptoStream* stream,
- QuicSession* session,
+TlsServerHandshaker::TlsServerHandshaker(QuicSession* session,
SSL_CTX* ssl_ctx,
ProofSource* proof_source)
- : TlsHandshaker(stream, session, ssl_ctx),
+ : TlsHandshaker(this, session),
+ QuicCryptoServerStreamBase(session),
proof_source_(proof_source),
crypto_negotiated_params_(new QuicCryptoNegotiatedParameters),
tls_connection_(ssl_ctx, this) {
@@ -52,11 +57,6 @@ TlsServerHandshaker::TlsServerHandshaker(QuicCryptoStream* stream,
// Configure the SSL to be a server.
SSL_set_accept_state(ssl());
-
- if (!SetTransportParameters()) {
- CloseConnection(QUIC_HANDSHAKE_FAILED,
- "Server failed to set Transport Parameters");
- }
}
TlsServerHandshaker::~TlsServerHandshaker() {
@@ -81,14 +81,9 @@ void TlsServerHandshaker::SendServerConfigUpdate(
// SCUP messages aren't supported when using the TLS handshake.
}
-uint8_t TlsServerHandshaker::NumHandshakeMessages() const {
- // TODO(nharper): Return a sensible value here.
- return 0;
-}
-
-uint8_t TlsServerHandshaker::NumHandshakeMessagesWithServerNonces() const {
- // TODO(nharper): Return a sensible value here.
- return 0;
+bool TlsServerHandshaker::IsZeroRtt() const {
+ // TODO(nharper): Support 0-RTT with TLS 1.3 in QUIC.
+ return false;
}
int TlsServerHandshaker::NumServerConfigUpdateMessagesSent() const {
@@ -113,11 +108,15 @@ void TlsServerHandshaker::OnPacketDecrypted(EncryptionLevel level) {
if (level == ENCRYPTION_HANDSHAKE &&
state_ < STATE_ENCRYPTION_HANDSHAKE_DATA_PROCESSED) {
state_ = STATE_ENCRYPTION_HANDSHAKE_DATA_PROCESSED;
- delegate()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
- delegate()->DiscardOldDecryptionKey(ENCRYPTION_INITIAL);
+ handshaker_delegate()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
+ handshaker_delegate()->DiscardOldDecryptionKey(ENCRYPTION_INITIAL);
}
}
+void TlsServerHandshaker::OnHandshakeDoneReceived() {
+ DCHECK(false);
+}
+
bool TlsServerHandshaker::ShouldSendExpectCTHeader() const {
return false;
}
@@ -126,8 +125,8 @@ bool TlsServerHandshaker::encryption_established() const {
return encryption_established_;
}
-bool TlsServerHandshaker::handshake_confirmed() const {
- return handshake_confirmed_;
+bool TlsServerHandshaker::one_rtt_keys_available() const {
+ return one_rtt_keys_available_;
}
const QuicCryptoNegotiatedParameters&
@@ -139,11 +138,36 @@ CryptoMessageParser* TlsServerHandshaker::crypto_message_parser() {
return TlsHandshaker::crypto_message_parser();
}
+HandshakeState TlsServerHandshaker::GetHandshakeState() const {
+ if (one_rtt_keys_available_) {
+ return HANDSHAKE_CONFIRMED;
+ }
+ if (state_ >= STATE_ENCRYPTION_HANDSHAKE_DATA_PROCESSED) {
+ return HANDSHAKE_PROCESSED;
+ }
+ return HANDSHAKE_START;
+}
+
size_t TlsServerHandshaker::BufferSizeLimitForLevel(
EncryptionLevel level) const {
return TlsHandshaker::BufferSizeLimitForLevel(level);
}
+void TlsServerHandshaker::OverrideQuicConfigDefaults(QuicConfig* /*config*/) {}
+
+bool TlsServerHandshaker::SetReadSecret(
+ EncryptionLevel level,
+ const SSL_CIPHER* cipher,
+ const std::vector<uint8_t>& read_secret) {
+ if (level != ENCRYPTION_FORWARD_SECURE || one_rtt_keys_available_) {
+ return TlsHandshaker::SetReadSecret(level, cipher, read_secret);
+ }
+ // Delay setting read secret for ENCRYPTION_FORWARD_SECURE until handshake
+ // completes.
+ app_data_read_secret_ = read_secret;
+ return true;
+}
+
void TlsServerHandshaker::AdvanceHandshake() {
if (state_ == STATE_CONNECTION_CLOSED) {
QUIC_LOG(INFO) << "TlsServerHandshaker received handshake message after "
@@ -186,7 +210,7 @@ void TlsServerHandshaker::AdvanceHandshake() {
void TlsServerHandshaker::CloseConnection(QuicErrorCode error,
const std::string& reason_phrase) {
state_ = STATE_CONNECTION_CLOSED;
- stream()->CloseConnectionWithDetails(error, reason_phrase);
+ stream()->OnUnrecoverableError(error, reason_phrase);
}
bool TlsServerHandshaker::ProcessTransportParameters(
@@ -196,11 +220,18 @@ bool TlsServerHandshaker::ProcessTransportParameters(
size_t params_bytes_len;
SSL_get_peer_quic_transport_params(ssl(), &client_params_bytes,
&params_bytes_len);
- if (params_bytes_len == 0 ||
- !ParseTransportParameters(session()->connection()->version(),
+ if (params_bytes_len == 0) {
+ *error_details = "Client's transport parameters are missing";
+ return false;
+ }
+ std::string parse_error_details;
+ if (!ParseTransportParameters(session()->connection()->version(),
Perspective::IS_CLIENT, client_params_bytes,
- params_bytes_len, &client_params)) {
- *error_details = "Unable to parse Transport Parameters";
+ params_bytes_len, &client_params,
+ &parse_error_details)) {
+ DCHECK(!parse_error_details.empty());
+ *error_details =
+ "Unable to parse client's transport parameters: " + parse_error_details;
return false;
}
@@ -218,6 +249,7 @@ bool TlsServerHandshaker::ProcessTransportParameters(
client_params, CLIENT, error_details) != QUIC_NO_ERROR) {
return false;
}
+ ProcessAdditionalTransportParameters(client_params);
session()->OnConfigNegotiated();
return true;
@@ -247,6 +279,23 @@ bool TlsServerHandshaker::SetTransportParameters() {
return true;
}
+void TlsServerHandshaker::SetWriteSecret(
+ EncryptionLevel level,
+ const SSL_CIPHER* cipher,
+ const std::vector<uint8_t>& write_secret) {
+ if (GetQuicRestartFlag(quic_send_settings_on_write_key_available) &&
+ level == ENCRYPTION_FORWARD_SECURE) {
+ encryption_established_ = true;
+ // Fill crypto_negotiated_params_:
+ const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl());
+ if (cipher) {
+ crypto_negotiated_params_->cipher_suite = SSL_CIPHER_get_value(cipher);
+ }
+ crypto_negotiated_params_->key_exchange_group = SSL_get_curve_id(ssl());
+ }
+ TlsHandshaker::SetWriteSecret(level, cipher, write_secret);
+}
+
void TlsServerHandshaker::FinishHandshake() {
if (!valid_alpn_received_) {
QUIC_DLOG(ERROR)
@@ -261,19 +310,33 @@ void TlsServerHandshaker::FinishHandshake() {
QUIC_LOG(INFO) << "Server: handshake finished";
state_ = STATE_HANDSHAKE_COMPLETE;
- encryption_established_ = true;
- handshake_confirmed_ = true;
- delegate()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ if (!GetQuicRestartFlag(quic_send_settings_on_write_key_available)) {
+ encryption_established_ = true;
+ }
+ one_rtt_keys_available_ = true;
- // Fill crypto_negotiated_params_:
const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl());
- if (cipher) {
- crypto_negotiated_params_->cipher_suite = SSL_CIPHER_get_value(cipher);
+ if (!GetQuicRestartFlag(quic_send_settings_on_write_key_available)) {
+ // Fill crypto_negotiated_params_:
+ if (cipher) {
+ crypto_negotiated_params_->cipher_suite = SSL_CIPHER_get_value(cipher);
+ }
+ crypto_negotiated_params_->key_exchange_group = SSL_get_curve_id(ssl());
+ }
+
+ if (!app_data_read_secret_.empty()) {
+ if (!SetReadSecret(ENCRYPTION_FORWARD_SECURE, cipher,
+ app_data_read_secret_)) {
+ QUIC_BUG << "Failed to set forward secure read key.";
+ CloseConnection(QUIC_HANDSHAKE_FAILED, "Failed to set app data read key");
+ return;
+ }
+ app_data_read_secret_.clear();
}
- crypto_negotiated_params_->key_exchange_group = SSL_get_curve_id(ssl());
- // TODO(fayang): Replace this with DiscardOldKeys(ENCRYPTION_HANDSHAKE) when
- // handshake key discarding settles down.
- delegate()->NeuterHandshakeData();
+
+ handshaker_delegate()->OnOneRttKeysAvailable();
+ handshaker_delegate()->DiscardOldEncryptionKey(ENCRYPTION_HANDSHAKE);
+ handshaker_delegate()->DiscardOldDecryptionKey(ENCRYPTION_HANDSHAKE);
}
ssl_private_key_result_t TlsServerHandshaker::PrivateKeySign(
@@ -281,7 +344,7 @@ ssl_private_key_result_t TlsServerHandshaker::PrivateKeySign(
size_t* out_len,
size_t max_out,
uint16_t sig_alg,
- QuicStringPiece in) {
+ quiche::QuicheStringPiece in) {
signature_callback_ = new SignatureCallback(this);
proof_source_->ComputeTlsSignature(
session()->connection()->self_address(), hostname_, sig_alg, in,
@@ -314,6 +377,8 @@ int TlsServerHandshaker::SelectCertificate(int* out_alert) {
const char* hostname = SSL_get_servername(ssl(), TLSEXT_NAMETYPE_host_name);
if (hostname) {
hostname_ = hostname;
+ crypto_negotiated_params_->sni =
+ QuicHostnameUtils::NormalizeHostname(hostname_);
} else {
QUIC_LOG(INFO) << "No hostname indicated in SNI";
}
@@ -346,8 +411,14 @@ int TlsServerHandshaker::SelectCertificate(int* out_alert) {
*out_alert = SSL_AD_INTERNAL_ERROR;
return SSL_TLSEXT_ERR_ALERT_FATAL;
}
+ OverrideQuicConfigDefaults(session()->config());
+ if (!SetTransportParameters()) {
+ QUIC_LOG(ERROR) << "Failed to set transport parameters";
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
+ }
- QUIC_LOG(INFO) << "Set " << chain->certs.size() << " certs for server";
+ QUIC_LOG(INFO) << "Set " << chain->certs.size() << " certs for server "
+ << "with hostname " << hostname_;
return SSL_TLSEXT_ERR_OK;
}
@@ -366,7 +437,7 @@ int TlsServerHandshaker::SelectAlpn(const uint8_t** out,
CBS all_alpns;
CBS_init(&all_alpns, in, in_len);
- std::vector<QuicStringPiece> alpns;
+ std::vector<quiche::QuicheStringPiece> alpns;
while (CBS_len(&all_alpns) > 0) {
CBS alpn;
if (!CBS_get_u8_length_prefixed(&all_alpns, &alpn)) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.h b/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.h
index 507324b9ccd..22ae45df9ed 100644
--- a/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.h
+++ b/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.h
@@ -11,22 +11,22 @@
#include "third_party/boringssl/src/include/openssl/ssl.h"
#include "net/third_party/quiche/src/quic/core/crypto/tls_server_connection.h"
#include "net/third_party/quiche/src/quic/core/proto/cached_network_parameters_proto.h"
-#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
+#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h"
#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
#include "net/third_party/quiche/src/quic/core/tls_handshaker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
-// An implementation of QuicCryptoServerStream::HandshakerDelegate which uses
+// An implementation of QuicCryptoServerStreamBase which uses
// TLS 1.3 for the crypto handshake protocol.
class QUIC_EXPORT_PRIVATE TlsServerHandshaker
: public TlsHandshaker,
public TlsServerConnection::Delegate,
- public QuicCryptoServerStream::HandshakerDelegate {
+ public QuicCryptoServerStreamBase {
public:
- TlsServerHandshaker(QuicCryptoStream* stream,
- QuicSession* session,
+ TlsServerHandshaker(QuicSession* session,
SSL_CTX* ssl_ctx,
ProofSource* proof_source);
TlsServerHandshaker(const TlsServerHandshaker&) = delete;
@@ -34,34 +34,57 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
~TlsServerHandshaker() override;
- // From QuicCryptoServerStream::HandshakerDelegate
+ // From QuicCryptoServerStreamBase
void CancelOutstandingCallbacks() override;
bool GetBase64SHA256ClientChannelID(std::string* output) const override;
void SendServerConfigUpdate(
const CachedNetworkParameters* cached_network_params) override;
- uint8_t NumHandshakeMessages() const override;
- uint8_t NumHandshakeMessagesWithServerNonces() const override;
+ bool IsZeroRtt() const override;
int NumServerConfigUpdateMessagesSent() const override;
const CachedNetworkParameters* PreviousCachedNetworkParams() const override;
bool ZeroRttAttempted() const override;
void SetPreviousCachedNetworkParams(
CachedNetworkParameters cached_network_params) override;
void OnPacketDecrypted(EncryptionLevel level) override;
+ void OnOneRttPacketAcknowledged() override {}
+ void OnHandshakeDoneReceived() override;
bool ShouldSendExpectCTHeader() const override;
- // From QuicCryptoServerStream::HandshakerDelegate and TlsHandshaker
+ // From QuicCryptoServerStreamBase and TlsHandshaker
bool encryption_established() const override;
- bool handshake_confirmed() const override;
+ bool one_rtt_keys_available() const override;
const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
const override;
CryptoMessageParser* crypto_message_parser() override;
+ HandshakeState GetHandshakeState() const override;
size_t BufferSizeLimitForLevel(EncryptionLevel level) const override;
+ void SetWriteSecret(EncryptionLevel level,
+ const SSL_CIPHER* cipher,
+ const std::vector<uint8_t>& write_secret) override;
protected:
+ // Hook to allow the server to override parts of the QuicConfig based on SNI
+ // before we generate transport parameters.
+ virtual void OverrideQuicConfigDefaults(QuicConfig* config);
+
const TlsConnection* tls_connection() const override {
return &tls_connection_;
}
+ ProofSource::Details* proof_source_details() const {
+ return proof_source_details_.get();
+ }
+
+ virtual void ProcessAdditionalTransportParameters(
+ const TransportParameters& /*params*/) {}
+
+ // Override of TlsHandshaker::SetReadSecret so that setting the read secret
+ // for ENCRYPTION_FORWARD_SECURE can be delayed until the handshake is
+ // complete.
+ bool SetReadSecret(EncryptionLevel level,
+ const SSL_CIPHER* cipher,
+ const std::vector<uint8_t>& read_secret) override;
+
// Called when a new message is received on the crypto stream and is available
// for the TLS stack to read.
void AdvanceHandshake() override;
@@ -74,11 +97,12 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
uint8_t* out_len,
const uint8_t* in,
unsigned in_len) override;
- ssl_private_key_result_t PrivateKeySign(uint8_t* out,
- size_t* out_len,
- size_t max_out,
- uint16_t sig_alg,
- QuicStringPiece in) override;
+ ssl_private_key_result_t PrivateKeySign(
+ uint8_t* out,
+ size_t* out_len,
+ size_t max_out,
+ uint16_t sig_alg,
+ quiche::QuicheStringPiece in) override;
ssl_private_key_result_t PrivateKeyComplete(uint8_t* out,
size_t* out_len,
size_t max_out) override;
@@ -89,7 +113,9 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
: public ProofSource::SignatureCallback {
public:
explicit SignatureCallback(TlsServerHandshaker* handshaker);
- void Run(bool ok, std::string signature) override;
+ void Run(bool ok,
+ std::string signature,
+ std::unique_ptr<ProofSource::Details> details) override;
// If called, Cancel causes the pending callback to be a no-op.
void Cancel();
@@ -122,9 +148,15 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
std::string hostname_;
std::string cert_verify_sig_;
+ std::unique_ptr<ProofSource::Details> proof_source_details_;
+
+ // Used to hold the ENCRYPTION_FORWARD_SECURE read secret until the handshake
+ // is complete. This is temporary until
+ // https://bugs.chromium.org/p/boringssl/issues/detail?id=303 is resolved.
+ std::vector<uint8_t> app_data_read_secret_;
bool encryption_established_ = false;
- bool handshake_confirmed_ = false;
+ bool one_rtt_keys_available_ = false;
bool valid_alpn_received_ = false;
QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters>
crypto_negotiated_params_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.cc b/chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.cc
index 3fb5be8379b..daa56302145 100644
--- a/chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.cc
@@ -13,7 +13,6 @@ UberQuicStreamIdManager::UberQuicStreamIdManager(
Perspective perspective,
ParsedQuicVersion version,
QuicStreamIdManager::DelegateInterface* delegate,
- QuicStreamCount num_expected_unidirectiona_static_streams,
QuicStreamCount max_open_outgoing_bidirectional_streams,
QuicStreamCount max_open_outgoing_unidirectional_streams,
QuicStreamCount max_open_incoming_bidirectional_streams,
@@ -22,7 +21,6 @@ UberQuicStreamIdManager::UberQuicStreamIdManager(
/*unidirectional=*/false,
perspective,
version.transport_version,
- 0,
max_open_outgoing_bidirectional_streams,
max_open_incoming_bidirectional_streams),
unidirectional_stream_id_manager_(
@@ -30,32 +28,33 @@ UberQuicStreamIdManager::UberQuicStreamIdManager(
/*unidirectional=*/true,
perspective,
version.transport_version,
- num_expected_unidirectiona_static_streams,
max_open_outgoing_unidirectional_streams,
max_open_incoming_unidirectional_streams) {}
-void UberQuicStreamIdManager::SetMaxOpenOutgoingBidirectionalStreams(
- size_t max_open_streams) {
- bidirectional_stream_id_manager_.SetMaxOpenOutgoingStreams(max_open_streams);
+bool UberQuicStreamIdManager::MaybeAllowNewOutgoingBidirectionalStreams(
+ QuicStreamCount max_open_streams) {
+ return bidirectional_stream_id_manager_.MaybeAllowNewOutgoingStreams(
+ max_open_streams);
}
-void UberQuicStreamIdManager::SetMaxOpenOutgoingUnidirectionalStreams(
- size_t max_open_streams) {
- unidirectional_stream_id_manager_.SetMaxOpenOutgoingStreams(max_open_streams);
+bool UberQuicStreamIdManager::MaybeAllowNewOutgoingUnidirectionalStreams(
+ QuicStreamCount max_open_streams) {
+ return unidirectional_stream_id_manager_.MaybeAllowNewOutgoingStreams(
+ max_open_streams);
}
void UberQuicStreamIdManager::SetMaxOpenIncomingBidirectionalStreams(
- size_t max_open_streams) {
+ QuicStreamCount max_open_streams) {
bidirectional_stream_id_manager_.SetMaxOpenIncomingStreams(max_open_streams);
}
void UberQuicStreamIdManager::SetMaxOpenIncomingUnidirectionalStreams(
- size_t max_open_streams) {
+ QuicStreamCount max_open_streams) {
unidirectional_stream_id_manager_.SetMaxOpenIncomingStreams(max_open_streams);
}
-bool UberQuicStreamIdManager::CanOpenNextOutgoingBidirectionalStream() {
+bool UberQuicStreamIdManager::CanOpenNextOutgoingBidirectionalStream() const {
return bidirectional_stream_id_manager_.CanOpenNextOutgoingStream();
}
-bool UberQuicStreamIdManager::CanOpenNextOutgoingUnidirectionalStream() {
+bool UberQuicStreamIdManager::CanOpenNextOutgoingUnidirectionalStream() const {
return unidirectional_stream_id_manager_.CanOpenNextOutgoingStream();
}
@@ -68,12 +67,14 @@ QuicStreamId UberQuicStreamIdManager::GetNextOutgoingUnidirectionalStreamId() {
}
bool UberQuicStreamIdManager::MaybeIncreaseLargestPeerStreamId(
- QuicStreamId id) {
+ QuicStreamId id,
+ std::string* error_details) {
if (QuicUtils::IsBidirectionalStreamId(id)) {
return bidirectional_stream_id_manager_.MaybeIncreaseLargestPeerStreamId(
- id);
+ id, error_details);
}
- return unidirectional_stream_id_manager_.MaybeIncreaseLargestPeerStreamId(id);
+ return unidirectional_stream_id_manager_.MaybeIncreaseLargestPeerStreamId(
+ id, error_details);
}
void UberQuicStreamIdManager::OnStreamClosed(QuicStreamId id) {
@@ -84,20 +85,15 @@ void UberQuicStreamIdManager::OnStreamClosed(QuicStreamId id) {
unidirectional_stream_id_manager_.OnStreamClosed(id);
}
-bool UberQuicStreamIdManager::OnMaxStreamsFrame(
- const QuicMaxStreamsFrame& frame) {
- if (frame.unidirectional) {
- return unidirectional_stream_id_manager_.OnMaxStreamsFrame(frame);
- }
- return bidirectional_stream_id_manager_.OnMaxStreamsFrame(frame);
-}
-
bool UberQuicStreamIdManager::OnStreamsBlockedFrame(
- const QuicStreamsBlockedFrame& frame) {
+ const QuicStreamsBlockedFrame& frame,
+ std::string* error_details) {
if (frame.unidirectional) {
- return unidirectional_stream_id_manager_.OnStreamsBlockedFrame(frame);
+ return unidirectional_stream_id_manager_.OnStreamsBlockedFrame(
+ frame, error_details);
}
- return bidirectional_stream_id_manager_.OnStreamsBlockedFrame(frame);
+ return bidirectional_stream_id_manager_.OnStreamsBlockedFrame(frame,
+ error_details);
}
bool UberQuicStreamIdManager::IsIncomingStream(QuicStreamId id) const {
@@ -114,27 +110,16 @@ bool UberQuicStreamIdManager::IsAvailableStream(QuicStreamId id) const {
return unidirectional_stream_id_manager_.IsAvailableStream(id);
}
-size_t UberQuicStreamIdManager::GetMaxAllowdIncomingBidirectionalStreams()
- const {
+QuicStreamCount
+UberQuicStreamIdManager::GetMaxAllowdIncomingBidirectionalStreams() const {
return bidirectional_stream_id_manager_.incoming_initial_max_open_streams();
}
-size_t UberQuicStreamIdManager::GetMaxAllowdIncomingUnidirectionalStreams()
- const {
+QuicStreamCount
+UberQuicStreamIdManager::GetMaxAllowdIncomingUnidirectionalStreams() const {
return unidirectional_stream_id_manager_.incoming_initial_max_open_streams();
}
-void UberQuicStreamIdManager::SetLargestPeerCreatedStreamId(
- QuicStreamId largest_peer_created_stream_id) {
- if (QuicUtils::IsBidirectionalStreamId(largest_peer_created_stream_id)) {
- bidirectional_stream_id_manager_.set_largest_peer_created_stream_id(
- largest_peer_created_stream_id);
- return;
- }
- unidirectional_stream_id_manager_.set_largest_peer_created_stream_id(
- largest_peer_created_stream_id);
-}
-
QuicStreamId UberQuicStreamIdManager::GetLargestPeerCreatedStreamId(
bool unidirectional) const {
if (unidirectional) {
@@ -153,11 +138,13 @@ QuicStreamId UberQuicStreamIdManager::next_outgoing_unidirectional_stream_id()
return unidirectional_stream_id_manager_.next_outgoing_stream_id();
}
-size_t UberQuicStreamIdManager::max_outgoing_bidirectional_streams() const {
+QuicStreamCount UberQuicStreamIdManager::max_outgoing_bidirectional_streams()
+ const {
return bidirectional_stream_id_manager_.outgoing_max_streams();
}
-size_t UberQuicStreamIdManager::max_outgoing_unidirectional_streams() const {
+QuicStreamCount UberQuicStreamIdManager::max_outgoing_unidirectional_streams()
+ const {
return unidirectional_stream_id_manager_.outgoing_max_streams();
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.h b/chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.h
index 75fcb9d7d3c..d3f374a83a5 100644
--- a/chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.h
+++ b/chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.h
@@ -6,6 +6,7 @@
#define QUICHE_QUIC_CORE_UBER_QUIC_STREAM_ID_MANAGER_H_
#include "net/third_party/quiche/src/quic/core/quic_stream_id_manager.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
namespace quic {
@@ -24,23 +25,29 @@ class QUIC_EXPORT_PRIVATE UberQuicStreamIdManager {
Perspective perspective,
ParsedQuicVersion version,
QuicStreamIdManager::DelegateInterface* delegate,
- QuicStreamCount num_expected_unidirectional_static_streams,
QuicStreamCount max_open_outgoing_bidirectional_streams,
QuicStreamCount max_open_outgoing_unidirectional_streams,
QuicStreamCount max_open_incoming_bidirectional_streams,
QuicStreamCount max_open_incoming_unidirectional_streams);
+ // Called on |max_open_streams| outgoing streams can be created because of 1)
+ // config negotiated or 2) MAX_STREAMS received. Returns true if new
+ // streams can be created.
+ bool MaybeAllowNewOutgoingBidirectionalStreams(
+ QuicStreamCount max_open_streams);
+ bool MaybeAllowNewOutgoingUnidirectionalStreams(
+ QuicStreamCount max_open_streams);
+
// Sets the limits to max_open_streams.
- void SetMaxOpenOutgoingBidirectionalStreams(size_t max_open_streams);
- void SetMaxOpenOutgoingUnidirectionalStreams(size_t max_open_streams);
- void SetMaxOpenIncomingBidirectionalStreams(size_t max_open_streams);
- void SetMaxOpenIncomingUnidirectionalStreams(size_t max_open_streams);
+ void SetMaxOpenIncomingBidirectionalStreams(QuicStreamCount max_open_streams);
+ void SetMaxOpenIncomingUnidirectionalStreams(
+ QuicStreamCount max_open_streams);
// Returns true if next outgoing bidirectional stream ID can be allocated.
- bool CanOpenNextOutgoingBidirectionalStream();
+ bool CanOpenNextOutgoingBidirectionalStream() const;
// Returns true if next outgoing unidirectional stream ID can be allocated.
- bool CanOpenNextOutgoingUnidirectionalStream();
+ bool CanOpenNextOutgoingUnidirectionalStream() const;
// Returns the next outgoing bidirectional stream id.
QuicStreamId GetNextOutgoingBidirectionalStreamId();
@@ -49,16 +56,15 @@ class QUIC_EXPORT_PRIVATE UberQuicStreamIdManager {
QuicStreamId GetNextOutgoingUnidirectionalStreamId();
// Returns true if the incoming |id| is within the limit.
- bool MaybeIncreaseLargestPeerStreamId(QuicStreamId id);
+ bool MaybeIncreaseLargestPeerStreamId(QuicStreamId id,
+ std::string* error_details);
// Called when |id| is released.
void OnStreamClosed(QuicStreamId id);
- // Called when a MAX_STREAMS frame is received.
- bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame);
-
// Called when a STREAMS_BLOCKED frame is received.
- bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame);
+ bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame,
+ std::string* error_details);
// Return true if |id| is peer initiated.
bool IsIncomingStream(QuicStreamId id) const;
@@ -66,20 +72,17 @@ class QUIC_EXPORT_PRIVATE UberQuicStreamIdManager {
// Returns true if |id| is still available.
bool IsAvailableStream(QuicStreamId id) const;
- size_t GetMaxAllowdIncomingBidirectionalStreams() const;
+ QuicStreamCount GetMaxAllowdIncomingBidirectionalStreams() const;
- size_t GetMaxAllowdIncomingUnidirectionalStreams() const;
-
- void SetLargestPeerCreatedStreamId(
- QuicStreamId largest_peer_created_stream_id);
+ QuicStreamCount GetMaxAllowdIncomingUnidirectionalStreams() const;
QuicStreamId GetLargestPeerCreatedStreamId(bool unidirectional) const;
QuicStreamId next_outgoing_bidirectional_stream_id() const;
QuicStreamId next_outgoing_unidirectional_stream_id() const;
- size_t max_outgoing_bidirectional_streams() const;
- size_t max_outgoing_unidirectional_streams() const;
+ QuicStreamCount max_outgoing_bidirectional_streams() const;
+ QuicStreamCount max_outgoing_unidirectional_streams() const;
QuicStreamCount max_incoming_bidirectional_streams() const;
QuicStreamCount max_incoming_unidirectional_streams() const;
@@ -87,11 +90,6 @@ class QUIC_EXPORT_PRIVATE UberQuicStreamIdManager {
QuicStreamCount advertised_max_incoming_bidirectional_streams() const;
QuicStreamCount advertised_max_incoming_unidirectional_streams() const;
- void OnConfigNegotiated() {
- bidirectional_stream_id_manager_.OnConfigNegotiated();
- unidirectional_stream_id_manager_.OnConfigNegotiated();
- }
-
private:
friend class test::QuicSessionPeer;
friend class test::UberQuicStreamIdManagerPeer;
diff --git a/chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager_test.cc b/chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager_test.cc
index 265756f2b2c..4fc1ccab333 100644
--- a/chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager_test.cc
@@ -5,6 +5,7 @@
#include "net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_stream_id_manager_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
@@ -16,26 +17,47 @@ namespace quic {
namespace test {
namespace {
+struct TestParams {
+ explicit TestParams(ParsedQuicVersion version, Perspective perspective)
+ : version(version), perspective(perspective) {}
+
+ ParsedQuicVersion version;
+ Perspective perspective;
+};
+
+// Used by ::testing::PrintToStringParamName().
+std::string PrintToString(const TestParams& p) {
+ return quiche::QuicheStrCat(
+ ParsedQuicVersionToString(p.version), "_",
+ (p.perspective == Perspective::IS_CLIENT ? "client" : "server"));
+}
+
+std::vector<TestParams> GetTestParams() {
+ std::vector<TestParams> params;
+ for (const ParsedQuicVersion& version : AllSupportedVersions()) {
+ if (!version.HasIetfQuicFrames()) {
+ continue;
+ }
+ params.push_back(TestParams(version, Perspective::IS_CLIENT));
+ params.push_back(TestParams(version, Perspective::IS_SERVER));
+ }
+ return params;
+}
+
class MockDelegate : public QuicStreamIdManager::DelegateInterface {
public:
- MOCK_METHOD1(OnCanCreateNewOutgoingStream, void(bool unidirectional));
- MOCK_METHOD2(OnError,
- void(QuicErrorCode error_code, std::string error_details));
MOCK_METHOD2(SendMaxStreams,
void(QuicStreamCount stream_count, bool unidirectional));
- MOCK_METHOD2(SendStreamsBlocked,
- void(QuicStreamCount stream_count, bool unidirectional));
};
-class UberQuicStreamIdManagerTest : public QuicTestWithParam<Perspective> {
+class UberQuicStreamIdManagerTest : public QuicTestWithParam<TestParams> {
protected:
UberQuicStreamIdManagerTest()
: manager_(perspective(),
version(),
&delegate_,
- /*num_expected_unidirectional_static_streams=*/0,
- kDefaultMaxStreamsPerConnection,
- kDefaultMaxStreamsPerConnection,
+ 0,
+ 0,
kDefaultMaxStreamsPerConnection,
kDefaultMaxStreamsPerConnection) {}
@@ -63,24 +85,23 @@ class UberQuicStreamIdManagerTest : public QuicTestWithParam<Perspective> {
kV99StreamIdIncrement * n;
}
- // TODO(fkastenholz): Existing tests can use these helper functions.
QuicStreamId GetNthPeerInitiatedBidirectionalStreamId(int n) {
- return ((GetParam() == Perspective::IS_SERVER)
+ return ((perspective() == Perspective::IS_SERVER)
? GetNthClientInitiatedBidirectionalId(n)
: GetNthServerInitiatedBidirectionalId(n));
}
QuicStreamId GetNthPeerInitiatedUnidirectionalStreamId(int n) {
- return ((GetParam() == Perspective::IS_SERVER)
+ return ((perspective() == Perspective::IS_SERVER)
? GetNthClientInitiatedUnidirectionalId(n)
: GetNthServerInitiatedUnidirectionalId(n));
}
QuicStreamId GetNthSelfInitiatedBidirectionalStreamId(int n) {
- return ((GetParam() == Perspective::IS_CLIENT)
+ return ((perspective() == Perspective::IS_CLIENT)
? GetNthClientInitiatedBidirectionalId(n)
: GetNthServerInitiatedBidirectionalId(n));
}
QuicStreamId GetNthSelfInitiatedUnidirectionalStreamId(int n) {
- return ((GetParam() == Perspective::IS_CLIENT)
+ return ((perspective() == Perspective::IS_CLIENT)
? GetNthClientInitiatedUnidirectionalId(n)
: GetNthServerInitiatedUnidirectionalId(n));
}
@@ -95,10 +116,12 @@ class UberQuicStreamIdManagerTest : public QuicTestWithParam<Perspective> {
((stream_count - 1) * QuicUtils::StreamIdDelta(transport_version()));
}
- ParsedQuicVersion version() { return {PROTOCOL_TLS1_3, transport_version()}; }
- QuicTransportVersion transport_version() { return QUIC_VERSION_99; }
+ ParsedQuicVersion version() { return GetParam().version; }
+ QuicTransportVersion transport_version() {
+ return version().transport_version;
+ }
- Perspective perspective() { return GetParam(); }
+ Perspective perspective() { return GetParam().perspective; }
testing::StrictMock<MockDelegate> delegate_;
UberQuicStreamIdManager manager_;
@@ -106,32 +129,24 @@ class UberQuicStreamIdManagerTest : public QuicTestWithParam<Perspective> {
INSTANTIATE_TEST_SUITE_P(Tests,
UberQuicStreamIdManagerTest,
- ::testing::ValuesIn({Perspective::IS_CLIENT,
- Perspective::IS_SERVER}),
+ ::testing::ValuesIn(GetTestParams()),
::testing::PrintToStringParamName());
TEST_P(UberQuicStreamIdManagerTest, Initialization) {
- if (perspective() == Perspective::IS_SERVER) {
- EXPECT_EQ(GetNthServerInitiatedBidirectionalId(0),
- manager_.next_outgoing_bidirectional_stream_id());
- EXPECT_EQ(GetNthServerInitiatedUnidirectionalId(0),
- manager_.next_outgoing_unidirectional_stream_id());
- } else {
- EXPECT_EQ(GetNthClientInitiatedBidirectionalId(0),
- manager_.next_outgoing_bidirectional_stream_id());
- EXPECT_EQ(GetNthClientInitiatedUnidirectionalId(0),
- manager_.next_outgoing_unidirectional_stream_id());
- }
+ EXPECT_EQ(GetNthSelfInitiatedBidirectionalStreamId(0),
+ manager_.next_outgoing_bidirectional_stream_id());
+ EXPECT_EQ(GetNthSelfInitiatedUnidirectionalStreamId(0),
+ manager_.next_outgoing_unidirectional_stream_id());
}
TEST_P(UberQuicStreamIdManagerTest, SetMaxOpenOutgoingStreams) {
const size_t kNumMaxOutgoingStream = 123;
// Set the uni- and bi- directional limits to different values to ensure
// that they are managed separately.
- EXPECT_CALL(delegate_, OnCanCreateNewOutgoingStream(false));
- manager_.SetMaxOpenOutgoingBidirectionalStreams(kNumMaxOutgoingStream);
- EXPECT_CALL(delegate_, OnCanCreateNewOutgoingStream(true));
- manager_.SetMaxOpenOutgoingUnidirectionalStreams(kNumMaxOutgoingStream + 1);
+ EXPECT_TRUE(manager_.MaybeAllowNewOutgoingBidirectionalStreams(
+ kNumMaxOutgoingStream));
+ EXPECT_TRUE(manager_.MaybeAllowNewOutgoingUnidirectionalStreams(
+ kNumMaxOutgoingStream + 1));
EXPECT_EQ(kNumMaxOutgoingStream,
manager_.max_outgoing_bidirectional_streams());
EXPECT_EQ(kNumMaxOutgoingStream + 1,
@@ -173,156 +188,98 @@ TEST_P(UberQuicStreamIdManagerTest, SetMaxOpenIncomingStreams) {
size_t i;
for (i = 0; i < kNumMaxIncomingStreams; i++) {
EXPECT_TRUE(manager_.MaybeIncreaseLargestPeerStreamId(
- GetNthPeerInitiatedUnidirectionalStreamId(i)));
+ GetNthPeerInitiatedUnidirectionalStreamId(i), nullptr));
EXPECT_TRUE(manager_.MaybeIncreaseLargestPeerStreamId(
- GetNthPeerInitiatedBidirectionalStreamId(i)));
+ GetNthPeerInitiatedBidirectionalStreamId(i), nullptr));
}
// Should be able to open the next bidirectional stream
EXPECT_TRUE(manager_.MaybeIncreaseLargestPeerStreamId(
- GetNthPeerInitiatedBidirectionalStreamId(i)));
+ GetNthPeerInitiatedBidirectionalStreamId(i), nullptr));
// We should have exhausted the counts, the next streams should fail
- EXPECT_CALL(delegate_, OnError(QUIC_INVALID_STREAM_ID, _));
+ std::string error_details;
EXPECT_FALSE(manager_.MaybeIncreaseLargestPeerStreamId(
- GetNthPeerInitiatedUnidirectionalStreamId(i)));
- EXPECT_CALL(delegate_, OnError(QUIC_INVALID_STREAM_ID, _));
+ GetNthPeerInitiatedUnidirectionalStreamId(i), &error_details));
+ EXPECT_EQ(error_details,
+ quiche::QuicheStrCat(
+ "Stream id ", GetNthPeerInitiatedUnidirectionalStreamId(i),
+ " would exceed stream count limit ", kNumMaxIncomingStreams));
EXPECT_FALSE(manager_.MaybeIncreaseLargestPeerStreamId(
- GetNthPeerInitiatedBidirectionalStreamId(i + 1)));
+ GetNthPeerInitiatedBidirectionalStreamId(i + 1), &error_details));
+ EXPECT_EQ(
+ error_details,
+ quiche::QuicheStrCat(
+ "Stream id ", GetNthPeerInitiatedBidirectionalStreamId(i + 1),
+ " would exceed stream count limit ", kNumMaxIncomingStreams + 1));
}
TEST_P(UberQuicStreamIdManagerTest, GetNextOutgoingStreamId) {
- if (perspective() == Perspective::IS_SERVER) {
- EXPECT_EQ(GetNthServerInitiatedBidirectionalId(0),
- manager_.GetNextOutgoingBidirectionalStreamId());
- EXPECT_EQ(GetNthServerInitiatedBidirectionalId(1),
- manager_.GetNextOutgoingBidirectionalStreamId());
- EXPECT_EQ(GetNthServerInitiatedUnidirectionalId(0),
- manager_.GetNextOutgoingUnidirectionalStreamId());
- EXPECT_EQ(GetNthServerInitiatedUnidirectionalId(1),
- manager_.GetNextOutgoingUnidirectionalStreamId());
- } else {
- EXPECT_EQ(GetNthClientInitiatedBidirectionalId(0),
- manager_.GetNextOutgoingBidirectionalStreamId());
- EXPECT_EQ(GetNthClientInitiatedBidirectionalId(1),
- manager_.GetNextOutgoingBidirectionalStreamId());
- EXPECT_EQ(GetNthClientInitiatedUnidirectionalId(0),
- manager_.GetNextOutgoingUnidirectionalStreamId());
- EXPECT_EQ(GetNthClientInitiatedUnidirectionalId(1),
- manager_.GetNextOutgoingUnidirectionalStreamId());
- }
+ EXPECT_TRUE(manager_.MaybeAllowNewOutgoingBidirectionalStreams(10));
+ EXPECT_TRUE(manager_.MaybeAllowNewOutgoingUnidirectionalStreams(10));
+ EXPECT_EQ(GetNthSelfInitiatedBidirectionalStreamId(0),
+ manager_.GetNextOutgoingBidirectionalStreamId());
+ EXPECT_EQ(GetNthSelfInitiatedBidirectionalStreamId(1),
+ manager_.GetNextOutgoingBidirectionalStreamId());
+ EXPECT_EQ(GetNthSelfInitiatedUnidirectionalStreamId(0),
+ manager_.GetNextOutgoingUnidirectionalStreamId());
+ EXPECT_EQ(GetNthSelfInitiatedUnidirectionalStreamId(1),
+ manager_.GetNextOutgoingUnidirectionalStreamId());
}
TEST_P(UberQuicStreamIdManagerTest, AvailableStreams) {
- if (perspective() == Perspective::IS_SERVER) {
- EXPECT_TRUE(manager_.MaybeIncreaseLargestPeerStreamId(
- GetNthClientInitiatedBidirectionalId(3)));
- EXPECT_TRUE(
- manager_.IsAvailableStream(GetNthClientInitiatedBidirectionalId(1)));
- EXPECT_TRUE(
- manager_.IsAvailableStream(GetNthClientInitiatedBidirectionalId(2)));
-
- EXPECT_TRUE(manager_.MaybeIncreaseLargestPeerStreamId(
- GetNthClientInitiatedUnidirectionalId(3)));
- EXPECT_TRUE(
- manager_.IsAvailableStream(GetNthClientInitiatedUnidirectionalId(1)));
- EXPECT_TRUE(
- manager_.IsAvailableStream(GetNthClientInitiatedUnidirectionalId(2)));
- } else {
- EXPECT_TRUE(manager_.MaybeIncreaseLargestPeerStreamId(
- GetNthServerInitiatedBidirectionalId(3)));
- EXPECT_TRUE(
- manager_.IsAvailableStream(GetNthServerInitiatedBidirectionalId(1)));
- EXPECT_TRUE(
- manager_.IsAvailableStream(GetNthServerInitiatedBidirectionalId(2)));
+ EXPECT_TRUE(manager_.MaybeIncreaseLargestPeerStreamId(
+ GetNthPeerInitiatedBidirectionalStreamId(3), nullptr));
+ EXPECT_TRUE(
+ manager_.IsAvailableStream(GetNthPeerInitiatedBidirectionalStreamId(1)));
+ EXPECT_TRUE(
+ manager_.IsAvailableStream(GetNthPeerInitiatedBidirectionalStreamId(2)));
- EXPECT_TRUE(manager_.MaybeIncreaseLargestPeerStreamId(
- GetNthServerInitiatedUnidirectionalId(3)));
- EXPECT_TRUE(
- manager_.IsAvailableStream(GetNthServerInitiatedUnidirectionalId(1)));
- EXPECT_TRUE(
- manager_.IsAvailableStream(GetNthServerInitiatedUnidirectionalId(2)));
- }
+ EXPECT_TRUE(manager_.MaybeIncreaseLargestPeerStreamId(
+ GetNthPeerInitiatedUnidirectionalStreamId(3), nullptr));
+ EXPECT_TRUE(
+ manager_.IsAvailableStream(GetNthPeerInitiatedUnidirectionalStreamId(1)));
+ EXPECT_TRUE(
+ manager_.IsAvailableStream(GetNthPeerInitiatedUnidirectionalStreamId(2)));
}
TEST_P(UberQuicStreamIdManagerTest, MaybeIncreaseLargestPeerStreamId) {
- EXPECT_CALL(delegate_, OnError(_, _)).Times(0);
- EXPECT_TRUE(manager_.MaybeIncreaseLargestPeerStreamId(StreamCountToId(
- manager_.max_incoming_bidirectional_streams(),
- QuicUtils::InvertPerspective(perspective()), /* bidirectional=*/true)));
- EXPECT_TRUE(manager_.MaybeIncreaseLargestPeerStreamId(StreamCountToId(
- manager_.max_incoming_bidirectional_streams(),
- QuicUtils::InvertPerspective(perspective()), /* bidirectional=*/false)));
-
- std::string error_details =
+ EXPECT_TRUE(manager_.MaybeIncreaseLargestPeerStreamId(
+ StreamCountToId(manager_.max_incoming_bidirectional_streams(),
+ QuicUtils::InvertPerspective(perspective()),
+ /* bidirectional=*/true),
+ nullptr));
+ EXPECT_TRUE(manager_.MaybeIncreaseLargestPeerStreamId(
+ StreamCountToId(manager_.max_incoming_bidirectional_streams(),
+ QuicUtils::InvertPerspective(perspective()),
+ /* bidirectional=*/false),
+ nullptr));
+
+ std::string expected_error_details =
perspective() == Perspective::IS_SERVER
? "Stream id 400 would exceed stream count limit 100"
: "Stream id 401 would exceed stream count limit 100";
+ std::string error_details;
- EXPECT_CALL(delegate_, OnError(QUIC_INVALID_STREAM_ID, error_details));
- EXPECT_FALSE(manager_.MaybeIncreaseLargestPeerStreamId(StreamCountToId(
- manager_.max_incoming_bidirectional_streams() + 1,
- QuicUtils::InvertPerspective(perspective()), /* bidirectional=*/true)));
- error_details = perspective() == Perspective::IS_SERVER
- ? "Stream id 402 would exceed stream count limit 100"
- : "Stream id 403 would exceed stream count limit 100";
- EXPECT_CALL(delegate_, OnError(QUIC_INVALID_STREAM_ID, error_details));
- EXPECT_FALSE(manager_.MaybeIncreaseLargestPeerStreamId(StreamCountToId(
- manager_.max_incoming_bidirectional_streams() + 1,
- QuicUtils::InvertPerspective(perspective()), /* bidirectional=*/false)));
-}
-
-TEST_P(UberQuicStreamIdManagerTest, OnMaxStreamsFrame) {
- QuicStreamCount max_outgoing_bidirectional_stream_count =
- manager_.max_outgoing_bidirectional_streams();
-
- QuicStreamCount max_outgoing_unidirectional_stream_count =
- manager_.max_outgoing_unidirectional_streams();
-
- // Inject a MAX_STREAMS frame that does not increase the limit and then
- // check that there are no changes. First try the bidirectional manager.
- QuicMaxStreamsFrame frame(kInvalidControlFrameId,
- max_outgoing_bidirectional_stream_count,
- /*unidirectional=*/false);
- EXPECT_CALL(delegate_, OnCanCreateNewOutgoingStream(frame.unidirectional));
- EXPECT_TRUE(manager_.OnMaxStreamsFrame(frame));
- EXPECT_EQ(max_outgoing_bidirectional_stream_count,
- manager_.max_outgoing_bidirectional_streams());
-
- // Now try the unidirectioanl manager
- frame.stream_count = max_outgoing_unidirectional_stream_count;
- frame.unidirectional = true;
- EXPECT_CALL(delegate_, OnCanCreateNewOutgoingStream(frame.unidirectional));
- EXPECT_TRUE(manager_.OnMaxStreamsFrame(frame));
- EXPECT_EQ(max_outgoing_unidirectional_stream_count,
- manager_.max_outgoing_unidirectional_streams());
-
- // Now try to increase the bidirectional stream count.
- frame.stream_count = max_outgoing_bidirectional_stream_count + 1;
- frame.unidirectional = false;
- EXPECT_CALL(delegate_, OnCanCreateNewOutgoingStream(frame.unidirectional));
- EXPECT_TRUE(manager_.OnMaxStreamsFrame(frame));
- EXPECT_EQ(max_outgoing_bidirectional_stream_count + 1,
- manager_.max_outgoing_bidirectional_streams());
- // Make sure that the unidirectional state does not change.
- EXPECT_EQ(max_outgoing_unidirectional_stream_count,
- manager_.max_outgoing_unidirectional_streams());
+ EXPECT_FALSE(manager_.MaybeIncreaseLargestPeerStreamId(
+ StreamCountToId(manager_.max_incoming_bidirectional_streams() + 1,
+ QuicUtils::InvertPerspective(perspective()),
+ /* bidirectional=*/true),
+ &error_details));
+ EXPECT_EQ(expected_error_details, error_details);
+ expected_error_details =
+ perspective() == Perspective::IS_SERVER
+ ? "Stream id 402 would exceed stream count limit 100"
+ : "Stream id 403 would exceed stream count limit 100";
- // Now check that a MAX_STREAMS for the unidirectional manager increases
- // just the unidirectiomal manager's state.
- frame.stream_count = max_outgoing_unidirectional_stream_count + 1;
- frame.unidirectional = true;
- EXPECT_CALL(delegate_, OnCanCreateNewOutgoingStream(frame.unidirectional));
- EXPECT_TRUE(manager_.OnMaxStreamsFrame(frame));
- EXPECT_EQ(max_outgoing_bidirectional_stream_count + 1,
- manager_.max_outgoing_bidirectional_streams());
- EXPECT_EQ(max_outgoing_unidirectional_stream_count + 1,
- manager_.max_outgoing_unidirectional_streams());
+ EXPECT_FALSE(manager_.MaybeIncreaseLargestPeerStreamId(
+ StreamCountToId(manager_.max_incoming_bidirectional_streams() + 1,
+ QuicUtils::InvertPerspective(perspective()),
+ /* bidirectional=*/false),
+ &error_details));
+ EXPECT_EQ(expected_error_details, error_details);
}
TEST_P(UberQuicStreamIdManagerTest, OnStreamsBlockedFrame) {
- // Allow MAX_STREAMS frame transmission
- manager_.OnConfigNegotiated();
-
QuicStreamCount stream_count =
manager_.advertised_max_incoming_bidirectional_streams() - 1;
@@ -331,7 +288,7 @@ TEST_P(UberQuicStreamIdManagerTest, OnStreamsBlockedFrame) {
EXPECT_CALL(delegate_,
SendMaxStreams(manager_.max_incoming_bidirectional_streams(),
frame.unidirectional));
- manager_.OnStreamsBlockedFrame(frame);
+ EXPECT_TRUE(manager_.OnStreamsBlockedFrame(frame, nullptr));
stream_count = manager_.advertised_max_incoming_unidirectional_streams() - 1;
frame.stream_count = stream_count;
@@ -340,39 +297,28 @@ TEST_P(UberQuicStreamIdManagerTest, OnStreamsBlockedFrame) {
EXPECT_CALL(delegate_,
SendMaxStreams(manager_.max_incoming_unidirectional_streams(),
frame.unidirectional));
- manager_.OnStreamsBlockedFrame(frame);
+ EXPECT_TRUE(manager_.OnStreamsBlockedFrame(frame, nullptr));
}
TEST_P(UberQuicStreamIdManagerTest, IsIncomingStream) {
- if (perspective() == Perspective::IS_SERVER) {
- EXPECT_TRUE(
- manager_.IsIncomingStream(GetNthClientInitiatedBidirectionalId(0)));
- EXPECT_TRUE(
- manager_.IsIncomingStream(GetNthClientInitiatedUnidirectionalId(0)));
- EXPECT_FALSE(
- manager_.IsIncomingStream(GetNthServerInitiatedBidirectionalId(0)));
- EXPECT_FALSE(
- manager_.IsIncomingStream(GetNthServerInitiatedUnidirectionalId(0)));
- } else {
- EXPECT_FALSE(
- manager_.IsIncomingStream(GetNthClientInitiatedBidirectionalId(0)));
- EXPECT_FALSE(
- manager_.IsIncomingStream(GetNthClientInitiatedUnidirectionalId(0)));
- EXPECT_TRUE(
- manager_.IsIncomingStream(GetNthServerInitiatedBidirectionalId(0)));
- EXPECT_TRUE(
- manager_.IsIncomingStream(GetNthServerInitiatedUnidirectionalId(0)));
- }
+ EXPECT_TRUE(
+ manager_.IsIncomingStream(GetNthPeerInitiatedBidirectionalStreamId(0)));
+ EXPECT_TRUE(
+ manager_.IsIncomingStream(GetNthPeerInitiatedUnidirectionalStreamId(0)));
+ EXPECT_FALSE(
+ manager_.IsIncomingStream(GetNthSelfInitiatedBidirectionalStreamId(0)));
+ EXPECT_FALSE(
+ manager_.IsIncomingStream(GetNthSelfInitiatedUnidirectionalStreamId(0)));
}
TEST_P(UberQuicStreamIdManagerTest, SetMaxOpenOutgoingStreamsPlusFrame) {
const size_t kNumMaxOutgoingStream = 123;
// Set the uni- and bi- directional limits to different values to ensure
// that they are managed separately.
- EXPECT_CALL(delegate_, OnCanCreateNewOutgoingStream(false));
- manager_.SetMaxOpenOutgoingBidirectionalStreams(kNumMaxOutgoingStream);
- EXPECT_CALL(delegate_, OnCanCreateNewOutgoingStream(true));
- manager_.SetMaxOpenOutgoingUnidirectionalStreams(kNumMaxOutgoingStream + 1);
+ EXPECT_TRUE(manager_.MaybeAllowNewOutgoingBidirectionalStreams(
+ kNumMaxOutgoingStream));
+ EXPECT_TRUE(manager_.MaybeAllowNewOutgoingUnidirectionalStreams(
+ kNumMaxOutgoingStream + 1));
EXPECT_EQ(kNumMaxOutgoingStream,
manager_.max_outgoing_bidirectional_streams());
EXPECT_EQ(kNumMaxOutgoingStream + 1,
@@ -394,16 +340,6 @@ TEST_P(UberQuicStreamIdManagerTest, SetMaxOpenOutgoingStreamsPlusFrame) {
// Both should be exhausted...
EXPECT_FALSE(manager_.CanOpenNextOutgoingUnidirectionalStream());
EXPECT_FALSE(manager_.CanOpenNextOutgoingBidirectionalStream());
-
- // Now cons a MAX STREAMS frame for unidirectional streams to raise
- // the limit.
- QuicMaxStreamsFrame frame(1, kNumMaxOutgoingStream + 10,
- /*unidirectional=*/true);
- EXPECT_CALL(delegate_, OnCanCreateNewOutgoingStream(frame.unidirectional));
- manager_.OnMaxStreamsFrame(frame);
- // We now should be able to get another uni- stream, but not a bi.
- EXPECT_TRUE(manager_.CanOpenNextOutgoingUnidirectionalStream());
- EXPECT_FALSE(manager_.CanOpenNextOutgoingBidirectionalStream());
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager.cc b/chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager.cc
index 78cf35919d1..723ac303eb7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager.cc
@@ -115,9 +115,9 @@ void UberReceivedPacketManager::EnableMultiplePacketNumberSpacesSupport() {
// In IETF QUIC, the peer is expected to acknowledge packets in Initial and
// Handshake packets with minimal delay.
received_packet_managers_[INITIAL_DATA].set_local_max_ack_delay(
- QuicTime::Delta::FromMilliseconds(1));
+ kAlarmGranularity);
received_packet_managers_[HANDSHAKE_DATA].set_local_max_ack_delay(
- QuicTime::Delta::FromMilliseconds(1));
+ kAlarmGranularity);
supports_multiple_packet_number_spaces_ = true;
}
@@ -168,6 +168,14 @@ QuicTime UberReceivedPacketManager::GetEarliestAckTimeout() const {
return ack_timeout;
}
+bool UberReceivedPacketManager::IsAckFrameEmpty(
+ PacketNumberSpace packet_number_space) const {
+ if (!supports_multiple_packet_number_spaces_) {
+ return received_packet_managers_[0].IsAckFrameEmpty();
+ }
+ return received_packet_managers_[packet_number_space].IsAckFrameEmpty();
+}
+
QuicPacketNumber UberReceivedPacketManager::peer_least_packet_awaiting_ack()
const {
DCHECK(!supports_multiple_packet_number_spaces_);
diff --git a/chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager.h b/chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager.h
index 14ba8684f5a..d76ce134ed9 100644
--- a/chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager.h
+++ b/chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager.h
@@ -70,6 +70,9 @@ class QUIC_EXPORT_PRIVATE UberReceivedPacketManager {
// Get the earliest ack_timeout of all packet number spaces.
QuicTime GetEarliestAckTimeout() const;
+ // Return true if ack frame of |packet_number_space| is empty.
+ bool IsAckFrameEmpty(PacketNumberSpace packet_number_space) const;
+
QuicPacketNumber peer_least_packet_awaiting_ack() const;
size_t min_received_before_ack_decimation() const;
diff --git a/chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager_test.cc b/chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager_test.cc
index b1e714074d7..a2fb64014e8 100644
--- a/chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager_test.cc
@@ -134,7 +134,9 @@ class UberReceivedPacketManagerTest : public QuicTest {
};
TEST_F(UberReceivedPacketManagerTest, DontWaitForPacketsBefore) {
+ EXPECT_TRUE(manager_->IsAckFrameEmpty(APPLICATION_DATA));
RecordPacketReceipt(2);
+ EXPECT_FALSE(manager_->IsAckFrameEmpty(APPLICATION_DATA));
RecordPacketReceipt(7);
EXPECT_TRUE(manager_->IsAwaitingPacket(ENCRYPTION_FORWARD_SECURE,
QuicPacketNumber(3u)));
diff --git a/chromium/net/third_party/quiche/src/quic/masque/README.md b/chromium/net/third_party/quiche/src/quic/masque/README.md
new file mode 100644
index 00000000000..6bfc08ee0f8
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/masque/README.md
@@ -0,0 +1,4 @@
+# MASQUE
+
+The files in this directory implement MASQUE as described in
+<https://tools.ietf.org/html/draft-schinazi-masque>.
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_client_bin.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_client_bin.cc
new file mode 100644
index 00000000000..8bdeef5dc35
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_client_bin.cc
@@ -0,0 +1,93 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is reponsible for the masque_client binary. It allows testing
+// our MASQUE client code by connecting to a MASQUE proxy and then sending
+// HTTP/3 requests to web servers tunnelled over that MASQUE connection.
+// e.g.: masque_client $PROXY_HOST:$PROXY_PORT $URL1 $URL2
+
+#include <memory>
+
+#include "net/third_party/quiche/src/quic/core/quic_server_id.h"
+#include "net/third_party/quiche/src/quic/masque/masque_client_tools.h"
+#include "net/third_party/quiche/src/quic/masque/masque_encapsulated_epoll_client.h"
+#include "net/third_party/quiche/src/quic/masque/masque_epoll_client.h"
+#include "net/third_party/quiche/src/quic/masque/masque_utils.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_default_proof_providers.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_system_event_loop.h"
+#include "net/third_party/quiche/src/quic/tools/fake_proof_verifier.h"
+#include "net/third_party/quiche/src/quic/tools/quic_url.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(bool,
+ disable_certificate_verification,
+ false,
+ "If true, don't verify the server certificate.");
+
+namespace quic {
+
+namespace {
+
+int RunMasqueClient(int argc, char* argv[]) {
+ QuicSystemEventLoop event_loop("masque_client");
+ const char* usage = "Usage: masque_client [options] <url>";
+
+ // The first non-flag argument is the MASQUE server. All subsequent ones are
+ // interpreted as URLs to fetch via the MASQUE server.
+ std::vector<std::string> urls = QuicParseCommandLineFlags(usage, argc, argv);
+ if (urls.empty()) {
+ QuicPrintCommandLineFlagHelp(usage);
+ return 1;
+ }
+
+ const bool disable_certificate_verification =
+ GetQuicFlag(FLAGS_disable_certificate_verification);
+ QuicEpollServer epoll_server;
+
+ QuicUrl masque_url(urls[0], "https");
+ if (masque_url.host().empty()) {
+ masque_url = QuicUrl(quiche::QuicheStrCat("https://", urls[0]), "https");
+ }
+ if (masque_url.host().empty()) {
+ QUIC_LOG(ERROR) << "Failed to parse MASQUE server address " << urls[0];
+ return 1;
+ }
+ std::unique_ptr<ProofVerifier> proof_verifier;
+ if (disable_certificate_verification) {
+ proof_verifier = std::make_unique<FakeProofVerifier>();
+ } else {
+ proof_verifier = CreateDefaultProofVerifier(masque_url.host());
+ }
+ std::unique_ptr<MasqueEpollClient> masque_client =
+ MasqueEpollClient::Create(masque_url.host(), masque_url.port(),
+ &epoll_server, std::move(proof_verifier));
+ if (masque_client == nullptr) {
+ return 1;
+ }
+
+ std::cerr << "MASQUE is connected " << masque_client->connection_id()
+ << std::endl;
+
+ for (size_t i = 1; i < urls.size(); ++i) {
+ if (!tools::SendEncapsulatedMasqueRequest(
+ masque_client.get(), &epoll_server, urls[i],
+ disable_certificate_verification)) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+} // namespace
+
+} // namespace quic
+
+int main(int argc, char* argv[]) {
+ return quic::RunMasqueClient(argc, argv);
+}
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_client_session.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_client_session.cc
new file mode 100644
index 00000000000..3db36f3769a
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_client_session.cc
@@ -0,0 +1,96 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/masque/masque_client_session.h"
+
+namespace quic {
+
+MasqueClientSession::MasqueClientSession(
+ const QuicConfig& config,
+ const ParsedQuicVersionVector& supported_versions,
+ QuicConnection* connection,
+ const QuicServerId& server_id,
+ QuicCryptoClientConfig* crypto_config,
+ QuicClientPushPromiseIndex* push_promise_index,
+ Owner* owner)
+ : QuicSpdyClientSession(config,
+ supported_versions,
+ connection,
+ server_id,
+ crypto_config,
+ push_promise_index),
+ owner_(owner),
+ compression_engine_(this) {}
+
+void MasqueClientSession::OnMessageReceived(quiche::QuicheStringPiece message) {
+ QUIC_DVLOG(1) << "Received DATAGRAM frame of length " << message.length();
+
+ QuicConnectionId client_connection_id, server_connection_id;
+ QuicSocketAddress server_address;
+ std::vector<char> packet;
+ bool version_present;
+ if (!compression_engine_.DecompressDatagram(
+ message, &client_connection_id, &server_connection_id,
+ &server_address, &packet, &version_present)) {
+ return;
+ }
+
+ auto connection_id_registration =
+ client_connection_id_registrations_.find(client_connection_id);
+ if (connection_id_registration == client_connection_id_registrations_.end()) {
+ QUIC_DLOG(ERROR) << "MasqueClientSession failed to dispatch "
+ << client_connection_id;
+ return;
+ }
+ EncapsulatedClientSession* encapsulated_client_session =
+ connection_id_registration->second;
+ encapsulated_client_session->ProcessPacket(
+ quiche::QuicheStringPiece(packet.data(), packet.size()), server_address);
+
+ QUIC_DVLOG(1) << "Sent " << packet.size() << " bytes to connection for "
+ << client_connection_id;
+}
+
+void MasqueClientSession::OnMessageAcked(QuicMessageId message_id,
+ QuicTime /*receive_timestamp*/) {
+ QUIC_DVLOG(1) << "Received ack for DATAGRAM frame " << message_id;
+}
+
+void MasqueClientSession::OnMessageLost(QuicMessageId message_id) {
+ QUIC_DVLOG(1) << "We believe DATAGRAM frame " << message_id << " was lost";
+}
+
+void MasqueClientSession::SendPacket(QuicConnectionId client_connection_id,
+ QuicConnectionId server_connection_id,
+ quiche::QuicheStringPiece packet,
+ const QuicSocketAddress& server_address) {
+ compression_engine_.CompressAndSendPacket(
+ packet, client_connection_id, server_connection_id, server_address);
+}
+
+void MasqueClientSession::RegisterConnectionId(
+ QuicConnectionId client_connection_id,
+ EncapsulatedClientSession* encapsulated_client_session) {
+ QUIC_DLOG(INFO) << "Registering " << client_connection_id
+ << " to encapsulated client";
+ DCHECK(client_connection_id_registrations_.find(client_connection_id) ==
+ client_connection_id_registrations_.end() ||
+ client_connection_id_registrations_[client_connection_id] ==
+ encapsulated_client_session);
+ client_connection_id_registrations_[client_connection_id] =
+ encapsulated_client_session;
+}
+
+void MasqueClientSession::UnregisterConnectionId(
+ QuicConnectionId client_connection_id) {
+ QUIC_DLOG(INFO) << "Unregistering " << client_connection_id;
+ if (client_connection_id_registrations_.find(client_connection_id) !=
+ client_connection_id_registrations_.end()) {
+ client_connection_id_registrations_.erase(client_connection_id);
+ owner_->UnregisterClientConnectionId(client_connection_id);
+ compression_engine_.UnregisterClientConnectionId(client_connection_id);
+ }
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_client_session.h b/chromium/net/third_party/quiche/src/quic/masque/masque_client_session.h
new file mode 100644
index 00000000000..acf21118c59
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_client_session.h
@@ -0,0 +1,99 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_MASQUE_MASQUE_CLIENT_SESSION_H_
+#define QUICHE_QUIC_MASQUE_MASQUE_CLIENT_SESSION_H_
+
+#include "net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.h"
+#include "net/third_party/quiche/src/quic/masque/masque_compression_engine.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+
+namespace quic {
+
+// QUIC client session for connection to MASQUE proxy. This session establishes
+// a connection to a MASQUE proxy and handles sending and receiving DATAGRAM
+// frames for operation of the MASQUE protocol. Multiple end-to-end encapsulated
+// sessions can then coexist inside this session. Once these are created, they
+// need to be registered with this session.
+class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession {
+ public:
+ // Interface meant to be implemented by the owner of the
+ // MasqueClientSession instance.
+ class QUIC_NO_EXPORT Owner {
+ public:
+ virtual ~Owner() {}
+
+ // Notifies the owner that the client connection ID is no longer in use.
+ virtual void UnregisterClientConnectionId(
+ QuicConnectionId client_connection_id) = 0;
+ };
+ // Interface meant to be implemented by encapsulated client sessions, i.e.
+ // the end-to-end QUIC client sessions that run inside MASQUE encapsulation.
+ class QUIC_NO_EXPORT EncapsulatedClientSession {
+ public:
+ virtual ~EncapsulatedClientSession() {}
+
+ // Process packet that was just decapsulated.
+ virtual void ProcessPacket(quiche::QuicheStringPiece packet,
+ QuicSocketAddress server_address) = 0;
+ };
+
+ // Takes ownership of |connection|, but not of |crypto_config| or
+ // |push_promise_index| or |owner|. All pointers must be non-null. Caller
+ // must ensure that |push_promise_index| and |owner| stay valid for the
+ // lifetime of the newly created MasqueClientSession.
+ MasqueClientSession(const QuicConfig& config,
+ const ParsedQuicVersionVector& supported_versions,
+ QuicConnection* connection,
+ const QuicServerId& server_id,
+ QuicCryptoClientConfig* crypto_config,
+ QuicClientPushPromiseIndex* push_promise_index,
+ Owner* owner);
+
+ // Disallow copy and assign.
+ MasqueClientSession(const MasqueClientSession&) = delete;
+ MasqueClientSession& operator=(const MasqueClientSession&) = delete;
+
+ // From QuicSession.
+ void OnMessageReceived(quiche::QuicheStringPiece message) override;
+
+ void OnMessageAcked(QuicMessageId message_id,
+ QuicTime receive_timestamp) override;
+
+ void OnMessageLost(QuicMessageId message_id) override;
+
+ // Send encapsulated packet.
+ void SendPacket(QuicConnectionId client_connection_id,
+ QuicConnectionId server_connection_id,
+ quiche::QuicheStringPiece packet,
+ const QuicSocketAddress& server_address);
+
+ // Register encapsulated client. This allows clients that are encapsulated
+ // within this MASQUE session to indicate they own a given client connection
+ // ID so incoming packets with that connection ID are routed back to them.
+ // Callers must not register a second different |encapsulated_client_session|
+ // with the same |client_connection_id|. Every call must be matched with a
+ // call to UnregisterConnectionId.
+ void RegisterConnectionId(
+ QuicConnectionId client_connection_id,
+ EncapsulatedClientSession* encapsulated_client_session);
+
+ // Unregister encapsulated client. |client_connection_id| must match a
+ // value previously passed to RegisterConnectionId.
+ void UnregisterConnectionId(QuicConnectionId client_connection_id);
+
+ private:
+ QuicUnorderedMap<QuicConnectionId,
+ EncapsulatedClientSession*,
+ QuicConnectionIdHash>
+ client_connection_id_registrations_;
+ Owner* owner_; // Unowned;
+ MasqueCompressionEngine compression_engine_;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_MASQUE_MASQUE_CLIENT_SESSION_H_
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_client_tools.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_client_tools.cc
new file mode 100644
index 00000000000..7b96abe9758
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_client_tools.cc
@@ -0,0 +1,107 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/masque/masque_client_tools.h"
+#include "net/third_party/quiche/src/quic/masque/masque_encapsulated_epoll_client.h"
+#include "net/third_party/quiche/src/quic/masque/masque_utils.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_default_proof_providers.h"
+#include "net/third_party/quiche/src/quic/tools/fake_proof_verifier.h"
+#include "net/third_party/quiche/src/quic/tools/quic_url.h"
+
+namespace quic {
+namespace tools {
+
+bool SendEncapsulatedMasqueRequest(MasqueEpollClient* masque_client,
+ QuicEpollServer* epoll_server,
+ std::string url_string,
+ bool disable_certificate_verification) {
+ const QuicUrl url(url_string, "https");
+ std::unique_ptr<ProofVerifier> proof_verifier;
+ if (disable_certificate_verification) {
+ proof_verifier = std::make_unique<FakeProofVerifier>();
+ } else {
+ proof_verifier = CreateDefaultProofVerifier(url.host());
+ }
+
+ // Build the client, and try to connect.
+ const QuicSocketAddress addr =
+ LookupAddress(url.host(), quiche::QuicheStrCat(url.port()));
+ if (!addr.IsInitialized()) {
+ QUIC_LOG(ERROR) << "Unable to resolve address: " << url.host();
+ return false;
+ }
+ const QuicServerId server_id(url.host(), url.port());
+ auto client = std::make_unique<MasqueEncapsulatedEpollClient>(
+ addr, server_id, epoll_server, std::move(proof_verifier), masque_client);
+
+ if (client == nullptr) {
+ QUIC_LOG(ERROR) << "Failed to create MasqueEncapsulatedEpollClient for "
+ << url_string;
+ return false;
+ }
+
+ client->set_initial_max_packet_length(kMasqueMaxEncapsulatedPacketSize);
+ client->set_drop_response_body(false);
+ if (!client->Initialize()) {
+ QUIC_LOG(ERROR) << "Failed to initialize MasqueEncapsulatedEpollClient for "
+ << url_string;
+ return false;
+ }
+
+ if (!client->Connect()) {
+ QuicErrorCode error = client->session()->error();
+ QUIC_LOG(ERROR) << "Failed to connect with client "
+ << client->session()->connection()->client_connection_id()
+ << " server " << client->session()->connection_id()
+ << " to " << url.HostPort()
+ << ". Error: " << QuicErrorCodeToString(error);
+ return false;
+ }
+
+ QUIC_LOG(INFO) << "Connected client "
+ << client->session()->connection()->client_connection_id()
+ << " server " << client->session()->connection_id() << " for "
+ << url_string;
+
+ // Construct the string body from flags, if provided.
+ // TODO(dschinazi) Add support for HTTP POST and non-empty bodies.
+ const std::string body = "";
+
+ // Construct a GET or POST request for supplied URL.
+ spdy::SpdyHeaderBlock header_block;
+ header_block[":method"] = "GET";
+ header_block[":scheme"] = url.scheme();
+ header_block[":authority"] = url.HostPort();
+ header_block[":path"] = url.PathParamsQuery();
+
+ // Make sure to store the response, for later output.
+ client->set_store_response(true);
+
+ // Send the MASQUE init request.
+ client->SendRequestAndWaitForResponse(header_block, body,
+ /*fin=*/true);
+
+ if (!client->connected()) {
+ QUIC_LOG(ERROR) << "Request for " << url_string
+ << " caused connection failure. Error: "
+ << QuicErrorCodeToString(client->session()->error());
+ return false;
+ }
+
+ const int response_code = client->latest_response_code();
+ if (response_code < 200 || response_code >= 300) {
+ QUIC_LOG(ERROR) << "Request for " << url_string
+ << " failed with HTTP response code " << response_code;
+ return false;
+ }
+
+ const std::string response_body = client->latest_response_body();
+ QUIC_LOG(INFO) << "Request succeeded for " << url_string << std::endl
+ << response_body;
+
+ return true;
+}
+
+} // namespace tools
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_client_tools.h b/chromium/net/third_party/quiche/src/quic/masque/masque_client_tools.h
new file mode 100644
index 00000000000..4ddc2d70846
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_client_tools.h
@@ -0,0 +1,25 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_MASQUE_MASQUE_CLIENT_TOOLS_H_
+#define QUICHE_QUIC_MASQUE_MASQUE_CLIENT_TOOLS_H_
+
+#include "net/third_party/quiche/src/quic/masque/masque_epoll_client.h"
+
+namespace quic {
+namespace tools {
+
+// Sends an HTTP GET request for |url_string|, proxied over the MASQUE
+// connection represented by |masque_client|. A valid and owned |epoll_server|
+// is required. |disable_certificate_verification| allows disabling verification
+// of the HTTP server's TLS certificate.
+bool SendEncapsulatedMasqueRequest(MasqueEpollClient* masque_client,
+ QuicEpollServer* epoll_server,
+ std::string url_string,
+ bool disable_certificate_verification);
+
+} // namespace tools
+} // namespace quic
+
+#endif // QUICHE_QUIC_MASQUE_MASQUE_CLIENT_TOOLS_H_
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_compression_engine.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_compression_engine.cc
new file mode 100644
index 00000000000..dbc4580c892
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_compression_engine.cc
@@ -0,0 +1,543 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/masque/masque_compression_engine.h"
+
+#include <cstdint>
+
+#include "net/third_party/quiche/src/quic/core/quic_buffer_allocator.h"
+#include "net/third_party/quiche/src/quic/core/quic_data_reader.h"
+#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
+#include "net/third_party/quiche/src/quic/core/quic_framer.h"
+#include "net/third_party/quiche/src/quic/core/quic_session.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
+
+namespace quic {
+
+namespace {
+// |kFlowId0| is used to indicate creation of a new compression context.
+const QuicDatagramFlowId kFlowId0 = 0;
+
+enum MasqueAddressFamily : uint8_t {
+ MasqueAddressFamilyIPv4 = 4,
+ MasqueAddressFamilyIPv6 = 6,
+};
+
+} // namespace
+
+MasqueCompressionEngine::MasqueCompressionEngine(QuicSession* masque_session)
+ : masque_session_(masque_session) {
+ if (masque_session_->perspective() == Perspective::IS_SERVER) {
+ next_flow_id_ = 1;
+ } else {
+ next_flow_id_ = 2;
+ }
+}
+
+QuicDatagramFlowId MasqueCompressionEngine::FindOrCreateCompressionContext(
+ QuicConnectionId client_connection_id,
+ QuicConnectionId server_connection_id,
+ const QuicSocketAddress& server_address,
+ bool client_connection_id_present,
+ bool server_connection_id_present,
+ bool* validated) {
+ QuicDatagramFlowId flow_id = kFlowId0;
+ *validated = false;
+ for (const auto& kv : contexts_) {
+ const MasqueCompressionContext& context = kv.second;
+ if (context.server_address != server_address) {
+ continue;
+ }
+ if (client_connection_id_present &&
+ context.client_connection_id != client_connection_id) {
+ continue;
+ }
+ if (server_connection_id_present &&
+ context.server_connection_id != server_connection_id) {
+ continue;
+ }
+
+ flow_id = kv.first;
+ DCHECK_NE(flow_id, kFlowId0);
+ *validated = context.validated;
+ QUIC_DVLOG(1) << "Compressing using " << (*validated ? "" : "un")
+ << "validated flow_id " << flow_id << " to "
+ << context.server_address << " client "
+ << context.client_connection_id << " server "
+ << context.server_connection_id;
+ break;
+ }
+
+ if (flow_id != kFlowId0) {
+ // Found a compression context, use it.
+ return flow_id;
+ }
+
+ // Create new compression context.
+ flow_id = GetNextFlowId();
+ QUIC_DVLOG(1) << "Compression assigning new flow_id " << flow_id << " to "
+ << server_address << " client " << client_connection_id
+ << " server " << server_connection_id;
+ MasqueCompressionContext context;
+ context.client_connection_id = client_connection_id;
+ context.server_connection_id = server_connection_id;
+ context.server_address = server_address;
+ contexts_[flow_id] = context;
+
+ return flow_id;
+}
+
+bool MasqueCompressionEngine::WriteCompressedPacketToSlice(
+ QuicConnectionId client_connection_id,
+ QuicConnectionId server_connection_id,
+ const QuicSocketAddress& server_address,
+ QuicConnectionId destination_connection_id,
+ QuicConnectionId source_connection_id,
+ QuicDatagramFlowId flow_id,
+ bool validated,
+ uint8_t first_byte,
+ bool long_header,
+ QuicDataReader* reader,
+ QuicDataWriter* writer) {
+ if (validated) {
+ QUIC_DVLOG(1) << "Compressing using validated flow_id " << flow_id;
+ if (!writer->WriteVarInt62(flow_id)) {
+ QUIC_BUG << "Failed to write flow_id";
+ return false;
+ }
+ } else {
+ QUIC_DVLOG(1) << "Compressing using unvalidated flow_id " << flow_id;
+ if (!writer->WriteVarInt62(kFlowId0)) {
+ QUIC_BUG << "Failed to write kFlowId0";
+ return false;
+ }
+ if (!writer->WriteVarInt62(flow_id)) {
+ QUIC_BUG << "Failed to write flow_id";
+ return false;
+ }
+ if (!writer->WriteLengthPrefixedConnectionId(client_connection_id)) {
+ QUIC_BUG << "Failed to write client_connection_id";
+ return false;
+ }
+ if (!writer->WriteLengthPrefixedConnectionId(server_connection_id)) {
+ QUIC_BUG << "Failed to write server_connection_id";
+ return false;
+ }
+ if (!writer->WriteUInt16(server_address.port())) {
+ QUIC_BUG << "Failed to write port";
+ return false;
+ }
+ QuicIpAddress peer_ip = server_address.host();
+ DCHECK(peer_ip.IsInitialized());
+ std::string peer_ip_bytes = peer_ip.ToPackedString();
+ DCHECK(!peer_ip_bytes.empty());
+ uint8_t address_id;
+ if (peer_ip.address_family() == IpAddressFamily::IP_V6) {
+ address_id = MasqueAddressFamilyIPv6;
+ if (peer_ip_bytes.length() != QuicIpAddress::kIPv6AddressSize) {
+ QUIC_BUG << "Bad IPv6 length " << server_address;
+ return false;
+ }
+ } else if (peer_ip.address_family() == IpAddressFamily::IP_V4) {
+ address_id = MasqueAddressFamilyIPv4;
+ if (peer_ip_bytes.length() != QuicIpAddress::kIPv4AddressSize) {
+ QUIC_BUG << "Bad IPv4 length " << server_address;
+ return false;
+ }
+ } else {
+ QUIC_BUG << "Unexpected server_address " << server_address;
+ return false;
+ }
+ if (!writer->WriteUInt8(address_id)) {
+ QUIC_BUG << "Failed to write address_id";
+ return false;
+ }
+ if (!writer->WriteStringPiece(peer_ip_bytes)) {
+ QUIC_BUG << "Failed to write IP address";
+ return false;
+ }
+ }
+ if (!writer->WriteUInt8(first_byte)) {
+ QUIC_BUG << "Failed to write first_byte";
+ return false;
+ }
+ if (long_header) {
+ QuicVersionLabel version_label;
+ if (!reader->ReadUInt32(&version_label)) {
+ QUIC_DLOG(ERROR) << "Failed to read version";
+ return false;
+ }
+ if (!writer->WriteUInt32(version_label)) {
+ QUIC_BUG << "Failed to write version";
+ return false;
+ }
+ QuicConnectionId packet_destination_connection_id,
+ packet_source_connection_id;
+ if (!reader->ReadLengthPrefixedConnectionId(
+ &packet_destination_connection_id) ||
+ !reader->ReadLengthPrefixedConnectionId(&packet_source_connection_id)) {
+ QUIC_DLOG(ERROR) << "Failed to parse long header connection IDs";
+ return false;
+ }
+ if (packet_destination_connection_id != destination_connection_id) {
+ QUIC_DLOG(ERROR) << "Long header packet's destination_connection_id "
+ << packet_destination_connection_id
+ << " does not match expected "
+ << destination_connection_id;
+ return false;
+ }
+ if (packet_source_connection_id != source_connection_id) {
+ QUIC_DLOG(ERROR) << "Long header packet's source_connection_id "
+ << packet_source_connection_id
+ << " does not match expected " << source_connection_id;
+ return false;
+ }
+ } else {
+ QuicConnectionId packet_destination_connection_id;
+ if (!reader->ReadConnectionId(&packet_destination_connection_id,
+ destination_connection_id.length())) {
+ QUIC_DLOG(ERROR)
+ << "Failed to read short header packet's destination_connection_id";
+ return false;
+ }
+ if (packet_destination_connection_id != destination_connection_id) {
+ QUIC_DLOG(ERROR) << "Short header packet's destination_connection_id "
+ << packet_destination_connection_id
+ << " does not match expected "
+ << destination_connection_id;
+ return false;
+ }
+ }
+ quiche::QuicheStringPiece packet_payload = reader->ReadRemainingPayload();
+ if (!writer->WriteStringPiece(packet_payload)) {
+ QUIC_BUG << "Failed to write packet_payload";
+ return false;
+ }
+ return true;
+}
+
+void MasqueCompressionEngine::CompressAndSendPacket(
+ quiche::QuicheStringPiece packet,
+ QuicConnectionId client_connection_id,
+ QuicConnectionId server_connection_id,
+ const QuicSocketAddress& server_address) {
+ QUIC_DVLOG(2) << "Compressing client " << client_connection_id << " server "
+ << server_connection_id << "\n"
+ << quiche::QuicheTextUtils::HexDump(packet);
+ DCHECK(server_address.IsInitialized());
+ if (packet.empty()) {
+ QUIC_BUG << "Tried to send empty packet";
+ return;
+ }
+ QuicDataReader reader(packet.data(), packet.length());
+ uint8_t first_byte;
+ if (!reader.ReadUInt8(&first_byte)) {
+ QUIC_BUG << "Failed to read first_byte";
+ return;
+ }
+ const bool long_header = (first_byte & FLAGS_LONG_HEADER) != 0;
+ bool client_connection_id_present = true, server_connection_id_present = true;
+ QuicConnectionId destination_connection_id, source_connection_id;
+ if (masque_session_->perspective() == Perspective::IS_SERVER) {
+ destination_connection_id = client_connection_id;
+ source_connection_id = server_connection_id;
+ if (!long_header) {
+ server_connection_id_present = false;
+ }
+ } else {
+ destination_connection_id = server_connection_id;
+ source_connection_id = client_connection_id;
+ if (!long_header) {
+ client_connection_id_present = false;
+ }
+ }
+
+ bool validated = false;
+ QuicDatagramFlowId flow_id = FindOrCreateCompressionContext(
+ client_connection_id, server_connection_id, server_address,
+ client_connection_id_present, server_connection_id_present, &validated);
+
+ size_t slice_length = packet.length() - destination_connection_id.length();
+ if (long_header) {
+ slice_length -= sizeof(uint8_t) * 2 + source_connection_id.length();
+ }
+ if (validated) {
+ slice_length += QuicDataWriter::GetVarInt62Len(flow_id);
+ } else {
+ slice_length += QuicDataWriter::GetVarInt62Len(kFlowId0) +
+ QuicDataWriter::GetVarInt62Len(flow_id) + sizeof(uint8_t) +
+ client_connection_id.length() + sizeof(uint8_t) +
+ server_connection_id.length() +
+ sizeof(server_address.port()) + sizeof(uint8_t) +
+ server_address.host().ToPackedString().length();
+ }
+ QuicUniqueBufferPtr buffer = MakeUniqueBuffer(
+ masque_session_->connection()->helper()->GetStreamSendBufferAllocator(),
+ slice_length);
+ QuicDataWriter writer(slice_length, buffer.get());
+
+ if (!WriteCompressedPacketToSlice(
+ client_connection_id, server_connection_id, server_address,
+ destination_connection_id, source_connection_id, flow_id, validated,
+ first_byte, long_header, &reader, &writer)) {
+ return;
+ }
+
+ QuicMemSlice slice(std::move(buffer), slice_length);
+ MessageResult message_result =
+ masque_session_->SendMessage(QuicMemSliceSpan(&slice));
+
+ QUIC_DVLOG(1) << "Sent packet compressed with flow ID " << flow_id
+ << " and got message result " << message_result;
+}
+
+bool MasqueCompressionEngine::ParseCompressionContext(
+ QuicDataReader* reader,
+ MasqueCompressionContext* context) {
+ QuicDatagramFlowId new_flow_id;
+ if (!reader->ReadVarInt62(&new_flow_id)) {
+ QUIC_DLOG(ERROR) << "Could not read new_flow_id";
+ return false;
+ }
+ QuicConnectionId new_client_connection_id;
+ if (!reader->ReadLengthPrefixedConnectionId(&new_client_connection_id)) {
+ QUIC_DLOG(ERROR) << "Could not read new_client_connection_id";
+ return false;
+ }
+ QuicConnectionId new_server_connection_id;
+ if (!reader->ReadLengthPrefixedConnectionId(&new_server_connection_id)) {
+ QUIC_DLOG(ERROR) << "Could not read new_server_connection_id";
+ return false;
+ }
+ uint16_t port;
+ if (!reader->ReadUInt16(&port)) {
+ QUIC_DLOG(ERROR) << "Could not read port";
+ return false;
+ }
+ uint8_t address_id;
+ if (!reader->ReadUInt8(&address_id)) {
+ QUIC_DLOG(ERROR) << "Could not read address_id";
+ return false;
+ }
+ size_t ip_bytes_length;
+ if (address_id == MasqueAddressFamilyIPv6) {
+ ip_bytes_length = QuicIpAddress::kIPv6AddressSize;
+ } else if (address_id == MasqueAddressFamilyIPv4) {
+ ip_bytes_length = QuicIpAddress::kIPv4AddressSize;
+ } else {
+ QUIC_DLOG(ERROR) << "Unknown address_id " << static_cast<int>(address_id);
+ return false;
+ }
+ char ip_bytes[QuicIpAddress::kMaxAddressSize];
+ if (!reader->ReadBytes(ip_bytes, ip_bytes_length)) {
+ QUIC_DLOG(ERROR) << "Could not read IP address";
+ return false;
+ }
+ QuicIpAddress ip_address;
+ ip_address.FromPackedString(ip_bytes, ip_bytes_length);
+ if (!ip_address.IsInitialized()) {
+ QUIC_BUG << "Failed to parse IP address";
+ return false;
+ }
+ QuicSocketAddress new_server_address = QuicSocketAddress(ip_address, port);
+ auto context_pair = contexts_.find(new_flow_id);
+ if (context_pair == contexts_.end()) {
+ context->client_connection_id = new_client_connection_id;
+ context->server_connection_id = new_server_connection_id;
+ context->server_address = new_server_address;
+ context->validated = true;
+ contexts_[new_flow_id] = *context;
+ QUIC_DVLOG(1) << "Registered new flow_id " << new_flow_id << " to "
+ << new_server_address << " client "
+ << new_client_connection_id << " server "
+ << new_server_connection_id;
+ } else {
+ *context = context_pair->second;
+ if (context->client_connection_id != new_client_connection_id) {
+ QUIC_LOG(ERROR)
+ << "Received incorrect context registration for existing flow_id "
+ << new_flow_id << " mismatched client "
+ << context->client_connection_id << " " << new_client_connection_id;
+ return false;
+ }
+ if (context->server_connection_id != new_server_connection_id) {
+ QUIC_LOG(ERROR)
+ << "Received incorrect context registration for existing flow_id "
+ << new_flow_id << " mismatched server "
+ << context->server_connection_id << " " << new_server_connection_id;
+ return false;
+ }
+ if (context->server_address != new_server_address) {
+ QUIC_LOG(ERROR)
+ << "Received incorrect context registration for existing flow_id "
+ << new_flow_id << " mismatched server " << context->server_address
+ << " " << new_server_address;
+ return false;
+ }
+ if (!context->validated) {
+ context->validated = true;
+ contexts_[new_flow_id] = *context;
+ QUIC_DLOG(INFO) << "Successfully validated remotely-unvalidated flow_id "
+ << new_flow_id << " to " << new_server_address
+ << " client " << new_client_connection_id << " server "
+ << new_server_connection_id;
+ } else {
+ QUIC_DVLOG(1) << "Decompressing using incoming locally-validated "
+ "remotely-unvalidated flow_id "
+ << new_flow_id << " to " << new_server_address << " client "
+ << new_client_connection_id << " server "
+ << new_server_connection_id;
+ }
+ }
+ return true;
+}
+
+bool MasqueCompressionEngine::WriteDecompressedPacket(
+ QuicDataReader* reader,
+ const MasqueCompressionContext& context,
+ std::vector<char>* packet,
+ bool* version_present) {
+ QuicConnectionId destination_connection_id, source_connection_id;
+ if (masque_session_->perspective() == Perspective::IS_SERVER) {
+ destination_connection_id = context.server_connection_id;
+ source_connection_id = context.client_connection_id;
+ } else {
+ destination_connection_id = context.client_connection_id;
+ source_connection_id = context.server_connection_id;
+ }
+
+ size_t packet_length =
+ reader->BytesRemaining() + destination_connection_id.length();
+ uint8_t first_byte;
+ if (!reader->ReadUInt8(&first_byte)) {
+ QUIC_DLOG(ERROR) << "Failed to read first_byte";
+ return false;
+ }
+ *version_present = (first_byte & FLAGS_LONG_HEADER) != 0;
+ if (*version_present) {
+ packet_length += sizeof(uint8_t) * 2 + source_connection_id.length();
+ }
+ *packet = std::vector<char>(packet_length);
+ QuicDataWriter writer(packet->size(), packet->data());
+ if (!writer.WriteUInt8(first_byte)) {
+ QUIC_BUG << "Failed to write first_byte";
+ return false;
+ }
+ if (*version_present) {
+ QuicVersionLabel version_label;
+ if (!reader->ReadUInt32(&version_label)) {
+ QUIC_DLOG(ERROR) << "Failed to read version";
+ return false;
+ }
+ if (!writer.WriteUInt32(version_label)) {
+ QUIC_BUG << "Failed to write version";
+ return false;
+ }
+ if (!writer.WriteLengthPrefixedConnectionId(destination_connection_id)) {
+ QUIC_BUG << "Failed to write long header destination_connection_id";
+ return false;
+ }
+ if (!writer.WriteLengthPrefixedConnectionId(source_connection_id)) {
+ QUIC_BUG << "Failed to write long header source_connection_id";
+ return false;
+ }
+ } else {
+ if (!writer.WriteConnectionId(destination_connection_id)) {
+ QUIC_BUG << "Failed to write short header destination_connection_id";
+ return false;
+ }
+ }
+ quiche::QuicheStringPiece payload = reader->ReadRemainingPayload();
+ if (!writer.WriteStringPiece(payload)) {
+ QUIC_BUG << "Failed to write payload";
+ return false;
+ }
+ return true;
+}
+
+bool MasqueCompressionEngine::DecompressDatagram(
+ quiche::QuicheStringPiece datagram,
+ QuicConnectionId* client_connection_id,
+ QuicConnectionId* server_connection_id,
+ QuicSocketAddress* server_address,
+ std::vector<char>* packet,
+ bool* version_present) {
+ QUIC_DVLOG(1) << "Decompressing DATAGRAM frame of length "
+ << datagram.length();
+ QuicDataReader reader(datagram);
+ QuicDatagramFlowId flow_id;
+ if (!reader.ReadVarInt62(&flow_id)) {
+ QUIC_DLOG(ERROR) << "Could not read flow_id";
+ return false;
+ }
+ MasqueCompressionContext context;
+ if (flow_id == kFlowId0) {
+ if (!ParseCompressionContext(&reader, &context)) {
+ return false;
+ }
+ } else {
+ auto context_pair = contexts_.find(flow_id);
+ if (context_pair == contexts_.end()) {
+ QUIC_DLOG(ERROR) << "Received unknown flow_id " << flow_id;
+ return false;
+ }
+ context = context_pair->second;
+
+ if (!context.validated) {
+ context.validated = true;
+ contexts_[flow_id] = context;
+ QUIC_DLOG(INFO) << "Successfully validated remotely-validated flow_id "
+ << flow_id << " to " << context.server_address
+ << " client " << context.client_connection_id
+ << " server " << context.server_connection_id;
+ } else {
+ QUIC_DVLOG(1) << "Decompressing using incoming locally-validated "
+ "remotely-validated flow_id "
+ << flow_id << " to " << context.server_address << " client "
+ << context.client_connection_id << " server "
+ << context.server_connection_id;
+ }
+ }
+
+ if (!WriteDecompressedPacket(&reader, context, packet, version_present)) {
+ return false;
+ }
+
+ *server_address = context.server_address;
+ *client_connection_id = context.client_connection_id;
+ *server_connection_id = context.server_connection_id;
+
+ QUIC_DVLOG(2) << "Decompressed client " << context.client_connection_id
+ << " server " << context.server_connection_id << "\n"
+ << quiche::QuicheTextUtils::HexDump(quiche::QuicheStringPiece(
+ packet->data(), packet->size()));
+
+ return true;
+}
+
+QuicDatagramFlowId MasqueCompressionEngine::GetNextFlowId() {
+ const QuicDatagramFlowId next_flow_id = next_flow_id_;
+ next_flow_id_ += 2;
+ return next_flow_id;
+}
+
+void MasqueCompressionEngine::UnregisterClientConnectionId(
+ QuicConnectionId client_connection_id) {
+ std::vector<QuicDatagramFlowId> flow_ids_to_remove;
+ for (const auto& kv : contexts_) {
+ const MasqueCompressionContext& context = kv.second;
+ if (context.client_connection_id == client_connection_id) {
+ flow_ids_to_remove.push_back(kv.first);
+ }
+ }
+ for (QuicDatagramFlowId flow_id : flow_ids_to_remove) {
+ contexts_.erase(flow_id);
+ }
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_compression_engine.h b/chromium/net/third_party/quiche/src/quic/masque/masque_compression_engine.h
new file mode 100644
index 00000000000..95328df7acf
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_compression_engine.h
@@ -0,0 +1,126 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_MASQUE_MASQUE_PROTOCOL_H_
+#define QUICHE_QUIC_MASQUE_MASQUE_PROTOCOL_H_
+
+#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
+#include "net/third_party/quiche/src/quic/core/quic_session.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+
+namespace quic {
+
+// MASQUE compression engine used by client and servers.
+// This class allows converting QUIC packets into a compressed form suitable
+// for sending over QUIC DATAGRAM frames. It leverages a flow identifier at the
+// start of each datagram to indicate which compression context was used to
+// compress this packet, or to create new compression contexts.
+// Compression contexts contain client and server connection IDs and the
+// server's IP and port. This allows compressing that information in most
+// packets without requiring access to the cryptographic keys of the end-to-end
+// encapsulated session. When the flow identifier is 0, the DATAGRAM contains
+// all the contents of the compression context. When the flow identifier is
+// non-zero, those fields are removed so the encapsulated QUIC packet is
+// transmitted without connection IDs and reassembled by the peer on
+// decompression. This only needs to contain the HTTP server's IP address since
+// the client's IP address is not visible to the HTTP server.
+
+class QUIC_NO_EXPORT MasqueCompressionEngine {
+ public:
+ // Caller must ensure that |masque_session| has a lifetime longer than the
+ // newly constructed MasqueCompressionEngine.
+ explicit MasqueCompressionEngine(QuicSession* masque_session);
+
+ // Disallow copy and assign.
+ MasqueCompressionEngine(const MasqueCompressionEngine&) = delete;
+ MasqueCompressionEngine& operator=(const MasqueCompressionEngine&) = delete;
+
+ // Compresses packet and sends it in a DATAGRAM frame over a MASQUE session.
+ // When used from MASQUE client to MASQUE server, the MASQUE server will then
+ // send the packet to the provided |server_address|.
+ // When used from MASQUE server to MASQUE client, the MASQUE client will then
+ // hand off the uncompressed packet to an encapsulated session that will treat
+ // it as having come from the provided |server_address|.
+ // The connection IDs are the one used by the encapsulated |packet|.
+ void CompressAndSendPacket(quiche::QuicheStringPiece packet,
+ QuicConnectionId client_connection_id,
+ QuicConnectionId server_connection_id,
+ const QuicSocketAddress& server_address);
+
+ // Decompresses received DATAGRAM frame contents from |datagram| and places
+ // them in |packet|. Reverses the transformation from CompressAndSendPacket.
+ // The connection IDs are the one used by the encapsulated |packet|.
+ // |server_address| will be filled with the |server_address| passed to
+ // CompressAndSendPacket. |version_present| will contain whether the
+ // encapsulated |packet| contains a Version field.
+ bool DecompressDatagram(quiche::QuicheStringPiece datagram,
+ QuicConnectionId* client_connection_id,
+ QuicConnectionId* server_connection_id,
+ QuicSocketAddress* server_address,
+ std::vector<char>* packet,
+ bool* version_present);
+
+ // Clears all entries referencing |client_connection_id| from the
+ // compression table.
+ void UnregisterClientConnectionId(QuicConnectionId client_connection_id);
+
+ private:
+ struct QUIC_NO_EXPORT MasqueCompressionContext {
+ QuicConnectionId client_connection_id;
+ QuicConnectionId server_connection_id;
+ QuicSocketAddress server_address;
+ bool validated = false;
+ };
+
+ // Generates a new datagram flow ID.
+ QuicDatagramFlowId GetNextFlowId();
+
+ // Finds or creates a new compression context to use during compression.
+ // |client_connection_id_present| and |server_connection_id_present| indicate
+ // whether the corresponding connection ID is present in the current packet.
+ // |validated| will contain whether the compression context that matches
+ // these arguments is currently validated or not.
+ QuicDatagramFlowId FindOrCreateCompressionContext(
+ QuicConnectionId client_connection_id,
+ QuicConnectionId server_connection_id,
+ const QuicSocketAddress& server_address,
+ bool client_connection_id_present,
+ bool server_connection_id_present,
+ bool* validated);
+
+ // Writes compressed packet to |slice| during compression.
+ bool WriteCompressedPacketToSlice(QuicConnectionId client_connection_id,
+ QuicConnectionId server_connection_id,
+ const QuicSocketAddress& server_address,
+ QuicConnectionId destination_connection_id,
+ QuicConnectionId source_connection_id,
+ QuicDatagramFlowId flow_id,
+ bool validated,
+ uint8_t first_byte,
+ bool long_header,
+ QuicDataReader* reader,
+ QuicDataWriter* writer);
+
+ // Parses compression context from flow ID 0 during decompression.
+ bool ParseCompressionContext(QuicDataReader* reader,
+ MasqueCompressionContext* context);
+
+ // Writes decompressed packet to |packet| during decompression.
+ bool WriteDecompressedPacket(QuicDataReader* reader,
+ const MasqueCompressionContext& context,
+ std::vector<char>* packet,
+ bool* version_present);
+
+ QuicSession* masque_session_; // Unowned.
+ QuicUnorderedMap<QuicDatagramFlowId, MasqueCompressionContext> contexts_;
+ QuicDatagramFlowId next_flow_id_;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_MASQUE_MASQUE_PROTOCOL_H_
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_dispatcher.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_dispatcher.cc
new file mode 100644
index 00000000000..9856fb41541
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_dispatcher.cc
@@ -0,0 +1,86 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/masque/masque_dispatcher.h"
+#include "net/third_party/quiche/src/quic/masque/masque_server_session.h"
+
+namespace quic {
+
+MasqueDispatcher::MasqueDispatcher(
+ const QuicConfig* config,
+ const QuicCryptoServerConfig* crypto_config,
+ QuicVersionManager* version_manager,
+ std::unique_ptr<QuicConnectionHelperInterface> helper,
+ std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
+ std::unique_ptr<QuicAlarmFactory> alarm_factory,
+ MasqueServerBackend* masque_server_backend,
+ uint8_t expected_server_connection_id_length)
+ : QuicSimpleDispatcher(config,
+ crypto_config,
+ version_manager,
+ std::move(helper),
+ std::move(session_helper),
+ std::move(alarm_factory),
+ masque_server_backend,
+ expected_server_connection_id_length),
+ masque_server_backend_(masque_server_backend) {}
+
+std::unique_ptr<QuicSession> MasqueDispatcher::CreateQuicSession(
+ QuicConnectionId connection_id,
+ const QuicSocketAddress& client_address,
+ quiche::QuicheStringPiece /*alpn*/,
+ const ParsedQuicVersion& version) {
+ // The MasqueServerSession takes ownership of |connection| below.
+ QuicConnection* connection = new QuicConnection(
+ connection_id, client_address, helper(), alarm_factory(), writer(),
+ /*owns_writer=*/false, Perspective::IS_SERVER,
+ ParsedQuicVersionVector{version});
+
+ auto session = std::make_unique<MasqueServerSession>(
+ config(), GetSupportedVersions(), connection, this, this,
+ session_helper(), crypto_config(), compressed_certs_cache(),
+ masque_server_backend_);
+ session->Initialize();
+ return session;
+}
+
+bool MasqueDispatcher::OnFailedToDispatchPacket(
+ const ReceivedPacketInfo& packet_info) {
+ auto connection_id_registration = client_connection_id_registrations_.find(
+ packet_info.destination_connection_id);
+ if (connection_id_registration == client_connection_id_registrations_.end()) {
+ QUIC_DLOG(INFO) << "MasqueDispatcher failed to dispatch " << packet_info;
+ return false;
+ }
+ MasqueServerSession* masque_server_session =
+ connection_id_registration->second;
+ masque_server_session->HandlePacketFromServer(packet_info);
+ return true;
+}
+
+void MasqueDispatcher::RegisterClientConnectionId(
+ QuicConnectionId client_connection_id,
+ MasqueServerSession* masque_server_session) {
+ QUIC_DLOG(INFO) << "Registering encapsulated " << client_connection_id
+ << " to MASQUE session "
+ << masque_server_session->connection_id();
+
+ // Make sure we don't try to overwrite an existing registration with a
+ // different session.
+ QUIC_BUG_IF(client_connection_id_registrations_.find(client_connection_id) !=
+ client_connection_id_registrations_.end() &&
+ client_connection_id_registrations_[client_connection_id] !=
+ masque_server_session)
+ << "Overwriting existing registration for " << client_connection_id;
+ client_connection_id_registrations_[client_connection_id] =
+ masque_server_session;
+}
+
+void MasqueDispatcher::UnregisterClientConnectionId(
+ QuicConnectionId client_connection_id) {
+ QUIC_DLOG(INFO) << "Unregistering " << client_connection_id;
+ client_connection_id_registrations_.erase(client_connection_id);
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_dispatcher.h b/chromium/net/third_party/quiche/src/quic/masque/masque_dispatcher.h
new file mode 100644
index 00000000000..4817b7bd391
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_dispatcher.h
@@ -0,0 +1,61 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_MASQUE_MASQUE_DISPATCHER_H_
+#define QUICHE_QUIC_MASQUE_MASQUE_DISPATCHER_H_
+
+#include "net/third_party/quiche/src/quic/masque/masque_server_backend.h"
+#include "net/third_party/quiche/src/quic/masque/masque_server_session.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.h"
+
+namespace quic {
+
+// QUIC dispatcher that handles new MASQUE connections and can proxy traffic
+// between MASQUE clients and QUIC servers.
+class QUIC_NO_EXPORT MasqueDispatcher : public QuicSimpleDispatcher,
+ public MasqueServerSession::Visitor {
+ public:
+ explicit MasqueDispatcher(
+ const QuicConfig* config,
+ const QuicCryptoServerConfig* crypto_config,
+ QuicVersionManager* version_manager,
+ std::unique_ptr<QuicConnectionHelperInterface> helper,
+ std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
+ std::unique_ptr<QuicAlarmFactory> alarm_factory,
+ MasqueServerBackend* masque_server_backend,
+ uint8_t expected_server_connection_id_length);
+
+ // Disallow copy and assign.
+ MasqueDispatcher(const MasqueDispatcher&) = delete;
+ MasqueDispatcher& operator=(const MasqueDispatcher&) = delete;
+
+ // From QuicSimpleDispatcher.
+ std::unique_ptr<QuicSession> CreateQuicSession(
+ QuicConnectionId connection_id,
+ const QuicSocketAddress& client_address,
+ quiche::QuicheStringPiece alpn,
+ const ParsedQuicVersion& version) override;
+
+ bool OnFailedToDispatchPacket(const ReceivedPacketInfo& packet_info) override;
+
+ // From MasqueServerSession::Visitor.
+ void RegisterClientConnectionId(
+ QuicConnectionId client_connection_id,
+ MasqueServerSession* masque_server_session) override;
+
+ void UnregisterClientConnectionId(
+ QuicConnectionId client_connection_id) override;
+
+ private:
+ MasqueServerBackend* masque_server_backend_; // Unowned.
+ // Mapping from client connection IDs to server sessions, allows routing
+ // incoming packets to the right MASQUE connection.
+ QuicUnorderedMap<QuicConnectionId, MasqueServerSession*, QuicConnectionIdHash>
+ client_connection_id_registrations_;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_MASQUE_MASQUE_DISPATCHER_H_
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_client_session.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_client_session.cc
new file mode 100644
index 00000000000..818ff76c8dc
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_client_session.cc
@@ -0,0 +1,41 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/masque/masque_encapsulated_client_session.h"
+
+namespace quic {
+
+MasqueEncapsulatedClientSession::MasqueEncapsulatedClientSession(
+ const QuicConfig& config,
+ const ParsedQuicVersionVector& supported_versions,
+ QuicConnection* connection,
+ const QuicServerId& server_id,
+ QuicCryptoClientConfig* crypto_config,
+ QuicClientPushPromiseIndex* push_promise_index,
+ MasqueClientSession* masque_client_session)
+ : QuicSpdyClientSession(config,
+ supported_versions,
+ connection,
+ server_id,
+ crypto_config,
+ push_promise_index),
+ masque_client_session_(masque_client_session) {}
+
+void MasqueEncapsulatedClientSession::ProcessPacket(
+ quiche::QuicheStringPiece packet,
+ QuicSocketAddress server_address) {
+ QuicTime now = connection()->clock()->ApproximateNow();
+ QuicReceivedPacket received_packet(packet.data(), packet.length(), now);
+ connection()->ProcessUdpPacket(connection()->self_address(), server_address,
+ received_packet);
+}
+
+void MasqueEncapsulatedClientSession::OnConnectionClosed(
+ const QuicConnectionCloseFrame& /*frame*/,
+ ConnectionCloseSource /*source*/) {
+ masque_client_session_->UnregisterConnectionId(
+ connection()->client_connection_id());
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_client_session.h b/chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_client_session.h
new file mode 100644
index 00000000000..75ccc1f58ec
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_client_session.h
@@ -0,0 +1,58 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_MASQUE_MASQUE_ENCAPSULATED_CLIENT_SESSION_H_
+#define QUICHE_QUIC_MASQUE_MASQUE_ENCAPSULATED_CLIENT_SESSION_H_
+
+#include "net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.h"
+#include "net/third_party/quiche/src/quic/masque/masque_client_session.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+
+namespace quic {
+
+// QUIC client session for QUIC encapsulated in MASQUE. This client session is
+// maintained end-to-end between the client and the web-server (the MASQUE
+// session does not have access to the cryptographic keys for the end-to-end
+// session), but its packets are sent encapsulated inside DATAGRAM frames in a
+// MASQUE session, as opposed to regular QUIC packets. Multiple encapsulated
+// sessions can coexist inside a MASQUE session.
+class QUIC_NO_EXPORT MasqueEncapsulatedClientSession
+ : public QuicSpdyClientSession,
+ public MasqueClientSession::EncapsulatedClientSession {
+ public:
+ // Takes ownership of |connection|, but not of |crypto_config| or
+ // |push_promise_index| or |masque_client_session|. All pointers must be
+ // non-null. Caller must ensure that |push_promise_index| and
+ // |masque_client_session| stay valid for the lifetime of the newly created
+ // MasqueEncapsulatedClientSession.
+ MasqueEncapsulatedClientSession(
+ const QuicConfig& config,
+ const ParsedQuicVersionVector& supported_versions,
+ QuicConnection* connection,
+ const QuicServerId& server_id,
+ QuicCryptoClientConfig* crypto_config,
+ QuicClientPushPromiseIndex* push_promise_index,
+ MasqueClientSession* masque_client_session);
+
+ // Disallow copy and assign.
+ MasqueEncapsulatedClientSession(const MasqueEncapsulatedClientSession&) =
+ delete;
+ MasqueEncapsulatedClientSession& operator=(
+ const MasqueEncapsulatedClientSession&) = delete;
+
+ // From MasqueClientSession::EncapsulatedClientSession.
+ void ProcessPacket(quiche::QuicheStringPiece packet,
+ QuicSocketAddress server_address) override;
+
+ // From QuicSession.
+ void OnConnectionClosed(const QuicConnectionCloseFrame& frame,
+ ConnectionCloseSource source) override;
+
+ private:
+ MasqueClientSession* masque_client_session_; // Unowned.
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_MASQUE_MASQUE_ENCAPSULATED_CLIENT_SESSION_H_
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_epoll_client.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_epoll_client.cc
new file mode 100644
index 00000000000..7c9749aa374
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_epoll_client.cc
@@ -0,0 +1,125 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/masque/masque_encapsulated_epoll_client.h"
+#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/masque/masque_client_session.h"
+#include "net/third_party/quiche/src/quic/masque/masque_encapsulated_client_session.h"
+#include "net/third_party/quiche/src/quic/masque/masque_epoll_client.h"
+#include "net/third_party/quiche/src/quic/masque/masque_utils.h"
+
+namespace quic {
+
+namespace {
+
+// Custom packet writer that allows getting all of a connection's outgoing
+// packets.
+class MasquePacketWriter : public QuicPacketWriter {
+ public:
+ explicit MasquePacketWriter(MasqueEncapsulatedEpollClient* client)
+ : client_(client) {}
+ WriteResult WritePacket(const char* buffer,
+ size_t buf_len,
+ const QuicIpAddress& /*self_address*/,
+ const QuicSocketAddress& peer_address,
+ PerPacketOptions* /*options*/) override {
+ DCHECK(peer_address.IsInitialized());
+ QUIC_DVLOG(1) << "MasquePacketWriter trying to write " << buf_len
+ << " bytes to " << peer_address;
+ quiche::QuicheStringPiece packet(buffer, buf_len);
+ client_->masque_client()->masque_client_session()->SendPacket(
+ client_->session()->connection()->client_connection_id(),
+ client_->session()->connection()->connection_id(), packet,
+ peer_address);
+ return WriteResult(WRITE_STATUS_OK, buf_len);
+ }
+
+ bool IsWriteBlocked() const override { return false; }
+
+ void SetWritable() override {}
+
+ QuicByteCount GetMaxPacketSize(
+ const QuicSocketAddress& /*peer_address*/) const override {
+ return kMasqueMaxEncapsulatedPacketSize;
+ }
+
+ bool SupportsReleaseTime() const override { return false; }
+
+ bool IsBatchMode() const override { return false; }
+ char* GetNextWriteLocation(
+ const QuicIpAddress& /*self_address*/,
+ const QuicSocketAddress& /*peer_address*/) override {
+ return nullptr;
+ }
+
+ WriteResult Flush() override { return WriteResult(WRITE_STATUS_OK, 0); }
+
+ private:
+ MasqueEncapsulatedEpollClient* client_; // Unowned.
+};
+
+// Custom network helper that allows injecting a custom packet writer in order
+// to get all of a connection's outgoing packets.
+class MasqueClientEpollNetworkHelper : public QuicClientEpollNetworkHelper {
+ public:
+ MasqueClientEpollNetworkHelper(QuicEpollServer* epoll_server,
+ MasqueEncapsulatedEpollClient* client)
+ : QuicClientEpollNetworkHelper(epoll_server, client), client_(client) {}
+ QuicPacketWriter* CreateQuicPacketWriter() override {
+ return new MasquePacketWriter(client_);
+ }
+
+ private:
+ MasqueEncapsulatedEpollClient* client_; // Unowned.
+};
+
+} // namespace
+
+MasqueEncapsulatedEpollClient::MasqueEncapsulatedEpollClient(
+ QuicSocketAddress server_address,
+ const QuicServerId& server_id,
+ QuicEpollServer* epoll_server,
+ std::unique_ptr<ProofVerifier> proof_verifier,
+ MasqueEpollClient* masque_client)
+ : QuicClient(
+ server_address,
+ server_id,
+ MasqueSupportedVersions(),
+ MasqueEncapsulatedConfig(),
+ epoll_server,
+ std::make_unique<MasqueClientEpollNetworkHelper>(epoll_server, this),
+ std::move(proof_verifier)),
+ masque_client_(masque_client) {}
+
+MasqueEncapsulatedEpollClient::~MasqueEncapsulatedEpollClient() {
+ masque_client_->masque_client_session()->UnregisterConnectionId(
+ client_connection_id_);
+}
+
+std::unique_ptr<QuicSession>
+MasqueEncapsulatedEpollClient::CreateQuicClientSession(
+ const ParsedQuicVersionVector& supported_versions,
+ QuicConnection* connection) {
+ QUIC_DLOG(INFO) << "Creating MASQUE encapsulated session for "
+ << connection->connection_id();
+ return std::make_unique<MasqueEncapsulatedClientSession>(
+ *config(), supported_versions, connection, server_id(), crypto_config(),
+ push_promise_index(), masque_client_->masque_client_session());
+}
+
+MasqueEncapsulatedClientSession*
+MasqueEncapsulatedEpollClient::masque_encapsulated_client_session() {
+ return static_cast<MasqueEncapsulatedClientSession*>(QuicClient::session());
+}
+
+QuicConnectionId MasqueEncapsulatedEpollClient::GetClientConnectionId() {
+ if (client_connection_id_.IsEmpty()) {
+ client_connection_id_ = QuicUtils::CreateRandomConnectionId();
+ masque_client_->masque_client_session()->RegisterConnectionId(
+ client_connection_id_, masque_encapsulated_client_session());
+ }
+ return client_connection_id_;
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_epoll_client.h b/chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_epoll_client.h
new file mode 100644
index 00000000000..c8bff2154c4
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_epoll_client.h
@@ -0,0 +1,50 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_MASQUE_MASQUE_ENCAPSULATED_EPOLL_CLIENT_H_
+#define QUICHE_QUIC_MASQUE_MASQUE_ENCAPSULATED_EPOLL_CLIENT_H_
+
+#include "net/third_party/quiche/src/quic/masque/masque_encapsulated_client_session.h"
+#include "net/third_party/quiche/src/quic/masque/masque_epoll_client.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/tools/quic_client.h"
+
+namespace quic {
+
+// QUIC client for QUIC encapsulated in MASQUE.
+class QUIC_NO_EXPORT MasqueEncapsulatedEpollClient : public QuicClient {
+ public:
+ MasqueEncapsulatedEpollClient(QuicSocketAddress server_address,
+ const QuicServerId& server_id,
+ QuicEpollServer* epoll_server,
+ std::unique_ptr<ProofVerifier> proof_verifier,
+ MasqueEpollClient* masque_client);
+ ~MasqueEncapsulatedEpollClient() override;
+
+ // Disallow copy and assign.
+ MasqueEncapsulatedEpollClient(const MasqueEncapsulatedEpollClient&) = delete;
+ MasqueEncapsulatedEpollClient& operator=(
+ const MasqueEncapsulatedEpollClient&) = delete;
+
+ // From QuicClient.
+ std::unique_ptr<QuicSession> CreateQuicClientSession(
+ const ParsedQuicVersionVector& supported_versions,
+ QuicConnection* connection) override;
+
+ QuicConnectionId GetClientConnectionId() override;
+
+ // MASQUE client that this client is encapsulated in.
+ MasqueEpollClient* masque_client() { return masque_client_; }
+
+ // Client session for this client.
+ MasqueEncapsulatedClientSession* masque_encapsulated_client_session();
+
+ private:
+ MasqueEpollClient* masque_client_; // Unowned.
+ QuicConnectionId client_connection_id_;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_MASQUE_MASQUE_ENCAPSULATED_EPOLL_CLIENT_H_
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.cc
new file mode 100644
index 00000000000..24cbaa6a75d
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.cc
@@ -0,0 +1,131 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/masque/masque_epoll_client.h"
+#include "net/third_party/quiche/src/quic/masque/masque_client_session.h"
+#include "net/third_party/quiche/src/quic/masque/masque_utils.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
+
+namespace quic {
+
+MasqueEpollClient::MasqueEpollClient(
+ QuicSocketAddress server_address,
+ const QuicServerId& server_id,
+ QuicEpollServer* epoll_server,
+ std::unique_ptr<ProofVerifier> proof_verifier,
+ const std::string& authority)
+ : QuicClient(server_address,
+ server_id,
+ MasqueSupportedVersions(),
+ epoll_server,
+ std::move(proof_verifier)),
+ authority_(authority) {}
+
+std::unique_ptr<QuicSession> MasqueEpollClient::CreateQuicClientSession(
+ const ParsedQuicVersionVector& supported_versions,
+ QuicConnection* connection) {
+ QUIC_DLOG(INFO) << "Creating MASQUE session for "
+ << connection->connection_id();
+ return std::make_unique<MasqueClientSession>(
+ *config(), supported_versions, connection, server_id(), crypto_config(),
+ push_promise_index(), this);
+}
+
+MasqueClientSession* MasqueEpollClient::masque_client_session() {
+ return static_cast<MasqueClientSession*>(QuicClient::session());
+}
+
+QuicConnectionId MasqueEpollClient::connection_id() {
+ return masque_client_session()->connection_id();
+}
+
+// static
+std::unique_ptr<MasqueEpollClient> MasqueEpollClient::Create(
+ const std::string& host,
+ int port,
+ QuicEpollServer* epoll_server,
+ std::unique_ptr<ProofVerifier> proof_verifier) {
+ // Build the masque_client, and try to connect.
+ QuicSocketAddress addr =
+ tools::LookupAddress(host, quiche::QuicheStrCat(port));
+ if (!addr.IsInitialized()) {
+ QUIC_LOG(ERROR) << "Unable to resolve address: " << host;
+ return nullptr;
+ }
+ QuicServerId server_id(host, port);
+ // Use QuicWrapUnique(new MasqueEpollClient(...)) instead of
+ // std::make_unique<MasqueEpollClient>(...) because the constructor for
+ // MasqueEpollClient is private and therefore not accessible from make_unique.
+ auto masque_client = QuicWrapUnique(new MasqueEpollClient(
+ addr, server_id, epoll_server, std::move(proof_verifier),
+ quiche::QuicheStrCat(host, ":", port)));
+
+ if (masque_client == nullptr) {
+ QUIC_LOG(ERROR) << "Failed to create masque_client";
+ return nullptr;
+ }
+
+ masque_client->set_initial_max_packet_length(kDefaultMaxPacketSize);
+ masque_client->set_drop_response_body(false);
+ if (!masque_client->Initialize()) {
+ QUIC_LOG(ERROR) << "Failed to initialize masque_client";
+ return nullptr;
+ }
+ if (!masque_client->Connect()) {
+ QuicErrorCode error = masque_client->session()->error();
+ QUIC_LOG(ERROR) << "Failed to connect to " << host << ":" << port
+ << ". Error: " << QuicErrorCodeToString(error);
+ return nullptr;
+ }
+
+ std::string body = "foo";
+
+ // Construct a GET or POST request for supplied URL.
+ spdy::SpdyHeaderBlock header_block;
+ header_block[":method"] = "POST";
+ header_block[":scheme"] = "https";
+ header_block[":authority"] = masque_client->authority_;
+ header_block[":path"] = "/.well-known/masque/init";
+
+ // Make sure to store the response, for later output.
+ masque_client->set_store_response(true);
+
+ // Send the MASQUE init command.
+ masque_client->SendRequestAndWaitForResponse(header_block, body,
+ /*fin=*/true);
+
+ if (!masque_client->connected()) {
+ QUIC_LOG(ERROR) << "MASQUE init request caused connection failure. Error: "
+ << QuicErrorCodeToString(masque_client->session()->error());
+ return nullptr;
+ }
+
+ const int response_code = masque_client->latest_response_code();
+ if (response_code != 200) {
+ QUIC_LOG(ERROR) << "MASQUE init request failed with HTTP response code "
+ << response_code;
+ return nullptr;
+ }
+ return masque_client;
+}
+
+void MasqueEpollClient::UnregisterClientConnectionId(
+ QuicConnectionId client_connection_id) {
+ std::string body(client_connection_id.data(), client_connection_id.length());
+
+ // Construct a GET or POST request for supplied URL.
+ spdy::SpdyHeaderBlock header_block;
+ header_block[":method"] = "POST";
+ header_block[":scheme"] = "https";
+ header_block[":authority"] = authority_;
+ header_block[":path"] = "/.well-known/masque/unregister";
+
+ // Make sure to store the response, for later output.
+ set_store_response(true);
+
+ // Send the MASQUE unregister command.
+ SendRequest(header_block, body, /*fin=*/true);
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.h b/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.h
new file mode 100644
index 00000000000..403216bc9a5
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.h
@@ -0,0 +1,57 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_MASQUE_MASQUE_EPOLL_CLIENT_H_
+#define QUICHE_QUIC_MASQUE_MASQUE_EPOLL_CLIENT_H_
+
+#include "net/third_party/quiche/src/quic/masque/masque_client_session.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/tools/quic_client.h"
+
+namespace quic {
+
+// QUIC client that implements MASQUE.
+class QUIC_NO_EXPORT MasqueEpollClient : public QuicClient,
+ public MasqueClientSession::Owner {
+ public:
+ // Constructs a MasqueEpollClient, performs a synchronous DNS lookup.
+ static std::unique_ptr<MasqueEpollClient> Create(
+ const std::string& host,
+ int port,
+ QuicEpollServer* epoll_server,
+ std::unique_ptr<ProofVerifier> proof_verifier);
+
+ // From QuicClient.
+ std::unique_ptr<QuicSession> CreateQuicClientSession(
+ const ParsedQuicVersionVector& supported_versions,
+ QuicConnection* connection) override;
+
+ // Client session for this client.
+ MasqueClientSession* masque_client_session();
+
+ // Convenience accessor for the underlying connection ID.
+ QuicConnectionId connection_id();
+
+ // Send a MASQUE client connection ID unregister command to the server.
+ void UnregisterClientConnectionId(
+ QuicConnectionId client_connection_id) override;
+
+ private:
+ // Constructor is private, use Create() instead.
+ MasqueEpollClient(QuicSocketAddress server_address,
+ const QuicServerId& server_id,
+ QuicEpollServer* epoll_server,
+ std::unique_ptr<ProofVerifier> proof_verifier,
+ const std::string& authority);
+
+ // Disallow copy and assign.
+ MasqueEpollClient(const MasqueEpollClient&) = delete;
+ MasqueEpollClient& operator=(const MasqueEpollClient&) = delete;
+
+ std::string authority_;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_MASQUE_MASQUE_EPOLL_CLIENT_H_
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_server.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_server.cc
new file mode 100644
index 00000000000..60adecab108
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_server.cc
@@ -0,0 +1,31 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/masque/masque_epoll_server.h"
+#include "net/third_party/quiche/src/quic/core/quic_epoll_alarm_factory.h"
+#include "net/third_party/quiche/src/quic/masque/masque_dispatcher.h"
+#include "net/third_party/quiche/src/quic/masque/masque_utils.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_default_proof_providers.h"
+#include "net/third_party/quiche/src/quic/tools/quic_simple_crypto_server_stream_helper.h"
+
+namespace quic {
+
+MasqueEpollServer::MasqueEpollServer(MasqueServerBackend* masque_server_backend)
+ : QuicServer(CreateDefaultProofSource(),
+ masque_server_backend,
+ MasqueSupportedVersions()),
+ masque_server_backend_(masque_server_backend) {}
+
+QuicDispatcher* MasqueEpollServer::CreateQuicDispatcher() {
+ QuicEpollAlarmFactory alarm_factory(epoll_server());
+ return new MasqueDispatcher(
+ &config(), &crypto_config(), version_manager(),
+ std::make_unique<QuicEpollConnectionHelper>(epoll_server(),
+ QuicAllocator::BUFFER_POOL),
+ std::make_unique<QuicSimpleCryptoServerStreamHelper>(),
+ std::make_unique<QuicEpollAlarmFactory>(epoll_server()),
+ masque_server_backend_, expected_server_connection_id_length());
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_server.h b/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_server.h
new file mode 100644
index 00000000000..8d462e80b67
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_server.h
@@ -0,0 +1,32 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_MASQUE_MASQUE_EPOLL_SERVER_H_
+#define QUICHE_QUIC_MASQUE_MASQUE_EPOLL_SERVER_H_
+
+#include "net/third_party/quiche/src/quic/masque/masque_server_backend.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/tools/quic_server.h"
+
+namespace quic {
+
+// QUIC server that implements MASQUE.
+class QUIC_NO_EXPORT MasqueEpollServer : public QuicServer {
+ public:
+ explicit MasqueEpollServer(MasqueServerBackend* masque_server_backend);
+
+ // Disallow copy and assign.
+ MasqueEpollServer(const MasqueEpollServer&) = delete;
+ MasqueEpollServer& operator=(const MasqueEpollServer&) = delete;
+
+ // From QuicServer.
+ QuicDispatcher* CreateQuicDispatcher() override;
+
+ private:
+ MasqueServerBackend* masque_server_backend_; // Unowned.
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_MASQUE_MASQUE_EPOLL_SERVER_H_
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_server_backend.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_server_backend.cc
new file mode 100644
index 00000000000..a3c2b9725d0
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_server_backend.cc
@@ -0,0 +1,139 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/masque/masque_server_backend.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+
+namespace quic {
+
+namespace {
+
+std::string GetRequestHandlerKey(
+ const QuicSimpleServerBackend::RequestHandler* request_handler) {
+ return quiche::QuicheStrCat(request_handler->connection_id().ToString(), "_",
+ request_handler->stream_id(), "_",
+ request_handler->peer_host());
+}
+
+} // namespace
+
+MasqueServerBackend::MasqueServerBackend(const std::string& server_authority,
+ const std::string& cache_directory)
+ : server_authority_(server_authority) {
+ if (!cache_directory.empty()) {
+ QuicMemoryCacheBackend::InitializeBackend(cache_directory);
+ }
+}
+
+bool MasqueServerBackend::MaybeHandleMasqueRequest(
+ const spdy::SpdyHeaderBlock& request_headers,
+ const std::string& request_body,
+ QuicSimpleServerBackend::RequestHandler* request_handler) {
+ auto path_pair = request_headers.find(":path");
+ auto method_pair = request_headers.find(":method");
+ auto scheme_pair = request_headers.find(":scheme");
+ if (path_pair == request_headers.end() ||
+ method_pair == request_headers.end() ||
+ scheme_pair == request_headers.end()) {
+ // This request is missing required headers.
+ return false;
+ }
+ quiche::QuicheStringPiece path = path_pair->second;
+ quiche::QuicheStringPiece scheme = scheme_pair->second;
+ quiche::QuicheStringPiece method = method_pair->second;
+ if (scheme != "https" || method != "POST" || request_body.empty()) {
+ // MASQUE requests MUST be a non-empty https POST.
+ return false;
+ }
+
+ if (path.rfind("/.well-known/masque/", 0) != 0) {
+ // This request is not a MASQUE path.
+ return false;
+ }
+ std::string masque_path(path.substr(sizeof("/.well-known/masque/") - 1));
+
+ if (!server_authority_.empty()) {
+ auto authority_pair = request_headers.find(":authority");
+ if (authority_pair == request_headers.end()) {
+ // Cannot enforce missing authority.
+ return false;
+ }
+ quiche::QuicheStringPiece authority = authority_pair->second;
+ if (server_authority_ != authority) {
+ // This request does not match server_authority.
+ return false;
+ }
+ }
+
+ auto backend_client_pair =
+ backend_clients_.find(request_handler->connection_id());
+ if (backend_client_pair == backend_clients_.end()) {
+ QUIC_LOG(ERROR) << "Could not find backend client for "
+ << GetRequestHandlerKey(request_handler) << " "
+ << masque_path << request_headers.DebugString();
+ return false;
+ }
+
+ BackendClient* backend_client = backend_client_pair->second;
+
+ std::unique_ptr<QuicBackendResponse> response =
+ backend_client->HandleMasqueRequest(masque_path, request_headers,
+ request_body, request_handler);
+ if (response == nullptr) {
+ QUIC_LOG(ERROR) << "Backend client did not process request for "
+ << GetRequestHandlerKey(request_handler) << " "
+ << masque_path << request_headers.DebugString();
+ return false;
+ }
+
+ QUIC_DLOG(INFO) << "Sending MASQUE response for "
+ << GetRequestHandlerKey(request_handler) << " " << masque_path
+ << request_headers.DebugString();
+
+ request_handler->OnResponseBackendComplete(response.get(), {});
+ active_response_map_[GetRequestHandlerKey(request_handler)] =
+ std::move(response);
+
+ return true;
+}
+
+void MasqueServerBackend::FetchResponseFromBackend(
+ const spdy::SpdyHeaderBlock& request_headers,
+ const std::string& request_body,
+ QuicSimpleServerBackend::RequestHandler* request_handler) {
+ if (MaybeHandleMasqueRequest(request_headers, request_body,
+ request_handler)) {
+ // Request was handled as a MASQUE request.
+ return;
+ }
+ QUIC_DLOG(INFO) << "Fetching non-MASQUE response for "
+ << GetRequestHandlerKey(request_handler)
+ << request_headers.DebugString();
+ QuicMemoryCacheBackend::FetchResponseFromBackend(
+ request_headers, request_body, request_handler);
+}
+
+void MasqueServerBackend::CloseBackendResponseStream(
+ QuicSimpleServerBackend::RequestHandler* request_handler) {
+ QUIC_DLOG(INFO) << "Closing response stream for "
+ << GetRequestHandlerKey(request_handler);
+ active_response_map_.erase(GetRequestHandlerKey(request_handler));
+ QuicMemoryCacheBackend::CloseBackendResponseStream(request_handler);
+}
+
+void MasqueServerBackend::RegisterBackendClient(QuicConnectionId connection_id,
+ BackendClient* backend_client) {
+ QUIC_BUG_IF(backend_clients_.find(connection_id) != backend_clients_.end())
+ << connection_id << " already in backend clients map";
+ backend_clients_[connection_id] = backend_client;
+ QUIC_DLOG(INFO) << "Registering backend client for " << connection_id;
+}
+
+void MasqueServerBackend::RemoveBackendClient(QuicConnectionId connection_id) {
+ backend_clients_.erase(connection_id);
+ QUIC_DLOG(INFO) << "Removing backend client for " << connection_id;
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_server_backend.h b/chromium/net/third_party/quiche/src/quic/masque/masque_server_backend.h
new file mode 100644
index 00000000000..78dfbf4105a
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_server_backend.h
@@ -0,0 +1,68 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_MASQUE_MASQUE_SERVER_BACKEND_H_
+#define QUICHE_QUIC_MASQUE_MASQUE_SERVER_BACKEND_H_
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.h"
+
+namespace quic {
+
+// QUIC server backend that understands MASQUE requests, but otherwise answers
+// HTTP queries using an in-memory cache.
+class QUIC_NO_EXPORT MasqueServerBackend : public QuicMemoryCacheBackend {
+ public:
+ // Interface meant to be implemented by the owner of the MasqueServerBackend
+ // instance.
+ class QUIC_NO_EXPORT BackendClient {
+ public:
+ virtual std::unique_ptr<QuicBackendResponse> HandleMasqueRequest(
+ const std::string& masque_path,
+ const spdy::SpdyHeaderBlock& request_headers,
+ const std::string& request_body,
+ QuicSimpleServerBackend::RequestHandler* request_handler) = 0;
+ virtual ~BackendClient() = default;
+ };
+
+ explicit MasqueServerBackend(const std::string& server_authority,
+ const std::string& cache_directory);
+
+ // Disallow copy and assign.
+ MasqueServerBackend(const MasqueServerBackend&) = delete;
+ MasqueServerBackend& operator=(const MasqueServerBackend&) = delete;
+
+ // From QuicMemoryCacheBackend.
+ void FetchResponseFromBackend(
+ const spdy::SpdyHeaderBlock& request_headers,
+ const std::string& request_body,
+ QuicSimpleServerBackend::RequestHandler* request_handler) override;
+
+ void CloseBackendResponseStream(
+ QuicSimpleServerBackend::RequestHandler* request_handler) override;
+
+ // Register backend client that can handle MASQUE requests.
+ void RegisterBackendClient(QuicConnectionId connection_id,
+ BackendClient* backend_client);
+
+ // Unregister backend client.
+ void RemoveBackendClient(QuicConnectionId connection_id);
+
+ private:
+ // Handle MASQUE request.
+ bool MaybeHandleMasqueRequest(
+ const spdy::SpdyHeaderBlock& request_headers,
+ const std::string& request_body,
+ QuicSimpleServerBackend::RequestHandler* request_handler);
+
+ std::string server_authority_;
+ QuicUnorderedMap<std::string, std::unique_ptr<QuicBackendResponse>>
+ active_response_map_;
+ QuicUnorderedMap<QuicConnectionId, BackendClient*, QuicConnectionIdHash>
+ backend_clients_;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_MASQUE_MASQUE_SERVER_BACKEND_H_
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_server_bin.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_server_bin.cc
new file mode 100644
index 00000000000..08ead0c6f2c
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_server_bin.cc
@@ -0,0 +1,60 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is reponsible for the masque_server binary. It allows testing
+// our MASQUE server code by creating a MASQUE proxy that relays HTTP/3
+// requests to web servers tunnelled over MASQUE connections.
+// e.g.: masque_server
+
+#include <memory>
+
+#include "net/third_party/quiche/src/quic/masque/masque_epoll_server.h"
+#include "net/third_party/quiche/src/quic/masque/masque_server_backend.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(int32_t,
+ port,
+ 9661,
+ "The port the MASQUE server will listen on.");
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(
+ std::string,
+ cache_dir,
+ "",
+ "Specifies the directory used during QuicHttpResponseCache "
+ "construction to seed the cache. Cache directory can be "
+ "generated using `wget -p --save-headers <url>`");
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(
+ std::string,
+ server_authority,
+ "",
+ "Specifies the authority over which the server will accept MASQUE "
+ "requests. Defaults to empty which allows all authorities.");
+
+int main(int argc, char* argv[]) {
+ const char* usage = "Usage: masque_server [options]";
+ std::vector<std::string> non_option_args =
+ quic::QuicParseCommandLineFlags(usage, argc, argv);
+ if (!non_option_args.empty()) {
+ quic::QuicPrintCommandLineFlagHelp(usage);
+ return 0;
+ }
+
+ auto backend = std::make_unique<quic::MasqueServerBackend>(
+ GetQuicFlag(FLAGS_server_authority), GetQuicFlag(FLAGS_cache_dir));
+
+ auto server = std::make_unique<quic::MasqueEpollServer>(backend.get());
+
+ if (!server->CreateUDPSocketAndListen(quic::QuicSocketAddress(
+ quic::QuicIpAddress::Any6(), GetQuicFlag(FLAGS_port)))) {
+ return 1;
+ }
+
+ std::cerr << "Started MASQUE server" << std::endl;
+ server->HandleEventsForever();
+ return 0;
+}
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_server_session.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_server_session.cc
new file mode 100644
index 00000000000..e884e416702
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_server_session.cc
@@ -0,0 +1,128 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/masque/masque_server_session.h"
+
+namespace quic {
+
+MasqueServerSession::MasqueServerSession(
+ const QuicConfig& config,
+ const ParsedQuicVersionVector& supported_versions,
+ QuicConnection* connection,
+ QuicSession::Visitor* visitor,
+ Visitor* owner,
+ QuicCryptoServerStreamBase::Helper* helper,
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache,
+ MasqueServerBackend* masque_server_backend)
+ : QuicSimpleServerSession(config,
+ supported_versions,
+ connection,
+ visitor,
+ helper,
+ crypto_config,
+ compressed_certs_cache,
+ masque_server_backend),
+ masque_server_backend_(masque_server_backend),
+ owner_(owner),
+ compression_engine_(this) {
+ masque_server_backend_->RegisterBackendClient(connection_id(), this);
+}
+
+void MasqueServerSession::OnMessageReceived(quiche::QuicheStringPiece message) {
+ QUIC_DVLOG(1) << "Received DATAGRAM frame of length " << message.length();
+
+ QuicConnectionId client_connection_id, server_connection_id;
+ QuicSocketAddress server_address;
+ std::vector<char> packet;
+ bool version_present;
+ if (!compression_engine_.DecompressDatagram(
+ message, &client_connection_id, &server_connection_id,
+ &server_address, &packet, &version_present)) {
+ return;
+ }
+
+ QUIC_DVLOG(1) << "Received packet of length " << packet.size() << " for "
+ << server_address << " client " << client_connection_id;
+
+ if (version_present) {
+ if (client_connection_id.length() != kQuicDefaultConnectionIdLength) {
+ QUIC_DLOG(ERROR)
+ << "Dropping long header with invalid client_connection_id "
+ << client_connection_id;
+ return;
+ }
+ owner_->RegisterClientConnectionId(client_connection_id, this);
+ }
+
+ WriteResult write_result = connection()->writer()->WritePacket(
+ packet.data(), packet.size(), connection()->self_address().host(),
+ server_address, nullptr);
+ QUIC_DVLOG(1) << "Got " << write_result << " for " << packet.size()
+ << " bytes to " << server_address;
+}
+
+void MasqueServerSession::OnMessageAcked(QuicMessageId message_id,
+ QuicTime /*receive_timestamp*/) {
+ QUIC_DVLOG(1) << "Received ack for DATAGRAM frame " << message_id;
+}
+
+void MasqueServerSession::OnMessageLost(QuicMessageId message_id) {
+ QUIC_DVLOG(1) << "We believe DATAGRAM frame " << message_id << " was lost";
+}
+
+void MasqueServerSession::OnConnectionClosed(
+ const QuicConnectionCloseFrame& /*frame*/,
+ ConnectionCloseSource /*source*/) {
+ QUIC_DLOG(INFO) << "Closing connection for " << connection_id();
+ masque_server_backend_->RemoveBackendClient(connection_id());
+}
+
+std::unique_ptr<QuicBackendResponse> MasqueServerSession::HandleMasqueRequest(
+ const std::string& masque_path,
+ const spdy::SpdyHeaderBlock& /*request_headers*/,
+ const std::string& request_body,
+ QuicSimpleServerBackend::RequestHandler* /*request_handler*/) {
+ QUIC_DLOG(INFO) << "MasqueServerSession handling MASQUE request";
+
+ if (masque_path == "init") {
+ if (masque_initialized_) {
+ QUIC_DLOG(ERROR) << "Got second MASQUE init request";
+ return nullptr;
+ }
+ masque_initialized_ = true;
+ } else if (masque_path == "unregister") {
+ QuicConnectionId connection_id(request_body.data(), request_body.length());
+ QUIC_DLOG(INFO) << "Received MASQUE request to unregister "
+ << connection_id;
+ owner_->UnregisterClientConnectionId(connection_id);
+ compression_engine_.UnregisterClientConnectionId(connection_id);
+ } else {
+ if (!masque_initialized_) {
+ QUIC_DLOG(ERROR) << "Got MASQUE request before init";
+ return nullptr;
+ }
+ }
+
+ // TODO(dschinazi) implement binary protocol sent in response body.
+ const std::string response_body = "";
+ spdy::SpdyHeaderBlock response_headers;
+ response_headers[":status"] = "200";
+ auto response = std::make_unique<QuicBackendResponse>();
+ response->set_response_type(QuicBackendResponse::REGULAR_RESPONSE);
+ response->set_headers(std::move(response_headers));
+ response->set_body(response_body);
+
+ return response;
+}
+
+void MasqueServerSession::HandlePacketFromServer(
+ const ReceivedPacketInfo& packet_info) {
+ QUIC_DVLOG(1) << "MasqueServerSession received " << packet_info;
+ compression_engine_.CompressAndSendPacket(
+ packet_info.packet.AsStringPiece(), packet_info.destination_connection_id,
+ packet_info.source_connection_id, packet_info.peer_address);
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_server_session.h b/chromium/net/third_party/quiche/src/quic/masque/masque_server_session.h
new file mode 100644
index 00000000000..bc70f5e49f5
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_server_session.h
@@ -0,0 +1,77 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_MASQUE_MASQUE_SERVER_SESSION_H_
+#define QUICHE_QUIC_MASQUE_MASQUE_SERVER_SESSION_H_
+
+#include "net/third_party/quiche/src/quic/masque/masque_compression_engine.h"
+#include "net/third_party/quiche/src/quic/masque/masque_server_backend.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/tools/quic_simple_server_session.h"
+
+namespace quic {
+
+// QUIC server session for connection to MASQUE proxy.
+class QUIC_NO_EXPORT MasqueServerSession
+ : public QuicSimpleServerSession,
+ public MasqueServerBackend::BackendClient {
+ public:
+ // Interface meant to be implemented by owner of this MasqueServerSession
+ // instance.
+ class QUIC_NO_EXPORT Visitor {
+ public:
+ virtual ~Visitor() {}
+ // Register a client connection ID as being handled by this session.
+ virtual void RegisterClientConnectionId(
+ QuicConnectionId client_connection_id,
+ MasqueServerSession* masque_server_session) = 0;
+
+ // Unregister a client connection ID.
+ virtual void UnregisterClientConnectionId(
+ QuicConnectionId client_connection_id) = 0;
+ };
+
+ explicit MasqueServerSession(
+ const QuicConfig& config,
+ const ParsedQuicVersionVector& supported_versions,
+ QuicConnection* connection,
+ QuicSession::Visitor* visitor,
+ Visitor* owner,
+ QuicCryptoServerStreamBase::Helper* helper,
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache,
+ MasqueServerBackend* masque_server_backend);
+
+ // Disallow copy and assign.
+ MasqueServerSession(const MasqueServerSession&) = delete;
+ MasqueServerSession& operator=(const MasqueServerSession&) = delete;
+
+ // From QuicSession.
+ void OnMessageReceived(quiche::QuicheStringPiece message) override;
+ void OnMessageAcked(QuicMessageId message_id,
+ QuicTime receive_timestamp) override;
+ void OnMessageLost(QuicMessageId message_id) override;
+ void OnConnectionClosed(const QuicConnectionCloseFrame& frame,
+ ConnectionCloseSource source) override;
+
+ // From MasqueServerBackend::BackendClient.
+ std::unique_ptr<QuicBackendResponse> HandleMasqueRequest(
+ const std::string& masque_path,
+ const spdy::SpdyHeaderBlock& request_headers,
+ const std::string& request_body,
+ QuicSimpleServerBackend::RequestHandler* request_handler) override;
+
+ // Handle packet for client, meant to be called by MasqueDispatcher.
+ void HandlePacketFromServer(const ReceivedPacketInfo& packet_info);
+
+ private:
+ MasqueServerBackend* masque_server_backend_; // Unowned.
+ Visitor* owner_; // Unowned.
+ MasqueCompressionEngine compression_engine_;
+ bool masque_initialized_ = false;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_MASQUE_MASQUE_SERVER_SESSION_H_
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_utils.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_utils.cc
new file mode 100644
index 00000000000..29e254f6360
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_utils.cc
@@ -0,0 +1,31 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/masque/masque_utils.h"
+
+namespace quic {
+
+ParsedQuicVersionVector MasqueSupportedVersions() {
+ QuicVersionInitializeSupportForIetfDraft();
+ ParsedQuicVersion version = UnsupportedQuicVersion();
+ for (const ParsedQuicVersion& vers : AllSupportedVersions()) {
+ // Find the first version that supports IETF QUIC.
+ if (vers.HasIetfQuicFrames() &&
+ vers.handshake_protocol == quic::PROTOCOL_TLS1_3) {
+ version = vers;
+ break;
+ }
+ }
+ CHECK_NE(version.transport_version, QUIC_VERSION_UNSUPPORTED);
+ QuicEnableVersion(version);
+ return {version};
+}
+
+QuicConfig MasqueEncapsulatedConfig() {
+ QuicConfig config;
+ config.SetMaxPacketSizeToSend(kMasqueMaxEncapsulatedPacketSize);
+ return config;
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_utils.h b/chromium/net/third_party/quiche/src/quic/masque/masque_utils.h
new file mode 100644
index 00000000000..d8f9d0fcdb2
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_utils.h
@@ -0,0 +1,25 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_MASQUE_MASQUE_UTILS_H_
+#define QUICHE_QUIC_MASQUE_MASQUE_UTILS_H_
+
+#include "net/third_party/quiche/src/quic/core/quic_config.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
+
+namespace quic {
+
+// List of QUIC versions that support MASQUE. Currently restricted to IETF QUIC.
+QUIC_NO_EXPORT ParsedQuicVersionVector MasqueSupportedVersions();
+
+// Default QuicConfig for use with MASQUE. Sets a custom max_packet_size.
+QUIC_NO_EXPORT QuicConfig MasqueEncapsulatedConfig();
+
+// Maximum packet size for encapsulated connections.
+const QuicByteCount kMasqueMaxEncapsulatedPacketSize = 1300;
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_MASQUE_MASQUE_UTILS_H_
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_arraysize.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_arraysize.h
deleted file mode 100644
index eaa2a92a32b..00000000000
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_arraysize.h
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_ARRAYSIZE_H_
-#define QUICHE_QUIC_PLATFORM_API_QUIC_ARRAYSIZE_H_
-
-#include "net/quic/platform/impl/quic_arraysize_impl.h"
-
-#define QUIC_ARRAYSIZE(array) QUIC_ARRAYSIZE_IMPL(array)
-
-#endif // QUICHE_QUIC_PLATFORM_API_QUIC_ARRAYSIZE_H_
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_bbr2_sender.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_bbr2_sender.h
deleted file mode 100644
index 48bc86a1983..00000000000
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_bbr2_sender.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_BBR2_SENDER_H_
-#define QUICHE_QUIC_PLATFORM_API_QUIC_BBR2_SENDER_H_
-
-#include "net/quic/platform/impl/quic_bbr2_sender_impl.h"
-
-namespace quic {
-
-using QuicBbr2Sender = QuicBbr2SenderImpl;
-
-} // namespace quic
-
-#endif // QUICHE_QUIC_PLATFORM_API_QUIC_BBR2_SENDER_H_
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_cert_utils.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_cert_utils.h
index 8e21fcb65db..a680dd6e00d 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_cert_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_cert_utils.h
@@ -6,15 +6,16 @@
#define QUICHE_QUIC_PLATFORM_API_QUIC_CERT_UTILS_H_
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/quic/platform/impl/quic_cert_utils_impl.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
class QUIC_EXPORT_PRIVATE QuicCertUtils {
public:
- static bool ExtractSubjectNameFromDERCert(QuicStringPiece cert,
- QuicStringPiece* subject_out) {
+ static bool ExtractSubjectNameFromDERCert(
+ quiche::QuicheStringPiece cert,
+ quiche::QuicheStringPiece* subject_out) {
return QuicCertUtilsImpl::ExtractSubjectNameFromDERCert(cert, subject_out);
}
};
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_containers.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_containers.h
index 7cfb3117865..44c7ab10589 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_containers.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_containers.h
@@ -40,13 +40,6 @@ using QuicSmallMap = QuicSmallMapImpl<Key, Value, Size>;
template <typename T>
using QuicQueue = QuicQueueImpl<T>;
-// Represents a double-ended queue which may be backed by a list or
-// a flat circular buffer.
-//
-// DOES NOT GUARANTEE POINTER OR ITERATOR STABILITY!
-template <typename T>
-using QuicDeque = QuicDequeImpl<T>;
-
// A vector optimized for small sizes. Provides the same APIs as a std::vector.
template <typename T, size_t N, typename A = std::allocator<T>>
using QuicInlinedVector = QuicInlinedVectorImpl<T, N, A>;
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_file_utils.cc b/chromium/net/third_party/quiche/src/quic/platform/api/quic_file_utils.cc
index 29ec416b83a..40dea3ed1ca 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_file_utils.cc
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_file_utils.cc
@@ -5,6 +5,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_file_utils.h"
#include "net/quic/platform/impl/quic_file_utils_impl.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -15,7 +16,8 @@ std::vector<std::string> ReadFileContents(const std::string& dirname) {
}
// Reads the contents of |filename| as a string into |contents|.
-void ReadFileContents(QuicStringPiece filename, std::string* contents) {
+void ReadFileContents(quiche::QuicheStringPiece filename,
+ std::string* contents) {
ReadFileContentsImpl(filename, contents);
}
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_file_utils.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_file_utils.h
index 7558786f83a..8191e0a5ace 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_file_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_file_utils.h
@@ -9,7 +9,7 @@
#include <vector>
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -18,7 +18,7 @@ QUIC_EXPORT_PRIVATE std::vector<std::string> ReadFileContents(
const std::string& dirname);
// Reads the contents of |filename| as a string into |contents|.
-QUIC_EXPORT_PRIVATE void ReadFileContents(QuicStringPiece filename,
+QUIC_EXPORT_PRIVATE void ReadFileContents(quiche::QuicheStringPiece filename,
std::string* contents);
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_hostname_utils.cc b/chromium/net/third_party/quiche/src/quic/platform/api/quic_hostname_utils.cc
index b7e4642854a..5a0ccc09ccb 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_hostname_utils.cc
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_hostname_utils.cc
@@ -3,16 +3,18 @@
// found in the LICENSE file.
#include "net/third_party/quiche/src/quic/platform/api/quic_hostname_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
// static
-bool QuicHostnameUtils::IsValidSNI(QuicStringPiece sni) {
+bool QuicHostnameUtils::IsValidSNI(quiche::QuicheStringPiece sni) {
return QuicHostnameUtilsImpl::IsValidSNI(sni);
}
// static
-std::string QuicHostnameUtils::NormalizeHostname(QuicStringPiece hostname) {
+std::string QuicHostnameUtils::NormalizeHostname(
+ quiche::QuicheStringPiece hostname) {
return QuicHostnameUtilsImpl::NormalizeHostname(hostname);
}
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_hostname_utils.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_hostname_utils.h
index 672847c0733..6a04044b714 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_hostname_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_hostname_utils.h
@@ -8,8 +8,8 @@
#include <string>
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/quic/platform/impl/quic_hostname_utils_impl.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -21,12 +21,12 @@ class QUIC_EXPORT_PRIVATE QuicHostnameUtils {
// (1) disallow IP addresses;
// (2) check that the hostname contains valid characters only; and
// (3) contains at least one dot.
- static bool IsValidSNI(QuicStringPiece sni);
+ static bool IsValidSNI(quiche::QuicheStringPiece sni);
// Canonicalizes the specified hostname. This involves a wide variety of
// transformations, including lowercasing, removing trailing dots and IDNA
// conversion.
- static std::string NormalizeHostname(QuicStringPiece hostname);
+ static std::string NormalizeHostname(quiche::QuicheStringPiece hostname);
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_hostname_utils_test.cc b/chromium/net/third_party/quiche/src/quic/platform/api/quic_hostname_utils_test.cc
index 2c6573b1933..eba97c4cae5 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_hostname_utils_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_hostname_utils_test.cc
@@ -6,8 +6,8 @@
#include <string>
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
namespace quic {
namespace test {
@@ -78,7 +78,7 @@ TEST_F(QuicHostnameUtilsTest, NormalizeHostname) {
};
// clang-format on
- for (size_t i = 0; i < QUIC_ARRAYSIZE(tests); ++i) {
+ for (size_t i = 0; i < QUICHE_ARRAYSIZE(tests); ++i) {
EXPECT_EQ(std::string(tests[i].expected),
QuicHostnameUtils::NormalizeHostname(tests[i].input));
}
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_logging.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_logging.h
index ce706e53ec8..06a3a6156c0 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_logging.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_logging.h
@@ -5,36 +5,34 @@
#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_LOGGING_H_
#define QUICHE_QUIC_PLATFORM_API_QUIC_LOGGING_H_
-#include "net/quic/platform/impl/quic_logging_impl.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_logging.h"
// Please note following QUIC_LOG are platform dependent:
// INFO severity can be degraded (to VLOG(1) or DVLOG(1)).
// Some platforms may not support QUIC_LOG_FIRST_N or QUIC_LOG_EVERY_N_SEC, and
// they would simply be translated to LOG.
-#define QUIC_DVLOG(verbose_level) QUIC_DVLOG_IMPL(verbose_level)
-#define QUIC_DVLOG_IF(verbose_level, condition) \
- QUIC_DVLOG_IF_IMPL(verbose_level, condition)
-#define QUIC_DLOG(severity) QUIC_DLOG_IMPL(severity)
-#define QUIC_DLOG_IF(severity, condition) QUIC_DLOG_IF_IMPL(severity, condition)
-#define QUIC_VLOG(verbose_level) QUIC_VLOG_IMPL(verbose_level)
-#define QUIC_LOG(severity) QUIC_LOG_IMPL(severity)
-#define QUIC_LOG_FIRST_N(severity, n) QUIC_LOG_FIRST_N_IMPL(severity, n)
-#define QUIC_LOG_EVERY_N_SEC(severity, seconds) \
- QUIC_LOG_EVERY_N_SEC_IMPL(severity, seconds)
-#define QUIC_LOG_IF(severity, condition) QUIC_LOG_IF_IMPL(severity, condition)
-
-#define QUIC_PREDICT_FALSE(x) QUIC_PREDICT_FALSE_IMPL(x)
-#define QUIC_PREDICT_TRUE(x) QUIC_PREDICT_TRUE_IMPL(x)
+#define QUIC_DVLOG QUICHE_DVLOG
+#define QUIC_DVLOG_IF QUICHE_DVLOG_IF
+#define QUIC_DLOG QUICHE_DLOG
+#define QUIC_DLOG_IF QUICHE_DLOG_IF
+#define QUIC_VLOG QUICHE_VLOG
+#define QUIC_LOG QUICHE_LOG
+#define QUIC_LOG_FIRST_N QUICHE_LOG_FIRST_N
+#define QUIC_LOG_EVERY_N_SEC QUICHE_LOG_EVERY_N_SEC
+#define QUIC_LOG_IF QUICHE_LOG_IF
+
+#define QUIC_PREDICT_FALSE QUICHE_PREDICT_FALSE
+#define QUIC_PREDICT_TRUE QUICHE_PREDICT_TRUE
// This is a noop in release build.
-#define QUIC_NOTREACHED() QUIC_NOTREACHED_IMPL()
+#define QUIC_NOTREACHED QUICHE_NOTREACHED
-#define QUIC_PLOG(severity) QUIC_PLOG_IMPL(severity)
+#define QUIC_PLOG QUICHE_PLOG
-#define QUIC_DLOG_INFO_IS_ON() QUIC_DLOG_INFO_IS_ON_IMPL()
-#define QUIC_LOG_INFO_IS_ON() QUIC_LOG_INFO_IS_ON_IMPL()
-#define QUIC_LOG_WARNING_IS_ON() QUIC_LOG_WARNING_IS_ON_IMPL()
-#define QUIC_LOG_ERROR_IS_ON() QUIC_LOG_ERROR_IS_ON_IMPL()
+#define QUIC_DLOG_INFO_IS_ON QUICHE_DLOG_INFO_IS_ON
+#define QUIC_LOG_INFO_IS_ON QUICHE_LOG_INFO_IS_ON
+#define QUIC_LOG_WARNING_IS_ON QUICHE_LOG_WARNING_IS_ON
+#define QUIC_LOG_ERROR_IS_ON QUICHE_LOG_ERROR_IS_ON
#endif // QUICHE_QUIC_PLATFORM_API_QUIC_LOGGING_H_
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice.h
index a40d6384df9..2d44085588b 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice.h
@@ -26,14 +26,12 @@ class QUIC_EXPORT_PRIVATE QuicMemSlice {
// Constructs a empty QuicMemSlice with no underlying data and 0 reference
// count.
QuicMemSlice() = default;
- // Let |allocator| allocate a data buffer of |length|, then construct
- // QuicMemSlice with reference count 1 from the allocated data buffer.
- // Once all of the references to the allocated data buffer are released,
- // |allocator| is responsible to free the memory. |allocator| must
- // not be null, and |length| must not be 0. To construct an empty
- // QuicMemSlice, use the zero-argument constructor instead.
- QuicMemSlice(QuicBufferAllocator* allocator, size_t length)
- : impl_(allocator, length) {}
+
+ // Constructs a QuicMemSlice that takes ownership of |buffer|. |length| must
+ // not be zero. To construct an empty QuicMemSlice, use the zero-argument
+ // constructor instead.
+ QuicMemSlice(QuicUniqueBufferPtr buffer, size_t length)
+ : impl_(std::move(buffer), length) {}
// Constructs QuicMemSlice from |impl|. It takes the reference away from
// |impl|.
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice_span.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice_span.h
index 62cec4871c9..a1e0bd07433 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice_span.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice_span.h
@@ -7,6 +7,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/quic/platform/impl/quic_mem_slice_span_impl.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -37,8 +38,9 @@ class QUIC_EXPORT_PRIVATE QuicMemSliceSpan {
return impl_.ConsumeAll(consume);
}
- // Return data of the span at |index| by the form of a QuicStringPiece.
- QuicStringPiece GetData(int index) { return impl_.GetData(index); }
+ // Return data of the span at |index| by the form of a
+ // quiche::QuicheStringPiece.
+ quiche::QuicheStringPiece GetData(int index) { return impl_.GetData(index); }
// Return the total length of the data inside the span.
QuicByteCount total_length() { return impl_.total_length(); }
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice_test.cc b/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice_test.cc
index 185f536271d..d441aface45 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice_test.cc
@@ -15,7 +15,7 @@ class QuicMemSliceTest : public QuicTest {
public:
QuicMemSliceTest() {
size_t length = 1024;
- slice_ = QuicMemSlice(&allocator_, length);
+ slice_ = QuicMemSlice(MakeUniqueBuffer(&allocator_, length), length);
orig_data_ = slice_.data();
orig_length_ = slice_.length();
}
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_optional.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_optional.h
deleted file mode 100644
index 921c3a874a3..00000000000
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_optional.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_OPTIONAL_H_
-#define QUICHE_QUIC_PLATFORM_API_QUIC_OPTIONAL_H_
-
-#include "net/quic/platform/impl/quic_optional_impl.h"
-
-namespace quic {
-
-template <typename T>
-using QuicOptional = QuicOptionalImpl<T>;
-
-} // namespace quic
-
-#endif // QUICHE_QUIC_PLATFORM_API_QUIC_OPTIONAL_H_
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_socket_address.cc b/chromium/net/third_party/quiche/src/quic/platform/api/quic_socket_address.cc
index c53b7463601..72debb950f7 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_socket_address.cc
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_socket_address.cc
@@ -10,7 +10,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ip_address.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ip_address_family.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
namespace quic {
@@ -69,9 +69,9 @@ bool QuicSocketAddress::IsInitialized() const {
std::string QuicSocketAddress::ToString() const {
switch (host_.address_family()) {
case IpAddressFamily::IP_V4:
- return QuicStrCat(host_.ToString(), ":", port_);
+ return quiche::QuicheStrCat(host_.ToString(), ":", port_);
case IpAddressFamily::IP_V6:
- return QuicStrCat("[", host_.ToString(), "]:", port_);
+ return quiche::QuicheStrCat("[", host_.ToString(), "]:", port_);
default:
return "";
}
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_str_cat.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_str_cat.h
deleted file mode 100644
index 534e31e49bc..00000000000
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_str_cat.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_STR_CAT_H_
-#define QUICHE_QUIC_PLATFORM_API_QUIC_STR_CAT_H_
-
-#include <string>
-#include <utility>
-
-#include "net/quic/platform/impl/quic_str_cat_impl.h"
-
-namespace quic {
-
-// Merges given strings or numbers with no delimiter.
-template <typename... Args>
-inline std::string QuicStrCat(const Args&... args) {
- return QuicStrCatImpl(std::forward<const Args&>(args)...);
-}
-
-template <typename... Args>
-inline std::string QuicStringPrintf(const Args&... args) {
- return QuicStringPrintfImpl(std::forward<const Args&>(args)...);
-}
-
-} // namespace quic
-
-#endif // QUICHE_QUIC_PLATFORM_API_QUIC_STR_CAT_H_
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_str_cat_test.cc b/chromium/net/third_party/quiche/src/quic/platform/api/quic_str_cat_test.cc
deleted file mode 100644
index 06941bb5b4a..00000000000
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_str_cat_test.cc
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
-
-#include <string>
-
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-
-namespace quic {
-namespace test {
-namespace {
-
-class QuicStrCatTest : public QuicTest {};
-
-TEST_F(QuicStrCatTest, Ints) {
- const int16_t s = -1;
- const uint16_t us = 2;
- const int i = -3;
- const uint32_t ui = 4;
- const int64_t l = -5;
- const uint64_t ul = 6;
- const ptrdiff_t ptrdiff = -7;
- const size_t size = 8;
- const intptr_t intptr = -9;
- const uintptr_t uintptr = 10;
- std::string answer;
- answer = QuicStrCat(s, us);
- EXPECT_EQ(answer, "-12");
- answer = QuicStrCat(i, ui);
- EXPECT_EQ(answer, "-34");
- answer = QuicStrCat(l, ul);
- EXPECT_EQ(answer, "-56");
- answer = QuicStrCat(ptrdiff, size);
- EXPECT_EQ(answer, "-78");
- answer = QuicStrCat(size, intptr);
- EXPECT_EQ(answer, "8-9");
- answer = QuicStrCat(uintptr, 0);
- EXPECT_EQ(answer, "100");
-}
-
-TEST_F(QuicStrCatTest, Basics) {
- std::string result;
-
- std::string strs[] = {"Hello", "Cruel", "World"};
-
- QuicStringPiece pieces[] = {"Hello", "Cruel", "World"};
-
- const char* c_strs[] = {"Hello", "Cruel", "World"};
-
- int32_t i32s[] = {'H', 'C', 'W'};
- uint64_t ui64s[] = {12345678910LL, 10987654321LL};
-
- result = QuicStrCat(false, true, 2, 3);
- EXPECT_EQ(result, "0123");
-
- result = QuicStrCat(-1);
- EXPECT_EQ(result, "-1");
-
- result = QuicStrCat(0.5);
- EXPECT_EQ(result, "0.5");
-
- result = QuicStrCat(strs[1], pieces[2]);
- EXPECT_EQ(result, "CruelWorld");
-
- result = QuicStrCat(strs[0], ", ", pieces[2]);
- EXPECT_EQ(result, "Hello, World");
-
- result = QuicStrCat(strs[0], ", ", strs[1], " ", strs[2], "!");
- EXPECT_EQ(result, "Hello, Cruel World!");
-
- result = QuicStrCat(pieces[0], ", ", pieces[1], " ", pieces[2]);
- EXPECT_EQ(result, "Hello, Cruel World");
-
- result = QuicStrCat(c_strs[0], ", ", c_strs[1], " ", c_strs[2]);
- EXPECT_EQ(result, "Hello, Cruel World");
-
- result = QuicStrCat("ASCII ", i32s[0], ", ", i32s[1], " ", i32s[2], "!");
- EXPECT_EQ(result, "ASCII 72, 67 87!");
-
- result = QuicStrCat(ui64s[0], ", ", ui64s[1], "!");
- EXPECT_EQ(result, "12345678910, 10987654321!");
-
- std::string one = "1";
- result = QuicStrCat("And a ", one.size(), " and a ", &result[2] - &result[0],
- " and a ", one, " 2 3 4", "!");
- EXPECT_EQ(result, "And a 1 and a 2 and a 1 2 3 4!");
-
- result =
- QuicStrCat("To output a char by ASCII/numeric value, use +: ", '!' + 0);
- EXPECT_EQ(result, "To output a char by ASCII/numeric value, use +: 33");
-
- float f = 10000.5;
- result = QuicStrCat("Ten K and a half is ", f);
- EXPECT_EQ(result, "Ten K and a half is 10000.5");
-
- double d = 99999.9;
- result = QuicStrCat("This double number is ", d);
- EXPECT_EQ(result, "This double number is 99999.9");
-
- result =
- QuicStrCat(1, 22, 333, 4444, 55555, 666666, 7777777, 88888888, 999999999);
- EXPECT_EQ(result, "122333444455555666666777777788888888999999999");
-}
-
-TEST_F(QuicStrCatTest, MaxArgs) {
- std::string result;
- // Test 10 up to 26 arguments, the current maximum
- result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a");
- EXPECT_EQ(result, "123456789a");
- result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b");
- EXPECT_EQ(result, "123456789ab");
- result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c");
- EXPECT_EQ(result, "123456789abc");
- result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d");
- EXPECT_EQ(result, "123456789abcd");
- result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e");
- EXPECT_EQ(result, "123456789abcde");
- result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f");
- EXPECT_EQ(result, "123456789abcdef");
- result =
- QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", "g");
- EXPECT_EQ(result, "123456789abcdefg");
- result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
- "g", "h");
- EXPECT_EQ(result, "123456789abcdefgh");
- result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
- "g", "h", "i");
- EXPECT_EQ(result, "123456789abcdefghi");
- result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
- "g", "h", "i", "j");
- EXPECT_EQ(result, "123456789abcdefghij");
- result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
- "g", "h", "i", "j", "k");
- EXPECT_EQ(result, "123456789abcdefghijk");
- result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
- "g", "h", "i", "j", "k", "l");
- EXPECT_EQ(result, "123456789abcdefghijkl");
- result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
- "g", "h", "i", "j", "k", "l", "m");
- EXPECT_EQ(result, "123456789abcdefghijklm");
- result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
- "g", "h", "i", "j", "k", "l", "m", "n");
- EXPECT_EQ(result, "123456789abcdefghijklmn");
- result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
- "g", "h", "i", "j", "k", "l", "m", "n", "o");
- EXPECT_EQ(result, "123456789abcdefghijklmno");
- result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
- "g", "h", "i", "j", "k", "l", "m", "n", "o", "p");
- EXPECT_EQ(result, "123456789abcdefghijklmnop");
- result = QuicStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f",
- "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q");
- EXPECT_EQ(result, "123456789abcdefghijklmnopq");
- // No limit thanks to C++11's variadic templates
- result = QuicStrCat(
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "a", "b", "c", "d", "e", "f", "g", "h",
- "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w",
- "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L",
- "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z");
- EXPECT_EQ(result,
- "12345678910abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
-}
-
-} // namespace
-} // namespace test
-} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_string_piece.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_string_piece.h
deleted file mode 100644
index 91cb1831181..00000000000
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_string_piece.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_STRING_PIECE_H_
-#define QUICHE_QUIC_PLATFORM_API_QUIC_STRING_PIECE_H_
-
-#include "net/quic/platform/impl/quic_string_piece_impl.h"
-
-namespace quic {
-
-using QuicStringPiece = QuicStringPieceImpl;
-
-} // namespace quic
-
-#endif // QUICHE_QUIC_PLATFORM_API_QUIC_STRING_PIECE_H_
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_string_utils.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_string_utils.h
index a30833e69be..e069948902c 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_string_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_string_utils.h
@@ -8,7 +8,6 @@
#include <string>
#include <utility>
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/quic/platform/impl/quic_string_utils_impl.h"
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_string_utils_test.cc b/chromium/net/third_party/quiche/src/quic/platform/api/quic_string_utils_test.cc
index 39f675f8bd3..4f65b7d119b 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_string_utils_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_string_utils_test.cc
@@ -6,69 +6,70 @@
#include <cstdint>
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
namespace {
-TEST(QuicStringUtilsTest, QuicStrCat) {
+TEST(QuicStringUtilsTest, QuicheStrCat) {
// No arguments.
- EXPECT_EQ("", QuicStrCat());
+ EXPECT_EQ("", quiche::QuicheStrCat());
// Single string-like argument.
const char kFoo[] = "foo";
const std::string string_foo(kFoo);
- const QuicStringPiece stringpiece_foo(string_foo);
- EXPECT_EQ("foo", QuicStrCat(kFoo));
- EXPECT_EQ("foo", QuicStrCat(string_foo));
- EXPECT_EQ("foo", QuicStrCat(stringpiece_foo));
+ const quiche::QuicheStringPiece stringpiece_foo(string_foo);
+ EXPECT_EQ("foo", quiche::QuicheStrCat(kFoo));
+ EXPECT_EQ("foo", quiche::QuicheStrCat(string_foo));
+ EXPECT_EQ("foo", quiche::QuicheStrCat(stringpiece_foo));
// Two string-like arguments.
const char kBar[] = "bar";
- const QuicStringPiece stringpiece_bar(kBar);
+ const quiche::QuicheStringPiece stringpiece_bar(kBar);
const std::string string_bar(kBar);
- EXPECT_EQ("foobar", QuicStrCat(kFoo, kBar));
- EXPECT_EQ("foobar", QuicStrCat(kFoo, string_bar));
- EXPECT_EQ("foobar", QuicStrCat(kFoo, stringpiece_bar));
- EXPECT_EQ("foobar", QuicStrCat(string_foo, kBar));
- EXPECT_EQ("foobar", QuicStrCat(string_foo, string_bar));
- EXPECT_EQ("foobar", QuicStrCat(string_foo, stringpiece_bar));
- EXPECT_EQ("foobar", QuicStrCat(stringpiece_foo, kBar));
- EXPECT_EQ("foobar", QuicStrCat(stringpiece_foo, string_bar));
- EXPECT_EQ("foobar", QuicStrCat(stringpiece_foo, stringpiece_bar));
+ EXPECT_EQ("foobar", quiche::QuicheStrCat(kFoo, kBar));
+ EXPECT_EQ("foobar", quiche::QuicheStrCat(kFoo, string_bar));
+ EXPECT_EQ("foobar", quiche::QuicheStrCat(kFoo, stringpiece_bar));
+ EXPECT_EQ("foobar", quiche::QuicheStrCat(string_foo, kBar));
+ EXPECT_EQ("foobar", quiche::QuicheStrCat(string_foo, string_bar));
+ EXPECT_EQ("foobar", quiche::QuicheStrCat(string_foo, stringpiece_bar));
+ EXPECT_EQ("foobar", quiche::QuicheStrCat(stringpiece_foo, kBar));
+ EXPECT_EQ("foobar", quiche::QuicheStrCat(stringpiece_foo, string_bar));
+ EXPECT_EQ("foobar", quiche::QuicheStrCat(stringpiece_foo, stringpiece_bar));
// Many-many arguments.
- EXPECT_EQ(
- "foobarbazquxquuxquuzcorgegraultgarplywaldofredplughxyzzythud",
- QuicStrCat("foo", "bar", "baz", "qux", "quux", "quuz", "corge", "grault",
- "garply", "waldo", "fred", "plugh", "xyzzy", "thud"));
+ EXPECT_EQ("foobarbazquxquuxquuzcorgegraultgarplywaldofredplughxyzzythud",
+ quiche::QuicheStrCat("foo", "bar", "baz", "qux", "quux", "quuz",
+ "corge", "grault", "garply", "waldo", "fred",
+ "plugh", "xyzzy", "thud"));
// Numerical arguments.
const int16_t i = 1;
const uint64_t u = 8;
const double d = 3.1415;
- EXPECT_EQ("1 8", QuicStrCat(i, " ", u));
- EXPECT_EQ("3.14151181", QuicStrCat(d, i, i, u, i));
+ EXPECT_EQ("1 8", quiche::QuicheStrCat(i, " ", u));
+ EXPECT_EQ("3.14151181", quiche::QuicheStrCat(d, i, i, u, i));
EXPECT_EQ("i: 1, u: 8, d: 3.1415",
- QuicStrCat("i: ", i, ", u: ", u, ", d: ", d));
+ quiche::QuicheStrCat("i: ", i, ", u: ", u, ", d: ", d));
// Boolean arguments.
const bool t = true;
const bool f = false;
- EXPECT_EQ("1", QuicStrCat(t));
- EXPECT_EQ("0", QuicStrCat(f));
- EXPECT_EQ("0110", QuicStrCat(f, t, t, f));
+ EXPECT_EQ("1", quiche::QuicheStrCat(t));
+ EXPECT_EQ("0", quiche::QuicheStrCat(f));
+ EXPECT_EQ("0110", quiche::QuicheStrCat(f, t, t, f));
// Mixed string-like, numerical, and Boolean arguments.
EXPECT_EQ("foo1foo081bar3.14151",
- QuicStrCat(kFoo, i, string_foo, f, u, t, stringpiece_bar, d, t));
+ quiche::QuicheStrCat(kFoo, i, string_foo, f, u, t, stringpiece_bar,
+ d, t));
EXPECT_EQ("3.141511bar18bar13.14150",
- QuicStrCat(d, t, t, string_bar, i, u, kBar, t, d, f));
+ quiche::QuicheStrCat(d, t, t, string_bar, i, u, kBar, t, d, f));
}
TEST(QuicStringUtilsTest, QuicStrAppend) {
@@ -80,7 +81,7 @@ TEST(QuicStringUtilsTest, QuicStrAppend) {
// Single string-like argument.
const char kFoo[] = "foo";
const std::string string_foo(kFoo);
- const QuicStringPiece stringpiece_foo(string_foo);
+ const quiche::QuicheStringPiece stringpiece_foo(string_foo);
QuicStrAppend(&output, kFoo);
EXPECT_EQ("foo", output);
QuicStrAppend(&output, string_foo);
@@ -96,7 +97,7 @@ TEST(QuicStringUtilsTest, QuicStrAppend) {
// Two string-like arguments.
const char kBar[] = "bar";
- const QuicStringPiece stringpiece_bar(kBar);
+ const quiche::QuicheStringPiece stringpiece_bar(kBar);
const std::string string_bar(kBar);
QuicStrAppend(&output, kFoo, kBar);
EXPECT_EQ("foobar", output);
@@ -167,10 +168,11 @@ TEST(QuicStringUtilsTest, QuicStrAppend) {
}
TEST(QuicStringUtilsTest, QuicStringPrintf) {
- EXPECT_EQ("", QuicStringPrintf("%s", ""));
- EXPECT_EQ("foobar", QuicStringPrintf("%sbar", "foo"));
- EXPECT_EQ("foobar", QuicStringPrintf("%s%s", "foo", "bar"));
- EXPECT_EQ("foo: 1, bar: 2.0", QuicStringPrintf("foo: %d, bar: %.1f", 1, 2.0));
+ EXPECT_EQ("", quiche::QuicheStringPrintf("%s", ""));
+ EXPECT_EQ("foobar", quiche::QuicheStringPrintf("%sbar", "foo"));
+ EXPECT_EQ("foobar", quiche::QuicheStringPrintf("%s%s", "foo", "bar"));
+ EXPECT_EQ("foo: 1, bar: 2.0",
+ quiche::QuicheStringPrintf("foo: %d, bar: %.1f", 1, 2.0));
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_test.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_test.h
index f4ef99a3624..ffd9bb0571c 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_test.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_test.h
@@ -23,10 +23,10 @@ using ScopedEnvironmentForThreads = ScopedEnvironmentForThreadsImpl;
inline std::string QuicGetTestMemoryCachePath() {
return QuicGetTestMemoryCachePathImpl();
+}
#define EXPECT_QUIC_DEBUG_DEATH(condition, message) \
EXPECT_QUIC_DEBUG_DEATH_IMPL(condition, message)
-}
#define QUIC_SLOW_TEST(test) QUIC_SLOW_TEST_IMPL(test)
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_test_output.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_test_output.h
index 3cb13933e51..24998761832 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_test_output.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_test_output.h
@@ -5,20 +5,35 @@
#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_TEST_OUTPUT_H_
#define QUICHE_QUIC_PLATFORM_API_QUIC_TEST_OUTPUT_H_
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/quic/platform/impl/quic_test_output_impl.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
-// Records a QUIC test output file into a directory specified by QUIC_TRACE_DIR
-// environment variable. Assumes that it's called from a unit test.
+// Save |data| into ${QUIC_TEST_OUTPUT_DIR}/filename. If a file with the same
+// path already exists, overwrite it.
+inline void QuicSaveTestOutput(quiche::QuicheStringPiece filename,
+ quiche::QuicheStringPiece data) {
+ QuicSaveTestOutputImpl(filename, data);
+}
+
+// Load the content of ${QUIC_TEST_OUTPUT_DIR}/filename into |*data|.
+// Return whether it is successfully loaded.
+inline bool QuicLoadTestOutput(quiche::QuicheStringPiece filename,
+ std::string* data) {
+ return QuicLoadTestOutputImpl(filename, data);
+}
+
+// Records a QUIC trace file(.qtr) into a directory specified by the
+// QUIC_TEST_OUTPUT_DIR environment variable. Assumes that it's called from a
+// unit test.
//
// The |identifier| is a human-readable identifier that will be combined with
-// the name of the unit test and a timestamp. |data| is the test output data
-// that is being recorded into the file.
-inline void QuicRecordTestOutput(QuicStringPiece identifier,
- QuicStringPiece data) {
- QuicRecordTestOutputImpl(identifier, data);
+// the name of the unit test and a timestamp. |data| is the serialized
+// quic_trace.Trace protobuf that is being recorded into the file.
+inline void QuicRecordTrace(quiche::QuicheStringPiece identifier,
+ quiche::QuicheStringPiece data) {
+ QuicRecordTraceImpl(identifier, data);
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_text_utils.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_text_utils.h
deleted file mode 100644
index 186368f4f37..00000000000
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_text_utils.h
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_TEXT_UTILS_H_
-#define QUICHE_QUIC_PLATFORM_API_QUIC_TEXT_UTILS_H_
-
-#include <string>
-
-#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
-#include "net/quic/platform/impl/quic_text_utils_impl.h"
-
-namespace quic {
-
-// Various utilities for manipulating text.
-class QUIC_EXPORT_PRIVATE QuicTextUtils {
- public:
- // Returns true if |data| starts with |prefix|, case sensitively.
- static bool StartsWith(QuicStringPiece data, QuicStringPiece prefix) {
- return QuicTextUtilsImpl::StartsWith(data, prefix);
- }
-
- // Returns true if |data| ends with |suffix|, case insensitively.
- static bool EndsWithIgnoreCase(QuicStringPiece data, QuicStringPiece suffix) {
- return QuicTextUtilsImpl::EndsWithIgnoreCase(data, suffix);
- }
-
- // Returns a new string in which |data| has been converted to lower case.
- static std::string ToLower(QuicStringPiece data) {
- return QuicTextUtilsImpl::ToLower(data);
- }
-
- // Removes leading and trailing whitespace from |data|.
- static void RemoveLeadingAndTrailingWhitespace(QuicStringPiece* data) {
- QuicTextUtilsImpl::RemoveLeadingAndTrailingWhitespace(data);
- }
-
- // Returns true if |in| represents a valid uint64, and stores that value in
- // |out|.
- static bool StringToUint64(QuicStringPiece in, uint64_t* out) {
- return QuicTextUtilsImpl::StringToUint64(in, out);
- }
-
- // Returns true if |in| represents a valid int, and stores that value in
- // |out|.
- static bool StringToInt(QuicStringPiece in, int* out) {
- return QuicTextUtilsImpl::StringToInt(in, out);
- }
-
- // Returns true if |in| represents a valid uint32, and stores that value in
- // |out|.
- static bool StringToUint32(QuicStringPiece in, uint32_t* out) {
- return QuicTextUtilsImpl::StringToUint32(in, out);
- }
-
- // Returns true if |in| represents a valid size_t, and stores that value in
- // |out|.
- static bool StringToSizeT(QuicStringPiece in, size_t* out) {
- return QuicTextUtilsImpl::StringToSizeT(in, out);
- }
-
- // Returns a new string representing |in|.
- static std::string Uint64ToString(uint64_t in) {
- return QuicTextUtilsImpl::Uint64ToString(in);
- }
-
- // This converts |length| bytes of binary to a 2*|length|-character
- // hexadecimal representation.
- // Return value: 2*|length| characters of ASCII string.
- static std::string HexEncode(const char* data, size_t length) {
- return HexEncode(QuicStringPiece(data, length));
- }
-
- // This converts |data.length()| bytes of binary to a
- // 2*|data.length()|-character hexadecimal representation.
- // Return value: 2*|data.length()| characters of ASCII string.
- static std::string HexEncode(QuicStringPiece data) {
- return QuicTextUtilsImpl::HexEncode(data);
- }
-
- // This converts a uint32 into an 8-character hexidecimal
- // representation. Return value: 8 characters of ASCII string.
- static std::string Hex(uint32_t v) { return QuicTextUtilsImpl::Hex(v); }
-
- // Converts |data| from a hexadecimal ASCII string to a binary string
- // that is |data.length()/2| bytes long.
- static std::string HexDecode(QuicStringPiece data) {
- return QuicTextUtilsImpl::HexDecode(data);
- }
-
- // Base64 encodes with no padding |data_len| bytes of |data| into |output|.
- static void Base64Encode(const uint8_t* data,
- size_t data_len,
- std::string* output) {
- return QuicTextUtilsImpl::Base64Encode(data, data_len, output);
- }
-
- // Returns a string containing hex and ASCII representations of |binary|,
- // side-by-side in the style of hexdump. Non-printable characters will be
- // printed as '.' in the ASCII output.
- // For example, given the input "Hello, QUIC!\01\02\03\04", returns:
- // "0x0000: 4865 6c6c 6f2c 2051 5549 4321 0102 0304 Hello,.QUIC!...."
- static std::string HexDump(QuicStringPiece binary_data) {
- return QuicTextUtilsImpl::HexDump(binary_data);
- }
-
- // Returns true if |data| contains any uppercase characters.
- static bool ContainsUpperCase(QuicStringPiece data) {
- return QuicTextUtilsImpl::ContainsUpperCase(data);
- }
-
- // Returns true if |data| contains only decimal digits.
- static bool IsAllDigits(QuicStringPiece data) {
- return QuicTextUtilsImpl::IsAllDigits(data);
- }
-
- // Splits |data| into a vector of pieces delimited by |delim|.
- static std::vector<QuicStringPiece> Split(QuicStringPiece data, char delim) {
- return QuicTextUtilsImpl::Split(data, delim);
- }
-};
-
-} // namespace quic
-
-#endif // QUICHE_QUIC_PLATFORM_API_QUIC_TEXT_UTILS_H_
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_text_utils_test.cc b/chromium/net/third_party/quiche/src/quic/platform/api/quic_text_utils_test.cc
deleted file mode 100644
index af4e81d7092..00000000000
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_text_utils_test.cc
+++ /dev/null
@@ -1,212 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
-
-#include <string>
-
-#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-
-namespace quic {
-namespace test {
-
-class QuicTextUtilsTest : public QuicTest {};
-
-TEST_F(QuicTextUtilsTest, StartsWith) {
- EXPECT_TRUE(QuicTextUtils::StartsWith("hello world", "hello"));
- EXPECT_TRUE(QuicTextUtils::StartsWith("hello world", "hello world"));
- EXPECT_TRUE(QuicTextUtils::StartsWith("hello world", ""));
- EXPECT_FALSE(QuicTextUtils::StartsWith("hello world", "Hello"));
- EXPECT_FALSE(QuicTextUtils::StartsWith("hello world", "world"));
- EXPECT_FALSE(QuicTextUtils::StartsWith("hello world", "bar"));
-}
-
-TEST_F(QuicTextUtilsTest, EndsWithIgnoreCase) {
- EXPECT_TRUE(QuicTextUtils::EndsWithIgnoreCase("hello world", "world"));
- EXPECT_TRUE(QuicTextUtils::EndsWithIgnoreCase("hello world", "hello world"));
- EXPECT_TRUE(QuicTextUtils::EndsWithIgnoreCase("hello world", ""));
- EXPECT_TRUE(QuicTextUtils::EndsWithIgnoreCase("hello world", "WORLD"));
- EXPECT_FALSE(QuicTextUtils::EndsWithIgnoreCase("hello world", "hello"));
-}
-
-TEST_F(QuicTextUtilsTest, ToLower) {
- EXPECT_EQ("lower", QuicTextUtils::ToLower("LOWER"));
- EXPECT_EQ("lower", QuicTextUtils::ToLower("lower"));
- EXPECT_EQ("lower", QuicTextUtils::ToLower("lOwEr"));
- EXPECT_EQ("123", QuicTextUtils::ToLower("123"));
- EXPECT_EQ("", QuicTextUtils::ToLower(""));
-}
-
-TEST_F(QuicTextUtilsTest, RemoveLeadingAndTrailingWhitespace) {
- std::string input;
-
- for (auto* input : {"text", " text", " text", "text ", "text ", " text ",
- " text ", "\r\n\ttext", "text\n\r\t"}) {
- QuicStringPiece piece(input);
- QuicTextUtils::RemoveLeadingAndTrailingWhitespace(&piece);
- EXPECT_EQ("text", piece);
- }
-}
-
-TEST_F(QuicTextUtilsTest, StringToNumbers) {
- const std::string kMaxInt32Plus1 = "2147483648";
- const std::string kMinInt32Minus1 = "-2147483649";
- const std::string kMaxUint32Plus1 = "4294967296";
-
- {
- // StringToUint64
- uint64_t uint64_val = 0;
- EXPECT_TRUE(QuicTextUtils::StringToUint64("123", &uint64_val));
- EXPECT_EQ(123u, uint64_val);
- EXPECT_TRUE(QuicTextUtils::StringToUint64("1234", &uint64_val));
- EXPECT_EQ(1234u, uint64_val);
- EXPECT_FALSE(QuicTextUtils::StringToUint64("", &uint64_val));
- EXPECT_FALSE(QuicTextUtils::StringToUint64("-123", &uint64_val));
- EXPECT_FALSE(QuicTextUtils::StringToUint64("-123.0", &uint64_val));
- EXPECT_TRUE(QuicTextUtils::StringToUint64(kMaxUint32Plus1, &uint64_val));
- EXPECT_EQ(4294967296u, uint64_val);
- }
-
- {
- // StringToint
- int int_val = 0;
- EXPECT_TRUE(QuicTextUtils::StringToInt("123", &int_val));
- EXPECT_EQ(123, int_val);
- EXPECT_TRUE(QuicTextUtils::StringToInt("1234", &int_val));
- EXPECT_EQ(1234, int_val);
- EXPECT_FALSE(QuicTextUtils::StringToInt("", &int_val));
- EXPECT_TRUE(QuicTextUtils::StringToInt("-123", &int_val));
- EXPECT_EQ(-123, int_val);
- EXPECT_FALSE(QuicTextUtils::StringToInt("-123.0", &int_val));
- if (sizeof(int) > 4) {
- EXPECT_TRUE(QuicTextUtils::StringToInt(kMinInt32Minus1, &int_val));
- EXPECT_EQ(-2147483649ll, int_val);
- EXPECT_TRUE(QuicTextUtils::StringToInt(kMaxInt32Plus1, &int_val));
- EXPECT_EQ(2147483648ll, int_val);
- } else {
- EXPECT_FALSE(QuicTextUtils::StringToInt(kMinInt32Minus1, &int_val));
- EXPECT_FALSE(QuicTextUtils::StringToInt(kMaxInt32Plus1, &int_val));
- }
- }
-
- {
- // StringToUint32
- uint32_t uint32_val = 0;
- EXPECT_TRUE(QuicTextUtils::StringToUint32("123", &uint32_val));
- EXPECT_EQ(123u, uint32_val);
- EXPECT_TRUE(QuicTextUtils::StringToUint32("1234", &uint32_val));
- EXPECT_EQ(1234u, uint32_val);
- EXPECT_FALSE(QuicTextUtils::StringToUint32("", &uint32_val));
- EXPECT_FALSE(QuicTextUtils::StringToUint32("-123", &uint32_val));
- EXPECT_FALSE(QuicTextUtils::StringToUint32("-123.0", &uint32_val));
- EXPECT_FALSE(QuicTextUtils::StringToUint32(kMaxUint32Plus1, &uint32_val));
- }
-
- {
- // StringToSizeT
- size_t size_t_val = 0;
- EXPECT_TRUE(QuicTextUtils::StringToSizeT("123", &size_t_val));
- EXPECT_EQ(123u, size_t_val);
- EXPECT_TRUE(QuicTextUtils::StringToSizeT("1234", &size_t_val));
- EXPECT_EQ(1234u, size_t_val);
- EXPECT_FALSE(QuicTextUtils::StringToSizeT("", &size_t_val));
- EXPECT_FALSE(QuicTextUtils::StringToSizeT("-123", &size_t_val));
- EXPECT_FALSE(QuicTextUtils::StringToSizeT("-123.0", &size_t_val));
- if (sizeof(size_t) > 4) {
- EXPECT_TRUE(QuicTextUtils::StringToSizeT(kMaxUint32Plus1, &size_t_val));
- EXPECT_EQ(4294967296ull, size_t_val);
- } else {
- EXPECT_FALSE(QuicTextUtils::StringToSizeT(kMaxUint32Plus1, &size_t_val));
- }
- }
-}
-
-TEST_F(QuicTextUtilsTest, Uint64ToString) {
- EXPECT_EQ("123", QuicTextUtils::Uint64ToString(123));
- EXPECT_EQ("1234", QuicTextUtils::Uint64ToString(1234));
-}
-
-TEST_F(QuicTextUtilsTest, HexEncode) {
- EXPECT_EQ("48656c6c6f", QuicTextUtils::HexEncode("Hello", 5));
- EXPECT_EQ("48656c6c6f", QuicTextUtils::HexEncode("Hello World", 5));
- EXPECT_EQ("48656c6c6f", QuicTextUtils::HexEncode("Hello"));
- EXPECT_EQ("0102779cfa", QuicTextUtils::HexEncode("\x01\x02\x77\x9c\xfa"));
-}
-
-TEST_F(QuicTextUtilsTest, HexDecode) {
- EXPECT_EQ("Hello", QuicTextUtils::HexDecode("48656c6c6f"));
- EXPECT_EQ("", QuicTextUtils::HexDecode(""));
- EXPECT_EQ("\x01\x02\x77\x9c\xfa", QuicTextUtils::HexDecode("0102779cfa"));
-}
-
-TEST_F(QuicTextUtilsTest, HexDump) {
- // Verify output of the HexDump method is as expected.
- char packet[] = {
- 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x51, 0x55, 0x49, 0x43, 0x21,
- 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
- 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x6c,
- 0x6f, 0x6e, 0x67, 0x20, 0x65, 0x6e, 0x6f, 0x75, 0x67, 0x68, 0x20, 0x74,
- 0x6f, 0x20, 0x73, 0x70, 0x61, 0x6e, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69,
- 0x70, 0x6c, 0x65, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x6f, 0x66,
- 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2e, 0x01, 0x02, 0x03, 0x00,
- };
- EXPECT_EQ(
- QuicTextUtils::HexDump(packet),
- "0x0000: 4865 6c6c 6f2c 2051 5549 4321 2054 6869 Hello,.QUIC!.Thi\n"
- "0x0010: 7320 7374 7269 6e67 2073 686f 756c 6420 s.string.should.\n"
- "0x0020: 6265 206c 6f6e 6720 656e 6f75 6768 2074 be.long.enough.t\n"
- "0x0030: 6f20 7370 616e 206d 756c 7469 706c 6520 o.span.multiple.\n"
- "0x0040: 6c69 6e65 7320 6f66 206f 7574 7075 742e lines.of.output.\n"
- "0x0050: 0102 03 ...\n");
- // Verify that 0x21 and 0x7e are printable, 0x20 and 0x7f are not.
- EXPECT_EQ("0x0000: 2021 7e7f .!~.\n",
- QuicTextUtils::HexDump(QuicTextUtils::HexDecode("20217e7f")));
- // Verify that values above numeric_limits<unsigned char>::max() are formatted
- // properly on platforms where char is unsigned.
- EXPECT_EQ("0x0000: 90aa ff ...\n",
- QuicTextUtils::HexDump(QuicTextUtils::HexDecode("90aaff")));
-}
-
-TEST_F(QuicTextUtilsTest, Base64Encode) {
- std::string output;
- std::string input = "Hello";
- QuicTextUtils::Base64Encode(reinterpret_cast<const uint8_t*>(input.data()),
- input.length(), &output);
- EXPECT_EQ("SGVsbG8", output);
-
- input =
- "Hello, QUIC! This string should be long enough to span"
- "multiple lines of output\n";
- QuicTextUtils::Base64Encode(reinterpret_cast<const uint8_t*>(input.data()),
- input.length(), &output);
- EXPECT_EQ(
- "SGVsbG8sIFFVSUMhIFRoaXMgc3RyaW5nIHNob3VsZCBiZSBsb25n"
- "IGVub3VnaCB0byBzcGFubXVsdGlwbGUgbGluZXMgb2Ygb3V0cHV0Cg",
- output);
-}
-
-TEST_F(QuicTextUtilsTest, ContainsUpperCase) {
- EXPECT_FALSE(QuicTextUtils::ContainsUpperCase("abc"));
- EXPECT_FALSE(QuicTextUtils::ContainsUpperCase(""));
- EXPECT_FALSE(QuicTextUtils::ContainsUpperCase("123"));
- EXPECT_TRUE(QuicTextUtils::ContainsUpperCase("ABC"));
- EXPECT_TRUE(QuicTextUtils::ContainsUpperCase("aBc"));
-}
-
-TEST_F(QuicTextUtilsTest, Split) {
- EXPECT_EQ(std::vector<QuicStringPiece>({"a", "b", "c"}),
- QuicTextUtils::Split("a,b,c", ','));
- EXPECT_EQ(std::vector<QuicStringPiece>({"a", "b", "c"}),
- QuicTextUtils::Split("a:b:c", ':'));
- EXPECT_EQ(std::vector<QuicStringPiece>({"a:b:c"}),
- QuicTextUtils::Split("a:b:c", ','));
- // Leading and trailing whitespace is preserved.
- EXPECT_EQ(std::vector<QuicStringPiece>({"a", "b", "c"}),
- QuicTextUtils::Split("a,b,c", ','));
- EXPECT_EQ(std::vector<QuicStringPiece>({" a", "b ", " c "}),
- QuicTextUtils::Split(" a:b : c ", ':'));
-}
-
-} // namespace test
-} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_udp_socket_platform_api.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_udp_socket_platform_api.h
new file mode 100644
index 00000000000..2b1f9c3fbc5
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_udp_socket_platform_api.h
@@ -0,0 +1,25 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_UDP_SOCKET_PLATFORM_API_H_
+#define QUICHE_QUIC_PLATFORM_API_QUIC_UDP_SOCKET_PLATFORM_API_H_
+
+#include "net/quic/platform/impl/quic_udp_socket_platform_impl.h"
+
+namespace quic {
+
+const size_t kCmsgSpaceForGooglePacketHeader =
+ kCmsgSpaceForGooglePacketHeaderImpl;
+
+inline bool GetGooglePacketHeadersFromControlMessage(
+ struct ::cmsghdr* cmsg,
+ char** packet_headers,
+ size_t* packet_headers_len) {
+ return GetGooglePacketHeadersFromControlMessageImpl(cmsg, packet_headers,
+ packet_headers_len);
+}
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_PLATFORM_API_QUIC_UDP_SOCKET_PLATFORM_API_H_
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable.cc b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable.cc
index a6913d10fd6..c6dd96d6b6c 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable.cc
@@ -9,9 +9,10 @@
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_mutex.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/qbone/platform/icmp_packet.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
namespace {
@@ -126,7 +127,8 @@ bool IcmpReachable::OnEvent(int fd) {
return false;
}
- QUIC_VLOG(2) << QuicTextUtils::HexDump(QuicStringPiece(buffer, size));
+ QUIC_VLOG(2) << quiche::QuicheTextUtils::HexDump(
+ quiche::QuicheStringPiece(buffer, size));
auto* header = reinterpret_cast<const icmp6_hdr*>(&buffer);
QuicWriterMutexLock mu(&header_lock_);
@@ -141,7 +143,7 @@ bool IcmpReachable::OnEvent(int fd) {
QUIC_VLOG(1) << "Received ping response in "
<< absl::ToInt64Microseconds(end_ - start_) << "us.";
- string source;
+ std::string source;
QuicIpAddress source_ip;
if (!source_ip.FromPackedString(
reinterpret_cast<char*>(&source_addr.sin6_addr), sizeof(in6_addr))) {
@@ -166,8 +168,8 @@ int64 /* allow-non-std-int */ IcmpReachable::OnAlarm() {
icmp_header_.icmp6_seq++;
CreateIcmpPacket(src_.sin6_addr, dst_.sin6_addr, icmp_header_, "",
- [this](QuicStringPiece packet) {
- QUIC_VLOG(2) << QuicTextUtils::HexDump(packet);
+ [this](quiche::QuicheStringPiece packet) {
+ QUIC_VLOG(2) << quiche::QuicheTextUtils::HexDump(packet);
ssize_t size = kernel_->sendto(
send_fd_, packet.data(), packet.size(), 0,
@@ -183,7 +185,8 @@ int64 /* allow-non-std-int */ IcmpReachable::OnAlarm() {
return absl::ToUnixMicros(absl::Now() + timeout_);
}
-QuicStringPiece IcmpReachable::StatusName(IcmpReachable::Status status) {
+quiche::QuicheStringPiece IcmpReachable::StatusName(
+ IcmpReachable::Status status) {
switch (status) {
case REACHABLE:
return "REACHABLE";
@@ -205,7 +208,7 @@ void IcmpReachable::EpollCallback::OnShutdown(QuicEpollServer* eps, int fd) {
eps->UnregisterFD(fd);
}
-string IcmpReachable::EpollCallback::Name() const {
+std::string IcmpReachable::EpollCallback::Name() const {
return "ICMP Reachable";
}
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable.h b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable.h
index b4ce4c13966..f58efd08242 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable.h
@@ -9,9 +9,9 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_ip_address.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_mutex.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable_interface.h"
#include "net/third_party/quiche/src/quic/qbone/platform/kernel_interface.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -30,7 +30,7 @@ class IcmpReachable : public IcmpReachableInterface {
struct ReachableEvent {
Status status;
absl::Duration response_time;
- string source;
+ std::string source;
};
class StatsInterface {
@@ -80,7 +80,7 @@ class IcmpReachable : public IcmpReachableInterface {
int64 /* allow-non-std-int */ OnAlarm()
QUIC_LOCKS_EXCLUDED(header_lock_) override;
- static QuicStringPiece StatusName(Status status);
+ static quiche::QuicheStringPiece StatusName(Status status);
private:
class EpollCallback : public QuicEpollCallbackInterface {
@@ -105,7 +105,7 @@ class IcmpReachable : public IcmpReachableInterface {
void OnShutdown(QuicEpollServer* eps, int fd) override;
- string Name() const override;
+ std::string Name() const override;
private:
IcmpReachable* reachable_;
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable_test.cc b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable_test.cc
index 99de19ca9ad..fdadeff1ce3 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable_test.cc
@@ -65,13 +65,13 @@ class StatsInterface : public IcmpReachable::StatsInterface {
int unreachable_count() { return unreachable_count_; }
- string current_source() { return current_source_; }
+ std::string current_source() { return current_source_; }
private:
int reachable_count_ = 0;
int unreachable_count_ = 0;
- string current_source_{};
+ std::string current_source_{};
QuicUnorderedMap<int, int> read_errors_;
QuicUnorderedMap<int, int> write_errors_;
@@ -182,7 +182,7 @@ TEST_F(IcmpReachableTest, HandlesReachableEvents) {
}));
sockaddr_in6 source_addr{};
- string packed_source = source_.ToPackedString();
+ std::string packed_source = source_.ToPackedString();
memcpy(&source_addr.sin6_addr, packed_source.data(), packed_source.size());
EXPECT_CALL(kernel_, recvfrom(read_fd_, _, _, _, _, _))
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/mock_packet_exchanger_stats_interface.h b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/mock_packet_exchanger_stats_interface.h
index f74e2a3bd30..a265603c18f 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/mock_packet_exchanger_stats_interface.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/mock_packet_exchanger_stats_interface.h
@@ -13,10 +13,10 @@ namespace quic {
class MockPacketExchangerStatsInterface
: public TunDevicePacketExchanger::StatsInterface {
public:
- MOCK_METHOD0(OnPacketRead, void());
- MOCK_METHOD0(OnPacketWritten, void());
- MOCK_METHOD1(OnReadError, void(string*));
- MOCK_METHOD1(OnWriteError, void(string*));
+ MOCK_METHOD1(OnPacketRead, void(size_t));
+ MOCK_METHOD1(OnPacketWritten, void(size_t));
+ MOCK_METHOD1(OnReadError, void(std::string*));
+ MOCK_METHOD1(OnWriteError, void(std::string*));
MOCK_CONST_METHOD0(PacketsRead, int64_t());
MOCK_CONST_METHOD0(PacketsWritten, int64_t());
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device.cc b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device.cc
index e266654892b..c64e5b9e61f 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device.cc
@@ -19,13 +19,15 @@ namespace quic {
const char kTapTunDevicePath[] = "/dev/net/tun";
const int kInvalidFd = -1;
-TunDevice::TunDevice(const string& interface_name,
+TunDevice::TunDevice(const std::string& interface_name,
int mtu,
bool persist,
+ bool setup_tun,
KernelInterface* kernel)
: interface_name_(interface_name),
mtu_(mtu),
persist_(persist),
+ setup_tun_(setup_tun),
file_descriptor_(kInvalidFd),
kernel_(*kernel) {}
@@ -56,7 +58,7 @@ bool TunDevice::Init() {
// TODO(pengg): might be better to use netlink socket, once we have a library to
// use
bool TunDevice::Up() {
- if (!is_interface_up_) {
+ if (setup_tun_ && !is_interface_up_) {
struct ifreq if_request;
memset(&if_request, 0, sizeof(if_request));
// copy does not zero-terminate the result string, but we've memset the
@@ -75,7 +77,7 @@ bool TunDevice::Up() {
// TODO(pengg): might be better to use netlink socket, once we have a library to
// use
bool TunDevice::Down() {
- if (is_interface_up_) {
+ if (setup_tun_ && is_interface_up_) {
struct ifreq if_request;
memset(&if_request, 0, sizeof(if_request));
// copy does not zero-terminate the result string, but we've memset the
@@ -145,6 +147,10 @@ bool TunDevice::OpenDevice() {
// TODO(pengg): might be better to use netlink socket, once we have a library to
// use
bool TunDevice::ConfigureInterface() {
+ if (!setup_tun_) {
+ return true;
+ }
+
struct ifreq if_request;
memset(&if_request, 0, sizeof(if_request));
// copy does not zero-terminate the result string, but we've memset the entire
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device.h b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device.h
index 1828b81a1b0..9f76fa60796 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device.h
@@ -32,9 +32,10 @@ class TunDevice : public TunDeviceInterface {
// routing rules go away.
//
// The caller should own kernel and make sure it outlives this.
- TunDevice(const string& interface_name,
+ TunDevice(const std::string& interface_name,
int mtu,
bool persist,
+ bool setup_tun,
KernelInterface* kernel);
~TunDevice() override;
@@ -69,9 +70,10 @@ class TunDevice : public TunDeviceInterface {
// Opens a socket and makes netdevice ioctl call
bool NetdeviceIoctl(int request, void* argp);
- const string interface_name_;
+ const std::string interface_name_;
const int mtu_;
const bool persist_;
+ const bool setup_tun_;
int file_descriptor_;
KernelInterface& kernel_;
bool is_interface_up_ = false;
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger.cc b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger.cc
index 37fd2c0163b..4e7c93b1fe7 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger.cc
@@ -6,7 +6,7 @@
#include <utility>
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
namespace quic {
@@ -26,10 +26,11 @@ TunDevicePacketExchanger::TunDevicePacketExchanger(
bool TunDevicePacketExchanger::WritePacket(const char* packet,
size_t size,
bool* blocked,
- string* error) {
+ std::string* error) {
*blocked = false;
if (fd_ < 0) {
- *error = QuicStrCat("Invalid file descriptor of the TUN device: ", fd_);
+ *error = quiche::QuicheStrCat("Invalid file descriptor of the TUN device: ",
+ fd_);
stats_->OnWriteError(error);
return false;
}
@@ -40,22 +41,25 @@ bool TunDevicePacketExchanger::WritePacket(const char* packet,
// The tunnel is blocked. Note that this does not mean the receive buffer
// of a TCP connection is filled. This simply means the TUN device itself
// is blocked on handing packets to the rest part of the kernel.
- *error = QuicStrCat("Write to the TUN device was blocked: ", errno);
+ *error =
+ quiche::QuicheStrCat("Write to the TUN device was blocked: ", errno);
*blocked = true;
stats_->OnWriteError(error);
}
return false;
}
- stats_->OnPacketWritten();
+ stats_->OnPacketWritten(result);
return true;
}
-std::unique_ptr<QuicData> TunDevicePacketExchanger::ReadPacket(bool* blocked,
- string* error) {
+std::unique_ptr<QuicData> TunDevicePacketExchanger::ReadPacket(
+ bool* blocked,
+ std::string* error) {
*blocked = false;
if (fd_ < 0) {
- *error = QuicStrCat("Invalid file descriptor of the TUN device: ", fd_);
+ *error = quiche::QuicheStrCat("Invalid file descriptor of the TUN device: ",
+ fd_);
stats_->OnReadError(error);
return nullptr;
}
@@ -67,13 +71,14 @@ std::unique_ptr<QuicData> TunDevicePacketExchanger::ReadPacket(bool* blocked,
// is no end of file. Therefore 0 also indicates error.
if (result <= 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
- *error = QuicStrCat("Read from the TUN device was blocked: ", errno);
+ *error =
+ quiche::QuicheStrCat("Read from the TUN device was blocked: ", errno);
*blocked = true;
stats_->OnReadError(error);
}
return nullptr;
}
- stats_->OnPacketRead();
+ stats_->OnPacketRead(result);
return std::make_unique<QuicData>(read_buffer.release(), result, true);
}
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger.h b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger.h
index 42ed7fb5214..fe7c900c002 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger.h
@@ -26,10 +26,10 @@ class TunDevicePacketExchanger : public QbonePacketExchanger {
virtual ~StatsInterface() = default;
- virtual void OnPacketRead() = 0;
- virtual void OnPacketWritten() = 0;
- virtual void OnReadError(string* error) = 0;
- virtual void OnWriteError(string* error) = 0;
+ virtual void OnPacketRead(size_t count) = 0;
+ virtual void OnPacketWritten(size_t count) = 0;
+ virtual void OnReadError(std::string* error) = 0;
+ virtual void OnWriteError(std::string* error) = 0;
ABSL_MUST_USE_RESULT virtual int64_t PacketsRead() const = 0;
ABSL_MUST_USE_RESULT virtual int64_t PacketsWritten() const = 0;
@@ -57,13 +57,14 @@ class TunDevicePacketExchanger : public QbonePacketExchanger {
private:
// From QbonePacketExchanger.
- std::unique_ptr<QuicData> ReadPacket(bool* blocked, string* error) override;
+ std::unique_ptr<QuicData> ReadPacket(bool* blocked,
+ std::string* error) override;
// From QbonePacketExchanger.
bool WritePacket(const char* packet,
size_t size,
bool* blocked,
- string* error) override;
+ std::string* error) override;
int fd_ = -1;
size_t mtu_;
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger_test.cc b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger_test.cc
index 0f25e73eab4..30ef5edb1cd 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger_test.cc
@@ -23,8 +23,8 @@ using ::testing::StrictMock;
class MockVisitor : public QbonePacketExchanger::Visitor {
public:
- MOCK_METHOD1(OnReadError, void(const string&));
- MOCK_METHOD1(OnWriteError, void(const string&));
+ MOCK_METHOD1(OnReadError, void(const std::string&));
+ MOCK_METHOD1(OnWriteError, void(const std::string&));
};
class TunDevicePacketExchangerTest : public QuicTest {
@@ -47,7 +47,7 @@ class TunDevicePacketExchangerTest : public QuicTest {
};
TEST_F(TunDevicePacketExchangerTest, WritePacketReturnsFalseOnError) {
- string packet = "fake packet";
+ std::string packet = "fake packet";
EXPECT_CALL(mock_kernel_, write(kFd, _, packet.size()))
.WillOnce(Invoke([](int fd, const void* buf, size_t count) {
errno = ECOMM;
@@ -60,7 +60,7 @@ TEST_F(TunDevicePacketExchangerTest, WritePacketReturnsFalseOnError) {
TEST_F(TunDevicePacketExchangerTest,
WritePacketReturnFalseAndBlockedOnBlockedTunnel) {
- string packet = "fake packet";
+ std::string packet = "fake packet";
EXPECT_CALL(mock_kernel_, write(kFd, _, packet.size()))
.WillOnce(Invoke([](int fd, const void* buf, size_t count) {
errno = EAGAIN;
@@ -72,14 +72,14 @@ TEST_F(TunDevicePacketExchangerTest,
}
TEST_F(TunDevicePacketExchangerTest, WritePacketReturnsTrueOnSuccessfulWrite) {
- string packet = "fake packet";
+ std::string packet = "fake packet";
EXPECT_CALL(mock_kernel_, write(kFd, _, packet.size()))
.WillOnce(Invoke([packet](int fd, const void* buf, size_t count) {
EXPECT_THAT(reinterpret_cast<const char*>(buf), StrEq(packet));
return count;
}));
- EXPECT_CALL(mock_stats_, OnPacketWritten()).Times(1);
+ EXPECT_CALL(mock_stats_, OnPacketWritten(_)).Times(1);
exchanger_.WritePacketToNetwork(packet.data(), packet.size());
}
@@ -105,14 +105,14 @@ TEST_F(TunDevicePacketExchangerTest, ReadPacketReturnsNullOnBlockedRead) {
TEST_F(TunDevicePacketExchangerTest,
ReadPacketReturnsThePacketOnSuccessfulRead) {
- string packet = "fake_packet";
+ std::string packet = "fake_packet";
EXPECT_CALL(mock_kernel_, read(kFd, _, kMtu))
.WillOnce(Invoke([packet](int fd, void* buf, size_t count) {
memcpy(buf, packet.data(), packet.size());
return packet.size();
}));
EXPECT_CALL(mock_client_, ProcessPacketFromNetwork(StrEq(packet)));
- EXPECT_CALL(mock_stats_, OnPacketRead()).Times(1);
+ EXPECT_CALL(mock_stats_, OnPacketRead(_)).Times(1);
EXPECT_TRUE(exchanger_.ReadAndDeliverPacket(&mock_client_));
}
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_test.cc b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_test.cc
index e9ae4d336e7..e44f499e707 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_test.cc
@@ -123,7 +123,7 @@ class TunDeviceTest : public QuicTest {
// A TunDevice can be initialized and up
TEST_F(TunDeviceTest, BasicWorkFlow) {
SetInitExpectations(/* mtu = */ 1500, /* persist = */ false);
- TunDevice tun_device(kDeviceName, 1500, false, &mock_kernel_);
+ TunDevice tun_device(kDeviceName, 1500, false, true, &mock_kernel_);
EXPECT_TRUE(tun_device.Init());
EXPECT_GT(tun_device.GetFileDescriptor(), -1);
@@ -136,7 +136,7 @@ TEST_F(TunDeviceTest, FailToOpenTunDevice) {
SetInitExpectations(/* mtu = */ 1500, /* persist = */ false);
EXPECT_CALL(mock_kernel_, open(StrEq("/dev/net/tun"), _))
.WillOnce(Return(-1));
- TunDevice tun_device(kDeviceName, 1500, false, &mock_kernel_);
+ TunDevice tun_device(kDeviceName, 1500, false, true, &mock_kernel_);
EXPECT_FALSE(tun_device.Init());
EXPECT_EQ(tun_device.GetFileDescriptor(), -1);
}
@@ -144,7 +144,7 @@ TEST_F(TunDeviceTest, FailToOpenTunDevice) {
TEST_F(TunDeviceTest, FailToCheckFeature) {
SetInitExpectations(/* mtu = */ 1500, /* persist = */ false);
EXPECT_CALL(mock_kernel_, ioctl(_, TUNGETFEATURES, _)).WillOnce(Return(-1));
- TunDevice tun_device(kDeviceName, 1500, false, &mock_kernel_);
+ TunDevice tun_device(kDeviceName, 1500, false, true, &mock_kernel_);
EXPECT_FALSE(tun_device.Init());
EXPECT_EQ(tun_device.GetFileDescriptor(), -1);
}
@@ -157,7 +157,7 @@ TEST_F(TunDeviceTest, TooFewFeature) {
*actual_features = IFF_TUN | IFF_ONE_QUEUE;
return 0;
}));
- TunDevice tun_device(kDeviceName, 1500, false, &mock_kernel_);
+ TunDevice tun_device(kDeviceName, 1500, false, true, &mock_kernel_);
EXPECT_FALSE(tun_device.Init());
EXPECT_EQ(tun_device.GetFileDescriptor(), -1);
}
@@ -165,7 +165,7 @@ TEST_F(TunDeviceTest, TooFewFeature) {
TEST_F(TunDeviceTest, FailToSetFlag) {
SetInitExpectations(/* mtu = */ 1500, /* persist = */ true);
EXPECT_CALL(mock_kernel_, ioctl(_, TUNSETIFF, _)).WillOnce(Return(-1));
- TunDevice tun_device(kDeviceName, 1500, true, &mock_kernel_);
+ TunDevice tun_device(kDeviceName, 1500, true, true, &mock_kernel_);
EXPECT_FALSE(tun_device.Init());
EXPECT_EQ(tun_device.GetFileDescriptor(), -1);
}
@@ -173,7 +173,7 @@ TEST_F(TunDeviceTest, FailToSetFlag) {
TEST_F(TunDeviceTest, FailToPersistDevice) {
SetInitExpectations(/* mtu = */ 1500, /* persist = */ true);
EXPECT_CALL(mock_kernel_, ioctl(_, TUNSETPERSIST, _)).WillOnce(Return(-1));
- TunDevice tun_device(kDeviceName, 1500, true, &mock_kernel_);
+ TunDevice tun_device(kDeviceName, 1500, true, true, &mock_kernel_);
EXPECT_FALSE(tun_device.Init());
EXPECT_EQ(tun_device.GetFileDescriptor(), -1);
}
@@ -181,7 +181,7 @@ TEST_F(TunDeviceTest, FailToPersistDevice) {
TEST_F(TunDeviceTest, FailToOpenSocket) {
SetInitExpectations(/* mtu = */ 1500, /* persist = */ true);
EXPECT_CALL(mock_kernel_, socket(AF_INET6, _, _)).WillOnce(Return(-1));
- TunDevice tun_device(kDeviceName, 1500, true, &mock_kernel_);
+ TunDevice tun_device(kDeviceName, 1500, true, true, &mock_kernel_);
EXPECT_FALSE(tun_device.Init());
EXPECT_EQ(tun_device.GetFileDescriptor(), -1);
}
@@ -189,14 +189,14 @@ TEST_F(TunDeviceTest, FailToOpenSocket) {
TEST_F(TunDeviceTest, FailToSetMtu) {
SetInitExpectations(/* mtu = */ 1500, /* persist = */ true);
EXPECT_CALL(mock_kernel_, ioctl(_, SIOCSIFMTU, _)).WillOnce(Return(-1));
- TunDevice tun_device(kDeviceName, 1500, true, &mock_kernel_);
+ TunDevice tun_device(kDeviceName, 1500, true, true, &mock_kernel_);
EXPECT_FALSE(tun_device.Init());
EXPECT_EQ(tun_device.GetFileDescriptor(), -1);
}
TEST_F(TunDeviceTest, FailToUp) {
SetInitExpectations(/* mtu = */ 1500, /* persist = */ true);
- TunDevice tun_device(kDeviceName, 1500, true, &mock_kernel_);
+ TunDevice tun_device(kDeviceName, 1500, true, true, &mock_kernel_);
EXPECT_TRUE(tun_device.Init());
EXPECT_GT(tun_device.GetFileDescriptor(), -1);
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/mock_qbone_client.h b/chromium/net/third_party/quiche/src/quic/qbone/mock_qbone_client.h
index 37df26d5f49..0a089ea955c 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/mock_qbone_client.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/mock_qbone_client.h
@@ -7,12 +7,14 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_client_interface.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
class MockQboneClient : public QboneClientInterface {
public:
- MOCK_METHOD1(ProcessPacketFromNetwork, void(QuicStringPiece packet));
+ MOCK_METHOD1(ProcessPacketFromNetwork,
+ void(quiche::QuicheStringPiece packet));
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/mock_qbone_server_session.h b/chromium/net/third_party/quiche/src/quic/qbone/mock_qbone_server_session.h
index 652c017f64c..874ad216ca9 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/mock_qbone_server_session.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/mock_qbone_server_session.h
@@ -27,8 +27,8 @@ class MockQboneServerSession : public QboneServerSession {
MOCK_METHOD1(SendClientRequest, bool(const QboneClientRequest&));
- MOCK_METHOD1(ProcessPacketFromNetwork, void(QuicStringPiece));
- MOCK_METHOD1(ProcessPacketFromPeer, void(QuicStringPiece));
+ MOCK_METHOD1(ProcessPacketFromNetwork, void(quiche::QuicheStringPiece));
+ MOCK_METHOD1(ProcessPacketFromPeer, void(quiche::QuicheStringPiece));
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/platform/icmp_packet.cc b/chromium/net/third_party/quiche/src/quic/qbone/platform/icmp_packet.cc
index 9039944583c..e64dbbaf8f4 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/platform/icmp_packet.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/platform/icmp_packet.cc
@@ -8,6 +8,7 @@
#include "net/third_party/quiche/src/quic/qbone/platform/internet_checksum.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace {
@@ -35,11 +36,12 @@ struct IPv6PseudoHeader {
} // namespace
-void CreateIcmpPacket(in6_addr src,
- in6_addr dst,
- const icmp6_hdr& icmp_header,
- QuicStringPiece body,
- const std::function<void(QuicStringPiece)>& cb) {
+void CreateIcmpPacket(
+ in6_addr src,
+ in6_addr dst,
+ const icmp6_hdr& icmp_header,
+ quiche::QuicheStringPiece body,
+ const std::function<void(quiche::QuicheStringPiece)>& cb) {
const size_t body_size = std::min(body.size(), kICMPv6BodyMaxSize);
const size_t payload_size = kICMPv6HeaderSize + body_size;
@@ -80,7 +82,7 @@ void CreateIcmpPacket(in6_addr src,
const char* packet = reinterpret_cast<char*>(&icmp_packet);
const size_t packet_size = offsetof(ICMPv6Packet, body) + body_size;
- cb(QuicStringPiece(packet, packet_size));
+ cb(quiche::QuicheStringPiece(packet, packet_size));
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/platform/icmp_packet.h b/chromium/net/third_party/quiche/src/quic/qbone/platform/icmp_packet.h
index ae440d2901a..a76267968fc 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/platform/icmp_packet.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/platform/icmp_packet.h
@@ -11,7 +11,7 @@
#include <functional>
#include "net/third_party/quiche/src/quic/platform/api/quic_ip_address.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -21,8 +21,8 @@ namespace quic {
void CreateIcmpPacket(in6_addr src,
in6_addr dst,
const icmp6_hdr& icmp_header,
- quic::QuicStringPiece body,
- const std::function<void(quic::QuicStringPiece)>& cb);
+ quiche::QuicheStringPiece body,
+ const std::function<void(quiche::QuicheStringPiece)>& cb);
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/platform/icmp_packet_test.cc b/chromium/net/third_party/quiche/src/quic/qbone/platform/icmp_packet_test.cc
index 1aeabe08570..30fbe21ecbc 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/platform/icmp_packet_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/platform/icmp_packet_test.cc
@@ -9,7 +9,8 @@
#include <cstdint>
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
namespace {
@@ -84,13 +85,13 @@ TEST(IcmpPacketTest, CreatedPacketMatchesReference) {
icmp_header.icmp6_id = 0x82cb;
icmp_header.icmp6_seq = 0x0100;
- QuicStringPiece message_body = QuicStringPiece(
+ quiche::QuicheStringPiece message_body = quiche::QuicheStringPiece(
reinterpret_cast<const char*>(kReferenceICMPMessageBody), 56);
- QuicStringPiece expected_packet =
- QuicStringPiece(reinterpret_cast<const char*>(kReferenceICMPPacket), 104);
+ quiche::QuicheStringPiece expected_packet = quiche::QuicheStringPiece(
+ reinterpret_cast<const char*>(kReferenceICMPPacket), 104);
CreateIcmpPacket(src_addr, dst_addr, icmp_header, message_body,
- [&expected_packet](QuicStringPiece packet) {
- QUIC_LOG(INFO) << QuicTextUtils::HexDump(packet);
+ [&expected_packet](quiche::QuicheStringPiece packet) {
+ QUIC_LOG(INFO) << quiche::QuicheTextUtils::HexDump(packet);
ASSERT_EQ(packet, expected_packet);
});
}
@@ -113,13 +114,13 @@ TEST(IcmpPacketTest, NonZeroChecksumIsIgnored) {
// Set the checksum to a bogus value
icmp_header.icmp6_cksum = 0x1234;
- QuicStringPiece message_body = QuicStringPiece(
+ quiche::QuicheStringPiece message_body = quiche::QuicheStringPiece(
reinterpret_cast<const char*>(kReferenceICMPMessageBody), 56);
- QuicStringPiece expected_packet =
- QuicStringPiece(reinterpret_cast<const char*>(kReferenceICMPPacket), 104);
+ quiche::QuicheStringPiece expected_packet = quiche::QuicheStringPiece(
+ reinterpret_cast<const char*>(kReferenceICMPPacket), 104);
CreateIcmpPacket(src_addr, dst_addr, icmp_header, message_body,
- [&expected_packet](QuicStringPiece packet) {
- QUIC_LOG(INFO) << QuicTextUtils::HexDump(packet);
+ [&expected_packet](quiche::QuicheStringPiece packet) {
+ QUIC_LOG(INFO) << quiche::QuicheTextUtils::HexDump(packet);
ASSERT_EQ(packet, expected_packet);
});
}
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/platform/ip_range.cc b/chromium/net/third_party/quiche/src/quic/qbone/platform/ip_range.cc
index 03ad6407996..04198d0cf7d 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/platform/ip_range.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/platform/ip_range.cc
@@ -74,9 +74,9 @@ bool IpRange::operator!=(IpRange other) const {
return !(*this == other);
}
-bool IpRange::FromString(const string& range) {
+bool IpRange::FromString(const std::string& range) {
size_t slash_pos = range.find('/');
- if (slash_pos == string::npos) {
+ if (slash_pos == std::string::npos) {
return false;
}
QuicIpAddress prefix;
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/platform/ip_range.h b/chromium/net/third_party/quiche/src/quic/qbone/platform/ip_range.h
index 545c32c6cb9..c9f1f34e6cf 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/platform/ip_range.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/platform/ip_range.h
@@ -6,7 +6,7 @@
#define QUICHE_QUIC_QBONE_PLATFORM_IP_RANGE_H_
#include "net/third_party/quiche/src/quic/platform/api/quic_ip_address.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
namespace quic {
@@ -24,12 +24,12 @@ class IpRange {
// Parses range that looks like "10.0.0.1/8". Tailing bits will be set to zero
// after prefix_length. Return false if the parsing failed.
- bool FromString(const string& range);
+ bool FromString(const std::string& range);
// Returns the string representation of this object.
- string ToString() const {
+ std::string ToString() const {
if (IsInitialized()) {
- return absl::StrCat(prefix_.ToString(), "/", prefix_length_);
+ return quiche::QuicheStrCat(prefix_.ToString(), "/", prefix_length_);
}
return "(uninitialized)";
}
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/platform/mock_netlink.h b/chromium/net/third_party/quiche/src/quic/qbone/platform/mock_netlink.h
index 5c1e7bc2fde..e9f5d680980 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/platform/mock_netlink.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/platform/mock_netlink.h
@@ -12,7 +12,7 @@ namespace quic {
class MockNetlink : public NetlinkInterface {
public:
- MOCK_METHOD2(GetLinkInfo, bool(const string&, LinkInfo*));
+ MOCK_METHOD2(GetLinkInfo, bool(const std::string&, LinkInfo*));
MOCK_METHOD4(GetAddresses,
bool(int, uint8_t, std::vector<AddressInfo>*, int*));
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink.cc b/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink.cc
index da68e547f7b..719551d1e00 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink.cc
@@ -11,9 +11,9 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_fallthrough.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ip_address.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/quic/platform/impl/quic_ip_address_impl.h"
#include "net/third_party/quiche/src/quic/qbone/platform/rtnetlink_message.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
namespace quic {
@@ -75,12 +75,12 @@ namespace {
class LinkInfoParser : public NetlinkParserInterface {
public:
- LinkInfoParser(string interface_name, Netlink::LinkInfo* link_info)
+ LinkInfoParser(std::string interface_name, Netlink::LinkInfo* link_info)
: interface_name_(std::move(interface_name)), link_info_(link_info) {}
void Run(struct nlmsghdr* netlink_message) override {
if (netlink_message->nlmsg_type != RTM_NEWLINK) {
- QUIC_LOG(INFO) << QuicStrCat(
+ QUIC_LOG(INFO) << quiche::QuicheStrCat(
"Unexpected nlmsg_type: ", netlink_message->nlmsg_type,
" expected: ", RTM_NEWLINK);
return;
@@ -91,7 +91,7 @@ class LinkInfoParser : public NetlinkParserInterface {
// make sure interface_info is what we asked for.
if (interface_info->ifi_family != AF_UNSPEC) {
- QUIC_LOG(INFO) << QuicStrCat(
+ QUIC_LOG(INFO) << quiche::QuicheStrCat(
"Unexpected ifi_family: ", interface_info->ifi_family,
" expected: ", AF_UNSPEC);
return;
@@ -101,7 +101,7 @@ class LinkInfoParser : public NetlinkParserInterface {
size_t hardware_address_length = 0;
char broadcast_address[kHwAddrSize];
size_t broadcast_address_length = 0;
- string name;
+ std::string name;
// loop through the attributes
struct rtattr* rta;
@@ -131,8 +131,8 @@ class LinkInfoParser : public NetlinkParserInterface {
break;
}
case IFLA_IFNAME: {
- name =
- string(reinterpret_cast<char*>(RTA_DATA(rta)), RTA_PAYLOAD(rta));
+ name = std::string(reinterpret_cast<char*>(RTA_DATA(rta)),
+ RTA_PAYLOAD(rta));
// The name maybe a 0 terminated c string.
name = name.substr(0, name.find('\0'));
break;
@@ -163,14 +163,15 @@ class LinkInfoParser : public NetlinkParserInterface {
bool found_link() { return found_link_; }
private:
- const string interface_name_;
+ const std::string interface_name_;
Netlink::LinkInfo* const link_info_;
bool found_link_ = false;
};
} // namespace
-bool Netlink::GetLinkInfo(const string& interface_name, LinkInfo* link_info) {
+bool Netlink::GetLinkInfo(const std::string& interface_name,
+ LinkInfo* link_info) {
auto message = LinkMessage::New(RtnetlinkMessage::Operation::GET,
NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST,
seq_, getpid(), nullptr);
@@ -220,8 +221,8 @@ class LocalAddressParser : public NetlinkParserInterface {
// Make sure this is for an address family we're interested in.
if (interface_address->ifa_family != AF_INET &&
interface_address->ifa_family != AF_INET6) {
- QUIC_VLOG(2) << QuicStrCat("uninteresting ifa family: ",
- interface_address->ifa_family);
+ QUIC_VLOG(2) << quiche::QuicheStrCat("uninteresting ifa family: ",
+ interface_address->ifa_family);
return;
}
@@ -235,7 +236,8 @@ class LocalAddressParser : public NetlinkParserInterface {
uint8_t unwanted_flags = interface_address->ifa_flags & unwanted_flags_;
if (unwanted_flags != 0) {
- QUIC_VLOG(2) << QuicStrCat("unwanted ifa flags: ", unwanted_flags);
+ QUIC_VLOG(2) << quiche::QuicheStrCat("unwanted ifa flags: ",
+ unwanted_flags);
return;
}
@@ -274,8 +276,8 @@ class LocalAddressParser : public NetlinkParserInterface {
}
break;
default:
- QUIC_LOG(ERROR) << QuicStrCat("Unknown address family: ",
- interface_address->ifa_family);
+ QUIC_LOG(ERROR) << quiche::QuicheStrCat(
+ "Unknown address family: ", interface_address->ifa_family);
}
}
@@ -411,7 +413,7 @@ class RoutingRuleParser : public NetlinkParserInterface {
void Run(struct nlmsghdr* netlink_message) override {
if (netlink_message->nlmsg_type != RTM_NEWROUTE) {
- QUIC_LOG(WARNING) << QuicStrCat(
+ QUIC_LOG(WARNING) << quiche::QuicheStrCat(
"Unexpected nlmsg_type: ", netlink_message->nlmsg_type,
" expected: ", RTM_NEWROUTE);
return;
@@ -421,7 +423,8 @@ class RoutingRuleParser : public NetlinkParserInterface {
int payload_length = RTM_PAYLOAD(netlink_message);
if (route->rtm_family != AF_INET && route->rtm_family != AF_INET6) {
- QUIC_VLOG(2) << QuicStrCat("Uninteresting family: ", route->rtm_family);
+ QUIC_VLOG(2) << quiche::QuicheStrCat("Uninteresting family: ",
+ route->rtm_family);
return;
}
@@ -455,8 +458,8 @@ class RoutingRuleParser : public NetlinkParserInterface {
break;
}
default: {
- QUIC_VLOG(2) << QuicStrCat("Uninteresting attribute: ",
- rta->rta_type);
+ QUIC_VLOG(2) << quiche::QuicheStrCat("Uninteresting attribute: ",
+ rta->rta_type);
}
}
}
@@ -598,7 +601,7 @@ class IpRuleParser : public NetlinkParserInterface {
void Run(struct nlmsghdr* netlink_message) override {
if (netlink_message->nlmsg_type != RTM_NEWRULE) {
- QUIC_LOG(WARNING) << QuicStrCat(
+ QUIC_LOG(WARNING) << quiche::QuicheStrCat(
"Unexpected nlmsg_type: ", netlink_message->nlmsg_type,
" expected: ", RTM_NEWRULE);
return;
@@ -608,7 +611,8 @@ class IpRuleParser : public NetlinkParserInterface {
int payload_length = RTM_PAYLOAD(netlink_message);
if (rule->rtm_family != AF_INET6) {
- QUIC_LOG(ERROR) << QuicStrCat("Unexpected family: ", rule->rtm_family);
+ QUIC_LOG(ERROR) << quiche::QuicheStrCat("Unexpected family: ",
+ rule->rtm_family);
return;
}
@@ -632,8 +636,8 @@ class IpRuleParser : public NetlinkParserInterface {
break;
}
default: {
- QUIC_VLOG(2) << QuicStrCat("Uninteresting attribute: ",
- rta->rta_type);
+ QUIC_VLOG(2) << quiche::QuicheStrCat("Uninteresting attribute: ",
+ rta->rta_type);
}
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink.h b/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink.h
index 591da0f7ed0..6c856584068 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink.h
@@ -38,7 +38,8 @@ class Netlink : public NetlinkInterface {
//
// This is a synchronous communication. That should not be a problem since the
// kernel should answer immediately.
- bool GetLinkInfo(const string& interface_name, LinkInfo* link_info) override;
+ bool GetLinkInfo(const std::string& interface_name,
+ LinkInfo* link_info) override;
// Gets the addresses for the given interface referred by the given
// interface_index.
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink_interface.h b/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink_interface.h
index 447c8b2014f..1b1ba111ac7 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink_interface.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink_interface.h
@@ -36,7 +36,7 @@ class NetlinkInterface {
// Gets the link information for the interface referred by the given
// interface_name.
- virtual bool GetLinkInfo(const string& interface_name,
+ virtual bool GetLinkInfo(const std::string& interface_name,
LinkInfo* link_info) = 0;
// Address information reported back from GetAddresses.
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink_test.cc b/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink_test.cc
index 04ce68cd9a9..f8d0f193225 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink_test.cc
@@ -57,10 +57,11 @@ class NetlinkTest : public QuicTest {
EXPECT_GE(msg->msg_iovlen, 1);
EXPECT_GE(msg->msg_iov[0].iov_len, sizeof(struct nlmsghdr));
- string buf;
+ std::string buf;
for (int i = 0; i < msg->msg_iovlen; i++) {
- buf.append(string(reinterpret_cast<char*>(msg->msg_iov[i].iov_base),
- msg->msg_iov[i].iov_len));
+ buf.append(
+ std::string(reinterpret_cast<char*>(msg->msg_iov[i].iov_base),
+ msg->msg_iov[i].iov_len));
}
auto* netlink_message =
@@ -130,7 +131,7 @@ void AddRTA(struct nlmsghdr* netlink_message,
}
void CreateIfinfomsg(struct nlmsghdr* netlink_message,
- const string& interface_name,
+ const std::string& interface_name,
uint16_t type,
int index,
unsigned int flags,
@@ -194,8 +195,8 @@ void CreateIfaddrmsg(struct nlmsghdr* nlm,
family = AF_INET6;
break;
default:
- QUIC_BUG << absl::StrCat("unexpected address family: ",
- ip.address_family());
+ QUIC_BUG << quiche::QuicheStrCat("unexpected address family: ",
+ ip.address_family());
family = AF_UNSPEC;
}
auto* msg = reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(nlm));
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/platform/rtnetlink_message.h b/chromium/net/third_party/quiche/src/quic/qbone/platform/rtnetlink_message.h
index 0412d54e3f4..f36cd4c505f 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/platform/rtnetlink_message.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/platform/rtnetlink_message.h
@@ -15,7 +15,6 @@
#include <vector>
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/platform/rtnetlink_message_test.cc b/chromium/net/third_party/quiche/src/quic/qbone/platform/rtnetlink_message_test.cc
index b1292373358..64931c79fbd 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/platform/rtnetlink_message_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/platform/rtnetlink_message_test.cc
@@ -48,7 +48,7 @@ TEST(RtnetlinkMessageTest, LinkMessageCanBeCreatedForNewOperation) {
auto message = LinkMessage::New(RtnetlinkMessage::Operation::NEW, flags, seq,
pid, &interface_info_header);
- string device_name = "device0";
+ std::string device_name = "device0";
message.AppendAttribute(IFLA_IFNAME, device_name.c_str(), device_name.size());
// One rtattr appended.
@@ -81,8 +81,9 @@ TEST(RtnetlinkMessageTest, LinkMessageCanBeCreatedForNewOperation) {
auto* rta = reinterpret_cast<struct rtattr*>(iov[1].iov_base);
EXPECT_EQ(IFLA_IFNAME, rta->rta_type);
EXPECT_EQ(RTA_LENGTH(device_name.size()), rta->rta_len);
- EXPECT_THAT(device_name, StrEq(string(reinterpret_cast<char*>(RTA_DATA(rta)),
- RTA_PAYLOAD(rta))));
+ EXPECT_THAT(device_name,
+ StrEq(std::string(reinterpret_cast<char*>(RTA_DATA(rta)),
+ RTA_PAYLOAD(rta))));
}
TEST(RtnetlinkMessageTest, AddressMessageCanBeCreatedForGetOperation) {
@@ -158,9 +159,9 @@ TEST(RtnetlinkMessageTest, AddressMessageCanBeCreatedForNewOperation) {
auto* rta = reinterpret_cast<struct rtattr*>(iov[1].iov_base);
EXPECT_EQ(IFA_ADDRESS, rta->rta_type);
EXPECT_EQ(RTA_LENGTH(ip.ToPackedString().size()), rta->rta_len);
- EXPECT_THAT(
- ip.ToPackedString(),
- StrEq(string(reinterpret_cast<char*>(RTA_DATA(rta)), RTA_PAYLOAD(rta))));
+ EXPECT_THAT(ip.ToPackedString(),
+ StrEq(std::string(reinterpret_cast<char*>(RTA_DATA(rta)),
+ RTA_PAYLOAD(rta))));
}
TEST(RtnetlinkMessageTest, RouteMessageCanBeCreatedFromNewOperation) {
@@ -219,9 +220,9 @@ TEST(RtnetlinkMessageTest, RouteMessageCanBeCreatedFromNewOperation) {
auto* rta = reinterpret_cast<struct rtattr*>(iov[1].iov_base);
EXPECT_EQ(RTA_PREFSRC, rta->rta_type);
EXPECT_EQ(RTA_LENGTH(preferred_source.ToPackedString().size()), rta->rta_len);
- EXPECT_THAT(
- preferred_source.ToPackedString(),
- StrEq(string(reinterpret_cast<char*>(RTA_DATA(rta)), RTA_PAYLOAD(rta))));
+ EXPECT_THAT(preferred_source.ToPackedString(),
+ StrEq(std::string(reinterpret_cast<char*>(RTA_DATA(rta)),
+ RTA_PAYLOAD(rta))));
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/platform/tcp_packet.cc b/chromium/net/third_party/quiche/src/quic/qbone/platform/tcp_packet.cc
index 2566d25eded..6da9faa749e 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/platform/tcp_packet.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/platform/tcp_packet.cc
@@ -9,6 +9,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/qbone/platform/internet_checksum.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace {
@@ -30,8 +31,8 @@ struct TCPv6PseudoHeader {
} // namespace
void CreateTcpResetPacket(
- quic::QuicStringPiece original_packet,
- const std::function<void(quic::QuicStringPiece)>& cb) {
+ quiche::QuicheStringPiece original_packet,
+ const std::function<void(quiche::QuicheStringPiece)>& cb) {
// By the time this method is called, original_packet should be fairly
// strongly validated. However, it's better to be more paranoid than not, so
// here are a bunch of very obvious checks.
@@ -120,7 +121,7 @@ void CreateTcpResetPacket(
const char* packet = reinterpret_cast<char*>(&tcp_packet);
- cb(QuicStringPiece(packet, sizeof(tcp_packet)));
+ cb(quiche::QuicheStringPiece(packet, sizeof(tcp_packet)));
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/platform/tcp_packet.h b/chromium/net/third_party/quiche/src/quic/qbone/platform/tcp_packet.h
index cf33f03709d..bb1364b41be 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/platform/tcp_packet.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/platform/tcp_packet.h
@@ -11,14 +11,15 @@
#include <functional>
#include "net/third_party/quiche/src/quic/platform/api/quic_ip_address.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
// Creates an TCPv6 RST packet, returning a packed string representation of the
// packet to |cb|.
-void CreateTcpResetPacket(quic::QuicStringPiece original_packet,
- const std::function<void(quic::QuicStringPiece)>& cb);
+void CreateTcpResetPacket(
+ quiche::QuicheStringPiece original_packet,
+ const std::function<void(quiche::QuicheStringPiece)>& cb);
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/platform/tcp_packet_test.cc b/chromium/net/third_party/quiche/src/quic/qbone/platform/tcp_packet_test.cc
index 53a2c3f9c01..84645c8a209 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/platform/tcp_packet_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/platform/tcp_packet_test.cc
@@ -9,7 +9,8 @@
#include <cstdint>
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
namespace {
@@ -101,16 +102,17 @@ constexpr uint8_t kReferenceTCPRSTPacket[] = {
} // namespace
TEST(TcpPacketTest, CreatedPacketMatchesReference) {
- QuicStringPiece syn =
- QuicStringPiece(reinterpret_cast<const char*>(kReferenceTCPSYNPacket),
- sizeof(kReferenceTCPSYNPacket));
- QuicStringPiece expected_packet =
- QuicStringPiece(reinterpret_cast<const char*>(kReferenceTCPRSTPacket),
- sizeof(kReferenceTCPRSTPacket));
- CreateTcpResetPacket(syn, [&expected_packet](QuicStringPiece packet) {
- QUIC_LOG(INFO) << QuicTextUtils::HexDump(packet);
- ASSERT_EQ(packet, expected_packet);
- });
+ quiche::QuicheStringPiece syn = quiche::QuicheStringPiece(
+ reinterpret_cast<const char*>(kReferenceTCPSYNPacket),
+ sizeof(kReferenceTCPSYNPacket));
+ quiche::QuicheStringPiece expected_packet = quiche::QuicheStringPiece(
+ reinterpret_cast<const char*>(kReferenceTCPRSTPacket),
+ sizeof(kReferenceTCPRSTPacket));
+ CreateTcpResetPacket(
+ syn, [&expected_packet](quiche::QuicheStringPiece packet) {
+ QUIC_LOG(INFO) << quiche::QuicheTextUtils::HexDump(packet);
+ ASSERT_EQ(packet, expected_packet);
+ });
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_client.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_client.cc
index 95e3aeaf090..a2ba1175ab4 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_client.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_client.cc
@@ -11,6 +11,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_epoll.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_exported_stats.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_stream.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace {
@@ -57,10 +58,18 @@ QboneClientSession* QboneClient::qbone_session() {
return static_cast<QboneClientSession*>(QuicClientBase::session());
}
-void QboneClient::ProcessPacketFromNetwork(QuicStringPiece packet) {
+void QboneClient::ProcessPacketFromNetwork(quiche::QuicheStringPiece packet) {
qbone_session()->ProcessPacketFromNetwork(packet);
}
+bool QboneClient::EarlyDataAccepted() {
+ return qbone_session()->EarlyDataAccepted();
+}
+
+bool QboneClient::ReceivedInchoateReject() {
+ return qbone_session()->ReceivedInchoateReject();
+}
+
int QboneClient::GetNumSentClientHellosFromSession() {
return qbone_session()->GetNumSentClientHellos();
}
@@ -85,7 +94,7 @@ class QboneClientSessionWithConnection : public QboneClientSession {
public:
using QboneClientSession::QboneClientSession;
- ~QboneClientSessionWithConnection() override { delete connection(); }
+ ~QboneClientSessionWithConnection() override { DeleteConnection(); }
};
// Takes ownership of |connection|.
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_client.h b/chromium/net/third_party/quiche/src/quic/qbone/qbone_client.h
index a0fe4fc70dd..209511023d9 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_client.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_client.h
@@ -10,14 +10,15 @@
#include "net/third_party/quiche/src/quic/qbone/qbone_packet_writer.h"
#include "net/third_party/quiche/src/quic/tools/quic_client_base.h"
#include "net/third_party/quiche/src/quic/tools/quic_client_epoll_network_helper.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
// A QboneClient encapsulates connecting to a server via an epoll server
-// and setting up a Qbone tunnel. See the QboneTestClient in qbone_client_test
+// and setting up a QBONE tunnel. See the QboneTestClient in qbone_client_test
// for usage.
class QboneClient : public QuicClientBase, public QboneClientInterface {
public:
- // Note that the epoll server, qbone writer, and handler are owned
+ // Note that the epoll server, QBONE writer, and handler are owned
// by the caller.
QboneClient(QuicSocketAddress server_address,
const QuicServerId& server_id,
@@ -33,7 +34,10 @@ class QboneClient : public QuicClientBase, public QboneClientInterface {
// From QboneClientInterface. Accepts a given packet from the network and
// sends the packet down to the QBONE connection.
- void ProcessPacketFromNetwork(QuicStringPiece packet) override;
+ void ProcessPacketFromNetwork(quiche::QuicheStringPiece packet) override;
+
+ bool EarlyDataAccepted() override;
+ bool ReceivedInchoateReject() override;
protected:
int GetNumSentClientHellosFromSession() override;
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_interface.h b/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_interface.h
index 28d88ac24ad..aec3a8fac89 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_interface.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_interface.h
@@ -7,7 +7,7 @@
#include <cstdint>
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -17,7 +17,7 @@ class QboneClientInterface {
virtual ~QboneClientInterface() {}
// Accepts a given packet from the network and sends the packet down to the
// QBONE connection.
- virtual void ProcessPacketFromNetwork(QuicStringPiece packet) = 0;
+ virtual void ProcessPacketFromNetwork(quiche::QuicheStringPiece packet) = 0;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_session.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_session.cc
index e59596df88c..13f8b5fc103 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_session.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_session.cc
@@ -8,6 +8,7 @@
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_constants.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -52,6 +53,16 @@ int QboneClientSession::GetNumSentClientHellos() const {
->num_sent_client_hellos();
}
+bool QboneClientSession::EarlyDataAccepted() const {
+ return static_cast<const QuicCryptoClientStreamBase*>(GetCryptoStream())
+ ->EarlyDataAccepted();
+}
+
+bool QboneClientSession::ReceivedInchoateReject() const {
+ return static_cast<const QuicCryptoClientStreamBase*>(GetCryptoStream())
+ ->ReceivedInchoateReject();
+}
+
int QboneClientSession::GetNumReceivedServerConfigUpdates() const {
return static_cast<const QuicCryptoClientStreamBase*>(GetCryptoStream())
->num_scup_messages_received();
@@ -65,11 +76,13 @@ bool QboneClientSession::SendServerRequest(const QboneServerRequest& request) {
return control_stream_->SendRequest(request);
}
-void QboneClientSession::ProcessPacketFromNetwork(QuicStringPiece packet) {
+void QboneClientSession::ProcessPacketFromNetwork(
+ quiche::QuicheStringPiece packet) {
SendPacketToPeer(packet);
}
-void QboneClientSession::ProcessPacketFromPeer(QuicStringPiece packet) {
+void QboneClientSession::ProcessPacketFromPeer(
+ quiche::QuicheStringPiece packet) {
writer_->WritePacketToNetwork(packet.data(), packet.size());
}
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_session.h b/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_session.h
index 5dcf2acfca4..4eeb7b171f7 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_session.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_session.h
@@ -11,6 +11,7 @@
#include "net/third_party/quiche/src/quic/qbone/qbone_control_stream.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_packet_writer.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_session_base.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -37,12 +38,25 @@ class QUIC_EXPORT_PRIVATE QboneClientSession
// crypto stream. If the handshake has completed then this is one greater
// than the number of round-trips needed for the handshake.
int GetNumSentClientHellos() const;
+
+ // Returns true if early data (0-RTT data) was sent and the server accepted
+ // it.
+ bool EarlyDataAccepted() const;
+
+ // Returns true if the handshake was delayed one round trip by the server
+ // because the server wanted proof the client controls its source address
+ // before progressing further. In Google QUIC, this would be due to an
+ // inchoate REJ in the QUIC Crypto handshake; in IETF QUIC this would be due
+ // to a Retry packet.
+ // TODO(nharper): Consider a better name for this method.
+ bool ReceivedInchoateReject() const;
+
int GetNumReceivedServerConfigUpdates() const;
bool SendServerRequest(const QboneServerRequest& request);
- void ProcessPacketFromNetwork(QuicStringPiece packet) override;
- void ProcessPacketFromPeer(QuicStringPiece packet) override;
+ void ProcessPacketFromNetwork(quiche::QuicheStringPiece packet) override;
+ void ProcessPacketFromPeer(quiche::QuicheStringPiece packet) override;
// Returns true if there are active requests on this session.
bool HasActiveRequests() const;
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_test.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_test.cc
index cb197a2053a..a41e6a94eba 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_test.cc
@@ -17,7 +17,6 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test_loopback.h"
-#include "net/quic/platform/impl/quic_socket_utils.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_constants.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_packet_processor_test_tools.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_server_session.h"
@@ -26,16 +25,32 @@
#include "net/third_party/quiche/src/quic/test_tools/server_thread.h"
#include "net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.h"
#include "net/third_party/quiche/src/quic/tools/quic_server.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
namespace {
-string TestPacketIn(const string& body) {
+ParsedQuicVersionVector GetTestParams() {
+ ParsedQuicVersionVector test_versions;
+
+ // TODO(b/113130636): Make QBONE work with TLS.
+ for (const auto& version : CurrentSupportedVersionsWithQuicCrypto()) {
+ // QBONE requires MESSAGE frames
+ if (!version.SupportsMessageFrames()) {
+ continue;
+ }
+ test_versions.push_back(version);
+ }
+
+ return test_versions;
+}
+
+std::string TestPacketIn(const std::string& body) {
return PrependIPv6HeaderForTest(body, 5);
}
-string TestPacketOut(const string& body) {
+std::string TestPacketOut(const std::string& body) {
return PrependIPv6HeaderForTest(body, 4);
}
@@ -43,20 +58,20 @@ class DataSavingQbonePacketWriter : public QbonePacketWriter {
public:
void WritePacketToNetwork(const char* packet, size_t size) override {
QuicWriterMutexLock lock(&mu_);
- data_.push_back(string(packet, size));
+ data_.push_back(std::string(packet, size));
}
- std::vector<string> data() {
+ std::vector<std::string> data() {
QuicWriterMutexLock lock(&mu_);
return data_;
}
private:
QuicMutex mu_;
- std::vector<string> data_;
+ std::vector<std::string> data_;
};
-// A subclass of a qbone session that will own the connection passed in.
+// A subclass of a QBONE session that will own the connection passed in.
class ConnectionOwningQboneServerSession : public QboneServerSession {
public:
ConnectionOwningQboneServerSession(
@@ -93,7 +108,7 @@ class QuicQboneDispatcher : public QuicDispatcher {
const QuicCryptoServerConfig* crypto_config,
QuicVersionManager* version_manager,
std::unique_ptr<QuicConnectionHelperInterface> helper,
- std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
+ std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
std::unique_ptr<QuicAlarmFactory> alarm_factory,
QbonePacketWriter* writer)
: QuicDispatcher(config,
@@ -105,10 +120,10 @@ class QuicQboneDispatcher : public QuicDispatcher {
kQuicDefaultConnectionIdLength),
writer_(writer) {}
- QuicSession* CreateQuicSession(
+ std::unique_ptr<QuicSession> CreateQuicSession(
QuicConnectionId id,
const QuicSocketAddress& client,
- QuicStringPiece alpn,
+ quiche::QuicheStringPiece alpn,
const quic::ParsedQuicVersion& version) override {
CHECK_EQ(alpn, "qbone");
QuicConnection* connection =
@@ -116,7 +131,7 @@ class QuicQboneDispatcher : public QuicDispatcher {
/* owns_writer= */ false, Perspective::IS_SERVER,
ParsedQuicVersionVector{version});
// The connection owning wrapper owns the connection created.
- QboneServerSession* session = new ConnectionOwningQboneServerSession(
+ auto session = std::make_unique<ConnectionOwningQboneServerSession>(
GetSupportedVersions(), connection, this, config(), crypto_config(),
compressed_certs_cache(), writer_);
session->Initialize();
@@ -145,14 +160,14 @@ class QboneTestServer : public QuicServer {
std::unique_ptr<QuicEpollConnectionHelper>(
new QuicEpollConnectionHelper(epoll_server(),
QuicAllocator::BUFFER_POOL)),
- std::unique_ptr<QuicCryptoServerStream::Helper>(
+ std::unique_ptr<QuicCryptoServerStreamBase::Helper>(
new QboneCryptoServerStreamHelper()),
std::unique_ptr<QuicEpollAlarmFactory>(
new QuicEpollAlarmFactory(epoll_server())),
&writer_);
}
- std::vector<string> data() { return writer_.data(); }
+ std::vector<std::string> data() { return writer_.data(); }
void WaitForDataSize(int n) {
while (data().size() != n) {
@@ -183,7 +198,7 @@ class QboneTestClient : public QboneClient {
~QboneTestClient() override {}
- void SendData(const string& data) {
+ void SendData(const std::string& data) {
qbone_session()->ProcessPacketFromNetwork(data);
}
@@ -199,13 +214,20 @@ class QboneTestClient : public QboneClient {
}
}
- std::vector<string> data() { return qbone_writer_.data(); }
+ std::vector<std::string> data() { return qbone_writer_.data(); }
private:
DataSavingQbonePacketWriter qbone_writer_;
};
-TEST(QboneClientTest, SendDataFromClient) {
+class QboneClientTest : public QuicTestWithParam<ParsedQuicVersion> {};
+
+INSTANTIATE_TEST_SUITE_P(Tests,
+ QboneClientTest,
+ ::testing::ValuesIn(GetTestParams()),
+ ::testing::PrintToStringParamName());
+
+TEST_P(QboneClientTest, SendDataFromClient) {
auto server = new QboneTestServer(crypto_test_utils::ProofSourceForTesting());
QuicSocketAddress server_address(TestLoopback(),
QuicPickServerPortForTestsOrDie());
@@ -217,7 +239,7 @@ TEST(QboneClientTest, SendDataFromClient) {
QboneTestClient client(
server_address,
QuicServerId("test.example.com", server_address.port(), false),
- AllSupportedVersions(), &epoll_server,
+ ParsedQuicVersionVector{GetParam()}, &epoll_server,
crypto_test_utils::ProofVerifierForTesting());
ASSERT_TRUE(client.Initialize());
ASSERT_TRUE(client.Connect());
@@ -233,8 +255,8 @@ TEST(QboneClientTest, SendDataFromClient) {
->session_map()
.begin()
->second.get());
- string long_data(QboneConstants::kMaxQbonePacketBytes - sizeof(ip6_hdr) - 1,
- 'A');
+ std::string long_data(
+ QboneConstants::kMaxQbonePacketBytes - sizeof(ip6_hdr) - 1, 'A');
// Pretend the server gets data.
server_thread.Schedule([&server_session, &long_data]() {
server_session->ProcessPacketFromNetwork(
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_constants.h b/chromium/net/third_party/quiche/src/quic/qbone/qbone_constants.h
index 1fa2688f518..eeb617148b7 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_constants.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_constants.h
@@ -13,11 +13,11 @@
namespace quic {
struct QboneConstants {
- // Qbone's ALPN
+ // QBONE's ALPN
static constexpr char kQboneAlpn[] = "qbone";
- // The maximum number of bytes allowed in a qbone packet.
+ // The maximum number of bytes allowed in a QBONE packet.
static const QuicByteCount kMaxQbonePacketBytes = 2000;
- // The table id for Qbone's routing table. 'bone' in ascii.
+ // The table id for QBONE's routing table. 'bone' in ascii.
static const uint32_t kQboneRouteTableId = 0x626F6E65;
// The stream ID of the control channel.
static QuicStreamId GetControlStreamId(QuicTransportVersion version);
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.cc
index 02b1cb8c771..0b453a7a954 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.cc
@@ -7,6 +7,7 @@
#include "net/third_party/quiche/src/quic/core/quic_session.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_constants.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -37,7 +38,7 @@ void QboneControlStreamBase::OnDataAvailable() {
if (buffer_.size() < pending_message_size_) {
return;
}
- string tmp = buffer_.substr(0, pending_message_size_);
+ std::string tmp = buffer_.substr(0, pending_message_size_);
buffer_.erase(0, pending_message_size_);
pending_message_size_ = 0;
OnMessage(tmp);
@@ -45,7 +46,7 @@ void QboneControlStreamBase::OnDataAvailable() {
}
bool QboneControlStreamBase::SendMessage(const proto2::Message& proto) {
- string tmp;
+ std::string tmp;
if (!proto.SerializeToString(&tmp)) {
QUIC_BUG << "Failed to serialize QboneControlRequest";
return false;
@@ -58,10 +59,16 @@ bool QboneControlStreamBase::SendMessage(const proto2::Message& proto) {
uint16_t size = tmp.size();
char size_str[kRequestSizeBytes];
memcpy(size_str, &size, kRequestSizeBytes);
- WriteOrBufferData(QuicStringPiece(size_str, kRequestSizeBytes), false,
- nullptr);
+ WriteOrBufferData(quiche::QuicheStringPiece(size_str, kRequestSizeBytes),
+ false, nullptr);
WriteOrBufferData(tmp, false, nullptr);
return true;
}
+void QboneControlStreamBase::OnStreamReset(
+ const QuicRstStreamFrame& /*frame*/) {
+ stream_delegate()->OnStreamError(QUIC_INVALID_STREAM_ID,
+ "Attempt to reset control stream");
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.h b/chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.h
index 6e3dead9d8e..10da82cfcf1 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.h
@@ -6,6 +6,7 @@
#define QUICHE_QUIC_QBONE_QBONE_CONTROL_STREAM_H_
#include "net/third_party/quiche/src/quic/core/quic_stream.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_control.pb.h"
namespace quic {
@@ -18,13 +19,15 @@ class QUIC_EXPORT_PRIVATE QboneControlStreamBase : public QuicStream {
void OnDataAvailable() override;
+ void OnStreamReset(const QuicRstStreamFrame& frame) override;
+
protected:
- virtual void OnMessage(const string& data) = 0;
+ virtual void OnMessage(const std::string& data) = 0;
bool SendMessage(const proto2::Message& proto);
private:
uint16_t pending_message_size_;
- string buffer_;
+ std::string buffer_;
};
template <class T>
@@ -47,7 +50,7 @@ class QUIC_EXPORT_PRIVATE QboneControlStream : public QboneControlStreamBase {
bool SendRequest(const Outgoing& request) { return SendMessage(request); }
protected:
- void OnMessage(const string& data) override {
+ void OnMessage(const std::string& data) override {
Incoming request;
if (!request.ParseFromString(data)) {
QUIC_LOG(ERROR) << "Failed to parse incoming request";
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_exchanger.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_exchanger.cc
index d06376dfd5b..ded41a24a6f 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_exchanger.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_exchanger.cc
@@ -11,7 +11,7 @@ namespace quic {
bool QbonePacketExchanger::ReadAndDeliverPacket(
QboneClientInterface* qbone_client) {
bool blocked = false;
- string error;
+ std::string error;
std::unique_ptr<QuicData> packet = ReadPacket(&blocked, &error);
if (packet == nullptr) {
if (!blocked) {
@@ -26,7 +26,7 @@ bool QbonePacketExchanger::ReadAndDeliverPacket(
void QbonePacketExchanger::WritePacketToNetwork(const char* packet,
size_t size) {
bool blocked = false;
- string error;
+ std::string error;
if (packet_queue_.empty() && !write_blocked_) {
if (WritePacket(packet, size, &blocked, &error)) {
return;
@@ -53,7 +53,7 @@ void QbonePacketExchanger::SetWritable() {
write_blocked_ = false;
while (!packet_queue_.empty()) {
bool blocked = false;
- string error;
+ std::string error;
if (WritePacket(packet_queue_.front()->data(),
packet_queue_.front()->length(), &blocked, &error)) {
packet_queue_.pop_front();
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_exchanger.h b/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_exchanger.h
index 8620a492fdb..1b3577a24f8 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_exchanger.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_exchanger.h
@@ -12,15 +12,15 @@
namespace quic {
// Handles reading and writing on the local network and exchange packets between
-// the local network with a Qbone connection.
+// the local network with a QBONE connection.
class QbonePacketExchanger : public QbonePacketWriter {
public:
// The owner might want to receive notifications when read or write fails.
class Visitor {
public:
virtual ~Visitor() {}
- virtual void OnReadError(const string& error) {}
- virtual void OnWriteError(const string& error) {}
+ virtual void OnReadError(const std::string& error) {}
+ virtual void OnWriteError(const std::string& error) {}
};
// Does not take ownership of visitor.
QbonePacketExchanger(Visitor* visitor, size_t max_pending_packets)
@@ -53,7 +53,7 @@ class QbonePacketExchanger : public QbonePacketWriter {
// there is no packet to read, b) the read failed. In the former case, blocked
// is set to true. error contains the error message.
virtual std::unique_ptr<QuicData> ReadPacket(bool* blocked,
- string* error) = 0;
+ std::string* error) = 0;
// The actual implementation that writes a packet to the local network.
// Returns true if the write succeeds. blocked will be set to true if the
@@ -62,7 +62,7 @@ class QbonePacketExchanger : public QbonePacketWriter {
virtual bool WritePacket(const char* packet,
size_t size,
bool* blocked,
- string* error) = 0;
+ std::string* error) = 0;
std::list<std::unique_ptr<QuicData>> packet_queue_;
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_exchanger_test.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_exchanger_test.cc
index f5721777fed..1f38910d4cc 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_exchanger_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_exchanger_test.cc
@@ -19,8 +19,8 @@ const size_t kMaxPendingPackets = 2;
class MockVisitor : public QbonePacketExchanger::Visitor {
public:
- MOCK_METHOD1(OnReadError, void(const string&));
- MOCK_METHOD1(OnWriteError, void(const string&));
+ MOCK_METHOD1(OnReadError, void(const std::string&));
+ MOCK_METHOD1(OnWriteError, void(const std::string&));
};
class FakeQbonePacketExchanger : public QbonePacketExchanger {
@@ -37,23 +37,24 @@ class FakeQbonePacketExchanger : public QbonePacketExchanger {
// Sets the error to be returned by ReadPacket when the list of packets is
// empty. If error is empty string, blocked is set by ReadPacket.
- void SetReadError(const string& error) { read_error_ = error; }
+ void SetReadError(const std::string& error) { read_error_ = error; }
// Force WritePacket to fail with the given status. WritePacket returns true
// when blocked == true and error is empty.
- void ForceWriteFailure(bool blocked, const string& error) {
+ void ForceWriteFailure(bool blocked, const std::string& error) {
write_blocked_ = blocked;
write_error_ = error;
}
// Packets that have been successfully written by WritePacket.
- const std::vector<string>& packets_written() const {
+ const std::vector<std::string>& packets_written() const {
return packets_written_;
}
private:
// Implements QbonePacketExchanger::ReadPacket.
- std::unique_ptr<QuicData> ReadPacket(bool* blocked, string* error) override {
+ std::unique_ptr<QuicData> ReadPacket(bool* blocked,
+ std::string* error) override {
*blocked = false;
if (packets_to_be_read_.empty()) {
@@ -71,7 +72,7 @@ class FakeQbonePacketExchanger : public QbonePacketExchanger {
bool WritePacket(const char* packet,
size_t size,
bool* blocked,
- string* error) override {
+ std::string* error) override {
*blocked = false;
if (write_blocked_ || !write_error_.empty()) {
@@ -80,16 +81,16 @@ class FakeQbonePacketExchanger : public QbonePacketExchanger {
return false;
}
- packets_written_.push_back(string(packet, size));
+ packets_written_.push_back(std::string(packet, size));
return true;
}
- string read_error_;
+ std::string read_error_;
std::list<std::unique_ptr<QuicData>> packets_to_be_read_;
- string write_error_;
+ std::string write_error_;
bool write_blocked_ = false;
- std::vector<string> packets_written_;
+ std::vector<std::string> packets_written_;
};
TEST(QbonePacketExchangerTest,
@@ -98,7 +99,7 @@ TEST(QbonePacketExchangerTest,
FakeQbonePacketExchanger exchanger(&visitor, kMaxPendingPackets);
StrictMock<MockQboneClient> client;
- string packet = "data";
+ std::string packet = "data";
exchanger.AddPacketToBeRead(
std::make_unique<QuicData>(packet.data(), packet.length()));
EXPECT_CALL(client, ProcessPacketFromNetwork(StrEq("data")));
@@ -113,7 +114,7 @@ TEST(QbonePacketExchangerTest,
MockQboneClient client;
// Force read error.
- string io_error = "I/O error";
+ std::string io_error = "I/O error";
exchanger.SetReadError(io_error);
EXPECT_CALL(visitor, OnReadError(StrEq(io_error))).Times(1);
@@ -136,7 +137,7 @@ TEST(QbonePacketExchangerTest,
FakeQbonePacketExchanger exchanger(&visitor, kMaxPendingPackets);
MockQboneClient client;
- string packet = "data";
+ std::string packet = "data";
exchanger.WritePacketToNetwork(packet.data(), packet.length());
ASSERT_EQ(exchanger.packets_written().size(), 1);
@@ -151,7 +152,7 @@ TEST(QbonePacketExchangerTest,
// Force write to be blocked so that packets are queued.
exchanger.ForceWriteFailure(true, "");
- std::vector<string> packets = {"packet0", "packet1"};
+ std::vector<std::string> packets = {"packet0", "packet1"};
for (int i = 0; i < packets.size(); i++) {
exchanger.WritePacketToNetwork(packets[i].data(), packets[i].length());
}
@@ -178,7 +179,7 @@ TEST(QbonePacketExchangerTest,
// Force write to be blocked so that packets are queued.
exchanger.ForceWriteFailure(true, "");
- std::vector<string> packets = {"packet0", "packet1"};
+ std::vector<std::string> packets = {"packet0", "packet1"};
for (int i = 0; i < packets.size(); i++) {
exchanger.WritePacketToNetwork(packets[i].data(), packets[i].length());
}
@@ -202,7 +203,7 @@ TEST(QbonePacketExchangerTest,
}
TEST(QbonePacketExchangerTest, WritePacketToNetworkDropsPacketIfQueueIfFull) {
- std::vector<string> packets = {"packet0", "packet1", "packet2"};
+ std::vector<std::string> packets = {"packet0", "packet1", "packet2"};
size_t queue_size = packets.size() - 1;
MockVisitor visitor;
// exchanger has smaller queue than number of packets.
@@ -230,10 +231,10 @@ TEST(QbonePacketExchangerTest, WriteErrorsGetNotified) {
MockVisitor visitor;
FakeQbonePacketExchanger exchanger(&visitor, kMaxPendingPackets);
MockQboneClient client;
- string packet = "data";
+ std::string packet = "data";
// Write error is delivered to visitor during WritePacketToNetwork.
- string io_error = "I/O error";
+ std::string io_error = "I/O error";
exchanger.ForceWriteFailure(false, io_error);
EXPECT_CALL(visitor, OnWriteError(StrEq(io_error))).Times(1);
exchanger.WritePacketToNetwork(packet.data(), packet.length());
@@ -243,7 +244,7 @@ TEST(QbonePacketExchangerTest, WriteErrorsGetNotified) {
exchanger.ForceWriteFailure(true, "");
exchanger.WritePacketToNetwork(packet.data(), packet.length());
- string sys_error = "sys error";
+ std::string sys_error = "sys error";
exchanger.ForceWriteFailure(false, sys_error);
EXPECT_CALL(visitor, OnWriteError(StrEq(sys_error))).Times(1);
exchanger.SetWritable();
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor.cc
index 39b622b4de5..ef78efaef73 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor.cc
@@ -12,6 +12,7 @@
#include "net/third_party/quiche/src/quic/qbone/platform/internet_checksum.h"
#include "net/third_party/quiche/src/quic/qbone/platform/tcp_packet.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace {
@@ -50,15 +51,17 @@ QbonePacketProcessor::StatsInterface::~StatsInterface() {}
QbonePacketProcessor::Filter::~Filter() {}
QbonePacketProcessor::ProcessingResult
-QbonePacketProcessor::Filter::FilterPacket(Direction direction,
- QuicStringPiece full_packet,
- QuicStringPiece payload,
- icmp6_hdr* icmp_header,
- OutputInterface* output) {
+QbonePacketProcessor::Filter::FilterPacket(
+ Direction direction,
+ quiche::QuicheStringPiece full_packet,
+ quiche::QuicheStringPiece payload,
+ icmp6_hdr* icmp_header,
+ OutputInterface* output) {
return ProcessingResult::OK;
}
-void QbonePacketProcessor::ProcessPacket(string* packet, Direction direction) {
+void QbonePacketProcessor::ProcessPacket(std::string* packet,
+ Direction direction) {
if (QUIC_PREDICT_FALSE(!IsValid())) {
QUIC_BUG << "QuicPacketProcessor is invoked in an invalid state.";
stats_->OnPacketDroppedSilently(direction);
@@ -75,7 +78,7 @@ void QbonePacketProcessor::ProcessPacket(string* packet, Direction direction) {
switch (result) {
case ProcessingResult::OK:
switch (direction) {
- case Direction::FROM_CLIENT:
+ case Direction::FROM_OFF_NETWORK:
output_->SendPacketToNetwork(*packet);
break;
case Direction::FROM_NETWORK:
@@ -104,7 +107,7 @@ void QbonePacketProcessor::ProcessPacket(string* packet, Direction direction) {
}
QbonePacketProcessor::ProcessingResult
-QbonePacketProcessor::ProcessIPv6HeaderAndFilter(string* packet,
+QbonePacketProcessor::ProcessIPv6HeaderAndFilter(std::string* packet,
Direction direction,
uint8_t* transport_protocol,
char** transport_data,
@@ -125,7 +128,8 @@ QbonePacketProcessor::ProcessIPv6HeaderAndFilter(string* packet,
result = filter_->FilterPacket(
direction, *packet,
- QuicStringPiece(*transport_data, packet->size() - header_size),
+ quiche::QuicheStringPiece(*transport_data,
+ packet->size() - header_size),
icmp_header, output_);
}
@@ -151,7 +155,7 @@ QbonePacketProcessor::ProcessIPv6HeaderAndFilter(string* packet,
}
QbonePacketProcessor::ProcessingResult QbonePacketProcessor::ProcessIPv6Header(
- string* packet,
+ std::string* packet,
Direction direction,
uint8_t* transport_protocol,
char** transport_data,
@@ -184,7 +188,7 @@ QbonePacketProcessor::ProcessingResult QbonePacketProcessor::ProcessIPv6Header(
uint8_t address_reject_code;
bool ip_parse_result;
switch (direction) {
- case Direction::FROM_CLIENT:
+ case Direction::FROM_OFF_NETWORK:
// Expect the source IP to match the client.
ip_parse_result = address_to_check.FromPackedString(
reinterpret_cast<const char*>(&header->ip6_src),
@@ -233,31 +237,34 @@ QbonePacketProcessor::ProcessingResult QbonePacketProcessor::ProcessIPv6Header(
return ProcessingResult::OK;
}
-void QbonePacketProcessor::SendIcmpResponse(icmp6_hdr* icmp_header,
- QuicStringPiece original_packet,
- Direction original_direction) {
+void QbonePacketProcessor::SendIcmpResponse(
+ icmp6_hdr* icmp_header,
+ quiche::QuicheStringPiece original_packet,
+ Direction original_direction) {
in6_addr dst;
// TODO(b/70339814): ensure this is actually a unicast address.
memcpy(dst.s6_addr, &original_packet[8], kIPv6AddressSize);
- CreateIcmpPacket(self_ip_, dst, *icmp_header, original_packet,
- [this, original_direction](QuicStringPiece packet) {
- SendResponse(original_direction, packet);
- });
+ CreateIcmpPacket(
+ self_ip_, dst, *icmp_header, original_packet,
+ [this, original_direction](quiche::QuicheStringPiece packet) {
+ SendResponse(original_direction, packet);
+ });
}
-void QbonePacketProcessor::SendTcpReset(QuicStringPiece original_packet,
- Direction original_direction) {
- CreateTcpResetPacket(original_packet,
- [this, original_direction](QuicStringPiece packet) {
- SendResponse(original_direction, packet);
- });
+void QbonePacketProcessor::SendTcpReset(
+ quiche::QuicheStringPiece original_packet,
+ Direction original_direction) {
+ CreateTcpResetPacket(original_packet, [this, original_direction](
+ quiche::QuicheStringPiece packet) {
+ SendResponse(original_direction, packet);
+ });
}
void QbonePacketProcessor::SendResponse(Direction original_direction,
- QuicStringPiece packet) {
+ quiche::QuicheStringPiece packet) {
switch (original_direction) {
- case Direction::FROM_CLIENT:
+ case Direction::FROM_OFF_NETWORK:
output_->SendPacketToClient(packet);
break;
case Direction::FROM_NETWORK:
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor.h b/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor.h
index 44767715c61..130770d3c67 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor.h
@@ -10,7 +10,7 @@
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ip_address.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -28,7 +28,7 @@ class QbonePacketProcessor {
public:
enum class Direction {
// Packet is going from the QBONE client into the network behind the QBONE.
- FROM_CLIENT = 0,
+ FROM_OFF_NETWORK = 0,
// Packet is going from the network begin QBONE to the client.
FROM_NETWORK = 1
};
@@ -52,8 +52,8 @@ class QbonePacketProcessor {
public:
virtual ~OutputInterface();
- virtual void SendPacketToClient(QuicStringPiece packet) = 0;
- virtual void SendPacketToNetwork(QuicStringPiece packet) = 0;
+ virtual void SendPacketToClient(quiche::QuicheStringPiece packet) = 0;
+ virtual void SendPacketToNetwork(quiche::QuicheStringPiece packet) = 0;
};
class StatsInterface {
@@ -94,8 +94,8 @@ class QbonePacketProcessor {
// Note that |output| should not be used except in the DEFER case, as the
// processor will perform the necessary writes itself.
virtual ProcessingResult FilterPacket(Direction direction,
- QuicStringPiece full_packet,
- QuicStringPiece payload,
+ quiche::QuicheStringPiece full_packet,
+ quiche::QuicheStringPiece payload,
icmp6_hdr* icmp_header,
OutputInterface* output);
@@ -104,16 +104,19 @@ class QbonePacketProcessor {
// for filtering from the |ipv6_header| argument. All of those assume that
// the header is of valid size, which is true for everything passed into
// FilterPacket().
- inline uint8_t TransportProtocolFromHeader(QuicStringPiece ipv6_header) {
+ inline uint8_t TransportProtocolFromHeader(
+ quiche::QuicheStringPiece ipv6_header) {
return ipv6_header[6];
}
- inline QuicIpAddress SourceIpFromHeader(QuicStringPiece ipv6_header) {
+ inline QuicIpAddress SourceIpFromHeader(
+ quiche::QuicheStringPiece ipv6_header) {
QuicIpAddress address;
address.FromPackedString(&ipv6_header[8],
QuicIpAddress::kIPv6AddressSize);
return address;
}
- inline QuicIpAddress DestinationIpFromHeader(QuicStringPiece ipv6_header) {
+ inline QuicIpAddress DestinationIpFromHeader(
+ quiche::QuicheStringPiece ipv6_header) {
QuicIpAddress address;
address.FromPackedString(&ipv6_header[24],
QuicIpAddress::kIPv6AddressSize);
@@ -140,7 +143,7 @@ class QbonePacketProcessor {
// Accepts an IPv6 packet and handles it accordingly by either forwarding it,
// replying with an ICMP packet or silently dropping it. |packet| will be
// modified in the process, by having the TTL field decreased.
- void ProcessPacket(string* packet, Direction direction);
+ void ProcessPacket(std::string* packet, Direction direction);
void set_filter(std::unique_ptr<Filter> filter) {
filter_ = std::move(filter);
@@ -157,17 +160,17 @@ class QbonePacketProcessor {
// Processes the header and returns what should be done with the packet.
// After that, calls an external packet filter if registered. TTL of the
// packet may be decreased in the process.
- ProcessingResult ProcessIPv6HeaderAndFilter(string* packet,
+ ProcessingResult ProcessIPv6HeaderAndFilter(std::string* packet,
Direction direction,
uint8_t* transport_protocol,
char** transport_data,
icmp6_hdr* icmp_header);
void SendIcmpResponse(icmp6_hdr* icmp_header,
- QuicStringPiece original_packet,
+ quiche::QuicheStringPiece original_packet,
Direction original_direction);
- void SendTcpReset(QuicStringPiece original_packet,
+ void SendTcpReset(quiche::QuicheStringPiece original_packet,
Direction original_direction);
inline bool IsValid() const { return client_ip_ != kInvalidIpAddress; }
@@ -185,13 +188,14 @@ class QbonePacketProcessor {
private:
// Performs basic sanity and permission checks on the packet, and decreases
// the TTL.
- ProcessingResult ProcessIPv6Header(string* packet,
+ ProcessingResult ProcessIPv6Header(std::string* packet,
Direction direction,
uint8_t* transport_protocol,
char** transport_data,
icmp6_hdr* icmp_header);
- void SendResponse(Direction original_direction, QuicStringPiece packet);
+ void SendResponse(Direction original_direction,
+ quiche::QuicheStringPiece packet);
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor_test.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor_test.cc
index f7e642a6ed5..77fb5d53231 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor_test.cc
@@ -8,6 +8,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_packet_processor_test_tools.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace {
@@ -100,15 +101,15 @@ static const char kReferenceClientSubnetPacketData[] = {
// clang-format on
-static const QuicStringPiece kReferenceClientPacket(
+static const quiche::QuicheStringPiece kReferenceClientPacket(
kReferenceClientPacketData,
arraysize(kReferenceClientPacketData));
-static const QuicStringPiece kReferenceNetworkPacket(
+static const quiche::QuicheStringPiece kReferenceNetworkPacket(
kReferenceNetworkPacketData,
arraysize(kReferenceNetworkPacketData));
-static const QuicStringPiece kReferenceClientSubnetPacket(
+static const quiche::QuicheStringPiece kReferenceClientSubnetPacket(
kReferenceClientSubnetPacketData,
arraysize(kReferenceClientSubnetPacketData));
@@ -126,8 +127,8 @@ class MockPacketFilter : public QbonePacketProcessor::Filter {
public:
MOCK_METHOD5(FilterPacket,
ProcessingResult(Direction,
- QuicStringPiece,
- QuicStringPiece,
+ quiche::QuicheStringPiece,
+ quiche::QuicheStringPiece,
icmp6_hdr*,
OutputInterface*));
};
@@ -144,13 +145,13 @@ class QbonePacketProcessorTest : public QuicTest {
&stats_);
}
- void SendPacketFromClient(QuicStringPiece packet) {
- string packet_buffer(packet.data(), packet.size());
- processor_->ProcessPacket(&packet_buffer, Direction::FROM_CLIENT);
+ void SendPacketFromClient(quiche::QuicheStringPiece packet) {
+ std::string packet_buffer(packet.data(), packet.size());
+ processor_->ProcessPacket(&packet_buffer, Direction::FROM_OFF_NETWORK);
}
- void SendPacketFromNetwork(QuicStringPiece packet) {
- string packet_buffer(packet.data(), packet.size());
+ void SendPacketFromNetwork(quiche::QuicheStringPiece packet) {
+ std::string packet_buffer(packet.data(), packet.size());
processor_->ProcessPacket(&packet_buffer, Direction::FROM_NETWORK);
}
@@ -164,7 +165,7 @@ class QbonePacketProcessorTest : public QuicTest {
};
TEST_F(QbonePacketProcessorTest, EmptyPacket) {
- EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_CLIENT));
+ EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_OFF_NETWORK));
SendPacketFromClient("");
EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_NETWORK));
@@ -172,31 +173,31 @@ TEST_F(QbonePacketProcessorTest, EmptyPacket) {
}
TEST_F(QbonePacketProcessorTest, RandomGarbage) {
- EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_CLIENT));
- SendPacketFromClient(string(1280, 'a'));
+ EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_OFF_NETWORK));
+ SendPacketFromClient(std::string(1280, 'a'));
EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_NETWORK));
- SendPacketFromNetwork(string(1280, 'a'));
+ SendPacketFromNetwork(std::string(1280, 'a'));
}
TEST_F(QbonePacketProcessorTest, RandomGarbageWithCorrectLengthFields) {
- string packet(40, 'a');
+ std::string packet(40, 'a');
packet[4] = 0;
packet[5] = 0;
- EXPECT_CALL(stats_, OnPacketDroppedWithIcmp(Direction::FROM_CLIENT));
+ EXPECT_CALL(stats_, OnPacketDroppedWithIcmp(Direction::FROM_OFF_NETWORK));
EXPECT_CALL(output_, SendPacketToClient(IsIcmpMessage(ICMP6_DST_UNREACH)));
SendPacketFromClient(packet);
}
TEST_F(QbonePacketProcessorTest, GoodPacketFromClient) {
- EXPECT_CALL(stats_, OnPacketForwarded(Direction::FROM_CLIENT));
+ EXPECT_CALL(stats_, OnPacketForwarded(Direction::FROM_OFF_NETWORK));
EXPECT_CALL(output_, SendPacketToNetwork(_));
SendPacketFromClient(kReferenceClientPacket);
}
TEST_F(QbonePacketProcessorTest, GoodPacketFromClientSubnet) {
- EXPECT_CALL(stats_, OnPacketForwarded(Direction::FROM_CLIENT));
+ EXPECT_CALL(stats_, OnPacketForwarded(Direction::FROM_OFF_NETWORK));
EXPECT_CALL(output_, SendPacketToNetwork(_));
SendPacketFromClient(kReferenceClientSubnetPacket);
}
@@ -208,13 +209,13 @@ TEST_F(QbonePacketProcessorTest, GoodPacketFromNetwork) {
}
TEST_F(QbonePacketProcessorTest, GoodPacketFromNetworkWrongDirection) {
- EXPECT_CALL(stats_, OnPacketDroppedWithIcmp(Direction::FROM_CLIENT));
+ EXPECT_CALL(stats_, OnPacketDroppedWithIcmp(Direction::FROM_OFF_NETWORK));
EXPECT_CALL(output_, SendPacketToClient(IsIcmpMessage(ICMP6_DST_UNREACH)));
SendPacketFromClient(kReferenceNetworkPacket);
}
TEST_F(QbonePacketProcessorTest, TtlExpired) {
- string packet(kReferenceNetworkPacket);
+ std::string packet(kReferenceNetworkPacket);
packet[7] = 1;
EXPECT_CALL(stats_, OnPacketDroppedWithIcmp(Direction::FROM_NETWORK));
@@ -223,7 +224,7 @@ TEST_F(QbonePacketProcessorTest, TtlExpired) {
}
TEST_F(QbonePacketProcessorTest, UnknownProtocol) {
- string packet(kReferenceNetworkPacket);
+ std::string packet(kReferenceNetworkPacket);
packet[6] = IPPROTO_SCTP;
EXPECT_CALL(stats_, OnPacketDroppedWithIcmp(Direction::FROM_NETWORK));
@@ -237,7 +238,7 @@ TEST_F(QbonePacketProcessorTest, FilterFromClient) {
.WillRepeatedly(Return(ProcessingResult::SILENT_DROP));
processor_->set_filter(std::move(filter));
- EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_CLIENT));
+ EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_OFF_NETWORK));
SendPacketFromClient(kReferenceClientPacket);
}
@@ -246,8 +247,8 @@ class TestFilter : public QbonePacketProcessor::Filter {
TestFilter(QuicIpAddress client_ip, QuicIpAddress network_ip)
: client_ip_(client_ip), network_ip_(network_ip) {}
ProcessingResult FilterPacket(Direction direction,
- QuicStringPiece full_packet,
- QuicStringPiece payload,
+ quiche::QuicheStringPiece full_packet,
+ quiche::QuicheStringPiece payload,
icmp6_hdr* icmp_header,
OutputInterface* output) override {
EXPECT_EQ(kIPv6HeaderSize, full_packet.size() - payload.size());
@@ -275,7 +276,7 @@ TEST_F(QbonePacketProcessorTest, FilterHelperFunctions) {
TestFilter* filter = filter_owned.get();
processor_->set_filter(std::move(filter_owned));
- EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_CLIENT));
+ EXPECT_CALL(stats_, OnPacketDroppedSilently(Direction::FROM_OFF_NETWORK));
SendPacketFromClient(kReferenceClientPacket);
ASSERT_EQ(1, filter->called());
}
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor_test_tools.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor_test_tools.cc
index 9f9b623be92..97655e08fc2 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor_test_tools.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor_test_tools.cc
@@ -8,7 +8,7 @@
namespace quic {
-string PrependIPv6HeaderForTest(const string& body, int hops) {
+std::string PrependIPv6HeaderForTest(const std::string& body, int hops) {
ip6_hdr header;
memset(&header, 0, sizeof(header));
@@ -19,7 +19,7 @@ string PrependIPv6HeaderForTest(const string& body, int hops) {
header.ip6_src = in6addr_loopback;
header.ip6_dst = in6addr_loopback;
- string packet(sizeof(header) + body.size(), '\0');
+ std::string packet(sizeof(header) + body.size(), '\0');
memcpy(&packet[0], &header, sizeof(header));
memcpy(&packet[sizeof(header)], body.data(), body.size());
return packet;
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor_test_tools.h b/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor_test_tools.h
index 646dc427c43..809b5422f78 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor_test_tools.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor_test_tools.h
@@ -7,6 +7,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_packet_processor.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -14,8 +15,8 @@ class MockPacketProcessorOutput : public QbonePacketProcessor::OutputInterface {
public:
MockPacketProcessorOutput() {}
- MOCK_METHOD1(SendPacketToClient, void(QuicStringPiece));
- MOCK_METHOD1(SendPacketToNetwork, void(QuicStringPiece));
+ MOCK_METHOD1(SendPacketToClient, void(quiche::QuicheStringPiece));
+ MOCK_METHOD1(SendPacketToNetwork, void(quiche::QuicheStringPiece));
};
class MockPacketProcessorStats : public QbonePacketProcessor::StatsInterface {
@@ -30,7 +31,7 @@ class MockPacketProcessorStats : public QbonePacketProcessor::StatsInterface {
MOCK_METHOD1(OnPacketDeferred, void(QbonePacketProcessor::Direction));
};
-string PrependIPv6HeaderForTest(const string& body, int hops);
+std::string PrependIPv6HeaderForTest(const std::string& body, int hops);
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_server_session.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_server_session.cc
index 2b4a736c5a2..6561f57c24a 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_server_session.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_server_session.cc
@@ -10,6 +10,7 @@
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_constants.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -18,8 +19,8 @@ bool QboneCryptoServerStreamHelper::CanAcceptClientHello(
const QuicSocketAddress& client_address,
const QuicSocketAddress& peer_address,
const QuicSocketAddress& self_address,
- string* error_details) const {
- absl::string_view alpn;
+ std::string* error_details) const {
+ quiche::QuicheStringPiece alpn;
chlo.GetStringPiece(quic::kALPN, &alpn);
if (alpn != QboneConstants::kQboneAlpn) {
*error_details = "ALPN-indicated protocol is not qbone";
@@ -49,9 +50,9 @@ QboneServerSession::QboneServerSession(
QboneServerSession::~QboneServerSession() {}
std::unique_ptr<QuicCryptoStream> QboneServerSession::CreateCryptoStream() {
- return std::make_unique<QuicCryptoServerStream>(quic_crypto_server_config_,
- compressed_certs_cache_, this,
- &stream_helper_);
+ return CreateCryptoServerStream(quic_crypto_server_config_,
+ compressed_certs_cache_, this,
+ &stream_helper_);
}
void QboneServerSession::Initialize() {
@@ -71,23 +72,25 @@ bool QboneServerSession::SendClientRequest(const QboneClientRequest& request) {
return control_stream_->SendRequest(request);
}
-void QboneServerSession::ProcessPacketFromNetwork(QuicStringPiece packet) {
- string buffer = string(packet);
+void QboneServerSession::ProcessPacketFromNetwork(
+ quiche::QuicheStringPiece packet) {
+ std::string buffer = std::string(packet);
processor_.ProcessPacket(&buffer,
QbonePacketProcessor::Direction::FROM_NETWORK);
}
-void QboneServerSession::ProcessPacketFromPeer(QuicStringPiece packet) {
- string buffer = string(packet);
+void QboneServerSession::ProcessPacketFromPeer(
+ quiche::QuicheStringPiece packet) {
+ std::string buffer = std::string(packet);
processor_.ProcessPacket(&buffer,
- QbonePacketProcessor::Direction::FROM_CLIENT);
+ QbonePacketProcessor::Direction::FROM_OFF_NETWORK);
}
-void QboneServerSession::SendPacketToClient(QuicStringPiece packet) {
+void QboneServerSession::SendPacketToClient(quiche::QuicheStringPiece packet) {
SendPacketToPeer(packet);
}
-void QboneServerSession::SendPacketToNetwork(QuicStringPiece packet) {
+void QboneServerSession::SendPacketToNetwork(quiche::QuicheStringPiece packet) {
DCHECK(writer_ != nullptr);
writer_->WritePacketToNetwork(packet.data(), packet.size());
}
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_server_session.h b/chromium/net/third_party/quiche/src/quic/qbone/qbone_server_session.h
index 9536f872de5..fee1c743784 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_server_session.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_server_session.h
@@ -5,7 +5,7 @@
#ifndef QUICHE_QUIC_QBONE_QBONE_SERVER_SESSION_H_
#define QUICHE_QUIC_QBONE_QBONE_SERVER_SESSION_H_
-#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
+#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h"
#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_control.pb.h"
@@ -13,18 +13,20 @@
#include "net/third_party/quiche/src/quic/qbone/qbone_packet_processor.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_packet_writer.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_session_base.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
// A helper class is used by the QuicCryptoServerStream.
-class QboneCryptoServerStreamHelper : public QuicCryptoServerStream::Helper {
+class QboneCryptoServerStreamHelper
+ : public QuicCryptoServerStreamBase::Helper {
public:
- // This will look for the qbone alpn.
+ // This will look for the QBONE alpn.
bool CanAcceptClientHello(const CryptoHandshakeMessage& chlo,
const QuicSocketAddress& client_address,
const QuicSocketAddress& peer_address,
const QuicSocketAddress& self_address,
- string* error_details) const override;
+ std::string* error_details) const override;
};
class QUIC_EXPORT_PRIVATE QboneServerSession
@@ -51,12 +53,12 @@ class QUIC_EXPORT_PRIVATE QboneServerSession
virtual bool SendClientRequest(const QboneClientRequest& request);
- void ProcessPacketFromNetwork(QuicStringPiece packet) override;
- void ProcessPacketFromPeer(QuicStringPiece packet) override;
+ void ProcessPacketFromNetwork(quiche::QuicheStringPiece packet) override;
+ void ProcessPacketFromPeer(quiche::QuicheStringPiece packet) override;
// QbonePacketProcessor::OutputInterface implementation.
- void SendPacketToClient(QuicStringPiece packet) override;
- void SendPacketToNetwork(QuicStringPiece packet) override;
+ void SendPacketToClient(quiche::QuicheStringPiece packet) override;
+ void SendPacketToNetwork(quiche::QuicheStringPiece packet) override;
// QbonePacketProcessor::StatsInterface implementation.
void OnPacketForwarded(QbonePacketProcessor::Direction direction) override {}
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_base.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_base.cc
index c3e7731bcd0..68f659c3a6a 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_base.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_base.cc
@@ -9,11 +9,14 @@
#include <utility>
+#include "net/third_party/quiche/src/quic/core/quic_buffer_allocator.h"
#include "net/third_party/quiche/src/quic/core/quic_data_reader.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_exported_stats.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/qbone/platform/icmp_packet.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_constants.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -35,9 +38,9 @@ QboneSessionBase::QboneSessionBase(
const uint32_t max_streams =
(std::numeric_limits<uint32_t>::max() / kMaxAvailableStreamsMultiplier) -
1;
- this->config()->SetMaxIncomingBidirectionalStreamsToSend(max_streams);
+ this->config()->SetMaxBidirectionalStreamsToSend(max_streams);
if (VersionHasIetfQuicFrames(transport_version())) {
- ConfigureMaxIncomingDynamicStreamsToSend(max_streams);
+ ConfigureMaxDynamicStreamsToSend(max_streams);
}
}
@@ -79,14 +82,14 @@ void QboneSessionBase::OnStreamFrame(const QuicStreamFrame& frame) {
if (frame.offset == 0 && frame.fin && frame.data_length > 0) {
++num_ephemeral_packets_;
ProcessPacketFromPeer(
- QuicStringPiece(frame.data_buffer, frame.data_length));
+ quiche::QuicheStringPiece(frame.data_buffer, frame.data_length));
flow_controller()->AddBytesConsumed(frame.data_length);
return;
}
QuicSession::OnStreamFrame(frame);
}
-void QboneSessionBase::OnMessageReceived(QuicStringPiece message) {
+void QboneSessionBase::OnMessageReceived(quiche::QuicheStringPiece message) {
++num_message_packets_;
ProcessPacketFromPeer(message);
}
@@ -101,7 +104,7 @@ QuicStream* QboneSessionBase::CreateIncomingStream(PendingStream* /*pending*/) {
}
bool QboneSessionBase::ShouldKeepConnectionAlive() const {
- // Qbone connections stay alive until they're explicitly closed.
+ // QBONE connections stay alive until they're explicitly closed.
return true;
}
@@ -131,16 +134,17 @@ QuicStream* QboneSessionBase::ActivateDataStream(
return raw;
}
-void QboneSessionBase::SendPacketToPeer(QuicStringPiece packet) {
+void QboneSessionBase::SendPacketToPeer(quiche::QuicheStringPiece packet) {
if (crypto_stream_ == nullptr) {
QUIC_BUG << "Attempting to send packet before encryption established";
return;
}
if (send_packets_as_messages_) {
- QuicMemSlice slice(connection()->helper()->GetStreamSendBufferAllocator(),
- packet.size());
- memcpy(const_cast<char*>(slice.data()), packet.data(), packet.size());
+ QuicUniqueBufferPtr buffer = MakeUniqueBuffer(
+ connection()->helper()->GetStreamSendBufferAllocator(), packet.size());
+ memcpy(buffer.get(), packet.data(), packet.size());
+ QuicMemSlice slice(std::move(buffer), packet.size());
switch (SendMessage(QuicMemSliceSpan(&slice), /*flush=*/true).status) {
case MESSAGE_STATUS_SUCCESS:
break;
@@ -156,7 +160,7 @@ void QboneSessionBase::SendPacketToPeer(QuicStringPiece packet) {
connection()->GetGuaranteedLargestMessagePayload();
CreateIcmpPacket(header->ip6_dst, header->ip6_src, icmp_header, packet,
- [this](QuicStringPiece icmp_packet) {
+ [this](quiche::QuicheStringPiece icmp_packet) {
writer_->WritePacketToNetwork(icmp_packet.data(),
icmp_packet.size());
});
@@ -178,7 +182,7 @@ void QboneSessionBase::SendPacketToPeer(QuicStringPiece packet) {
return;
}
- // Qbone streams are ephemeral.
+ // QBONE streams are ephemeral.
QuicStream* stream = CreateOutgoingStream();
if (!stream) {
QUIC_BUG << "Failed to create an outgoing QBONE stream.";
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_base.h b/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_base.h
index 41afc6bc68e..241a3c9c6e2 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_base.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_base.h
@@ -5,7 +5,7 @@
#ifndef QUICHE_QUIC_QBONE_QBONE_SESSION_BASE_H_
#define QUICHE_QUIC_QBONE_QBONE_SESSION_BASE_H_
-#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
+#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h"
#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/core/quic_session.h"
@@ -13,6 +13,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_packet_writer.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_stream.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -36,17 +37,17 @@ class QUIC_EXPORT_PRIVATE QboneSessionBase : public QuicSession {
// This will check if the packet is wholly contained.
void OnStreamFrame(const QuicStreamFrame& frame) override;
// Called whenever a MESSAGE frame is received.
- void OnMessageReceived(QuicStringPiece message) override;
+ void OnMessageReceived(quiche::QuicheStringPiece message) override;
- virtual void ProcessPacketFromNetwork(QuicStringPiece packet) = 0;
- virtual void ProcessPacketFromPeer(QuicStringPiece packet) = 0;
+ virtual void ProcessPacketFromNetwork(quiche::QuicheStringPiece packet) = 0;
+ virtual void ProcessPacketFromPeer(quiche::QuicheStringPiece packet) = 0;
- // Returns the number of qbone network packets that were received
+ // Returns the number of QBONE network packets that were received
// that fit into a single QuicStreamFrame and elided the creation of
// a QboneReadOnlyStream.
uint64_t GetNumEphemeralPackets() const;
- // Returns the number of qbone network packets that were via
+ // Returns the number of QBONE network packets that were via
// multiple packets, requiring the creation of a QboneReadOnlyStream.
uint64_t GetNumStreamedPackets() const;
@@ -88,7 +89,7 @@ class QUIC_EXPORT_PRIVATE QboneSessionBase : public QuicSession {
// packet. This function will return true if a stream was created
// and the packet sent. It will return false if the stream could not
// be created.
- void SendPacketToPeer(QuicStringPiece packet);
+ void SendPacketToPeer(quiche::QuicheStringPiece packet);
QbonePacketWriter* writer_;
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_test.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_test.cc
index 19ecd2c54fe..7ea1c519dd3 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_test.cc
@@ -11,7 +11,6 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_port_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test_loopback.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/qbone/platform/icmp_packet.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_client_session.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_constants.h"
@@ -22,6 +21,8 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_session_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
namespace test {
@@ -35,14 +36,29 @@ using ::testing::Invoke;
using ::testing::NiceMock;
using ::testing::Not;
-string TestPacketIn(const string& body) {
+std::string TestPacketIn(const std::string& body) {
return PrependIPv6HeaderForTest(body, 5);
}
-string TestPacketOut(const string& body) {
+std::string TestPacketOut(const std::string& body) {
return PrependIPv6HeaderForTest(body, 4);
}
+ParsedQuicVersionVector GetTestParams() {
+ ParsedQuicVersionVector test_versions;
+
+ // TODO(b/113130636): Make QBONE work with TLS.
+ for (const auto& version : CurrentSupportedVersionsWithQuicCrypto()) {
+ // QBONE requires MESSAGE frames
+ if (!version.SupportsMessageFrames()) {
+ continue;
+ }
+ test_versions.push_back(version);
+ }
+
+ return test_versions;
+}
+
// Used by QuicCryptoServerConfig to provide server credentials, returning a
// canned response equal to |success|.
class FakeProofSource : public ProofSource {
@@ -51,10 +67,10 @@ class FakeProofSource : public ProofSource {
// ProofSource override.
void GetProof(const QuicSocketAddress& server_address,
- const string& hostname,
- const string& server_config,
+ const std::string& hostname,
+ const std::string& server_config,
QuicTransportVersion transport_version,
- QuicStringPiece chlo_hash,
+ quiche::QuicheStringPiece chlo_hash,
std::unique_ptr<Callback> callback) override {
QuicReferenceCountedPointer<ProofSource::Chain> chain =
GetCertChain(server_address, hostname);
@@ -68,11 +84,11 @@ class FakeProofSource : public ProofSource {
QuicReferenceCountedPointer<Chain> GetCertChain(
const QuicSocketAddress& server_address,
- const string& hostname) override {
+ const std::string& hostname) override {
if (!success_) {
return QuicReferenceCountedPointer<Chain>();
}
- std::vector<string> certs;
+ std::vector<std::string> certs;
certs.push_back("Required to establish handshake");
return QuicReferenceCountedPointer<ProofSource::Chain>(
new ProofSource::Chain(certs));
@@ -80,11 +96,11 @@ class FakeProofSource : public ProofSource {
void ComputeTlsSignature(
const QuicSocketAddress& server_address,
- const string& hostname,
+ const std::string& hostname,
uint16_t signature_algorithm,
- QuicStringPiece in,
+ quiche::QuicheStringPiece in,
std::unique_ptr<SignatureCallback> callback) override {
- callback->Run(true, "Signature");
+ callback->Run(true, "Signature", /*details=*/nullptr);
}
private:
@@ -100,28 +116,28 @@ class FakeProofVerifier : public ProofVerifier {
// ProofVerifier override
QuicAsyncStatus VerifyProof(
- const string& hostname,
+ const std::string& hostname,
const uint16_t port,
- const string& server_config,
+ const std::string& server_config,
QuicTransportVersion transport_version,
- QuicStringPiece chlo_hash,
- const std::vector<string>& certs,
- const string& cert_sct,
- const string& signature,
+ quiche::QuicheStringPiece chlo_hash,
+ const std::vector<std::string>& certs,
+ const std::string& cert_sct,
+ const std::string& signature,
const ProofVerifyContext* context,
- string* error_details,
+ std::string* error_details,
std::unique_ptr<ProofVerifyDetails>* verify_details,
std::unique_ptr<ProofVerifierCallback> callback) override {
return success_ ? QUIC_SUCCESS : QUIC_FAILURE;
}
QuicAsyncStatus VerifyCertChain(
- const string& hostname,
- const std::vector<string>& certs,
+ const std::string& hostname,
+ const std::vector<std::string>& certs,
const std::string& ocsp_response,
const std::string& cert_sct,
const ProofVerifyContext* context,
- string* error_details,
+ std::string* error_details,
std::unique_ptr<ProofVerifyDetails>* details,
std::unique_ptr<ProofVerifierCallback> callback) override {
return success_ ? QUIC_SUCCESS : QUIC_FAILURE;
@@ -139,13 +155,13 @@ class FakeProofVerifier : public ProofVerifier {
class DataSavingQbonePacketWriter : public QbonePacketWriter {
public:
void WritePacketToNetwork(const char* packet, size_t size) override {
- data_.push_back(string(packet, size));
+ data_.push_back(std::string(packet, size));
}
- const std::vector<string>& data() { return data_; }
+ const std::vector<std::string>& data() { return data_; }
private:
- std::vector<string> data_;
+ std::vector<std::string> data_;
};
template <class T>
@@ -226,9 +242,12 @@ class FakeTaskRunner {
MockQuicConnectionHelper* helper_;
};
-class QboneSessionTest : public QuicTest {
+class QboneSessionTest : public QuicTestWithParam<ParsedQuicVersion> {
public:
- QboneSessionTest() : runner_(&helper_), compressed_certs_cache_(100) {}
+ QboneSessionTest()
+ : supported_versions_({GetParam()}),
+ runner_(&helper_),
+ compressed_certs_cache_(100) {}
~QboneSessionTest() override {
delete client_connection_;
@@ -266,7 +285,7 @@ class QboneSessionTest : public QuicTest {
client_connection_ = new QuicConnection(
TestConnectionId(), server_address, &helper_, alarm_factory_.get(),
new NiceMock<MockPacketWriter>(), true, Perspective::IS_CLIENT,
- ParsedVersionOfIndex(AllSupportedVersions(), 0));
+ supported_versions_);
client_connection_->SetSelfAddress(client_address);
QuicConfig config;
client_crypto_config_ = std::make_unique<QuicCryptoClientConfig>(
@@ -276,8 +295,7 @@ class QboneSessionTest : public QuicTest {
}
client_peer_ = std::make_unique<QboneClientSession>(
client_connection_, client_crypto_config_.get(),
- /*owner=*/nullptr, config,
- ParsedVersionOfIndex(AllSupportedVersions(), 0),
+ /*owner=*/nullptr, config, supported_versions_,
QuicServerId("test.example.com", 1234, false), client_writer_.get(),
client_handler_.get());
}
@@ -286,7 +304,7 @@ class QboneSessionTest : public QuicTest {
server_connection_ = new QuicConnection(
TestConnectionId(), client_address, &helper_, alarm_factory_.get(),
new NiceMock<MockPacketWriter>(), true, Perspective::IS_SERVER,
- ParsedVersionOfIndex(AllSupportedVersions(), 0));
+ supported_versions_);
server_connection_->SetSelfAddress(server_address);
QuicConfig config;
server_crypto_config_ = std::make_unique<QuicCryptoServerConfig>(
@@ -303,7 +321,7 @@ class QboneSessionTest : public QuicTest {
GetClock()->WallNow()));
server_peer_ = std::make_unique<QboneServerSession>(
- AllSupportedVersions(), server_connection_, nullptr, config,
+ supported_versions_, server_connection_, nullptr, config,
server_crypto_config_.get(), &compressed_certs_cache_,
server_writer_.get(), TestLoopback6(), TestLoopback6(), 64,
server_handler_.get());
@@ -354,18 +372,18 @@ class QboneSessionTest : public QuicTest {
runner_.Run();
}
- void ExpectICMPTooBigResponse(const std::vector<string>& written_packets,
+ void ExpectICMPTooBigResponse(const std::vector<std::string>& written_packets,
const int mtu,
- const string& packet) {
+ const std::string& packet) {
auto* header = reinterpret_cast<const ip6_hdr*>(packet.data());
icmp6_hdr icmp_header{};
icmp_header.icmp6_type = ICMP6_PACKET_TOO_BIG;
icmp_header.icmp6_mtu = mtu;
- string expected;
+ std::string expected;
CreateIcmpPacket(header->ip6_dst, header->ip6_src, icmp_header, packet,
- [&expected](QuicStringPiece icmp_packet) {
- expected = string(icmp_packet);
+ [&expected](quiche::QuicheStringPiece icmp_packet) {
+ expected = std::string(icmp_packet);
});
EXPECT_THAT(written_packets, Contains(expected));
@@ -374,8 +392,8 @@ class QboneSessionTest : public QuicTest {
// Test handshake establishment and sending/receiving of data for two
// directions.
void TestStreamConnection(bool use_messages) {
- ASSERT_TRUE(server_peer_->IsCryptoHandshakeConfirmed());
- ASSERT_TRUE(client_peer_->IsCryptoHandshakeConfirmed());
+ ASSERT_TRUE(server_peer_->OneRttKeysAvailable());
+ ASSERT_TRUE(client_peer_->OneRttKeysAvailable());
ASSERT_TRUE(server_peer_->IsEncryptionEstablished());
ASSERT_TRUE(client_peer_->IsEncryptionEstablished());
@@ -408,8 +426,8 @@ class QboneSessionTest : public QuicTest {
// Try to send long payloads that are larger than the QUIC MTU but
// smaller than the QBONE max size.
// This should trigger the non-ephemeral stream code path.
- string long_data(QboneConstants::kMaxQbonePacketBytes - sizeof(ip6_hdr) - 1,
- 'A');
+ std::string long_data(
+ QboneConstants::kMaxQbonePacketBytes - sizeof(ip6_hdr) - 1, 'A');
QUIC_LOG(INFO) << "Sending server -> client long data";
server_peer_->ProcessPacketFromNetwork(TestPacketIn(long_data));
runner_.Run();
@@ -437,7 +455,8 @@ class QboneSessionTest : public QuicTest {
} else {
EXPECT_THAT(server_writer_->data(), Contains(TestPacketOut(long_data)));
}
- EXPECT_THAT(client_peer_->GetNumSentClientHellos(), Eq(2));
+ EXPECT_FALSE(client_peer_->EarlyDataAccepted());
+ EXPECT_FALSE(client_peer_->ReceivedInchoateReject());
EXPECT_THAT(client_peer_->GetNumReceivedServerConfigUpdates(), Eq(0));
if (!use_messages) {
@@ -465,13 +484,14 @@ class QboneSessionTest : public QuicTest {
// Test that client and server are not connected after handshake failure.
void TestDisconnectAfterFailedHandshake() {
EXPECT_FALSE(client_peer_->IsEncryptionEstablished());
- EXPECT_FALSE(client_peer_->IsCryptoHandshakeConfirmed());
+ EXPECT_FALSE(client_peer_->OneRttKeysAvailable());
EXPECT_FALSE(server_peer_->IsEncryptionEstablished());
- EXPECT_FALSE(server_peer_->IsCryptoHandshakeConfirmed());
+ EXPECT_FALSE(server_peer_->OneRttKeysAvailable());
}
protected:
+ const ParsedQuicVersionVector supported_versions_;
QuicEpollServer epoll_server_;
std::unique_ptr<QuicAlarmFactory> alarm_factory_;
FakeTaskRunner runner_;
@@ -493,7 +513,12 @@ class QboneSessionTest : public QuicTest {
std::unique_ptr<QboneClientSession> client_peer_;
};
-TEST_F(QboneSessionTest, StreamConnection) {
+INSTANTIATE_TEST_SUITE_P(Tests,
+ QboneSessionTest,
+ ::testing::ValuesIn(GetTestParams()),
+ ::testing::PrintToStringParamName());
+
+TEST_P(QboneSessionTest, StreamConnection) {
CreateClientAndServerSessions();
client_peer_->set_send_packets_as_messages(false);
server_peer_->set_send_packets_as_messages(false);
@@ -501,7 +526,7 @@ TEST_F(QboneSessionTest, StreamConnection) {
TestStreamConnection(false);
}
-TEST_F(QboneSessionTest, Messages) {
+TEST_P(QboneSessionTest, Messages) {
CreateClientAndServerSessions();
client_peer_->set_send_packets_as_messages(true);
server_peer_->set_send_packets_as_messages(true);
@@ -509,7 +534,7 @@ TEST_F(QboneSessionTest, Messages) {
TestStreamConnection(true);
}
-TEST_F(QboneSessionTest, ClientRejection) {
+TEST_P(QboneSessionTest, ClientRejection) {
CreateClientAndServerSessions(false /*client_handshake_success*/,
true /*server_handshake_success*/,
true /*send_qbone_alpn*/);
@@ -517,7 +542,7 @@ TEST_F(QboneSessionTest, ClientRejection) {
TestDisconnectAfterFailedHandshake();
}
-TEST_F(QboneSessionTest, BadAlpn) {
+TEST_P(QboneSessionTest, BadAlpn) {
CreateClientAndServerSessions(true /*client_handshake_success*/,
true /*server_handshake_success*/,
false /*send_qbone_alpn*/);
@@ -525,7 +550,7 @@ TEST_F(QboneSessionTest, BadAlpn) {
TestDisconnectAfterFailedHandshake();
}
-TEST_F(QboneSessionTest, ServerRejection) {
+TEST_P(QboneSessionTest, ServerRejection) {
CreateClientAndServerSessions(true /*client_handshake_success*/,
false /*server_handshake_success*/,
true /*send_qbone_alpn*/);
@@ -534,7 +559,7 @@ TEST_F(QboneSessionTest, ServerRejection) {
}
// Test that data streams are not created before handshake.
-TEST_F(QboneSessionTest, CannotCreateDataStreamBeforeHandshake) {
+TEST_P(QboneSessionTest, CannotCreateDataStreamBeforeHandshake) {
CreateClientAndServerSessions();
EXPECT_QUIC_BUG(client_peer_->ProcessPacketFromNetwork(TestPacketIn("hello")),
"Attempting to send packet before encryption established");
@@ -544,7 +569,7 @@ TEST_F(QboneSessionTest, CannotCreateDataStreamBeforeHandshake) {
EXPECT_EQ(0u, client_peer_->GetNumActiveStreams());
}
-TEST_F(QboneSessionTest, ControlRequests) {
+TEST_P(QboneSessionTest, ControlRequests) {
CreateClientAndServerSessions();
StartHandshake();
EXPECT_TRUE(client_handler_->data().empty());
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_stream.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_stream.cc
index b7ac0078561..4d1888928f6 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_stream.cc
@@ -7,10 +7,11 @@
#include "net/third_party/quiche/src/quic/core/quic_data_reader.h"
#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_constants.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_session_base.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+
+ABSL_FLAG(int, qbone_stream_ttl_secs, 3, "The QBONE Stream TTL in seconds.");
namespace quic {
@@ -18,11 +19,13 @@ QboneWriteOnlyStream::QboneWriteOnlyStream(QuicStreamId id,
QuicSession* session)
: QuicStream(id, session, /*is_static=*/false, WRITE_UNIDIRECTIONAL) {
// QBONE uses a LIFO queue to try to always make progress. An individual
- // packet may persist for upto to 10 seconds in memory.
- MaybeSetTtl(QuicTime::Delta::FromSeconds(10));
+ // packet may persist for upto to qbone_stream_ttl_secs seconds in memory.
+ MaybeSetTtl(
+ QuicTime::Delta::FromSeconds(GetQuicFlag(FLAGS_qbone_stream_ttl_secs)));
}
-void QboneWriteOnlyStream::WritePacketToQuicStream(QuicStringPiece packet) {
+void QboneWriteOnlyStream::WritePacketToQuicStream(
+ quiche::QuicheStringPiece packet) {
// Streams are one way and ephemeral. This function should only be
// called once.
WriteOrBufferData(packet, /* fin= */ true, nullptr);
@@ -36,12 +39,11 @@ QboneReadOnlyStream::QboneReadOnlyStream(QuicStreamId id,
READ_UNIDIRECTIONAL),
session_(session) {
// QBONE uses a LIFO queue to try to always make progress. An individual
- // packet may persist for upto to 10 seconds in memory.
- MaybeSetTtl(QuicTime::Delta::FromSeconds(10));
+ // packet may persist for upto to qbone_stream_ttl_secs seconds in memory.
+ MaybeSetTtl(
+ QuicTime::Delta::FromSeconds(GetQuicFlag(FLAGS_qbone_stream_ttl_secs)));
}
-QboneReadOnlyStream::~QboneReadOnlyStream() {}
-
void QboneReadOnlyStream::OnDataAvailable() {
// Read in data and buffer it, attempt to frame to see if there's a packet.
sequencer()->Read(&buffer_);
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_stream.h b/chromium/net/third_party/quiche/src/quic/qbone/qbone_stream.h
index 73680051643..8a6313bc0c2 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_stream.h
@@ -8,6 +8,7 @@
#include "net/third_party/quiche/src/quic/core/quic_session.h"
#include "net/third_party/quiche/src/quic/core/quic_stream.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -20,12 +21,12 @@ class QUIC_EXPORT_PRIVATE QboneWriteOnlyStream : public QuicStream {
public:
QboneWriteOnlyStream(QuicStreamId id, QuicSession* session);
- // QuicStream implementation. Qbone writers are ephemeral and don't
+ // QuicStream implementation. QBONE writers are ephemeral and don't
// read any data.
void OnDataAvailable() override {}
// Write a network packet over the quic stream.
- void WritePacketToQuicStream(QuicStringPiece packet);
+ void WritePacketToQuicStream(quiche::QuicheStringPiece packet);
};
// QboneReadOnlyStream will be used if we find an incoming stream that
@@ -37,7 +38,7 @@ class QUIC_EXPORT_PRIVATE QboneReadOnlyStream : public QuicStream {
public:
QboneReadOnlyStream(QuicStreamId id, QboneSessionBase* session);
- ~QboneReadOnlyStream() override;
+ ~QboneReadOnlyStream() override = default;
// QuicStream overrides.
// OnDataAvailable is called when there is data in the quic stream buffer.
@@ -46,7 +47,7 @@ class QUIC_EXPORT_PRIVATE QboneReadOnlyStream : public QuicStream {
void OnDataAvailable() override;
private:
- string buffer_;
+ std::string buffer_;
QboneSessionBase* session_;
};
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_stream_test.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_stream_test.cc
index bb9195b7209..42840bebee0 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_stream_test.cc
@@ -16,6 +16,7 @@
#include "net/third_party/quiche/src/quic/qbone/qbone_session_base.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
namespace quic {
@@ -39,11 +40,13 @@ class MockQuicSession : public QboneSessionBase {
~MockQuicSession() override {}
// Writes outgoing data from QuicStream to a string.
- QuicConsumedData WritevData(QuicStream* stream,
- QuicStreamId id,
- size_t write_length,
- QuicStreamOffset offset,
- StreamSendingState state) override {
+ QuicConsumedData WritevData(
+ QuicStreamId id,
+ size_t write_length,
+ QuicStreamOffset offset,
+ StreamSendingState state,
+ TransmissionType type,
+ quiche::QuicheOptional<EncryptionLevel> level) override {
if (!writable_) {
return QuicConsumedData(0, false);
}
@@ -84,8 +87,8 @@ class MockQuicSession : public QboneSessionBase {
return nullptr;
}
- MOCK_METHOD1(ProcessPacketFromPeer, void(QuicStringPiece));
- MOCK_METHOD1(ProcessPacketFromNetwork, void(QuicStringPiece));
+ MOCK_METHOD1(ProcessPacketFromPeer, void(quiche::QuicheStringPiece));
+ MOCK_METHOD1(ProcessPacketFromNetwork, void(quiche::QuicheStringPiece));
private:
// Whether data is written to write_buffer_.
@@ -179,7 +182,7 @@ class QboneReadOnlyStreamTest : public ::testing::Test,
// Read an entire string.
TEST_F(QboneReadOnlyStreamTest, ReadDataWhole) {
- string packet = "Stuff";
+ std::string packet = "Stuff";
CreateReliableQuicStream();
QuicStreamFrame frame(kStreamId, true, 0, packet);
EXPECT_CALL(*session_, ProcessPacketFromPeer("Stuff"));
@@ -189,7 +192,7 @@ TEST_F(QboneReadOnlyStreamTest, ReadDataWhole) {
// Test buffering.
TEST_F(QboneReadOnlyStreamTest, ReadBuffered) {
CreateReliableQuicStream();
- string packet = "Stuf";
+ std::string packet = "Stuf";
{
QuicStreamFrame frame(kStreamId, false, 0, packet);
stream_->OnStreamFrame(frame);
@@ -206,7 +209,7 @@ TEST_F(QboneReadOnlyStreamTest, ReadBuffered) {
TEST_F(QboneReadOnlyStreamTest, ReadOutOfOrder) {
CreateReliableQuicStream();
- string packet = "f";
+ std::string packet = "f";
{
QuicStreamFrame frame(kStreamId, true, 4, packet);
stream_->OnStreamFrame(frame);
@@ -229,7 +232,7 @@ TEST_F(QboneReadOnlyStreamTest, ReadOutOfOrder) {
// Test buffering too many bytes.
TEST_F(QboneReadOnlyStreamTest, ReadBufferedTooLarge) {
CreateReliableQuicStream();
- string packet = "0123456789";
+ std::string packet = "0123456789";
int iterations = (QboneConstants::kMaxQbonePacketBytes / packet.size()) + 2;
EXPECT_CALL(*session_,
SendRstStream(kStreamId, QUIC_BAD_APPLICATION_PAYLOAD, _));
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_connection_helper.h b/chromium/net/third_party/quiche/src/quic/quartc/quartc_connection_helper.h
index 184dacc1aaf..72cc707aced 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_connection_helper.h
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_connection_helper.h
@@ -7,9 +7,9 @@
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
#include "net/third_party/quiche/src/quic/core/quic_buffer_allocator.h"
+#include "net/third_party/quiche/src/quic/core/quic_clock.h"
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
#include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.cc b/chromium/net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.cc
index edc699628cc..1a028458ecd 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.cc
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.cc
@@ -14,7 +14,7 @@ void DummyProofSource::GetProof(const QuicSocketAddress& server_address,
const std::string& hostname,
const std::string& /*server_config*/,
QuicTransportVersion /*transport_version*/,
- QuicStringPiece /*chlo_hash*/,
+ quiche::QuicheStringPiece /*chlo_hash*/,
std::unique_ptr<Callback> callback) {
QuicReferenceCountedPointer<ProofSource::Chain> chain =
GetCertChain(server_address, hostname);
@@ -37,9 +37,9 @@ void DummyProofSource::ComputeTlsSignature(
const QuicSocketAddress& /*server_address*/,
const std::string& /*hostname*/,
uint16_t /*signature_algorithm*/,
- QuicStringPiece /*in*/,
+ quiche::QuicheStringPiece /*in*/,
std::unique_ptr<SignatureCallback> callback) {
- callback->Run(true, "Dummy signature");
+ callback->Run(true, "Dummy signature", /*details=*/nullptr);
}
QuicAsyncStatus InsecureProofVerifier::VerifyProof(
@@ -47,7 +47,7 @@ QuicAsyncStatus InsecureProofVerifier::VerifyProof(
const uint16_t /*port*/,
const std::string& /*server_config*/,
QuicTransportVersion /*transport_version*/,
- QuicStringPiece /*chlo_hash*/,
+ quiche::QuicheStringPiece /*chlo_hash*/,
const std::vector<std::string>& /*certs*/,
const std::string& /*cert_sct*/,
const std::string& /*signature*/,
@@ -85,7 +85,7 @@ bool QuartcCryptoServerStreamHelper::CanAcceptClientHello(
}
std::unique_ptr<QuicCryptoClientConfig> CreateCryptoClientConfig(
- QuicStringPiece pre_shared_key) {
+ quiche::QuicheStringPiece pre_shared_key) {
auto config = std::make_unique<QuicCryptoClientConfig>(
std::make_unique<InsecureProofVerifier>());
config->set_pad_inchoate_hello(false);
@@ -96,9 +96,10 @@ std::unique_ptr<QuicCryptoClientConfig> CreateCryptoClientConfig(
return config;
}
-CryptoServerConfig CreateCryptoServerConfig(QuicRandom* random,
- const QuicClock* clock,
- QuicStringPiece pre_shared_key) {
+CryptoServerConfig CreateCryptoServerConfig(
+ QuicRandom* random,
+ const QuicClock* clock,
+ quiche::QuicheStringPiece pre_shared_key) {
CryptoServerConfig crypto_server_config;
// Generate a random source address token secret. For long-running servers
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.h b/chromium/net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.h
index cdf14a040eb..b1e2e186154 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.h
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.h
@@ -13,11 +13,11 @@
#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h"
#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
-#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
+#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_reference_counted.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -47,7 +47,7 @@ class DummyProofSource : public ProofSource {
const std::string& hostname,
const std::string& server_config,
QuicTransportVersion transport_version,
- QuicStringPiece chlo_hash,
+ quiche::QuicheStringPiece chlo_hash,
std::unique_ptr<Callback> callback) override;
QuicReferenceCountedPointer<Chain> GetCertChain(
@@ -58,7 +58,7 @@ class DummyProofSource : public ProofSource {
const QuicSocketAddress& server_address,
const std::string& hostname,
uint16_t signature_algorithm,
- QuicStringPiece in,
+ quiche::QuicheStringPiece in,
std::unique_ptr<SignatureCallback> callback) override;
};
@@ -76,7 +76,7 @@ class InsecureProofVerifier : public ProofVerifier {
const uint16_t port,
const std::string& server_config,
QuicTransportVersion transport_version,
- QuicStringPiece chlo_hash,
+ quiche::QuicheStringPiece chlo_hash,
const std::vector<std::string>& certs,
const std::string& cert_sct,
const std::string& signature,
@@ -99,7 +99,8 @@ class InsecureProofVerifier : public ProofVerifier {
};
// Implementation of the server-side crypto stream helper.
-class QuartcCryptoServerStreamHelper : public QuicCryptoServerStream::Helper {
+class QuartcCryptoServerStreamHelper
+ : public QuicCryptoServerStreamBase::Helper {
public:
bool CanAcceptClientHello(const CryptoHandshakeMessage& message,
const QuicSocketAddress& client_address,
@@ -109,11 +110,12 @@ class QuartcCryptoServerStreamHelper : public QuicCryptoServerStream::Helper {
};
std::unique_ptr<QuicCryptoClientConfig> CreateCryptoClientConfig(
- QuicStringPiece pre_shared_key);
+ quiche::QuicheStringPiece pre_shared_key);
-CryptoServerConfig CreateCryptoServerConfig(QuicRandom* random,
- const QuicClock* clock,
- QuicStringPiece pre_shared_key);
+CryptoServerConfig CreateCryptoServerConfig(
+ QuicRandom* random,
+ const QuicClock* clock,
+ quiche::QuicheStringPiece pre_shared_key);
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_dispatcher.cc b/chromium/net/third_party/quiche/src/quic/quartc/quartc_dispatcher.cc
index b1745197c3f..c5c4c4a742f 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_dispatcher.cc
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_dispatcher.cc
@@ -7,6 +7,7 @@
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_factory.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -15,7 +16,7 @@ QuartcDispatcher::QuartcDispatcher(
std::unique_ptr<QuicCryptoServerConfig> crypto_config,
QuicVersionManager* version_manager,
std::unique_ptr<QuicConnectionHelperInterface> helper,
- std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
+ std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
std::unique_ptr<QuicAlarmFactory> alarm_factory,
std::unique_ptr<QuartcPacketWriter> packet_writer,
Delegate* delegate)
@@ -49,21 +50,21 @@ QuartcDispatcher::~QuartcDispatcher() {
packet_writer_->SetPacketTransportDelegate(nullptr);
}
-QuartcSession* QuartcDispatcher::CreateQuicSession(
+std::unique_ptr<QuicSession> QuartcDispatcher::CreateQuicSession(
QuicConnectionId connection_id,
const QuicSocketAddress& client_address,
- QuicStringPiece /*alpn*/,
+ quiche::QuicheStringPiece /*alpn*/,
const ParsedQuicVersion& version) {
// Make our expected connection ID non-mutable since we have a connection.
SetShouldUpdateExpectedServerConnectionIdLength(false);
std::unique_ptr<QuicConnection> connection = CreateQuicConnection(
connection_id, client_address, helper(), alarm_factory(), writer(),
Perspective::IS_SERVER, ParsedQuicVersionVector{version});
- QuartcSession* session = new QuartcServerSession(
+ auto session = std::make_unique<QuartcServerSession>(
std::move(connection), /*visitor=*/this, config(), GetSupportedVersions(),
helper()->GetClock(), crypto_config(), compressed_certs_cache(),
session_helper());
- delegate_->OnSessionCreated(session);
+ delegate_->OnSessionCreated(session.get());
return session;
}
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_dispatcher.h b/chromium/net/third_party/quiche/src/quic/quartc/quartc_dispatcher.h
index 06e799ea98a..ca4fe2d6147 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_dispatcher.h
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_dispatcher.h
@@ -10,13 +10,13 @@
#include "net/third_party/quiche/src/quic/core/quic_config.h"
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
-#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
+#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h"
#include "net/third_party/quiche/src/quic/core/quic_dispatcher.h"
#include "net/third_party/quiche/src/quic/core/quic_version_manager.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_session.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -34,16 +34,17 @@ class QuartcDispatcher : public QuicDispatcher,
std::unique_ptr<QuicCryptoServerConfig> crypto_config,
QuicVersionManager* version_manager,
std::unique_ptr<QuicConnectionHelperInterface> helper,
- std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
+ std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
std::unique_ptr<QuicAlarmFactory> alarm_factory,
std::unique_ptr<QuartcPacketWriter> packet_writer,
Delegate* delegate);
~QuartcDispatcher() override;
- QuartcSession* CreateQuicSession(QuicConnectionId server_connection_id,
- const QuicSocketAddress& client_address,
- QuicStringPiece alpn,
- const ParsedQuicVersion& version) override;
+ std::unique_ptr<QuicSession> CreateQuicSession(
+ QuicConnectionId server_connection_id,
+ const QuicSocketAddress& client_address,
+ quiche::QuicheStringPiece alpn,
+ const ParsedQuicVersion& version) override;
// TODO(b/124399417): Override GenerateNewServerConnectionId and request a
// zero-length connection id when the QUIC server perspective supports it.
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint.cc b/chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint.cc
index 5860454176f..ca8fad6c9c4 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint.cc
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint.cc
@@ -11,6 +11,7 @@
#include "net/third_party/quiche/src/quic/quartc/quartc_connection_helper.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_dispatcher.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -52,7 +53,7 @@ QuartcClientEndpoint::QuartcClientEndpoint(
QuicRandom* random,
QuartcEndpoint::Delegate* delegate,
const QuartcSessionConfig& config,
- QuicStringPiece serialized_server_config,
+ quiche::QuicheStringPiece serialized_server_config,
std::unique_ptr<QuicVersionManager> version_manager)
: alarm_factory_(alarm_factory),
clock_(clock),
@@ -127,7 +128,8 @@ void QuartcClientEndpoint::OnConnectionClosed(
delegate_->OnConnectionClosed(frame, source);
}
-void QuartcClientEndpoint::OnMessageReceived(QuicStringPiece message) {
+void QuartcClientEndpoint::OnMessageReceived(
+ quiche::QuicheStringPiece message) {
delegate_->OnMessageReceived(message);
}
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint.h b/chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint.h
index 0f557a2c18c..ea1a63f0e33 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint.h
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint.h
@@ -8,13 +8,13 @@
#include <string>
#include "net/third_party/quiche/src/quic/core/quic_alarm_factory.h"
+#include "net/third_party/quiche/src/quic/core/quic_clock.h"
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_connection_helper.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_dispatcher.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_factory.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -62,7 +62,7 @@ class QuartcClientEndpoint : public QuartcEndpoint,
QuicRandom* random,
QuartcEndpoint::Delegate* delegate,
const QuartcSessionConfig& config,
- QuicStringPiece serialized_server_config,
+ quiche::QuicheStringPiece serialized_server_config,
std::unique_ptr<QuicVersionManager> version_manager = nullptr);
void Connect(QuartcPacketTransport* packet_transport) override;
@@ -76,7 +76,7 @@ class QuartcClientEndpoint : public QuartcEndpoint,
QuicTime::Delta latest_rtt) override;
void OnConnectionClosed(const QuicConnectionCloseFrame& frame,
ConnectionCloseSource source) override;
- void OnMessageReceived(QuicStringPiece message) override;
+ void OnMessageReceived(quiche::QuicheStringPiece message) override;
void OnMessageSent(int64_t datagram_id) override;
void OnMessageAcked(int64_t datagram_id, QuicTime receive_timestamp) override;
void OnMessageLost(int64_t datagram_id) override;
@@ -164,7 +164,7 @@ class QuartcServerEndpoint : public QuartcEndpoint,
// Accessor to retrieve the server crypto config. May only be called after
// Connect().
- QuicStringPiece server_crypto_config() const {
+ quiche::QuicheStringPiece server_crypto_config() const {
return crypto_config_.serialized_crypto_config;
}
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint_test.cc b/chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint_test.cc
index 8506067f13d..d2f94202aa1 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint_test.cc
@@ -49,7 +49,11 @@ class QuartcEndpointTest : public QuicTest {
simulator_.GetRandomGenerator(),
&client_endpoint_delegate_,
QuartcSessionConfig(),
- /*serialized_server_config=*/"")) {}
+ /*serialized_server_config=*/"")) {
+ // Make sure these versions are enabled since some tests use them.
+ SetQuicReloadableFlag(quic_disable_version_q043, false);
+ SetQuicReloadableFlag(quic_disable_version_q046, false);
+ }
simulator::Simulator simulator_;
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_factory.cc b/chromium/net/third_party/quiche/src/quic/quartc/quartc_factory.cc
index ad677fd8c94..ff98761b4c7 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_factory.cc
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_factory.cc
@@ -15,6 +15,7 @@
#include "net/third_party/quiche/src/quic/quartc/quartc_connection_helper.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_session.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -24,7 +25,7 @@ std::unique_ptr<QuartcSession> CreateQuartcClientSession(
QuicAlarmFactory* alarm_factory,
QuicConnectionHelperInterface* connection_helper,
const ParsedQuicVersionVector& supported_versions,
- QuicStringPiece server_crypto_config,
+ quiche::QuicheStringPiece server_crypto_config,
QuartcPacketTransport* packet_transport) {
DCHECK(packet_transport);
@@ -60,12 +61,6 @@ std::unique_ptr<QuartcSession> CreateQuartcClientSession(
}
void ConfigureGlobalQuicSettings() {
- // Fixes behavior of StopReading() with level-triggered stream sequencers.
- SetQuicReloadableFlag(quic_stop_reading_when_level_triggered, true);
-
- // Enable version 50 to be compatible with the latest version of Chrome.
- SetQuicReloadableFlag(quic_enable_version_50, true);
-
// Ensure that we don't drop data because QUIC streams refuse to buffer it.
// TODO(b/120099046): Replace this with correct handling of WriteMemSlices().
SetQuicFlag(FLAGS_quic_buffered_data_threshold,
@@ -80,7 +75,6 @@ void ConfigureGlobalQuicSettings() {
// Note: flag settings have no effect for Exoblaze builds since
// SetQuicReloadableFlag() gets stubbed out.
- SetQuicReloadableFlag(quic_bbr_less_probe_rtt, true); // Enable BBR6,7,8.
SetQuicReloadableFlag(quic_unified_iw_options, true); // Enable IWXX opts.
SetQuicReloadableFlag(quic_bbr_flexible_app_limited, true); // Enable BBR9.
}
@@ -93,12 +87,6 @@ QuicConfig CreateQuicConfig(const QuartcSessionConfig& quartc_session_config) {
// settings doesn't seem preferable.
ConfigureGlobalQuicSettings();
- // In exoblaze this may return false. DCHECK to avoid problems caused by
- // incorrect flags configuration.
- DCHECK(GetQuicReloadableFlag(quic_enable_version_50))
- << "Your build does not support quic reloadable flags and shouldn't "
- "place Quartc calls";
-
QuicTagVector copt;
copt.push_back(kNSTP);
@@ -117,8 +105,6 @@ QuicConfig CreateQuicConfig(const QuartcSessionConfig& quartc_session_config) {
copt.push_back(kBBR3); // Stay in low-gain until in-flight < BDP.
copt.push_back(kBBR5); // 40 RTT ack aggregation.
- copt.push_back(kBBR6); // Use a 0.75 * BDP cwnd during PROBE_RTT.
- copt.push_back(kBBR8); // Skip PROBE_RTT if app-limited.
copt.push_back(kBBR9); // Ignore app-limited if enough data is in flight.
copt.push_back(kBBQ1); // 2.773 pacing gain in STARTUP.
copt.push_back(kBBQ2); // 2.0 CWND gain in STARTUP.
@@ -179,7 +165,7 @@ QuicConfig CreateQuicConfig(const QuartcSessionConfig& quartc_session_config) {
// incomplete streams, but targets 1 second for recovery. Increasing the
// number of open streams gives sufficient headroom to recover before QUIC
// refuses new streams.
- quic_config.SetMaxIncomingBidirectionalStreamsToSend(1000);
+ quic_config.SetMaxBidirectionalStreamsToSend(1000);
return quic_config;
}
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_factory.h b/chromium/net/third_party/quiche/src/quic/quartc/quartc_factory.h
index df55cd3a3ba..665b8e7111d 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_factory.h
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_factory.h
@@ -10,6 +10,7 @@
#include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_packet_writer.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_session.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -43,7 +44,7 @@ std::unique_ptr<QuartcSession> CreateQuartcClientSession(
QuicAlarmFactory* alarm_factory,
QuicConnectionHelperInterface* connection_helper,
const ParsedQuicVersionVector& supported_versions,
- QuicStringPiece server_crypto_config,
+ quiche::QuicheStringPiece server_crypto_config,
QuartcPacketTransport* packet_transport);
// Configures global settings, such as supported quic versions.
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_fakes.h b/chromium/net/third_party/quiche/src/quic/quartc/quartc_fakes.h
index 91ea9a91b58..94bf1add1e7 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_fakes.h
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_fakes.h
@@ -7,12 +7,13 @@
#include <string>
+#include "net/third_party/quiche/src/quic/core/quic_clock.h"
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_endpoint.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_session.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_stream.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -54,7 +55,7 @@ class FakeQuartcEndpointDelegate : public QuartcEndpoint::Delegate {
last_incoming_stream_->SetDelegate(stream_delegate_);
}
- void OnMessageReceived(QuicStringPiece message) override {
+ void OnMessageReceived(quiche::QuicheStringPiece message) override {
incoming_messages_.emplace_back(message);
}
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_multiplexer.cc b/chromium/net/third_party/quiche/src/quic/quartc/quartc_multiplexer.cc
index cb7d77c405a..376fac02c8c 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_multiplexer.cc
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_multiplexer.cc
@@ -7,9 +7,11 @@
#include <cstdint>
#include <utility>
+#include "net/third_party/quiche/src/quic/core/quic_buffer_allocator.h"
#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice_span.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -94,10 +96,10 @@ void QuartcSendChannel::OnSessionCreated(QuartcSession* session) {
}
QuicMemSlice QuartcSendChannel::EncodeChannelId() {
- QuicMemSlice id_slice(allocator_, encoded_length_);
- QuicDataWriter writer(encoded_length_, const_cast<char*>(id_slice.data()));
+ QuicUniqueBufferPtr buffer = MakeUniqueBuffer(allocator_, encoded_length_);
+ QuicDataWriter writer(encoded_length_, buffer.get());
writer.WriteVarInt62(id_);
- return id_slice;
+ return QuicMemSlice(std::move(buffer), encoded_length_);
}
QuartcMultiplexer::QuartcMultiplexer(
@@ -176,7 +178,7 @@ void QuartcMultiplexer::OnConnectionClosed(
session_delegate_->OnConnectionClosed(frame, source);
}
-void QuartcMultiplexer::OnMessageReceived(QuicStringPiece message) {
+void QuartcMultiplexer::OnMessageReceived(quiche::QuicheStringPiece message) {
QuicDataReader reader(message);
QuicVariableLengthIntegerLength channel_id_length =
reader.PeekVarInt62Length();
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_multiplexer.h b/chromium/net/third_party/quiche/src/quic/quartc/quartc_multiplexer.h
index 9cb581d47b7..b90026b5495 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_multiplexer.h
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_multiplexer.h
@@ -11,10 +11,10 @@
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice_span.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_endpoint.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_session.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_stream.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -104,7 +104,7 @@ class QuartcReceiveChannel {
// Called when a message is recieved by this channel.
virtual void OnMessageReceived(uint64_t channel_id,
- QuicStringPiece message) = 0;
+ quiche::QuicheStringPiece message) = 0;
};
// Delegate for session-wide events.
@@ -159,7 +159,7 @@ class QuartcMultiplexer : public QuartcEndpoint::Delegate,
QuicTime::Delta latest_rtt) override;
void OnConnectionClosed(const QuicConnectionCloseFrame& frame,
ConnectionCloseSource source) override;
- void OnMessageReceived(QuicStringPiece message) override;
+ void OnMessageReceived(quiche::QuicheStringPiece message) override;
void OnMessageSent(int64_t datagram_id) override;
void OnMessageAcked(int64_t datagram_id, QuicTime receive_timestamp) override;
void OnMessageLost(int64_t datagram_id) override;
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_multiplexer_test.cc b/chromium/net/third_party/quiche/src/quic/quartc/quartc_multiplexer_test.cc
index 3cc088b4da1..fcdbe994f24 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_multiplexer_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_multiplexer_test.cc
@@ -14,7 +14,6 @@
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test_mem_slice_vector.h"
#include "net/third_party/quiche/src/quic/quartc/counting_packet_filter.h"
@@ -26,6 +25,8 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/link.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace {
@@ -126,7 +127,7 @@ class FakeReceiveDelegate : public QuartcReceiveChannel,
}
void OnMessageReceived(uint64_t channel_id,
- QuicStringPiece message) override {
+ quiche::QuicheStringPiece message) override {
messages_received_.emplace_back(channel_id, message);
}
@@ -199,8 +200,11 @@ class QuartcMultiplexerTest : public QuicTest {
simulator_.GetRandomGenerator(),
&server_multiplexer_,
quic::QuartcSessionConfig())) {
- // TODO(b/134175506): Remove when IETF QUIC supports receive timestamps.
- SetQuicReloadableFlag(quic_enable_version_99, false);
+ // TODO(b/150224094): Re-enable TLS handshake.
+ // TODO(b/150236522): Parametrize by QUIC version.
+ SetQuicReloadableFlag(quic_enable_version_draft_27, false);
+ SetQuicReloadableFlag(quic_enable_version_draft_25_v3, false);
+ SetQuicReloadableFlag(quic_enable_version_t050, false);
}
void Connect() {
@@ -265,7 +269,7 @@ TEST_F(QuartcMultiplexerTest, MultiplexMessages) {
std::vector<testing::Matcher<std::pair<int64_t, QuicTime>>> ack_matchers_1;
std::vector<testing::Matcher<std::pair<int64_t, QuicTime>>> ack_matchers_2;
for (int i = 0; i < num_messages; ++i) {
- messages_1.emplace_back(1, QuicStrCat("message for 1: ", i));
+ messages_1.emplace_back(1, quiche::QuicheStrCat("message for 1: ", i));
test::QuicTestMemSliceVector slice_1(
{std::make_pair(const_cast<char*>(messages_1.back().second.data()),
messages_1.back().second.size())});
@@ -273,7 +277,7 @@ TEST_F(QuartcMultiplexerTest, MultiplexMessages) {
messages_sent_1.push_back(i);
ack_matchers_1.push_back(Pair(i, Gt(QuicTime::Zero())));
- messages_2.emplace_back(2, QuicStrCat("message for 2: ", i));
+ messages_2.emplace_back(2, quiche::QuicheStrCat("message for 2: ", i));
test::QuicTestMemSliceVector slice_2(
{std::make_pair(const_cast<char*>(messages_2.back().second.data()),
messages_2.back().second.size())});
@@ -322,7 +326,7 @@ TEST_F(QuartcMultiplexerTest, MultiplexStreams) {
std::vector<std::pair<uint64_t, std::string>> messages_2;
messages_2.reserve(num_messages);
for (int i = 0; i < num_messages; ++i) {
- messages_1.emplace_back(1, QuicStrCat("message for 1: ", i));
+ messages_1.emplace_back(1, quiche::QuicheStrCat("message for 1: ", i));
test::QuicTestMemSliceVector slice_1(
{std::make_pair(const_cast<char*>(messages_1.back().second.data()),
messages_1.back().second.size())});
@@ -331,7 +335,7 @@ TEST_F(QuartcMultiplexerTest, MultiplexStreams) {
stream_1->SetDelegate(&fake_send_stream_delegate);
stream_1->WriteMemSlices(slice_1.span(), /*fin=*/true);
- messages_2.emplace_back(2, QuicStrCat("message for 2: ", i));
+ messages_2.emplace_back(2, quiche::QuicheStrCat("message for 2: ", i));
test::QuicTestMemSliceVector slice_2(
{std::make_pair(const_cast<char*>(messages_2.back().second.data()),
messages_2.back().second.size())});
@@ -384,14 +388,14 @@ TEST_F(QuartcMultiplexerTest, MultiplexLostDatagrams) {
std::vector<int64_t> messages_sent_1;
std::vector<int64_t> messages_sent_2;
for (int i = 0; i < num_messages; ++i) {
- messages_1.emplace_back(1, QuicStrCat("message for 1: ", i));
+ messages_1.emplace_back(1, quiche::QuicheStrCat("message for 1: ", i));
test::QuicTestMemSliceVector slice_1(
{std::make_pair(const_cast<char*>(messages_1.back().second.data()),
messages_1.back().second.size())});
send_channel_1->SendOrQueueMessage(slice_1.span(), i);
messages_sent_1.push_back(i);
- messages_2.emplace_back(2, QuicStrCat("message for 2: ", i));
+ messages_2.emplace_back(2, quiche::QuicheStrCat("message for 2: ", i));
test::QuicTestMemSliceVector slice_2(
{std::make_pair(const_cast<char*>(messages_2.back().second.data()),
messages_2.back().second.size())});
@@ -404,7 +408,8 @@ TEST_F(QuartcMultiplexerTest, MultiplexLostDatagrams) {
// Now send something retransmittable to prompt loss detection.
// If we never send anything retransmittable, we will never get acks, and
// never detect losses.
- messages_1.emplace_back(1, QuicStrCat("message for 1: ", num_messages));
+ messages_1.emplace_back(
+ 1, quiche::QuicheStrCat("message for 1: ", num_messages));
test::QuicTestMemSliceVector slice(
{std::make_pair(const_cast<char*>(messages_1.back().second.data()),
messages_1.back().second.size())});
@@ -447,7 +452,7 @@ TEST_F(QuartcMultiplexerTest, UnregisterReceiveChannel) {
std::vector<int64_t> messages_sent;
std::vector<testing::Matcher<std::pair<int64_t, QuicTime>>> ack_matchers;
for (int i = 0; i < num_messages; ++i) {
- messages.emplace_back(1, QuicStrCat("message for 1: ", i));
+ messages.emplace_back(1, quiche::QuicheStrCat("message for 1: ", i));
test::QuicTestMemSliceVector slice(
{std::make_pair(const_cast<char*>(messages.back().second.data()),
messages.back().second.size())});
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_session.cc b/chromium/net/third_party/quiche/src/quic/quartc/quartc_session.cc
index 654e54081aa..a93f4107ddb 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_session.cc
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_session.cc
@@ -11,6 +11,7 @@
#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice_storage.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace {
@@ -154,27 +155,6 @@ bool QuartcSession::SendProbingData() {
return true;
}
-void QuartcSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
- QuicSession::OnCryptoHandshakeEvent(event);
- switch (event) {
- case ENCRYPTION_ESTABLISHED:
- DCHECK(IsEncryptionEstablished());
- DCHECK(session_delegate_);
- session_delegate_->OnConnectionWritable();
- break;
- case HANDSHAKE_CONFIRMED:
- // On the server, handshake confirmed is the first time when you can start
- // writing packets.
- DCHECK(IsEncryptionEstablished());
- DCHECK(IsCryptoHandshakeConfirmed());
-
- DCHECK(session_delegate_);
- session_delegate_->OnConnectionWritable();
- session_delegate_->OnCryptoHandshakeComplete();
- break;
- }
-}
-
void QuartcSession::SetDefaultEncryptionLevel(EncryptionLevel level) {
QuicSession::SetDefaultEncryptionLevel(level);
switch (level) {
@@ -193,7 +173,7 @@ void QuartcSession::SetDefaultEncryptionLevel(EncryptionLevel level) {
// On the server, handshake confirmed is the first time when you can start
// writing packets.
DCHECK(IsEncryptionEstablished());
- DCHECK(IsCryptoHandshakeConfirmed());
+ DCHECK(OneRttKeysAvailable());
DCHECK(session_delegate_);
session_delegate_->OnConnectionWritable();
@@ -205,6 +185,18 @@ void QuartcSession::SetDefaultEncryptionLevel(EncryptionLevel level) {
}
}
+void QuartcSession::OnOneRttKeysAvailable() {
+ QuicSession::OnOneRttKeysAvailable();
+ // On the server, handshake confirmed is the first time when you can start
+ // writing packets.
+ DCHECK(IsEncryptionEstablished());
+ DCHECK(OneRttKeysAvailable());
+
+ DCHECK(session_delegate_);
+ session_delegate_->OnConnectionWritable();
+ session_delegate_->OnCryptoHandshakeComplete();
+}
+
void QuartcSession::CancelStream(QuicStreamId stream_id) {
ResetStream(stream_id, QuicRstStreamErrorCode::QUIC_STREAM_CANCELLED);
}
@@ -276,7 +268,7 @@ void QuartcSession::OnTransportReceived(const char* data, size_t data_len) {
packet);
}
-void QuartcSession::OnMessageReceived(QuicStringPiece message) {
+void QuartcSession::OnMessageReceived(quiche::QuicheStringPiece message) {
session_delegate_->OnMessageReceived(message);
}
@@ -363,7 +355,7 @@ QuartcClientSession::QuartcClientSession(
const QuicClock* clock,
std::unique_ptr<QuartcPacketWriter> packet_writer,
std::unique_ptr<QuicCryptoClientConfig> client_crypto_config,
- QuicStringPiece server_crypto_config)
+ quiche::QuicheStringPiece server_crypto_config)
: QuartcSession(std::move(connection),
/*visitor=*/nullptr,
config,
@@ -449,7 +441,7 @@ QuartcServerSession::QuartcServerSession(
const QuicClock* clock,
const QuicCryptoServerConfig* server_crypto_config,
QuicCompressedCertsCache* const compressed_certs_cache,
- QuicCryptoServerStream::Helper* const stream_helper)
+ QuicCryptoServerStreamBase::Helper* const stream_helper)
: QuartcSession(std::move(connection),
visitor,
config,
@@ -470,7 +462,7 @@ QuicCryptoStream* QuartcServerSession::GetMutableCryptoStream() {
}
void QuartcServerSession::StartCryptoHandshake() {
- crypto_stream_ = std::make_unique<QuicCryptoServerStream>(
+ crypto_stream_ = CreateCryptoServerStream(
server_crypto_config_, compressed_certs_cache_, this, stream_helper_);
Initialize();
}
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_session.h b/chromium/net/third_party/quiche/src/quic/quartc/quartc_session.h
index 1c0fd317b4c..db988a06654 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_session.h
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_session.h
@@ -9,7 +9,7 @@
#include <string>
#include "net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h"
-#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
+#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h"
#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/core/quic_session.h"
@@ -18,6 +18,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice_storage.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_packet_writer.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_stream.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -73,8 +74,8 @@ class QuartcSession : public QuicSession,
return VersionSupportsMessageFrames(transport_version());
}
- void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override;
void SetDefaultEncryptionLevel(EncryptionLevel level) override;
+ void OnOneRttKeysAvailable() override;
// QuicConnectionVisitorInterface overrides.
void OnCongestionWindowChange(QuicTime now) override;
@@ -139,7 +140,7 @@ class QuartcSession : public QuicSession,
ConnectionCloseSource source) = 0;
// Called when message (sent as SendMessage) is received.
- virtual void OnMessageReceived(QuicStringPiece message) = 0;
+ virtual void OnMessageReceived(quiche::QuicheStringPiece message) = 0;
// Called when message is sent to QUIC.
//
@@ -179,7 +180,7 @@ class QuartcSession : public QuicSession,
// QuicConnection.
void OnTransportReceived(const char* data, size_t data_len) override;
- void OnMessageReceived(QuicStringPiece message) override;
+ void OnMessageReceived(quiche::QuicheStringPiece message) override;
// Called when message with |message_id| gets acked.
void OnMessageAcked(QuicMessageId message_id,
@@ -239,7 +240,7 @@ class QuartcSession : public QuicSession,
// Queue of pending messages sent by SendQuartcMessage that were not sent
// yet or blocked by congestion control. Messages are queued in the order
// of sent by SendOrQueueMessage().
- QuicDeque<QueuedMessage> send_message_queue_;
+ QuicCircularDeque<QueuedMessage> send_message_queue_;
// Maps message ids to datagram ids, so we could translate message ACKs
// received from QUIC to datagram ACKs that are propagated up the stack.
@@ -256,7 +257,7 @@ class QuartcClientSession : public QuartcSession,
const QuicClock* clock,
std::unique_ptr<QuartcPacketWriter> packet_writer,
std::unique_ptr<QuicCryptoClientConfig> client_crypto_config,
- QuicStringPiece server_crypto_config);
+ quiche::QuicheStringPiece server_crypto_config);
QuartcClientSession(const QuartcClientSession&) = delete;
QuartcClientSession& operator=(const QuartcClientSession&) = delete;
@@ -308,7 +309,7 @@ class QuartcServerSession : public QuartcSession {
const QuicClock* clock,
const QuicCryptoServerConfig* server_crypto_config,
QuicCompressedCertsCache* const compressed_certs_cache,
- QuicCryptoServerStream::Helper* const stream_helper);
+ QuicCryptoServerStreamBase::Helper* const stream_helper);
QuartcServerSession(const QuartcServerSession&) = delete;
QuartcServerSession& operator=(const QuartcServerSession&) = delete;
@@ -327,10 +328,10 @@ class QuartcServerSession : public QuartcSession {
QuicCompressedCertsCache* const compressed_certs_cache_;
// This helper is needed to create QuicCryptoServerStream.
- QuicCryptoServerStream::Helper* const stream_helper_;
+ QuicCryptoServerStreamBase::Helper* const stream_helper_;
// Server perspective crypto stream.
- std::unique_ptr<QuicCryptoServerStream> crypto_stream_;
+ std::unique_ptr<QuicCryptoServerStreamBase> crypto_stream_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_session_test.cc b/chromium/net/third_party/quiche/src/quic/quartc/quartc_session_test.cc
index 956073bade9..47312059721 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_session_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_session_test.cc
@@ -6,11 +6,11 @@
#include <utility>
+#include "net/third_party/quiche/src/quic/core/quic_clock.h"
#include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h"
#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test_mem_slice_vector.h"
@@ -23,6 +23,8 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/packet_filter.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -41,7 +43,8 @@ constexpr QuicTime::Delta kPropagationDelayAndABit =
static QuicByteCount kDefaultMaxPacketSize = 1200;
-test::QuicTestMemSliceVector CreateMemSliceVector(QuicStringPiece data) {
+test::QuicTestMemSliceVector CreateMemSliceVector(
+ quiche::QuicheStringPiece data) {
return test::QuicTestMemSliceVector(
{std::pair<char*, size_t>(const_cast<char*>(data.data()), data.size())});
}
@@ -51,6 +54,12 @@ class QuartcSessionTest : public QuicTest {
~QuartcSessionTest() override {}
void Init(bool create_client_endpoint = true) {
+ // TODO(b/150224094): Re-enable TLS handshake.
+ // TODO(b/150236522): Parametrize by QUIC version.
+ SetQuicReloadableFlag(quic_enable_version_draft_27, false);
+ SetQuicReloadableFlag(quic_enable_version_draft_25_v3, false);
+ SetQuicReloadableFlag(quic_enable_version_t050, false);
+
client_transport_ =
std::make_unique<simulator::SimulatedQuartcPacketTransport>(
&simulator_, "client_transport", "server_transport",
@@ -116,16 +125,16 @@ class QuartcSessionTest : public QuicTest {
void AwaitHandshake() {
simulator_.RunUntil([this] {
- return client_peer_->IsCryptoHandshakeConfirmed() &&
- server_peer_->IsCryptoHandshakeConfirmed();
+ return client_peer_->OneRttKeysAvailable() &&
+ server_peer_->OneRttKeysAvailable();
});
}
// Test handshake establishment and sending/receiving of data for two
// directions.
void TestSendReceiveStreams() {
- ASSERT_TRUE(server_peer_->IsCryptoHandshakeConfirmed());
- ASSERT_TRUE(client_peer_->IsCryptoHandshakeConfirmed());
+ ASSERT_TRUE(server_peer_->OneRttKeysAvailable());
+ ASSERT_TRUE(client_peer_->OneRttKeysAvailable());
ASSERT_TRUE(server_peer_->IsEncryptionEstablished());
ASSERT_TRUE(client_peer_->IsEncryptionEstablished());
@@ -167,6 +176,11 @@ class QuartcSessionTest : public QuicTest {
ASSERT_TRUE(server_peer_->CanSendMessage());
ASSERT_TRUE(client_peer_->CanSendMessage());
+ // Disable probing retransmissions such that the first message from either
+ // side can be sent without being queued.
+ client_peer_->connection()->set_fill_up_link_during_probing(false);
+ server_peer_->connection()->set_fill_up_link_during_probing(false);
+
int64_t server_datagram_id = 111;
int64_t client_datagram_id = 222;
@@ -243,8 +257,8 @@ class QuartcSessionTest : public QuicTest {
std::vector<int64_t> sent_datagram_ids;
int64_t current_datagram_id = 0;
while (peer_sending->send_message_queue_size() < queue_size) {
- sent_messages.push_back(
- QuicStrCat("Sending message, index=", sent_messages.size()));
+ sent_messages.push_back(quiche::QuicheStrCat("Sending message, index=",
+ sent_messages.size()));
ASSERT_TRUE(peer_sending->SendOrQueueMessage(
CreateMemSliceVector(sent_messages.back()).span(),
current_datagram_id));
@@ -302,10 +316,10 @@ class QuartcSessionTest : public QuicTest {
EXPECT_TRUE(!server_session_delegate_->connected());
EXPECT_FALSE(client_peer_->IsEncryptionEstablished());
- EXPECT_FALSE(client_peer_->IsCryptoHandshakeConfirmed());
+ EXPECT_FALSE(client_peer_->OneRttKeysAvailable());
EXPECT_FALSE(server_peer_->IsEncryptionEstablished());
- EXPECT_FALSE(server_peer_->IsCryptoHandshakeConfirmed());
+ EXPECT_FALSE(server_peer_->OneRttKeysAvailable());
}
protected:
@@ -335,18 +349,12 @@ TEST_F(QuartcSessionTest, SendReceiveStreams) {
}
TEST_F(QuartcSessionTest, SendReceiveMessages) {
- // TODO(b/134175506): Remove when IETF QUIC supports receive timestamps.
- SetQuicReloadableFlag(quic_enable_version_99, false);
-
CreateClientAndServerSessions(QuartcSessionConfig());
AwaitHandshake();
TestSendReceiveMessage();
}
TEST_F(QuartcSessionTest, SendReceiveQueuedMessages) {
- // TODO(b/134175506): Remove when IETF QUIC supports receive timestamps.
- SetQuicReloadableFlag(quic_enable_version_99, false);
-
CreateClientAndServerSessions(QuartcSessionConfig());
AwaitHandshake();
TestSendReceiveQueuedMessages(/*direction_from_server=*/true);
@@ -405,9 +413,6 @@ TEST_F(QuartcSessionTest, TestCryptoHandshakeCanWriteTriggers) {
}
TEST_F(QuartcSessionTest, PreSharedKeyHandshake) {
- // TODO(b/134175506): Remove when IETF QUIC supports receive timestamps.
- SetQuicReloadableFlag(quic_enable_version_99, false);
-
QuartcSessionConfig config;
config.pre_shared_key = "foo";
CreateClientAndServerSessions(config);
@@ -426,8 +431,8 @@ TEST_F(QuartcSessionTest, CannotCreateDataStreamBeforeHandshake) {
TEST_F(QuartcSessionTest, CancelQuartcStream) {
CreateClientAndServerSessions(QuartcSessionConfig());
AwaitHandshake();
- ASSERT_TRUE(client_peer_->IsCryptoHandshakeConfirmed());
- ASSERT_TRUE(server_peer_->IsCryptoHandshakeConfirmed());
+ ASSERT_TRUE(client_peer_->OneRttKeysAvailable());
+ ASSERT_TRUE(server_peer_->OneRttKeysAvailable());
QuartcStream* stream = client_peer_->CreateOutgoingBidirectionalStream();
ASSERT_NE(nullptr, stream);
@@ -448,8 +453,8 @@ TEST_F(QuartcSessionTest, CancelQuartcStream) {
TEST_F(QuartcSessionTest, WriterGivesPacketNumberToTransport) {
CreateClientAndServerSessions(QuartcSessionConfig());
AwaitHandshake();
- ASSERT_TRUE(client_peer_->IsCryptoHandshakeConfirmed());
- ASSERT_TRUE(server_peer_->IsCryptoHandshakeConfirmed());
+ ASSERT_TRUE(client_peer_->OneRttKeysAvailable());
+ ASSERT_TRUE(server_peer_->OneRttKeysAvailable());
QuartcStream* stream = client_peer_->CreateOutgoingBidirectionalStream();
stream->SetDelegate(client_stream_delegate_.get());
@@ -467,8 +472,8 @@ TEST_F(QuartcSessionTest, WriterGivesPacketNumberToTransport) {
TEST_F(QuartcSessionTest, CloseConnection) {
CreateClientAndServerSessions(QuartcSessionConfig());
AwaitHandshake();
- ASSERT_TRUE(client_peer_->IsCryptoHandshakeConfirmed());
- ASSERT_TRUE(server_peer_->IsCryptoHandshakeConfirmed());
+ ASSERT_TRUE(client_peer_->OneRttKeysAvailable());
+ ASSERT_TRUE(server_peer_->OneRttKeysAvailable());
client_peer_->CloseConnection("Connection closed by client");
EXPECT_FALSE(client_session_delegate_->connected());
@@ -479,8 +484,8 @@ TEST_F(QuartcSessionTest, CloseConnection) {
TEST_F(QuartcSessionTest, StreamRetransmissionEnabled) {
CreateClientAndServerSessions(QuartcSessionConfig());
AwaitHandshake();
- ASSERT_TRUE(client_peer_->IsCryptoHandshakeConfirmed());
- ASSERT_TRUE(server_peer_->IsCryptoHandshakeConfirmed());
+ ASSERT_TRUE(client_peer_->OneRttKeysAvailable());
+ ASSERT_TRUE(server_peer_->OneRttKeysAvailable());
QuartcStream* stream = client_peer_->CreateOutgoingBidirectionalStream();
QuicStreamId stream_id = stream->id();
@@ -510,8 +515,8 @@ TEST_F(QuartcSessionTest, StreamRetransmissionDisabled) {
client_peer_->connection()->set_fill_up_link_during_probing(false);
AwaitHandshake();
- ASSERT_TRUE(client_peer_->IsCryptoHandshakeConfirmed());
- ASSERT_TRUE(server_peer_->IsCryptoHandshakeConfirmed());
+ ASSERT_TRUE(client_peer_->OneRttKeysAvailable());
+ ASSERT_TRUE(server_peer_->OneRttKeysAvailable());
// The client sends an ACK for the crypto handshake next. This must be
// flushed before we set the filter to drop the next packet, in order to
@@ -551,9 +556,6 @@ TEST_F(QuartcSessionTest, StreamRetransmissionDisabled) {
}
TEST_F(QuartcSessionTest, LostDatagramNotifications) {
- // TODO(b/134175506): Remove when IETF QUIC supports receive timestamps.
- SetQuicReloadableFlag(quic_enable_version_99, false);
-
// Disable tail loss probe, otherwise test maybe flaky because dropped
// message will be retransmitted to detect tail loss.
QuartcSessionConfig session_config;
@@ -566,8 +568,8 @@ TEST_F(QuartcSessionTest, LostDatagramNotifications) {
server_peer_->connection()->set_fill_up_link_during_probing(false);
AwaitHandshake();
- ASSERT_TRUE(client_peer_->IsCryptoHandshakeConfirmed());
- ASSERT_TRUE(server_peer_->IsCryptoHandshakeConfirmed());
+ ASSERT_TRUE(client_peer_->OneRttKeysAvailable());
+ ASSERT_TRUE(server_peer_->OneRttKeysAvailable());
// The client sends an ACK for the crypto handshake next. This must be
// flushed before we set the filter to drop the next packet, in order to
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_stream.cc b/chromium/net/third_party/quiche/src/quic/quartc/quartc_stream.cc
index 46f89db7268..9edf370120f 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_stream.cc
@@ -14,7 +14,7 @@
#include "net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_reference_counted.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -78,6 +78,7 @@ bool QuartcStream::OnStreamFrameAcked(QuicStreamOffset offset,
QuicByteCount data_length,
bool fin_acked,
QuicTime::Delta ack_delay_time,
+ QuicTime receive_timestamp,
QuicByteCount* newly_acked_length) {
// Previous losses of acked data are no longer relevant to the retransmission
// count. Once data is acked, it will never be retransmitted.
@@ -85,7 +86,8 @@ bool QuartcStream::OnStreamFrameAcked(QuicStreamOffset offset,
QuicInterval<QuicStreamOffset>(offset, offset + data_length));
return QuicStream::OnStreamFrameAcked(offset, data_length, fin_acked,
- ack_delay_time, newly_acked_length);
+ ack_delay_time, receive_timestamp,
+ newly_acked_length);
}
void QuartcStream::OnStreamFrameRetransmitted(QuicStreamOffset offset,
@@ -157,7 +159,7 @@ QuicStreamOffset QuartcStream::ReadOffset() {
}
void QuartcStream::FinishWriting() {
- WriteOrBufferData(QuicStringPiece(nullptr, 0), true, nullptr);
+ WriteOrBufferData(quiche::QuicheStringPiece(nullptr, 0), true, nullptr);
}
void QuartcStream::SetDelegate(Delegate* delegate) {
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_stream.h b/chromium/net/third_party/quiche/src/quic/quartc/quartc_stream.h
index 403ce6d73fe..40e8328efea 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_stream.h
@@ -46,6 +46,7 @@ class QuartcStream : public QuicStream {
QuicByteCount data_length,
bool fin_acked,
QuicTime::Delta ack_delay_time,
+ QuicTime receive_timestamp,
QuicByteCount* newly_acked_length) override;
void OnStreamFrameRetransmitted(QuicStreamOffset offset,
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_stream_test.cc b/chromium/net/third_party/quiche/src/quic/quartc/quartc_stream_test.cc
index 0e972e50aff..7a8b22d501b 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_stream_test.cc
@@ -13,6 +13,7 @@
#include "net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h"
#include "net/third_party/quiche/src/quic/core/quic_alarm_factory.h"
#include "net/third_party/quiche/src/quic/core/quic_buffer_allocator.h"
+#include "net/third_party/quiche/src/quic/core/quic_clock.h"
#include "net/third_party/quiche/src/quic/core/quic_config.h"
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
@@ -26,7 +27,6 @@
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ip_address.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
@@ -64,11 +64,13 @@ class MockQuicSession : public QuicSession {
~MockQuicSession() override {}
// Writes outgoing data from QuicStream to a string.
- QuicConsumedData WritevData(QuicStream* stream,
- QuicStreamId /*id*/,
- size_t write_length,
- QuicStreamOffset offset,
- StreamSendingState state) override {
+ QuicConsumedData WritevData(
+ QuicStreamId id,
+ size_t write_length,
+ QuicStreamOffset offset,
+ StreamSendingState state,
+ TransmissionType /*type*/,
+ quiche::QuicheOptional<EncryptionLevel> /*level*/) override {
if (!writable_) {
return QuicConsumedData(0, false);
}
@@ -77,6 +79,8 @@ class MockQuicSession : public QuicSession {
// data is consumed. Retrieve data from stream.
char* buf = new char[write_length];
QuicDataWriter writer(write_length, buf, quiche::NETWORK_BYTE_ORDER);
+ QuicStream* stream = GetOrCreateStream(id);
+ DCHECK(stream);
if (write_length > 0) {
stream->WriteStreamData(offset, write_length, &writer);
}
@@ -210,12 +214,10 @@ class MockQuartcStreamDelegate : public QuartcStream::Delegate {
QuicByteCount last_bytes_pending_retransmission_ = 0;
};
-class QuartcStreamTest : public QuicTest, public QuicConnectionHelperInterface {
+class QuartcStreamTest : public QuicTestWithParam<ParsedQuicVersion>,
+ public QuicConnectionHelperInterface {
public:
- QuartcStreamTest() {
- // Required to correctly handle StopReading().
- SetQuicReloadableFlag(quic_stop_reading_when_level_triggered, true);
- }
+ QuartcStreamTest() : version_(GetParam()) {}
~QuartcStreamTest() override = default;
@@ -229,11 +231,10 @@ class QuartcStreamTest : public QuicTest, public QuicConnectionHelperInterface {
alarm_factory_ = std::make_unique<test::MockAlarmFactory>();
connection_ = std::make_unique<QuicConnection>(
- QuicUtils::CreateZeroConnectionId(
- CurrentSupportedVersions()[0].transport_version),
+ QuicUtils::CreateZeroConnectionId(version_.transport_version),
QuicSocketAddress(ip, 0), this /*QuicConnectionHelperInterface*/,
alarm_factory_.get(), new DummyPacketWriter(), owns_writer, perspective,
- ParsedVersionOfIndex(CurrentSupportedVersions(), 0));
+ ParsedQuicVersionVector{version_});
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
session_ = std::make_unique<MockQuicSession>(connection_.get(),
QuicConfig(), &write_buffer_);
@@ -255,6 +256,7 @@ class QuartcStreamTest : public QuicTest, public QuicConnectionHelperInterface {
}
protected:
+ const ParsedQuicVersion version_;
// The QuicSession will take the ownership.
QuartcStream* stream_;
std::unique_ptr<MockQuartcStreamDelegate> mock_stream_delegate_;
@@ -270,8 +272,15 @@ class QuartcStreamTest : public QuicTest, public QuicConnectionHelperInterface {
MockClock clock_;
};
+// TODO(b/150224094): Enable versions with TLS handshake.
+INSTANTIATE_TEST_SUITE_P(
+ Tests,
+ QuartcStreamTest,
+ ::testing::ValuesIn(CurrentSupportedVersionsWithQuicCrypto()),
+ ::testing::PrintToStringParamName());
+
// Write an entire string.
-TEST_F(QuartcStreamTest, WriteDataWhole) {
+TEST_P(QuartcStreamTest, WriteDataWhole) {
CreateReliableQuicStream();
char message[] = "Foo bar";
test::QuicTestMemSliceVector data({std::make_pair(message, 7)});
@@ -280,7 +289,7 @@ TEST_F(QuartcStreamTest, WriteDataWhole) {
}
// Write part of a string.
-TEST_F(QuartcStreamTest, WriteDataPartial) {
+TEST_P(QuartcStreamTest, WriteDataPartial) {
CreateReliableQuicStream();
char message[] = "Foo bar";
test::QuicTestMemSliceVector data({std::make_pair(message, 5)});
@@ -289,7 +298,7 @@ TEST_F(QuartcStreamTest, WriteDataPartial) {
}
// Test that a QuartcStream buffers writes correctly.
-TEST_F(QuartcStreamTest, StreamBuffersData) {
+TEST_P(QuartcStreamTest, StreamBuffersData) {
CreateReliableQuicStream();
char message[] = "Foo bar";
@@ -334,7 +343,7 @@ TEST_F(QuartcStreamTest, StreamBuffersData) {
// Finish writing to a stream.
// It delivers the fin bit and closes the write-side as soon as possible.
-TEST_F(QuartcStreamTest, FinishWriting) {
+TEST_P(QuartcStreamTest, FinishWriting) {
CreateReliableQuicStream();
session_->set_writable(false);
@@ -349,7 +358,7 @@ TEST_F(QuartcStreamTest, FinishWriting) {
}
// Read an entire string.
-TEST_F(QuartcStreamTest, ReadDataWhole) {
+TEST_P(QuartcStreamTest, ReadDataWhole) {
CreateReliableQuicStream();
QuicStreamFrame frame(kStreamId, false, 0, "Hello, World!");
stream_->OnStreamFrame(frame);
@@ -358,7 +367,7 @@ TEST_F(QuartcStreamTest, ReadDataWhole) {
}
// Read part of a string.
-TEST_F(QuartcStreamTest, ReadDataPartial) {
+TEST_P(QuartcStreamTest, ReadDataPartial) {
CreateReliableQuicStream();
QuicStreamFrame frame(kStreamId, false, 0, "Hello, World!");
frame.data_length = 5;
@@ -369,7 +378,7 @@ TEST_F(QuartcStreamTest, ReadDataPartial) {
// Streams do not call OnReceived() after StopReading().
// Note: this is tested here because Quartc relies on this behavior.
-TEST_F(QuartcStreamTest, StopReading) {
+TEST_P(QuartcStreamTest, StopReading) {
CreateReliableQuicStream();
stream_->StopReading();
@@ -386,7 +395,7 @@ TEST_F(QuartcStreamTest, StopReading) {
}
// Test that closing the stream results in a callback.
-TEST_F(QuartcStreamTest, CloseStream) {
+TEST_P(QuartcStreamTest, CloseStream) {
CreateReliableQuicStream();
EXPECT_FALSE(mock_stream_delegate_->closed());
stream_->OnClose();
@@ -394,7 +403,7 @@ TEST_F(QuartcStreamTest, CloseStream) {
}
// Both sending and receiving fin automatically closes a stream.
-TEST_F(QuartcStreamTest, CloseOnFins) {
+TEST_P(QuartcStreamTest, CloseOnFins) {
CreateReliableQuicStream();
QuicStreamFrame frame(kStreamId, true, 0, 0);
stream_->OnStreamFrame(frame);
@@ -406,7 +415,7 @@ TEST_F(QuartcStreamTest, CloseOnFins) {
EXPECT_TRUE(mock_stream_delegate_->closed());
}
-TEST_F(QuartcStreamTest, TestCancelOnLossDisabled) {
+TEST_P(QuartcStreamTest, TestCancelOnLossDisabled) {
CreateReliableQuicStream();
// This should be the default state.
@@ -425,7 +434,7 @@ TEST_F(QuartcStreamTest, TestCancelOnLossDisabled) {
EXPECT_THAT(stream_->stream_error(), IsQuicStreamNoError());
}
-TEST_F(QuartcStreamTest, TestCancelOnLossEnabled) {
+TEST_P(QuartcStreamTest, TestCancelOnLossEnabled) {
CreateReliableQuicStream();
stream_->set_cancel_on_loss(true);
@@ -442,7 +451,7 @@ TEST_F(QuartcStreamTest, TestCancelOnLossEnabled) {
EXPECT_THAT(stream_->stream_error(), IsStreamError(QUIC_STREAM_CANCELLED));
}
-TEST_F(QuartcStreamTest, MaxRetransmissionsAbsent) {
+TEST_P(QuartcStreamTest, MaxRetransmissionsAbsent) {
CreateReliableQuicStream();
// This should be the default state.
@@ -462,7 +471,7 @@ TEST_F(QuartcStreamTest, MaxRetransmissionsAbsent) {
EXPECT_THAT(stream_->stream_error(), IsQuicStreamNoError());
}
-TEST_F(QuartcStreamTest, MaxRetransmissionsSet) {
+TEST_P(QuartcStreamTest, MaxRetransmissionsSet) {
CreateReliableQuicStream();
stream_->set_max_retransmission_count(2);
@@ -489,7 +498,7 @@ TEST_F(QuartcStreamTest, MaxRetransmissionsSet) {
EXPECT_THAT(stream_->stream_error(), IsStreamError(QUIC_STREAM_CANCELLED));
}
-TEST_F(QuartcStreamTest, MaxRetransmissionsDisjointFrames) {
+TEST_P(QuartcStreamTest, MaxRetransmissionsDisjointFrames) {
CreateReliableQuicStream();
stream_->set_max_retransmission_count(2);
@@ -518,7 +527,7 @@ TEST_F(QuartcStreamTest, MaxRetransmissionsDisjointFrames) {
EXPECT_EQ("Foo barFoo barFoo bar", write_buffer_);
}
-TEST_F(QuartcStreamTest, MaxRetransmissionsOverlappingFrames) {
+TEST_P(QuartcStreamTest, MaxRetransmissionsOverlappingFrames) {
CreateReliableQuicStream();
stream_->set_max_retransmission_count(2);
@@ -548,7 +557,7 @@ TEST_F(QuartcStreamTest, MaxRetransmissionsOverlappingFrames) {
EXPECT_THAT(stream_->stream_error(), IsStreamError(QUIC_STREAM_CANCELLED));
}
-TEST_F(QuartcStreamTest, MaxRetransmissionsWithAckedFrame) {
+TEST_P(QuartcStreamTest, MaxRetransmissionsWithAckedFrame) {
CreateReliableQuicStream();
stream_->set_max_retransmission_count(1);
@@ -568,7 +577,7 @@ TEST_F(QuartcStreamTest, MaxRetransmissionsWithAckedFrame) {
// the stream.
QuicByteCount newly_acked_length = 0;
stream_->OnStreamFrameAcked(0, 7, false, QuicTime::Delta::FromMilliseconds(1),
- &newly_acked_length);
+ QuicTime::Zero(), &newly_acked_length);
EXPECT_EQ(7u, newly_acked_length);
stream_->OnCanWrite();
@@ -585,7 +594,7 @@ TEST_F(QuartcStreamTest, MaxRetransmissionsWithAckedFrame) {
EXPECT_THAT(stream_->stream_error(), IsQuicStreamNoError());
}
-TEST_F(QuartcStreamTest, TestBytesPendingRetransmission) {
+TEST_P(QuartcStreamTest, TestBytesPendingRetransmission) {
CreateReliableQuicStream();
stream_->set_cancel_on_loss(false);
@@ -611,7 +620,7 @@ TEST_F(QuartcStreamTest, TestBytesPendingRetransmission) {
EXPECT_THAT(stream_->stream_error(), IsQuicStreamNoError());
}
-TEST_F(QuartcStreamTest, TestBytesPendingRetransmissionWithCancelOnLoss) {
+TEST_P(QuartcStreamTest, TestBytesPendingRetransmissionWithCancelOnLoss) {
CreateReliableQuicStream();
stream_->set_cancel_on_loss(true);
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/simulated_packet_transport.cc b/chromium/net/third_party/quiche/src/quic/quartc/simulated_packet_transport.cc
index 05f71c48291..263c21395e0 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/simulated_packet_transport.cc
+++ b/chromium/net/third_party/quiche/src/quic/quartc/simulated_packet_transport.cc
@@ -6,7 +6,7 @@
#include <utility>
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
namespace quic {
namespace simulator {
@@ -19,7 +19,7 @@ SimulatedQuartcPacketTransport::SimulatedQuartcPacketTransport(
: Endpoint(simulator, name),
peer_name_(peer_name),
egress_queue_(simulator,
- QuicStringPrintf("%s (TX Queue)", name.c_str()),
+ quiche::QuicheStringPrintf("%s (TX Queue)", name.c_str()),
queue_capacity) {
egress_queue_.set_listener_interface(this);
}
diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.cc b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.cc
index e9487ec0458..a35d0841b55 100644
--- a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.cc
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.cc
@@ -7,9 +7,11 @@
#include <cstdint>
#include <limits>
#include <memory>
+#include <string>
#include <utility>
#include "url/gurl.h"
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
#include "net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
@@ -18,10 +20,9 @@
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_protocol.h"
#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -36,6 +37,7 @@ class DummyProofHandler : public QuicCryptoClientStream::ProofHandler {
void OnProofVerifyDetailsAvailable(
const ProofVerifyDetails& /*verify_details*/) override {}
};
+
} // namespace
QuicTransportClientSession::QuicTransportClientSession(
@@ -67,6 +69,20 @@ QuicTransportClientSession::QuicTransportClientSession(
proof_handler);
}
+void QuicTransportClientSession::OnAlpnSelected(
+ quiche::QuicheStringPiece alpn) {
+ // Defense in-depth: ensure the ALPN selected is the desired one.
+ if (alpn != QuicTransportAlpn()) {
+ QUIC_BUG << "QuicTransport negotiated non-QuicTransport ALPN: " << alpn;
+ connection()->CloseConnection(
+ QUIC_INTERNAL_ERROR, "QuicTransport negotiated non-QuicTransport ALPN",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return;
+ }
+
+ alpn_received_ = true;
+}
+
QuicStream* QuicTransportClientSession::CreateIncomingStream(QuicStreamId id) {
QUIC_DVLOG(1) << "Creating incoming QuicTransport stream " << id;
QuicTransportStream* stream = CreateStream(id);
@@ -80,16 +96,6 @@ QuicStream* QuicTransportClientSession::CreateIncomingStream(QuicStreamId id) {
return stream;
}
-void QuicTransportClientSession::OnCryptoHandshakeEvent(
- CryptoHandshakeEvent event) {
- QuicSession::OnCryptoHandshakeEvent(event);
- if (event != HANDSHAKE_CONFIRMED) {
- return;
- }
-
- SendClientIndication();
-}
-
void QuicTransportClientSession::SetDefaultEncryptionLevel(
EncryptionLevel level) {
QuicSession::SetDefaultEncryptionLevel(level);
@@ -98,6 +104,11 @@ void QuicTransportClientSession::SetDefaultEncryptionLevel(
}
}
+void QuicTransportClientSession::OnOneRttKeysAvailable() {
+ QuicSession::OnOneRttKeysAvailable();
+ SendClientIndication();
+}
+
QuicTransportStream*
QuicTransportClientSession::AcceptIncomingBidirectionalStream() {
if (incoming_bidirectional_streams_.empty()) {
@@ -222,12 +233,38 @@ void QuicTransportClientSession::SendClientIndication() {
/*fin=*/true, nullptr);
client_indication_sent_ = true;
+ // Defense in depth: never set the ready bit unless ALPN has been confirmed.
+ if (!alpn_received_) {
+ QUIC_BUG << "ALPN confirmation missing after handshake complete";
+ connection()->CloseConnection(
+ QUIC_INTERNAL_ERROR,
+ "ALPN confirmation missing after handshake complete",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return;
+ }
+
// Don't set the ready bit if we closed the connection due to any error
// beforehand.
if (!connection()->connected()) {
return;
}
+
ready_ = true;
+ visitor_->OnSessionReady();
+}
+
+void QuicTransportClientSession::OnMessageReceived(
+ quiche::QuicheStringPiece message) {
+ visitor_->OnDatagramReceived(message);
+}
+
+void QuicTransportClientSession::OnCanCreateNewOutgoingStream(
+ bool unidirectional) {
+ if (unidirectional) {
+ visitor_->OnCanCreateNewOutgoingUnidirectionalStream();
+ } else {
+ visitor_->OnCanCreateNewOutgoingBidirectionalStream();
+ }
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.h b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.h
index b3d8f17186b..56b29e43d5b 100644
--- a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.h
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.h
@@ -21,10 +21,10 @@
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_protocol.h"
#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_session_interface.h"
#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -37,11 +37,22 @@ class QUIC_EXPORT_PRIVATE QuicTransportClientSession
public:
virtual ~ClientVisitor() {}
+ // Notifies the visitor when the client indication has been sent and the
+ // connection is ready to exchange application data.
+ virtual void OnSessionReady() = 0;
+
// Notifies the visitor when a new stream has been received. The stream in
// question can be retrieved using AcceptIncomingBidirectionalStream() or
// AcceptIncomingUnidirectionalStream().
virtual void OnIncomingBidirectionalStreamAvailable() = 0;
virtual void OnIncomingUnidirectionalStreamAvailable() = 0;
+
+ // Notifies the visitor when a new datagram has been received.
+ virtual void OnDatagramReceived(quiche::QuicheStringPiece datagram) = 0;
+
+ // Notifies the visitor that a new outgoing stream can now be created.
+ virtual void OnCanCreateNewOutgoingBidirectionalStream() = 0;
+ virtual void OnCanCreateNewOutgoingUnidirectionalStream() = 0;
};
QuicTransportClientSession(QuicConnection* connection,
@@ -56,6 +67,8 @@ class QUIC_EXPORT_PRIVATE QuicTransportClientSession
std::vector<std::string> GetAlpnsToOffer() const override {
return std::vector<std::string>({QuicTransportAlpn()});
}
+ void OnAlpnSelected(quiche::QuicheStringPiece alpn) override;
+ bool alpn_received() const { return alpn_received_; }
void CryptoConnect() { crypto_stream_->CryptoConnect(); }
@@ -81,8 +94,9 @@ class QUIC_EXPORT_PRIVATE QuicTransportClientSession
return nullptr;
}
- void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override;
void SetDefaultEncryptionLevel(EncryptionLevel level) override;
+ void OnOneRttKeysAvailable() override;
+ void OnMessageReceived(quiche::QuicheStringPiece message) override;
// Return the earliest incoming stream that has been received by the session
// but has not been accepted. Returns nullptr if there are no incoming
@@ -95,6 +109,8 @@ class QUIC_EXPORT_PRIVATE QuicTransportClientSession
QuicTransportStream* OpenOutgoingBidirectionalStream();
QuicTransportStream* OpenOutgoingUnidirectionalStream();
+ using QuicSession::datagram_queue;
+
protected:
class QUIC_EXPORT_PRIVATE ClientIndication : public QuicStream {
public:
@@ -116,11 +132,14 @@ class QUIC_EXPORT_PRIVATE QuicTransportClientSession
// Creates the client indication stream and sends the client indication on it.
void SendClientIndication();
+ void OnCanCreateNewOutgoingStream(bool unidirectional) override;
+
std::unique_ptr<QuicCryptoClientStream> crypto_stream_;
GURL url_;
url::Origin origin_;
ClientVisitor* visitor_; // not owned
bool client_indication_sent_ = false;
+ bool alpn_received_ = false;
bool ready_ = false;
// Contains all of the streams that has been received by the session but have
@@ -131,8 +150,8 @@ class QUIC_EXPORT_PRIVATE QuicTransportClientSession
// has not accepted to a smaller number, by checking the size of
// |incoming_bidirectional_streams_| and |incoming_unidirectional_streams_|
// before sending MAX_STREAMS.
- QuicDeque<QuicTransportStream*> incoming_bidirectional_streams_;
- QuicDeque<QuicTransportStream*> incoming_unidirectional_streams_;
+ QuicCircularDeque<QuicTransportStream*> incoming_bidirectional_streams_;
+ QuicCircularDeque<QuicTransportStream*> incoming_unidirectional_streams_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session_test.cc b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session_test.cc
index 17a475751d6..ba65ce29881 100644
--- a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session_test.cc
@@ -12,15 +12,14 @@
#include "net/third_party/quiche/src/quic/core/quic_server_id.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_session_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_transport_test_tools.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
namespace quic {
namespace test {
@@ -28,6 +27,7 @@ namespace {
using testing::_;
using testing::ElementsAre;
+using testing::Eq;
const char* kTestOrigin = "https://test-origin.test";
url::Origin GetTestOrigin() {
@@ -36,7 +36,7 @@ url::Origin GetTestOrigin() {
}
ParsedQuicVersionVector GetVersions() {
- return {ParsedQuicVersion{PROTOCOL_TLS1_3, QUIC_VERSION_99}};
+ return {DefaultVersionForQuicTransport()};
}
std::string DataInStream(QuicStream* stream) {
@@ -57,7 +57,7 @@ class QuicTransportClientSessionTest : public QuicTest {
Perspective::IS_CLIENT,
GetVersions()),
crypto_config_(crypto_test_utils::ProofVerifierForTesting()) {
- SetQuicReloadableFlag(quic_supports_tls_handshake, true);
+ QuicEnableVersion(DefaultVersionForQuicTransport());
CreateSession(GetTestOrigin(), "");
}
@@ -104,6 +104,7 @@ TEST_F(QuicTransportClientSessionTest, SuccessfulConnection) {
"\0\x01" // length
"/"; // value
+ EXPECT_CALL(visitor_, OnSessionReady());
Connect();
EXPECT_TRUE(session_->IsSessionReady());
@@ -114,7 +115,7 @@ TEST_F(QuicTransportClientSessionTest, SuccessfulConnection) {
const std::string client_indication = DataInStream(client_indication_stream);
const std::string expected_client_indication{
kTestOriginClientIndication,
- QUIC_ARRAYSIZE(kTestOriginClientIndication) - 1};
+ QUICHE_ARRAYSIZE(kTestOriginClientIndication) - 1};
EXPECT_EQ(client_indication, expected_client_indication);
}
@@ -139,7 +140,7 @@ TEST_F(QuicTransportClientSessionTest, SuccessfulConnectionWithPath) {
const std::string client_indication = DataInStream(client_indication_stream);
const std::string expected_client_indication{
kTestOriginClientIndication,
- QUIC_ARRAYSIZE(kTestOriginClientIndication) - 1};
+ QUICHE_ARRAYSIZE(kTestOriginClientIndication) - 1};
EXPECT_EQ(client_indication, expected_client_indication);
}
@@ -169,6 +170,11 @@ TEST_F(QuicTransportClientSessionTest, ReceiveNewStreams) {
EXPECT_EQ(stream->id(), id);
}
+TEST_F(QuicTransportClientSessionTest, ReceiveDatagram) {
+ EXPECT_CALL(visitor_, OnDatagramReceived(Eq("test")));
+ session_->OnMessageReceived("test");
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_integration_test.cc b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_integration_test.cc
index 57f53804c3a..355f6cc7f8b 100644
--- a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_integration_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_integration_test.cc
@@ -12,6 +12,7 @@
#include "url/origin.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h"
+#include "net/third_party/quiche/src/quic/core/quic_buffer_allocator.h"
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
@@ -29,6 +30,7 @@
#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/switch.h"
#include "net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
@@ -36,7 +38,9 @@ namespace {
using simulator::QuicEndpointBase;
using simulator::Simulator;
+using testing::_;
using testing::Assign;
+using testing::Eq;
url::Origin GetTestOrigin() {
constexpr char kTestOrigin[] = "https://test-origin.test";
@@ -45,7 +49,7 @@ url::Origin GetTestOrigin() {
}
ParsedQuicVersionVector GetVersions() {
- return {ParsedQuicVersion{PROTOCOL_TLS1_3, QUIC_VERSION_99}};
+ return {DefaultVersionForQuicTransport()};
}
class QuicTransportEndpointBase : public QuicEndpointBase {
@@ -55,13 +59,12 @@ class QuicTransportEndpointBase : public QuicEndpointBase {
const std::string& peer_name,
Perspective perspective)
: QuicEndpointBase(simulator, name, peer_name) {
+ QuicEnableVersion(DefaultVersionForQuicTransport());
connection_ = std::make_unique<QuicConnection>(
TestConnectionId(0x10), simulator::GetAddressFromName(peer_name),
simulator, simulator->GetAlarmFactory(), &writer_,
/*owns_writer=*/false, perspective, GetVersions());
connection_->SetSelfAddress(simulator::GetAddressFromName(name));
-
- SetQuicReloadableFlag(quic_supports_tls_handshake, true);
}
};
@@ -70,7 +73,9 @@ class QuicTransportClientEndpoint : public QuicTransportEndpointBase {
QuicTransportClientEndpoint(Simulator* simulator,
const std::string& name,
const std::string& peer_name,
- url::Origin origin)
+ const QuicConfig& config,
+ url::Origin origin,
+ const std::string& path)
: QuicTransportEndpointBase(simulator,
name,
peer_name,
@@ -78,9 +83,9 @@ class QuicTransportClientEndpoint : public QuicTransportEndpointBase {
crypto_config_(crypto_test_utils::ProofVerifierForTesting()),
session_(connection_.get(),
nullptr,
- DefaultQuicConfig(),
+ config,
GetVersions(),
- GURL("quic-transport://test.example.com:50000"),
+ GURL("quic-transport://test.example.com:50000" + path),
&crypto_config_,
origin,
&visitor_) {
@@ -101,7 +106,7 @@ class QuicTransportServerEndpoint : public QuicTransportEndpointBase {
QuicTransportServerEndpoint(Simulator* simulator,
const std::string& name,
const std::string& peer_name,
- QuicTransportSimpleServerSession::Mode mode,
+ const QuicConfig& config,
std::vector<url::Origin> accepted_origins)
: QuicTransportEndpointBase(simulator,
name,
@@ -116,11 +121,10 @@ class QuicTransportServerEndpoint : public QuicTransportEndpointBase {
session_(connection_.get(),
/*owns_connection=*/false,
nullptr,
- DefaultQuicConfig(),
+ config,
GetVersions(),
&crypto_config_,
&compressed_certs_cache_,
- mode,
accepted_origins) {
session_.Initialize();
}
@@ -161,11 +165,11 @@ class QuicTransportIntegrationTest : public QuicTest {
QuicTransportIntegrationTest()
: switch_(&simulator_, "Switch", 8, 2 * kBdp) {}
- void CreateDefaultEndpoints(QuicTransportSimpleServerSession::Mode mode) {
+ void CreateDefaultEndpoints(const std::string& path) {
client_ = std::make_unique<QuicTransportClientEndpoint>(
- &simulator_, "Client", "Server", GetTestOrigin());
+ &simulator_, "Client", "Server", client_config_, GetTestOrigin(), path);
server_ = std::make_unique<QuicTransportServerEndpoint>(
- &simulator_, "Server", "Client", mode, accepted_origins_);
+ &simulator_, "Server", "Client", server_config_, accepted_origins_);
}
void WireUpEndpoints() {
@@ -194,6 +198,9 @@ class QuicTransportIntegrationTest : public QuicTest {
return session->IsSessionReady() || session->error() != QUIC_NO_ERROR;
}
+ QuicConfig client_config_ = DefaultQuicConfig();
+ QuicConfig server_config_ = DefaultQuicConfig();
+
Simulator simulator_;
simulator::Switch switch_;
std::unique_ptr<simulator::SymmetricLink> client_link_;
@@ -206,8 +213,9 @@ class QuicTransportIntegrationTest : public QuicTest {
};
TEST_F(QuicTransportIntegrationTest, SuccessfulHandshake) {
- CreateDefaultEndpoints(QuicTransportSimpleServerSession::DISCARD);
+ CreateDefaultEndpoints("/discard");
WireUpEndpoints();
+ EXPECT_CALL(*client_->visitor(), OnSessionReady());
RunHandshake();
EXPECT_TRUE(client_->session()->IsSessionReady());
EXPECT_TRUE(server_->session()->IsSessionReady());
@@ -215,7 +223,7 @@ TEST_F(QuicTransportIntegrationTest, SuccessfulHandshake) {
TEST_F(QuicTransportIntegrationTest, OriginMismatch) {
accepted_origins_ = {url::Origin::Create(GURL{"https://wrong-origin.test"})};
- CreateDefaultEndpoints(QuicTransportSimpleServerSession::DISCARD);
+ CreateDefaultEndpoints("/discard");
WireUpEndpoints();
RunHandshake();
// Wait until the client receives CONNECTION_CLOSE.
@@ -233,7 +241,7 @@ TEST_F(QuicTransportIntegrationTest, OriginMismatch) {
}
TEST_F(QuicTransportIntegrationTest, SendOutgoingStreams) {
- CreateDefaultEndpoints(QuicTransportSimpleServerSession::DISCARD);
+ CreateDefaultEndpoints("/discard");
WireUpEndpoints();
RunHandshake();
@@ -259,7 +267,7 @@ TEST_F(QuicTransportIntegrationTest, SendOutgoingStreams) {
}
TEST_F(QuicTransportIntegrationTest, EchoBidirectionalStreams) {
- CreateDefaultEndpoints(QuicTransportSimpleServerSession::ECHO);
+ CreateDefaultEndpoints("/echo");
WireUpEndpoints();
RunHandshake();
@@ -281,7 +289,7 @@ TEST_F(QuicTransportIntegrationTest, EchoBidirectionalStreams) {
}
TEST_F(QuicTransportIntegrationTest, EchoUnidirectionalStreams) {
- CreateDefaultEndpoints(QuicTransportSimpleServerSession::ECHO);
+ CreateDefaultEndpoints("/echo");
WireUpEndpoints();
RunHandshake();
@@ -326,6 +334,79 @@ TEST_F(QuicTransportIntegrationTest, EchoUnidirectionalStreams) {
EXPECT_EQ(buffer, "Stream One");
}
+TEST_F(QuicTransportIntegrationTest, EchoDatagram) {
+ CreateDefaultEndpoints("/echo");
+ WireUpEndpoints();
+ RunHandshake();
+
+ client_->session()->datagram_queue()->SendOrQueueDatagram(
+ MemSliceFromString("test"));
+
+ bool datagram_received = false;
+ EXPECT_CALL(*client_->visitor(), OnDatagramReceived(Eq("test")))
+ .WillOnce(Assign(&datagram_received, true));
+ ASSERT_TRUE(simulator_.RunUntilOrTimeout(
+ [&datagram_received]() { return datagram_received; }, kDefaultTimeout));
+}
+
+// This test sets the datagram queue to an nearly-infinte queueing time, and
+// then sends 1000 datagrams. We expect to receive most of them back, since the
+// datagrams would be paced out by the congestion controller.
+TEST_F(QuicTransportIntegrationTest, EchoALotOfDatagrams) {
+ CreateDefaultEndpoints("/echo");
+ WireUpEndpoints();
+ RunHandshake();
+
+ // Set the datagrams to effectively never expire.
+ client_->session()->datagram_queue()->SetMaxTimeInQueue(10000 * kRtt);
+ for (int i = 0; i < 1000; i++) {
+ client_->session()->datagram_queue()->SendOrQueueDatagram(
+ MemSliceFromString(std::string(
+ client_->session()->GetGuaranteedLargestMessagePayload(), 'a')));
+ }
+
+ size_t received = 0;
+ EXPECT_CALL(*client_->visitor(), OnDatagramReceived(_))
+ .WillRepeatedly(
+ [&received](quiche::QuicheStringPiece /*datagram*/) { received++; });
+ ASSERT_TRUE(simulator_.RunUntilOrTimeout(
+ [this]() { return client_->session()->datagram_queue()->empty(); },
+ 3 * kServerBandwidth.TransferTime(1000 * kMaxOutgoingPacketSize)));
+ // Allow extra round-trips for the final flight of datagrams to arrive back.
+ simulator_.RunFor(2 * kRtt);
+
+ EXPECT_GT(received, 500u);
+ EXPECT_LT(received, 1000u);
+}
+
+TEST_F(QuicTransportIntegrationTest, OutgoingStreamFlowControlBlocked) {
+ server_config_.SetMaxUnidirectionalStreamsToSend(4);
+ CreateDefaultEndpoints("/discard");
+ WireUpEndpoints();
+ RunHandshake();
+
+ QuicTransportStream* stream;
+ // Note that since we've already used one stream for client indication, we can
+ // only send three streams at once.
+ for (int i = 0; i < 3; i++) {
+ ASSERT_TRUE(client_->session()->CanOpenNextOutgoingUnidirectionalStream());
+ stream = client_->session()->OpenOutgoingUnidirectionalStream();
+ ASSERT_TRUE(stream != nullptr);
+ ASSERT_TRUE(stream->SendFin());
+ }
+ EXPECT_FALSE(client_->session()->CanOpenNextOutgoingUnidirectionalStream());
+
+ // Receiving FINs for the streams we've just opened will cause the server to
+ // let us open more streams.
+ bool can_create_new_stream = false;
+ EXPECT_CALL(*client_->visitor(), OnCanCreateNewOutgoingUnidirectionalStream())
+ .WillOnce(Assign(&can_create_new_stream, true));
+ ASSERT_TRUE(simulator_.RunUntilOrTimeout(
+ [&can_create_new_stream]() { return can_create_new_stream; },
+ kDefaultTimeout));
+ EXPECT_TRUE(client_->session()->CanOpenNextOutgoingUnidirectionalStream());
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_protocol.h b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_protocol.h
index f97b8e777de..6d95accddaa 100644
--- a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_protocol.h
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_protocol.h
@@ -6,8 +6,9 @@
#define QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_PROTOCOL_H_
#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
namespace quic {
@@ -32,6 +33,23 @@ enum class QuicTransportClientIndicationKeys : uint16_t {
kPath = 0x0001,
};
+// Returns if the specified QUIC version can be used by QuicTransport.
+QUIC_EXPORT_PRIVATE constexpr bool IsVersionValidForQuicTransport(
+ const ParsedQuicVersion& version) {
+ return VersionSupportsMessageFrames(version.transport_version) &&
+ VersionHasIetfQuicFrames(version.transport_version) &&
+ version.handshake_protocol == PROTOCOL_TLS1_3;
+}
+
+// Returns default QUIC version used for QuicTransport.
+QUIC_EXPORT_PRIVATE inline ParsedQuicVersion DefaultVersionForQuicTransport() {
+ constexpr ParsedQuicVersion version(PROTOCOL_TLS1_3,
+ QUIC_VERSION_IETF_DRAFT_25);
+ static_assert(IsVersionValidForQuicTransport(version),
+ "Default QUIC version used by QuicTransport is invalid");
+ return version;
+}
+
} // namespace quic
#endif // QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_PROTOCOL_H_
diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.cc b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.cc
index 7f00acd470f..c2de6590b0e 100644
--- a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.cc
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.cc
@@ -4,21 +4,25 @@
#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.h"
+#include <algorithm>
#include <memory>
+#include <string>
#include "url/gurl.h"
+#include "url/url_constants.h"
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/core/quic_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_protocol.h"
#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace {
-class QuicTransportServerCryptoHelper : public QuicCryptoServerStream::Helper {
+class QuicTransportServerCryptoHelper
+ : public QuicCryptoServerStreamBase::Helper {
public:
bool CanAcceptClientHello(const CryptoHandshakeMessage& /*message*/,
const QuicSocketAddress& /*client_address*/,
@@ -28,6 +32,7 @@ class QuicTransportServerCryptoHelper : public QuicCryptoServerStream::Helper {
return true;
}
};
+
} // namespace
QuicTransportServerSession::QuicTransportServerSession(
@@ -51,7 +56,7 @@ QuicTransportServerSession::QuicTransportServerSession(
static QuicTransportServerCryptoHelper* helper =
new QuicTransportServerCryptoHelper();
- crypto_stream_ = std::make_unique<QuicCryptoServerStream>(
+ crypto_stream_ = CreateCryptoServerStream(
crypto_config, compressed_certs_cache, this, helper);
}
@@ -83,8 +88,8 @@ void QuicTransportServerSession::ClientIndication::OnDataAvailable() {
if (buffer_.size() > ClientIndicationMaxSize()) {
session_->connection()->CloseConnection(
QUIC_TRANSPORT_INVALID_CLIENT_INDICATION,
- QuicStrCat("Client indication size exceeds ", ClientIndicationMaxSize(),
- " bytes"),
+ quiche::QuicheStrCat("Client indication size exceeds ",
+ ClientIndicationMaxSize(), " bytes"),
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return;
}
@@ -96,6 +101,7 @@ void QuicTransportServerSession::ClientIndication::OnDataAvailable() {
bool QuicTransportServerSession::ClientIndicationParser::Parse() {
bool origin_received = false;
+ bool path_received = false;
while (!reader_.IsDoneReading()) {
uint16_t key;
if (!reader_.ReadUInt16(&key)) {
@@ -103,9 +109,9 @@ bool QuicTransportServerSession::ClientIndicationParser::Parse() {
return false;
}
- QuicStringPiece value;
+ quiche::QuicheStringPiece value;
if (!reader_.ReadStringPiece16(&value)) {
- ParseError(QuicStrCat("Failed to read value for key ", key));
+ ParseError(quiche::QuicheStrCat("Failed to read value for key ", key));
return false;
}
@@ -127,6 +133,14 @@ bool QuicTransportServerSession::ClientIndicationParser::Parse() {
break;
}
+ case QuicTransportClientIndicationKeys::kPath: {
+ if (!ProcessPath(value)) {
+ return false;
+ }
+ path_received = true;
+ break;
+ }
+
default:
QUIC_DLOG(INFO) << "Unknown client indication key: " << key;
break;
@@ -137,10 +151,40 @@ bool QuicTransportServerSession::ClientIndicationParser::Parse() {
Error("No origin received");
return false;
}
+ if (!path_received) {
+ Error("No path received");
+ return false;
+ }
return true;
}
+bool QuicTransportServerSession::ClientIndicationParser::ProcessPath(
+ quiche::QuicheStringPiece path) {
+ if (path.empty() || path[0] != '/') {
+ // https://tools.ietf.org/html/draft-vvv-webtransport-quic-01#section-3.2.2
+ Error("Path must begin with a '/'");
+ return false;
+ }
+
+ // TODO(b/145674008): use the SNI value from the handshake instead of the IP
+ // address.
+ std::string url_text = quiche::QuicheStrCat(
+ url::kQuicTransportScheme, url::kStandardSchemeSeparator,
+ session_->self_address().ToString(), path);
+ GURL url{url_text};
+ if (!url.is_valid()) {
+ Error("Invalid path specified");
+ return false;
+ }
+
+ if (!session_->visitor_->ProcessPath(url)) {
+ Error("Specified path rejected");
+ return false;
+ }
+ return true;
+}
+
void QuicTransportServerSession::ClientIndicationParser::Error(
const std::string& error_message) {
session_->connection()->CloseConnection(
@@ -149,13 +193,13 @@ void QuicTransportServerSession::ClientIndicationParser::Error(
}
void QuicTransportServerSession::ClientIndicationParser::ParseError(
- QuicStringPiece error_message) {
- Error(QuicStrCat("Failed to parse the client indication stream: ",
- error_message, reader_.DebugString()));
+ quiche::QuicheStringPiece error_message) {
+ Error(quiche::QuicheStrCat("Failed to parse the client indication stream: ",
+ error_message, reader_.DebugString()));
}
void QuicTransportServerSession::ProcessClientIndication(
- QuicStringPiece indication) {
+ quiche::QuicheStringPiece indication) {
ClientIndicationParser parser(this, indication);
if (!parser.Parse()) {
return;
diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.h b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.h
index b3fcfa07588..1b9dda03538 100644
--- a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.h
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.h
@@ -5,14 +5,15 @@
#ifndef QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_SERVER_SESSION_H_
#define QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_SERVER_SESSION_H_
+#include "url/gurl.h"
#include "url/origin.h"
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
-#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
+#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h"
#include "net/third_party/quiche/src/quic/core/quic_session.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_protocol.h"
#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_session_interface.h"
#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -25,7 +26,14 @@ class QUIC_EXPORT_PRIVATE QuicTransportServerSession
public:
virtual ~ServerVisitor() {}
+ // Allows the server to decide whether the specified origin is allowed to
+ // connect to it.
virtual bool CheckOrigin(url::Origin origin) = 0;
+
+ // Indicates that the server received a path parameter from the client. The
+ // path parameter is parsed, and can be retrived from url.path() and
+ // url.query(). If this method returns false, the connection is closed.
+ virtual bool ProcessPath(const GURL& url) = 0;
};
QuicTransportServerSession(QuicConnection* connection,
@@ -36,17 +44,17 @@ class QUIC_EXPORT_PRIVATE QuicTransportServerSession
QuicCompressedCertsCache* compressed_certs_cache,
ServerVisitor* visitor);
- std::vector<QuicStringPiece>::const_iterator SelectAlpn(
- const std::vector<QuicStringPiece>& alpns) const override {
+ std::vector<quiche::QuicheStringPiece>::const_iterator SelectAlpn(
+ const std::vector<quiche::QuicheStringPiece>& alpns) const override {
return std::find(alpns.cbegin(), alpns.cend(), QuicTransportAlpn());
}
bool ShouldKeepConnectionAlive() const override { return true; }
- QuicCryptoStream* GetMutableCryptoStream() override {
+ QuicCryptoServerStreamBase* GetMutableCryptoStream() override {
return crypto_stream_.get();
}
- const QuicCryptoStream* GetCryptoStream() const override {
+ const QuicCryptoServerStreamBase* GetCryptoStream() const override {
return crypto_stream_.get();
}
@@ -78,7 +86,7 @@ class QUIC_EXPORT_PRIVATE QuicTransportServerSession
class QUIC_EXPORT_PRIVATE ClientIndicationParser {
public:
ClientIndicationParser(QuicTransportServerSession* session,
- QuicStringPiece indication)
+ quiche::QuicheStringPiece indication)
: session_(session), reader_(indication) {}
// Parses the specified indication. Automatically closes the connection
@@ -88,7 +96,10 @@ class QUIC_EXPORT_PRIVATE QuicTransportServerSession
private:
void Error(const std::string& error_message);
- void ParseError(QuicStringPiece error_message);
+ void ParseError(quiche::QuicheStringPiece error_message);
+
+ // Processes the path portion of the client indication.
+ bool ProcessPath(quiche::QuicheStringPiece path);
QuicTransportServerSession* session_;
QuicDataReader reader_;
@@ -96,11 +107,11 @@ class QUIC_EXPORT_PRIVATE QuicTransportServerSession
// Parses and processes the client indication as described in
// https://vasilvv.github.io/webtransport/draft-vvv-webtransport-quic.html#rfc.section.3.2
- void ProcessClientIndication(QuicStringPiece indication);
+ void ProcessClientIndication(quiche::QuicheStringPiece indication);
virtual void OnIncomingDataStream(QuicTransportStream* /*stream*/) {}
- std::unique_ptr<QuicCryptoServerStream> crypto_stream_;
+ std::unique_ptr<QuicCryptoServerStreamBase> crypto_stream_;
bool ready_ = false;
ServerVisitor* visitor_;
};
diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session_test.cc b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session_test.cc
index 5e6774810f0..8176b03d156 100644
--- a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session_test.cc
@@ -15,13 +15,13 @@
#include "net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h"
#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_protocol.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_transport_test_tools.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
namespace test {
@@ -36,7 +36,12 @@ using testing::SaveArg;
constexpr char kTestOrigin[] = "https://test-origin.test";
constexpr char kTestOriginClientIndication[] =
- "\0\0\0\x18https://test-origin.test";
+ "\0\0" // key (0x0000, origin)
+ "\0\x18" // length
+ "https://test-origin.test" // value
+ "\0\x01" // key (0x0001, path)
+ "\0\x05" // length
+ "/test"; // value
const url::Origin GetTestOrigin() {
return url::Origin::Create(GURL(kTestOrigin));
}
@@ -46,7 +51,7 @@ const std::string GetTestOriginClientIndication() {
}
ParsedQuicVersionVector GetVersions() {
- return {ParsedQuicVersion{PROTOCOL_TLS1_3, QUIC_VERSION_99}};
+ return {DefaultVersionForQuicTransport()};
}
class QuicTransportServerSessionTest : public QuicTest {
@@ -62,7 +67,7 @@ class QuicTransportServerSessionTest : public QuicTest {
KeyExchangeSource::Default()),
compressed_certs_cache_(
QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) {
- SetQuicReloadableFlag(quic_supports_tls_handshake, true);
+ QuicEnableVersion(DefaultVersionForQuicTransport());
connection_.AdvanceTime(QuicTime::Delta::FromSeconds(100000));
crypto_test_utils::SetupCryptoServerConfigForTest(
helper_.GetClock(), helper_.GetRandomGenerator(), &crypto_config_);
@@ -70,11 +75,9 @@ class QuicTransportServerSessionTest : public QuicTest {
&connection_, nullptr, DefaultQuicConfig(), GetVersions(),
&crypto_config_, &compressed_certs_cache_, &visitor_);
session_->Initialize();
- crypto_stream_ = static_cast<QuicCryptoServerStream*>(
- session_->GetMutableCryptoStream());
- if (!GetQuicReloadableFlag(quic_version_negotiated_by_default_at_server)) {
- crypto_stream_->OnSuccessfulVersionNegotiation(GetVersions()[0]);
- }
+ crypto_stream_ = session_->GetMutableCryptoStream();
+ ON_CALL(visitor_, ProcessPath(_))
+ .WillByDefault(DoAll(SaveArg<0>(&path_), Return(true)));
}
void Connect() {
@@ -85,9 +88,9 @@ class QuicTransportServerSessionTest : public QuicTest {
QuicServerId("test.example.com", 443), options, QuicTransportAlpn());
}
- void ReceiveIndication(QuicStringPiece indication) {
+ void ReceiveIndication(quiche::QuicheStringPiece indication) {
QUIC_LOG(INFO) << "Receiving indication: "
- << QuicTextUtils::HexDump(indication);
+ << quiche::QuicheTextUtils::HexDump(indication);
constexpr size_t kChunkSize = 1024;
// Shard the indication, since some of the tests cause it to not fit into a
// single frame.
@@ -98,7 +101,21 @@ class QuicTransportServerSessionTest : public QuicTest {
}
session_->OnStreamFrame(QuicStreamFrame(ClientIndicationStream(),
/*fin=*/true, indication.size(),
- QuicStringPiece()));
+ quiche::QuicheStringPiece()));
+ }
+
+ void ReceiveIndicationWithPath(quiche::QuicheStringPiece path) {
+ constexpr char kTestOriginClientIndicationPrefix[] =
+ "\0\0" // key (0x0000, origin)
+ "\0\x18" // length
+ "https://test-origin.test" // value
+ "\0\x01"; // key (0x0001, path)
+ std::string indication{kTestOriginClientIndicationPrefix,
+ sizeof(kTestOriginClientIndicationPrefix) - 1};
+ indication.push_back(static_cast<char>(path.size() >> 8));
+ indication.push_back(static_cast<char>(path.size() & 0xff));
+ indication += std::string{path};
+ ReceiveIndication(indication);
}
protected:
@@ -109,8 +126,9 @@ class QuicTransportServerSessionTest : public QuicTest {
QuicCryptoServerConfig crypto_config_;
std::unique_ptr<QuicTransportServerSession> session_;
QuicCompressedCertsCache compressed_certs_cache_;
- testing::StrictMock<MockServerVisitor> visitor_;
- QuicCryptoServerStream* crypto_stream_;
+ testing::NiceMock<MockServerVisitor> visitor_;
+ QuicCryptoServerStreamBase* crypto_stream_;
+ GURL path_;
};
TEST_F(QuicTransportServerSessionTest, SuccessfulHandshake) {
@@ -122,21 +140,23 @@ TEST_F(QuicTransportServerSessionTest, SuccessfulHandshake) {
ReceiveIndication(GetTestOriginClientIndication());
EXPECT_TRUE(session_->IsSessionReady());
EXPECT_EQ(origin, GetTestOrigin());
+ EXPECT_EQ(path_.path(), "/test");
}
TEST_F(QuicTransportServerSessionTest, PiecewiseClientIndication) {
Connect();
size_t i = 0;
for (; i < sizeof(kTestOriginClientIndication) - 2; i++) {
- QuicStreamFrame frame(ClientIndicationStream(), false, i,
- QuicStringPiece(&kTestOriginClientIndication[i], 1));
+ QuicStreamFrame frame(
+ ClientIndicationStream(), false, i,
+ quiche::QuicheStringPiece(&kTestOriginClientIndication[i], 1));
session_->OnStreamFrame(frame);
}
EXPECT_CALL(visitor_, CheckOrigin(_)).WillOnce(Return(true));
QuicStreamFrame last_frame(
ClientIndicationStream(), true, i,
- QuicStringPiece(&kTestOriginClientIndication[i], 1));
+ quiche::QuicheStringPiece(&kTestOriginClientIndication[i], 1));
session_->OnStreamFrame(last_frame);
EXPECT_TRUE(session_->IsSessionReady());
}
@@ -150,7 +170,7 @@ TEST_F(QuicTransportServerSessionTest, OriginRejected) {
EXPECT_FALSE(session_->IsSessionReady());
}
-std::string MakeUnknownField(QuicStringPiece payload) {
+std::string MakeUnknownField(quiche::QuicheStringPiece payload) {
std::string buffer;
buffer.resize(payload.size() + 4);
QuicDataWriter writer(buffer.size(), &buffer[0]);
@@ -231,6 +251,41 @@ TEST_F(QuicTransportServerSessionTest, InvalidOrigin) {
EXPECT_FALSE(session_->IsSessionReady());
}
+TEST_F(QuicTransportServerSessionTest, PathWithQuery) {
+ Connect();
+ EXPECT_CALL(visitor_, CheckOrigin(_)).WillOnce(Return(true));
+ ReceiveIndicationWithPath("/test?foo=bar");
+ EXPECT_TRUE(session_->IsSessionReady());
+ EXPECT_EQ(path_.path(), "/test");
+ EXPECT_EQ(path_.query(), "foo=bar");
+}
+
+TEST_F(QuicTransportServerSessionTest, PathNormalization) {
+ Connect();
+ EXPECT_CALL(visitor_, CheckOrigin(_)).WillOnce(Return(true));
+ ReceiveIndicationWithPath("/foo/../bar");
+ EXPECT_TRUE(session_->IsSessionReady());
+ EXPECT_EQ(path_.path(), "/bar");
+}
+
+TEST_F(QuicTransportServerSessionTest, EmptyPath) {
+ Connect();
+ EXPECT_CALL(visitor_, CheckOrigin(_)).WillOnce(Return(true));
+ EXPECT_CALL(connection_,
+ CloseConnection(_, HasSubstr("Path must begin with a '/'"), _));
+ ReceiveIndicationWithPath("");
+ EXPECT_FALSE(session_->IsSessionReady());
+}
+
+TEST_F(QuicTransportServerSessionTest, UnprefixedPath) {
+ Connect();
+ EXPECT_CALL(visitor_, CheckOrigin(_)).WillOnce(Return(true));
+ EXPECT_CALL(connection_,
+ CloseConnection(_, HasSubstr("Path must begin with a '/'"), _));
+ ReceiveIndicationWithPath("test");
+ EXPECT_FALSE(session_->IsSessionReady());
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.cc b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.cc
index 61f4345d61b..401ae7e4278 100644
--- a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.cc
@@ -6,9 +6,11 @@
#include <sys/types.h>
+#include "net/third_party/quiche/src/quic/core/quic_buffer_allocator.h"
+#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -33,8 +35,8 @@ size_t QuicTransportStream::Read(char* buffer, size_t buffer_size) {
iov.iov_base = buffer;
iov.iov_len = buffer_size;
const size_t result = sequencer()->Readv(&iov, 1);
- if (sequencer()->IsClosed() && visitor_ != nullptr) {
- visitor_->OnFinRead();
+ if (sequencer()->IsClosed()) {
+ MaybeNotifyFinRead();
}
return result;
}
@@ -49,14 +51,37 @@ size_t QuicTransportStream::Read(std::string* output) {
return bytes_read;
}
-bool QuicTransportStream::Write(QuicStringPiece data) {
+bool QuicTransportStream::Write(quiche::QuicheStringPiece data) {
if (!CanWrite()) {
return false;
}
- // TODO(vasilvv): use WriteMemSlices()
- WriteOrBufferData(data, /*fin=*/false, nullptr);
- return true;
+ QuicUniqueBufferPtr buffer = MakeUniqueBuffer(
+ session()->connection()->helper()->GetStreamSendBufferAllocator(),
+ data.size());
+ memcpy(buffer.get(), data.data(), data.size());
+ QuicMemSlice memslice(std::move(buffer), data.size());
+ QuicConsumedData consumed =
+ WriteMemSlices(QuicMemSliceSpan(&memslice), /*fin=*/false);
+
+ if (consumed.bytes_consumed == data.size()) {
+ return true;
+ }
+ if (consumed.bytes_consumed == 0) {
+ return false;
+ }
+ // QuicTransportStream::Write() is an all-or-nothing write API. To achieve
+ // that property, it relies on WriteMemSlices() being an all-or-nothing API.
+ // If WriteMemSlices() fails to provide that guarantee, we have no way to
+ // communicate a partial write to the caller, and thus it's safer to just
+ // close the connection.
+ QUIC_BUG << "WriteMemSlices() unexpectedly partially consumed the input "
+ "data, provided: "
+ << data.size() << ", written: " << consumed.bytes_consumed;
+ OnUnrecoverableError(
+ QUIC_INTERNAL_ERROR,
+ "WriteMemSlices() unexpectedly partially consumed the input data");
+ return false;
}
bool QuicTransportStream::SendFin() {
@@ -64,12 +89,16 @@ bool QuicTransportStream::SendFin() {
return false;
}
- WriteOrBufferData(QuicStringPiece(), /*fin=*/true, nullptr);
- return true;
+ QuicMemSlice empty;
+ QuicConsumedData consumed =
+ WriteMemSlices(QuicMemSliceSpan(&empty), /*fin=*/true);
+ DCHECK_EQ(consumed.bytes_consumed, 0u);
+ return consumed.fin_consumed;
}
bool QuicTransportStream::CanWrite() const {
- return session_interface_->IsSessionReady() && CanWriteNewData();
+ return session_interface_->IsSessionReady() && CanWriteNewData() &&
+ !write_side_closed();
}
size_t QuicTransportStream::ReadableBytes() const {
@@ -82,10 +111,7 @@ size_t QuicTransportStream::ReadableBytes() const {
void QuicTransportStream::OnDataAvailable() {
if (sequencer()->IsClosed()) {
- if (visitor_ != nullptr) {
- visitor_->OnFinRead();
- }
- OnFinRead();
+ MaybeNotifyFinRead();
return;
}
@@ -109,4 +135,13 @@ void QuicTransportStream::OnCanWriteNewData() {
}
}
+void QuicTransportStream::MaybeNotifyFinRead() {
+ if (visitor_ == nullptr || fin_read_notified_) {
+ return;
+ }
+ fin_read_notified_ = true;
+ visitor_->OnFinRead();
+ OnFinRead();
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h
index 1651a1cb082..f2bac887a40 100644
--- a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h
@@ -12,8 +12,8 @@
#include "net/third_party/quiche/src/quic/core/quic_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_macros.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_session_interface.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -40,7 +40,7 @@ class QUIC_EXPORT_PRIVATE QuicTransportStream : public QuicStream {
// Reads all available data and appends it to the end of |output|.
size_t Read(std::string* output);
// Writes |data| into the stream. Returns true on success.
- QUIC_MUST_USE_RESULT bool Write(QuicStringPiece data);
+ QUIC_MUST_USE_RESULT bool Write(quiche::QuicheStringPiece data);
// Sends the FIN on the stream. Returns true on success.
QUIC_MUST_USE_RESULT bool SendFin();
@@ -63,8 +63,11 @@ class QUIC_EXPORT_PRIVATE QuicTransportStream : public QuicStream {
using QuicStream::WriteMemSlices;
using QuicStream::WriteOrBufferData;
+ void MaybeNotifyFinRead();
+
QuicTransportSessionInterface* session_interface_;
std::unique_ptr<Visitor> visitor_ = nullptr;
+ bool fin_read_notified_ = false;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream_test.cc b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream_test.cc
index c291b54cf2b..6a91702fa58 100644
--- a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream_test.cc
@@ -14,15 +14,17 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_transport_test_tools.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
namespace {
+using testing::_;
using testing::Return;
ParsedQuicVersionVector GetVersions() {
- return {ParsedQuicVersion{PROTOCOL_TLS1_3, QUIC_VERSION_99}};
+ return {DefaultVersionForQuicTransport()};
}
class MockQuicTransportSessionInterface : public QuicTransportSessionInterface {
@@ -38,6 +40,7 @@ class QuicTransportStreamTest : public QuicTest {
Perspective::IS_CLIENT,
GetVersions())),
session_(connection_) {
+ QuicEnableVersion(DefaultVersionForQuicTransport());
session_.Initialize();
stream_ = new QuicTransportStream(0, &session_, &interface_);
@@ -48,7 +51,8 @@ class QuicTransportStreamTest : public QuicTest {
stream_->set_visitor(std::move(visitor));
}
- void ReceiveStreamData(QuicStringPiece data, QuicStreamOffset offset) {
+ void ReceiveStreamData(quiche::QuicheStringPiece data,
+ QuicStreamOffset offset) {
QuicStreamFrame frame(0, false, offset, data);
stream_->OnStreamFrame(frame);
}
@@ -118,6 +122,32 @@ TEST_F(QuicTransportStreamTest, FinReadWithDataPending) {
ASSERT_EQ(stream_->Read(&buffer), 4u);
}
+TEST_F(QuicTransportStreamTest, WritingTooMuchData) {
+ EXPECT_CALL(interface_, IsSessionReady()).WillRepeatedly(Return(true));
+ ASSERT_TRUE(stream_->CanWrite());
+
+ std::string a_little_bit_of_data(128, 'A');
+ std::string a_lot_of_data(GetQuicFlag(FLAGS_quic_buffered_data_threshold) * 2,
+ 'a');
+
+ EXPECT_TRUE(stream_->Write(a_little_bit_of_data));
+ EXPECT_TRUE(stream_->Write(a_little_bit_of_data));
+ EXPECT_TRUE(stream_->Write(a_little_bit_of_data));
+
+ EXPECT_TRUE(stream_->Write(a_lot_of_data));
+ EXPECT_FALSE(stream_->Write(a_lot_of_data));
+}
+
+TEST_F(QuicTransportStreamTest, CannotSendFinTwice) {
+ EXPECT_CALL(interface_, IsSessionReady()).WillRepeatedly(Return(true));
+ ASSERT_TRUE(stream_->CanWrite());
+
+ EXPECT_CALL(session_, WritevData(stream_->id(), _, _, _, _, _))
+ .WillOnce(Return(QuicConsumedData(0, /*fin_consumed=*/true)));
+ EXPECT_TRUE(stream_->SendFin());
+ EXPECT_FALSE(stream_->CanWrite());
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.cc b/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.cc
index 6716dec2605..bfe4a5e349c 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.cc
@@ -4,6 +4,7 @@
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
+#include <algorithm>
#include <memory>
#include <string>
#include <utility>
@@ -21,23 +22,25 @@
#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
#include "net/third_party/quiche/src/quic/core/proto/crypto_server_config_proto.h"
+#include "net/third_party/quiche/src/quic/core/quic_clock.h"
#include "net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h"
-#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
+#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h"
#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_server_id.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_framer_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/simple_quic_framer.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
+#include "net/third_party/quiche/src/common/test_tools/quiche_test_utils.h"
namespace quic {
namespace test {
@@ -105,6 +108,7 @@ class FullChloGenerator {
QuicSocketAddress server_addr,
QuicSocketAddress client_addr,
const QuicClock* clock,
+ ParsedQuicVersion version,
QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
QuicCompressedCertsCache* compressed_certs_cache,
CryptoHandshakeMessage* out)
@@ -112,6 +116,7 @@ class FullChloGenerator {
server_addr_(server_addr),
client_addr_(client_addr),
clock_(clock),
+ version_(version),
signed_config_(signed_config),
compressed_certs_cache_(compressed_certs_cache),
out_(out),
@@ -143,9 +148,9 @@ class FullChloGenerator {
result_ = result;
crypto_config_->ProcessClientHello(
result_, /*reject_only=*/false, TestConnectionId(1), server_addr_,
- client_addr_, AllSupportedVersions().front(), AllSupportedVersions(),
- clock_, QuicRandom::GetInstance(), compressed_certs_cache_, params_,
- signed_config_, /*total_framing_overhead=*/50, kDefaultMaxPacketSize,
+ client_addr_, version_, {version_}, clock_, QuicRandom::GetInstance(),
+ compressed_certs_cache_, params_, signed_config_,
+ /*total_framing_overhead=*/50, kDefaultMaxPacketSize,
GetProcessClientHelloCallback());
}
@@ -153,12 +158,14 @@ class FullChloGenerator {
public:
explicit ProcessClientHelloCallback(FullChloGenerator* generator)
: generator_(generator) {}
- void Run(QuicErrorCode /*error*/,
- const std::string& /*error_details*/,
+ void Run(QuicErrorCode error,
+ const std::string& error_details,
std::unique_ptr<CryptoHandshakeMessage> message,
std::unique_ptr<DiversificationNonce> /*diversification_nonce*/,
std::unique_ptr<ProofSource::Details> /*proof_source_details*/)
override {
+ ASSERT_TRUE(message) << QuicErrorCodeToString(error) << " "
+ << error_details;
generator_->ProcessClientHelloDone(std::move(message));
}
@@ -175,15 +182,15 @@ class FullChloGenerator {
EXPECT_THAT(rej->tag(), testing::Eq(kREJ));
QUIC_VLOG(1) << "Extract valid STK and SCID from\n" << rej->DebugString();
- QuicStringPiece srct;
+ quiche::QuicheStringPiece srct;
ASSERT_TRUE(rej->GetStringPiece(kSourceAddressTokenTag, &srct));
- QuicStringPiece scfg;
+ quiche::QuicheStringPiece scfg;
ASSERT_TRUE(rej->GetStringPiece(kSCFG, &scfg));
std::unique_ptr<CryptoHandshakeMessage> server_config(
CryptoFramer::ParseMessage(scfg));
- QuicStringPiece scid;
+ quiche::QuicheStringPiece scid;
ASSERT_TRUE(server_config->GetStringPiece(kSCID, &scid));
*out_ = result_->client_hello;
@@ -198,6 +205,7 @@ class FullChloGenerator {
QuicSocketAddress server_addr_;
QuicSocketAddress client_addr_;
const QuicClock* clock_;
+ ParsedQuicVersion version_;
QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
QuicCompressedCertsCache* compressed_certs_cache_;
CryptoHandshakeMessage* out_;
@@ -235,10 +243,6 @@ int HandshakeWithFakeServer(QuicConfig* server_quic_config,
server_conn, *server_quic_config, client_conn->supported_versions(),
crypto_config, &compressed_certs_cache);
server_session.Initialize();
- if (!GetQuicReloadableFlag(quic_version_negotiated_by_default_at_server)) {
- server_session.OnSuccessfulVersionNegotiation(
- client_conn->supported_versions().front());
- }
EXPECT_CALL(*server_session.helper(),
CanAcceptClientHello(testing::_, testing::_, testing::_,
testing::_, testing::_))
@@ -246,9 +250,10 @@ int HandshakeWithFakeServer(QuicConfig* server_quic_config,
EXPECT_CALL(*server_conn, OnCanWrite()).Times(testing::AnyNumber());
EXPECT_CALL(*client_conn, OnCanWrite()).Times(testing::AnyNumber());
EXPECT_CALL(server_session, SelectAlpn(_))
- .WillRepeatedly([alpn](const std::vector<QuicStringPiece>& alpns) {
- return std::find(alpns.cbegin(), alpns.cend(), alpn);
- });
+ .WillRepeatedly(
+ [alpn](const std::vector<quiche::QuicheStringPiece>& alpns) {
+ return std::find(alpns.cbegin(), alpns.cend(), alpn);
+ });
// The client's handshake must have been started already.
CHECK_NE(0u, client_conn->encrypted_packets_.size());
@@ -263,18 +268,30 @@ int HandshakeWithFakeServer(QuicConfig* server_quic_config,
int HandshakeWithFakeClient(MockQuicConnectionHelper* helper,
MockAlarmFactory* alarm_factory,
PacketSavingConnection* server_conn,
- QuicCryptoServerStream* server,
+ QuicCryptoServerStreamBase* server,
const QuicServerId& server_id,
const FakeClientOptions& options,
std::string alpn) {
- ParsedQuicVersionVector supported_versions = AllSupportedVersions();
+ // This function does not do version negotiation; read the supported versions
+ // directly from the server connection instead.
+ ParsedQuicVersionVector supported_versions =
+ server_conn->supported_versions();
if (options.only_tls_versions) {
- supported_versions.clear();
- for (QuicTransportVersion transport_version :
- AllSupportedTransportVersions()) {
- supported_versions.push_back(
- ParsedQuicVersion(PROTOCOL_TLS1_3, transport_version));
- }
+ supported_versions.erase(
+ std::remove_if(supported_versions.begin(), supported_versions.end(),
+ [](const ParsedQuicVersion& version) {
+ return version.handshake_protocol != PROTOCOL_TLS1_3;
+ }),
+ supported_versions.end());
+ CHECK(!options.only_quic_crypto_versions);
+ } else if (options.only_quic_crypto_versions) {
+ supported_versions.erase(
+ std::remove_if(supported_versions.begin(), supported_versions.end(),
+ [](const ParsedQuicVersion& version) {
+ return version.handshake_protocol !=
+ PROTOCOL_QUIC_CRYPTO;
+ }),
+ supported_versions.end());
}
PacketSavingConnection* client_conn = new PacketSavingConnection(
helper, alarm_factory, Perspective::IS_CLIENT, supported_versions);
@@ -306,7 +323,7 @@ int HandshakeWithFakeClient(MockQuicConnectionHelper* helper,
client_session.GetMutableCryptoStream(),
server_conn, server);
- if (server->handshake_confirmed() && server->encryption_established()) {
+ if (server->one_rtt_keys_available() && server->encryption_established()) {
CompareClientAndServerKeys(client_session.GetMutableCryptoStream(), server);
}
@@ -345,7 +362,8 @@ void CommunicateHandshakeMessages(PacketSavingConnection* client_conn,
PacketSavingConnection* server_conn,
QuicCryptoStream* server) {
size_t client_i = 0, server_i = 0;
- while (!client->handshake_confirmed() || !server->handshake_confirmed()) {
+ while (!client->one_rtt_keys_available() ||
+ !server->one_rtt_keys_available()) {
ASSERT_GT(client_conn->encrypted_packets_.size(), client_i);
QUIC_LOG(INFO) << "Processing "
<< client_conn->encrypted_packets_.size() - client_i
@@ -353,7 +371,7 @@ void CommunicateHandshakeMessages(PacketSavingConnection* client_conn,
MovePackets(client_conn, &client_i, server, server_conn,
Perspective::IS_SERVER);
- if (client->handshake_confirmed() && server->handshake_confirmed() &&
+ if (client->one_rtt_keys_available() && server->one_rtt_keys_available() &&
server_conn->encrypted_packets_.size() == server_i) {
break;
}
@@ -437,23 +455,26 @@ uint64_t LeafCertHashForTesting() {
class MockCommonCertSets : public CommonCertSets {
public:
- MockCommonCertSets(QuicStringPiece cert, uint64_t hash, uint32_t index)
+ MockCommonCertSets(quiche::QuicheStringPiece cert,
+ uint64_t hash,
+ uint32_t index)
: cert_(cert), hash_(hash), index_(index) {}
- QuicStringPiece GetCommonHashes() const override {
+ quiche::QuicheStringPiece GetCommonHashes() const override {
QUIC_BUG << "not implemented";
- return QuicStringPiece();
+ return quiche::QuicheStringPiece();
}
- QuicStringPiece GetCert(uint64_t hash, uint32_t index) const override {
+ quiche::QuicheStringPiece GetCert(uint64_t hash,
+ uint32_t index) const override {
if (hash == hash_ && index == index_) {
return cert_;
}
- return QuicStringPiece();
+ return quiche::QuicheStringPiece();
}
- bool MatchCert(QuicStringPiece cert,
- QuicStringPiece common_set_hashes,
+ bool MatchCert(quiche::QuicheStringPiece cert,
+ quiche::QuicheStringPiece common_set_hashes,
uint64_t* out_hash,
uint32_t* out_index) const override {
if (cert != cert_) {
@@ -488,7 +509,7 @@ class MockCommonCertSets : public CommonCertSets {
const uint32_t index_;
};
-CommonCertSets* MockCommonCertSets(QuicStringPiece cert,
+CommonCertSets* MockCommonCertSets(quiche::QuicheStringPiece cert,
uint64_t hash,
uint32_t index) {
return new class MockCommonCertSets(cert, hash, index);
@@ -549,22 +570,22 @@ void CompareCrypters(const QuicEncrypter* encrypter,
<< decrypter;
return;
}
- QuicStringPiece encrypter_key = encrypter->GetKey();
- QuicStringPiece encrypter_iv = encrypter->GetNoncePrefix();
- QuicStringPiece decrypter_key = decrypter->GetKey();
- QuicStringPiece decrypter_iv = decrypter->GetNoncePrefix();
- CompareCharArraysWithHexError(label + " key", encrypter_key.data(),
- encrypter_key.length(), decrypter_key.data(),
- decrypter_key.length());
- CompareCharArraysWithHexError(label + " iv", encrypter_iv.data(),
- encrypter_iv.length(), decrypter_iv.data(),
- decrypter_iv.length());
+ quiche::QuicheStringPiece encrypter_key = encrypter->GetKey();
+ quiche::QuicheStringPiece encrypter_iv = encrypter->GetNoncePrefix();
+ quiche::QuicheStringPiece decrypter_key = decrypter->GetKey();
+ quiche::QuicheStringPiece decrypter_iv = decrypter->GetNoncePrefix();
+ quiche::test::CompareCharArraysWithHexError(
+ label + " key", encrypter_key.data(), encrypter_key.length(),
+ decrypter_key.data(), decrypter_key.length());
+ quiche::test::CompareCharArraysWithHexError(
+ label + " iv", encrypter_iv.data(), encrypter_iv.length(),
+ decrypter_iv.data(), decrypter_iv.length());
}
} // namespace
void CompareClientAndServerKeys(QuicCryptoClientStream* client,
- QuicCryptoServerStream* server) {
+ QuicCryptoServerStreamBase* server) {
QuicFramer* client_framer = QuicConnectionPeer::GetFramer(
QuicStreamPeer::session(client)->connection());
QuicFramer* server_framer = QuicConnectionPeer::GetFramer(
@@ -577,7 +598,8 @@ void CompareClientAndServerKeys(QuicCryptoClientStream* client,
const QuicDecrypter* server_decrypter(
QuicFramerPeer::GetDecrypter(server_framer, level));
if (level == ENCRYPTION_FORWARD_SECURE ||
- !(client_encrypter == nullptr && server_decrypter == nullptr)) {
+ !((level == ENCRYPTION_HANDSHAKE || client_encrypter == nullptr) &&
+ server_decrypter == nullptr)) {
CompareCrypters(client_encrypter, server_decrypter,
"client " + EncryptionLevelString(level) + " write");
}
@@ -586,20 +608,21 @@ void CompareClientAndServerKeys(QuicCryptoClientStream* client,
const QuicDecrypter* client_decrypter(
QuicFramerPeer::GetDecrypter(client_framer, level));
if (level == ENCRYPTION_FORWARD_SECURE ||
- !(server_encrypter == nullptr && client_decrypter == nullptr)) {
+ !(server_encrypter == nullptr &&
+ (level == ENCRYPTION_HANDSHAKE || client_decrypter == nullptr))) {
CompareCrypters(server_encrypter, client_decrypter,
"server " + EncryptionLevelString(level) + " write");
}
}
- QuicStringPiece client_subkey_secret =
+ quiche::QuicheStringPiece client_subkey_secret =
client->crypto_negotiated_params().subkey_secret;
- QuicStringPiece server_subkey_secret =
+ quiche::QuicheStringPiece server_subkey_secret =
server->crypto_negotiated_params().subkey_secret;
- CompareCharArraysWithHexError("subkey secret", client_subkey_secret.data(),
- client_subkey_secret.length(),
- server_subkey_secret.data(),
- server_subkey_secret.length());
+ quiche::test::CompareCharArraysWithHexError(
+ "subkey secret", client_subkey_secret.data(),
+ client_subkey_secret.length(), server_subkey_secret.data(),
+ server_subkey_secret.length());
const char kSampleLabel[] = "label";
const char kSampleContext[] = "context";
@@ -612,7 +635,7 @@ void CompareClientAndServerKeys(QuicCryptoClientStream* client,
EXPECT_TRUE(server->ExportKeyingMaterial(kSampleLabel, kSampleContext,
kSampleOutputLength,
&server_key_extraction));
- CompareCharArraysWithHexError(
+ quiche::test::CompareCharArraysWithHexError(
"sample key extraction", client_key_extraction.data(),
client_key_extraction.length(), server_key_extraction.data(),
server_key_extraction.length());
@@ -674,8 +697,8 @@ CryptoHandshakeMessage CreateCHLO(
size_t value_len = value.length();
if (value_len > 0 && value[0] == '#') {
// This is ascii encoded hex.
- std::string hex_value =
- QuicTextUtils::HexDecode(QuicStringPiece(&value[1]));
+ std::string hex_value = quiche::QuicheTextUtils::HexDecode(
+ quiche::QuicheStringPiece(&value[1]));
msg.SetStringPiece(quic_tag, hex_value);
continue;
}
@@ -759,7 +782,8 @@ void MovePackets(PacketSavingConnection* source_conn,
}
*inout_packet_index = index;
- QuicConnectionPeer::SetCurrentPacket(dest_conn, QuicStringPiece(nullptr, 0));
+ QuicConnectionPeer::SetCurrentPacket(dest_conn,
+ quiche::QuicheStringPiece(nullptr, 0));
}
CryptoHandshakeMessage GenerateDefaultInchoateCHLO(
@@ -791,35 +815,39 @@ std::string GenerateClientNonceHex(const QuicClock* clock,
primary_config.set_primary_time(clock->WallNow().ToUNIXSeconds());
std::unique_ptr<CryptoHandshakeMessage> msg =
crypto_config->AddConfig(primary_config, clock->WallNow());
- QuicStringPiece orbit;
+ quiche::QuicheStringPiece orbit;
CHECK(msg->GetStringPiece(kORBT, &orbit));
std::string nonce;
CryptoUtils::GenerateNonce(clock->WallNow(), QuicRandom::GetInstance(), orbit,
&nonce);
- return ("#" + QuicTextUtils::HexEncode(nonce));
+ return ("#" + quiche::QuicheTextUtils::HexEncode(nonce));
}
std::string GenerateClientPublicValuesHex() {
char public_value[32];
memset(public_value, 42, sizeof(public_value));
- return ("#" + QuicTextUtils::HexEncode(public_value, sizeof(public_value)));
+ return ("#" + quiche::QuicheTextUtils::HexEncode(public_value,
+ sizeof(public_value)));
}
-void GenerateFullCHLO(const CryptoHandshakeMessage& inchoate_chlo,
- QuicCryptoServerConfig* crypto_config,
- QuicSocketAddress server_addr,
- QuicSocketAddress client_addr,
- QuicTransportVersion version,
- const QuicClock* clock,
- QuicReferenceCountedPointer<QuicSignedServerConfig> proof,
- QuicCompressedCertsCache* compressed_certs_cache,
- CryptoHandshakeMessage* out) {
+void GenerateFullCHLO(
+ const CryptoHandshakeMessage& inchoate_chlo,
+ QuicCryptoServerConfig* crypto_config,
+ QuicSocketAddress server_addr,
+ QuicSocketAddress client_addr,
+ QuicTransportVersion transport_version,
+ const QuicClock* clock,
+ QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
+ QuicCompressedCertsCache* compressed_certs_cache,
+ CryptoHandshakeMessage* out) {
// Pass a inchoate CHLO.
- FullChloGenerator generator(crypto_config, server_addr, client_addr, clock,
- proof, compressed_certs_cache, out);
+ FullChloGenerator generator(
+ crypto_config, server_addr, client_addr, clock,
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, transport_version), signed_config,
+ compressed_certs_cache, out);
crypto_config->ValidateClientHello(
- inchoate_chlo, client_addr.host(), server_addr, version, clock, proof,
- generator.GetValidateClientHelloCallback());
+ inchoate_chlo, client_addr.host(), server_addr, transport_version, clock,
+ signed_config, generator.GetValidateClientHelloCallback());
}
} // namespace crypto_test_utils
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h b/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h
index 327eb673523..3d58837a813 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h
@@ -15,8 +15,8 @@
#include "net/third_party/quiche/src/quic/core/crypto/crypto_framer.h"
#include "net/third_party/quiche/src/quic/core/quic_framer.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -28,7 +28,7 @@ class QuicClock;
class QuicConfig;
class QuicCryptoClientStream;
class QuicCryptoServerConfig;
-class QuicCryptoServerStream;
+class QuicCryptoServerStreamBase;
class QuicCryptoStream;
class QuicRandom;
class QuicServerId;
@@ -62,6 +62,10 @@ struct FakeClientOptions {
// If only_tls_versions is set, then the client will only use TLS for the
// crypto handshake.
bool only_tls_versions = false;
+
+ // If only_quic_crypto_versions is set, then the client will only use
+ // PROTOCOL_QUIC_CRYPTO for the crypto handshake.
+ bool only_quic_crypto_versions = false;
};
// Returns a QuicCryptoServerConfig that is in a reasonable configuration to
@@ -81,7 +85,7 @@ int HandshakeWithFakeServer(QuicConfig* server_quic_config,
int HandshakeWithFakeClient(MockQuicConnectionHelper* helper,
MockAlarmFactory* alarm_factory,
PacketSavingConnection* server_conn,
- QuicCryptoServerStream* server,
+ QuicCryptoServerStreamBase* server,
const QuicServerId& server_id,
const FakeClientOptions& options,
std::string alpn);
@@ -132,7 +136,7 @@ std::unique_ptr<ProofVerifyContext> ProofVerifyContextForTesting();
// MockCommonCertSets returns a CommonCertSets that contains a single set with
// hash |hash|, consisting of the certificate |cert| at index |index|.
-CommonCertSets* MockCommonCertSets(QuicStringPiece cert,
+CommonCertSets* MockCommonCertSets(quiche::QuicheStringPiece cert,
uint64_t hash,
uint32_t index);
@@ -185,14 +189,14 @@ void GenerateFullCHLO(
QuicCryptoServerConfig* crypto_config,
QuicSocketAddress server_addr,
QuicSocketAddress client_addr,
- QuicTransportVersion version,
+ QuicTransportVersion transport_version,
const QuicClock* clock,
QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
QuicCompressedCertsCache* compressed_certs_cache,
CryptoHandshakeMessage* out);
void CompareClientAndServerKeys(QuicCryptoClientStream* client,
- QuicCryptoServerStream* server);
+ QuicCryptoServerStreamBase* server);
// Return a CHLO nonce in hexadecimal.
std::string GenerateClientNonceHex(const QuicClock* clock,
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils_test.cc b/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils_test.cc
index 656549772fa..6e64cb822fd 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils_test.cc
@@ -9,8 +9,9 @@
#include "net/third_party/quiche/src/quic/core/proto/crypto_server_config_proto.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
namespace test {
@@ -23,14 +24,16 @@ class ShloVerifier {
QuicSocketAddress client_addr,
const QuicClock* clock,
QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
- QuicCompressedCertsCache* compressed_certs_cache)
+ QuicCompressedCertsCache* compressed_certs_cache,
+ ParsedQuicVersion version)
: crypto_config_(crypto_config),
server_addr_(server_addr),
client_addr_(client_addr),
clock_(clock),
signed_config_(signed_config),
compressed_certs_cache_(compressed_certs_cache),
- params_(new QuicCryptoNegotiatedParameters) {}
+ params_(new QuicCryptoNegotiatedParameters),
+ version_(version) {}
class ValidateClientHelloCallback : public ValidateClientHelloResultCallback {
public:
@@ -59,9 +62,9 @@ class ShloVerifier {
crypto_config_->ProcessClientHello(
result_, /*reject_only=*/false,
/*connection_id=*/TestConnectionId(1), server_addr_, client_addr_,
- AllSupportedVersions().front(), AllSupportedVersions(), clock_,
- QuicRandom::GetInstance(), compressed_certs_cache_, params_,
- signed_config_, /*total_framing_overhead=*/50, kDefaultMaxPacketSize,
+ version_, AllSupportedVersions(), clock_, QuicRandom::GetInstance(),
+ compressed_certs_cache_, params_, signed_config_,
+ /*total_framing_overhead=*/50, kDefaultMaxPacketSize,
GetProcessClientHelloCallback());
}
@@ -102,6 +105,8 @@ class ShloVerifier {
QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
result_;
+
+ const ParsedQuicVersion version_;
};
class CryptoTestUtilsTest : public QuicTest {};
@@ -129,19 +134,29 @@ TEST_F(CryptoTestUtilsTest, TestGenerateFullCHLO) {
primary_config.set_primary_time(clock.WallNow().ToUNIXSeconds());
std::unique_ptr<CryptoHandshakeMessage> msg =
crypto_config.AddConfig(primary_config, clock.WallNow());
- QuicStringPiece orbit;
+ quiche::QuicheStringPiece orbit;
ASSERT_TRUE(msg->GetStringPiece(kORBT, &orbit));
std::string nonce;
CryptoUtils::GenerateNonce(clock.WallNow(), QuicRandom::GetInstance(), orbit,
&nonce);
- std::string nonce_hex = "#" + QuicTextUtils::HexEncode(nonce);
+ std::string nonce_hex = "#" + quiche::QuicheTextUtils::HexEncode(nonce);
char public_value[32];
memset(public_value, 42, sizeof(public_value));
- std::string pub_hex =
- "#" + QuicTextUtils::HexEncode(public_value, sizeof(public_value));
+ std::string pub_hex = "#" + quiche::QuicheTextUtils::HexEncode(
+ public_value, sizeof(public_value));
+
+ // The methods below use a PROTOCOL_QUIC_CRYPTO version so we pick the
+ // first one from the list of supported versions.
+ QuicTransportVersion transport_version = QUIC_VERSION_UNSUPPORTED;
+ for (const ParsedQuicVersion& version : AllSupportedVersions()) {
+ if (version.handshake_protocol == PROTOCOL_QUIC_CRYPTO) {
+ transport_version = version.transport_version;
+ break;
+ }
+ }
+ ASSERT_NE(QUIC_VERSION_UNSUPPORTED, transport_version);
- QuicTransportVersion version(AllSupportedTransportVersions().front());
CryptoHandshakeMessage inchoate_chlo = crypto_test_utils::CreateCHLO(
{{"PDMD", "X509"},
{"AEAD", "AESG"},
@@ -149,18 +164,21 @@ TEST_F(CryptoTestUtilsTest, TestGenerateFullCHLO) {
{"COPT", "SREJ"},
{"PUBS", pub_hex},
{"NONC", nonce_hex},
- {"VER\0",
- QuicVersionLabelToString(QuicVersionToQuicVersionLabel(version))}},
+ {"VER\0", QuicVersionLabelToString(
+ QuicVersionToQuicVersionLabel(transport_version))}},
kClientHelloMinimumSize);
- crypto_test_utils::GenerateFullCHLO(
- inchoate_chlo, &crypto_config, server_addr, client_addr, version, &clock,
- signed_config, &compressed_certs_cache, &full_chlo);
+ crypto_test_utils::GenerateFullCHLO(inchoate_chlo, &crypto_config,
+ server_addr, client_addr,
+ transport_version, &clock, signed_config,
+ &compressed_certs_cache, &full_chlo);
// Verify that full_chlo can pass crypto_config's verification.
- ShloVerifier shlo_verifier(&crypto_config, server_addr, client_addr, &clock,
- signed_config, &compressed_certs_cache);
+ ShloVerifier shlo_verifier(
+ &crypto_config, server_addr, client_addr, &clock, signed_config,
+ &compressed_certs_cache,
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, transport_version));
crypto_config.ValidateClientHello(
- full_chlo, client_addr.host(), server_addr, version, &clock,
+ full_chlo, client_addr.host(), server_addr, transport_version, &clock,
signed_config, shlo_verifier.GetValidateClientHelloCallback());
}
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/failing_proof_source.cc b/chromium/net/third_party/quiche/src/quic/test_tools/failing_proof_source.cc
index 60b6a95fd11..1f52476085a 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/failing_proof_source.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/failing_proof_source.cc
@@ -4,6 +4,8 @@
#include "net/third_party/quiche/src/quic/test_tools/failing_proof_source.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+
namespace quic {
namespace test {
@@ -11,7 +13,7 @@ void FailingProofSource::GetProof(const QuicSocketAddress& /*server_address*/,
const std::string& /*hostname*/,
const std::string& /*server_config*/,
QuicTransportVersion /*transport_version*/,
- QuicStringPiece /*chlo_hash*/,
+ quiche::QuicheStringPiece /*chlo_hash*/,
std::unique_ptr<Callback> callback) {
callback->Run(false, nullptr, QuicCryptoProof(), nullptr);
}
@@ -26,9 +28,9 @@ void FailingProofSource::ComputeTlsSignature(
const QuicSocketAddress& /*server_address*/,
const std::string& /*hostname*/,
uint16_t /*signature_algorithm*/,
- QuicStringPiece /*in*/,
+ quiche::QuicheStringPiece /*in*/,
std::unique_ptr<SignatureCallback> callback) {
- callback->Run(false, "");
+ callback->Run(false, "", nullptr);
}
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/failing_proof_source.h b/chromium/net/third_party/quiche/src/quic/test_tools/failing_proof_source.h
index 10f9971c4ff..36e23989117 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/failing_proof_source.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/failing_proof_source.h
@@ -6,7 +6,7 @@
#define QUICHE_QUIC_TEST_TOOLS_FAILING_PROOF_SOURCE_H_
#include "net/third_party/quiche/src/quic/core/crypto/proof_source.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
@@ -17,7 +17,7 @@ class FailingProofSource : public ProofSource {
const std::string& hostname,
const std::string& server_config,
QuicTransportVersion transport_version,
- QuicStringPiece chlo_hash,
+ quiche::QuicheStringPiece chlo_hash,
std::unique_ptr<Callback> callback) override;
QuicReferenceCountedPointer<Chain> GetCertChain(
@@ -28,7 +28,7 @@ class FailingProofSource : public ProofSource {
const QuicSocketAddress& server_address,
const std::string& hostname,
uint16_t signature_algorithm,
- QuicStringPiece in,
+ quiche::QuicheStringPiece in,
std::unique_ptr<SignatureCallback> callback) override;
};
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source.cc b/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source.cc
index 784ced4027e..0d85b5d450d 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source.cc
@@ -8,6 +8,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
@@ -47,7 +48,7 @@ FakeProofSource::ComputeSignatureOp::ComputeSignatureOp(
const QuicSocketAddress& server_address,
std::string hostname,
uint16_t sig_alg,
- QuicStringPiece in,
+ quiche::QuicheStringPiece in,
std::unique_ptr<ProofSource::SignatureCallback> callback,
ProofSource* delegate)
: server_address_(server_address),
@@ -73,7 +74,7 @@ void FakeProofSource::GetProof(
const std::string& hostname,
const std::string& server_config,
QuicTransportVersion transport_version,
- QuicStringPiece chlo_hash,
+ quiche::QuicheStringPiece chlo_hash,
std::unique_ptr<ProofSource::Callback> callback) {
if (!active_) {
delegate_->GetProof(server_address, hostname, server_config,
@@ -96,7 +97,7 @@ void FakeProofSource::ComputeTlsSignature(
const QuicSocketAddress& server_address,
const std::string& hostname,
uint16_t signature_algorithm,
- QuicStringPiece in,
+ quiche::QuicheStringPiece in,
std::unique_ptr<ProofSource::SignatureCallback> callback) {
QUIC_LOG(INFO) << "FakeProofSource::ComputeTlsSignature";
if (!active_) {
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source.h b/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source.h
index 62c3b29de9e..41b761ac119 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source.h
@@ -10,7 +10,7 @@
#include <vector>
#include "net/third_party/quiche/src/quic/core/crypto/proof_source.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
@@ -35,7 +35,7 @@ class FakeProofSource : public ProofSource {
const std::string& hostname,
const std::string& server_config,
QuicTransportVersion transport_version,
- QuicStringPiece chlo_hash,
+ quiche::QuicheStringPiece chlo_hash,
std::unique_ptr<ProofSource::Callback> callback) override;
QuicReferenceCountedPointer<Chain> GetCertChain(
const QuicSocketAddress& server_address,
@@ -44,7 +44,7 @@ class FakeProofSource : public ProofSource {
const QuicSocketAddress& server_address,
const std::string& hostname,
uint16_t signature_algorithm,
- QuicStringPiece in,
+ quiche::QuicheStringPiece in,
std::unique_ptr<ProofSource::SignatureCallback> callback) override;
// Get the number of callbacks which are pending
@@ -92,7 +92,7 @@ class FakeProofSource : public ProofSource {
ComputeSignatureOp(const QuicSocketAddress& server_address,
std::string hostname,
uint16_t sig_alg,
- QuicStringPiece in,
+ quiche::QuicheStringPiece in,
std::unique_ptr<ProofSource::SignatureCallback> callback,
ProofSource* delegate);
~ComputeSignatureOp() override;
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/mock_clock.h b/chromium/net/third_party/quiche/src/quic/test_tools/mock_clock.h
index dbd57d3b740..4bd51e9d6d6 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/mock_clock.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/mock_clock.h
@@ -5,8 +5,8 @@
#ifndef QUICHE_QUIC_TEST_TOOLS_MOCK_CLOCK_H_
#define QUICHE_QUIC_TEST_TOOLS_MOCK_CLOCK_H_
+#include "net/third_party/quiche/src/quic/core/quic_clock.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_dispatcher.cc b/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_dispatcher.cc
index 3b3ca4691b1..40869e022e3 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_dispatcher.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_dispatcher.cc
@@ -14,7 +14,7 @@ MockQuicDispatcher::MockQuicDispatcher(
const QuicCryptoServerConfig* crypto_config,
QuicVersionManager* version_manager,
std::unique_ptr<QuicConnectionHelperInterface> helper,
- std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
+ std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
std::unique_ptr<QuicAlarmFactory> alarm_factory,
QuicSimpleServerBackend* quic_simple_server_backend)
: QuicSimpleDispatcher(config,
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_dispatcher.h b/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_dispatcher.h
index 3134e1fea7b..b2ab45329d6 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_dispatcher.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_dispatcher.h
@@ -22,7 +22,7 @@ class MockQuicDispatcher : public QuicSimpleDispatcher {
const QuicCryptoServerConfig* crypto_config,
QuicVersionManager* version_manager,
std::unique_ptr<QuicConnectionHelperInterface> helper,
- std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
+ std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
std::unique_ptr<QuicAlarmFactory> alarm_factory,
QuicSimpleServerBackend* quic_simple_server_backend);
MockQuicDispatcher(const MockQuicDispatcher&) = delete;
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_session_visitor.h b/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_session_visitor.h
index 0954bb71390..0cc10d1d3d5 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_session_visitor.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_session_visitor.h
@@ -5,7 +5,7 @@
#ifndef QUICHE_QUIC_TEST_TOOLS_MOCK_QUIC_SESSION_VISITOR_H_
#define QUICHE_QUIC_TEST_TOOLS_MOCK_QUIC_SESSION_VISITOR_H_
-#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
+#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h"
#include "net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
@@ -31,7 +31,8 @@ class MockQuicSessionVisitor : public QuicTimeWaitListManager::Visitor {
void(QuicConnectionId connection_id));
};
-class MockQuicCryptoServerStreamHelper : public QuicCryptoServerStream::Helper {
+class MockQuicCryptoServerStreamHelper
+ : public QuicCryptoServerStreamBase::Helper {
public:
MockQuicCryptoServerStreamHelper();
MockQuicCryptoServerStreamHelper(const MockQuicCryptoServerStreamHelper&) =
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/packet_dropping_test_writer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/packet_dropping_test_writer.cc
index 87935d5c013..c897fdc33e7 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/packet_dropping_test_writer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/packet_dropping_test_writer.cc
@@ -6,7 +6,6 @@
#include "net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/quic/platform/impl/quic_socket_utils.h"
namespace quic {
namespace test {
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/packet_dropping_test_writer.h b/chromium/net/third_party/quiche/src/quic/test_tools/packet_dropping_test_writer.h
index 4b3e8af28ea..75b9a5dcb30 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/packet_dropping_test_writer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/packet_dropping_test_writer.h
@@ -10,8 +10,8 @@
#include <memory>
#include "net/third_party/quiche/src/quic/core/quic_alarm.h"
+#include "net/third_party/quiche/src/quic/core/quic_clock.h"
#include "net/third_party/quiche/src/quic/core/quic_packet_writer_wrapper.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_macros.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_client.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_decoder_test_utils.cc b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_decoder_test_utils.cc
index 2b835ae2e46..4189290eebf 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_decoder_test_utils.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_decoder_test_utils.cc
@@ -9,18 +9,19 @@
#include <utility>
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
void NoopEncoderStreamErrorDelegate::OnEncoderStreamError(
- QuicStringPiece /*error_message*/) {}
+ quiche::QuicheStringPiece /*error_message*/) {}
TestHeadersHandler::TestHeadersHandler()
: decoding_completed_(false), decoding_error_detected_(false) {}
-void TestHeadersHandler::OnHeaderDecoded(QuicStringPiece name,
- QuicStringPiece value) {
+void TestHeadersHandler::OnHeaderDecoded(quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value) {
ASSERT_FALSE(decoding_completed_);
ASSERT_FALSE(decoding_error_detected_);
@@ -35,7 +36,7 @@ void TestHeadersHandler::OnDecodingCompleted() {
}
void TestHeadersHandler::OnDecodingErrorDetected(
- QuicStringPiece error_message) {
+ quiche::QuicheStringPiece error_message) {
ASSERT_FALSE(decoding_completed_);
ASSERT_FALSE(decoding_error_detected_);
@@ -70,7 +71,7 @@ void QpackDecode(
QpackStreamSenderDelegate* decoder_stream_sender_delegate,
QpackProgressiveDecoder::HeadersHandlerInterface* handler,
const FragmentSizeGenerator& fragment_size_generator,
- QuicStringPiece data) {
+ quiche::QuicheStringPiece data) {
QpackDecoder decoder(maximum_dynamic_table_capacity, maximum_blocked_streams,
encoder_stream_error_delegate);
decoder.set_qpack_stream_sender_delegate(decoder_stream_sender_delegate);
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_decoder_test_utils.h b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_decoder_test_utils.h
index 213aded1ba5..2bd80ef65ed 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_decoder_test_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_decoder_test_utils.h
@@ -9,9 +9,9 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "net/third_party/quiche/src/spdy/core/spdy_header_block.h"
namespace quic {
@@ -23,7 +23,7 @@ class NoopEncoderStreamErrorDelegate
public:
~NoopEncoderStreamErrorDelegate() override = default;
- void OnEncoderStreamError(QuicStringPiece error_message) override;
+ void OnEncoderStreamError(quiche::QuicheStringPiece error_message) override;
};
// Mock QpackDecoder::EncoderStreamErrorDelegate implementation.
@@ -32,7 +32,8 @@ class MockEncoderStreamErrorDelegate
public:
~MockEncoderStreamErrorDelegate() override = default;
- MOCK_METHOD1(OnEncoderStreamError, void(QuicStringPiece error_message));
+ MOCK_METHOD1(OnEncoderStreamError,
+ void(quiche::QuicheStringPiece error_message));
};
// HeadersHandlerInterface implementation that collects decoded headers
@@ -44,9 +45,11 @@ class TestHeadersHandler
~TestHeadersHandler() override = default;
// HeadersHandlerInterface implementation:
- void OnHeaderDecoded(QuicStringPiece name, QuicStringPiece value) override;
+ void OnHeaderDecoded(quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value) override;
void OnDecodingCompleted() override;
- void OnDecodingErrorDetected(QuicStringPiece error_message) override;
+ void OnDecodingErrorDetected(
+ quiche::QuicheStringPiece error_message) override;
// Release decoded header list. Must only be called if decoding is complete
// and no errors have been detected.
@@ -72,9 +75,11 @@ class MockHeadersHandler
~MockHeadersHandler() override = default;
MOCK_METHOD2(OnHeaderDecoded,
- void(QuicStringPiece name, QuicStringPiece value));
+ void(quiche::QuicheStringPiece name,
+ quiche::QuicheStringPiece value));
MOCK_METHOD0(OnDecodingCompleted, void());
- MOCK_METHOD1(OnDecodingErrorDetected, void(QuicStringPiece error_message));
+ MOCK_METHOD1(OnDecodingErrorDetected,
+ void(quiche::QuicheStringPiece error_message));
};
class NoOpHeadersHandler
@@ -82,10 +87,11 @@ class NoOpHeadersHandler
public:
~NoOpHeadersHandler() override = default;
- void OnHeaderDecoded(QuicStringPiece /*name*/,
- QuicStringPiece /*value*/) override {}
+ void OnHeaderDecoded(quiche::QuicheStringPiece /*name*/,
+ quiche::QuicheStringPiece /*value*/) override {}
void OnDecodingCompleted() override {}
- void OnDecodingErrorDetected(QuicStringPiece /*error_message*/) override {}
+ void OnDecodingErrorDetected(
+ quiche::QuicheStringPiece /*error_message*/) override {}
};
void QpackDecode(
@@ -95,7 +101,7 @@ void QpackDecode(
QpackStreamSenderDelegate* decoder_stream_sender_delegate,
QpackProgressiveDecoder::HeadersHandlerInterface* handler,
const FragmentSizeGenerator& fragment_size_generator,
- QuicStringPiece data);
+ quiche::QuicheStringPiece data);
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_test_utils.cc b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_test_utils.cc
index dbdd3690d55..1303511e2d8 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_test_utils.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_test_utils.cc
@@ -4,13 +4,14 @@
#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.h"
namespace quic {
namespace test {
void NoopDecoderStreamErrorDelegate::OnDecoderStreamError(
- QuicStringPiece /*error_message*/) {}
+ quiche::QuicheStringPiece /*error_message*/) {}
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_test_utils.h b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_test_utils.h
index 5fa229256b4..0ea978f7b40 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_test_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_test_utils.h
@@ -8,9 +8,9 @@
#include <string>
#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "net/third_party/quiche/src/spdy/core/spdy_header_block.h"
namespace quic {
@@ -22,7 +22,7 @@ class NoopDecoderStreamErrorDelegate
public:
~NoopDecoderStreamErrorDelegate() override = default;
- void OnDecoderStreamError(QuicStringPiece error_message) override;
+ void OnDecoderStreamError(quiche::QuicheStringPiece error_message) override;
};
// Mock QpackEncoder::DecoderStreamErrorDelegate implementation.
@@ -31,7 +31,8 @@ class MockDecoderStreamErrorDelegate
public:
~MockDecoderStreamErrorDelegate() override = default;
- MOCK_METHOD1(OnDecoderStreamError, void(QuicStringPiece error_message));
+ MOCK_METHOD1(OnDecoderStreamError,
+ void(quiche::QuicheStringPiece error_message));
};
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_offline_decoder.cc b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_offline_decoder.cc
index a5a74aa4cb0..a7ba9e48876 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_offline_decoder.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_offline_decoder.cc
@@ -33,9 +33,10 @@
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_file_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
@@ -43,8 +44,8 @@ QpackOfflineDecoder::QpackOfflineDecoder()
: encoder_stream_error_detected_(false) {}
bool QpackOfflineDecoder::DecodeAndVerifyOfflineData(
- QuicStringPiece input_filename,
- QuicStringPiece expected_headers_filename) {
+ quiche::QuicheStringPiece input_filename,
+ quiche::QuicheStringPiece expected_headers_filename) {
if (!ParseInputFilename(input_filename)) {
QUIC_LOG(ERROR) << "Error parsing input filename " << input_filename;
return false;
@@ -65,13 +66,15 @@ bool QpackOfflineDecoder::DecodeAndVerifyOfflineData(
return true;
}
-void QpackOfflineDecoder::OnEncoderStreamError(QuicStringPiece error_message) {
+void QpackOfflineDecoder::OnEncoderStreamError(
+ quiche::QuicheStringPiece error_message) {
QUIC_LOG(ERROR) << "Encoder stream error: " << error_message;
encoder_stream_error_detected_ = true;
}
-bool QpackOfflineDecoder::ParseInputFilename(QuicStringPiece input_filename) {
- auto pieces = QuicTextUtils::Split(input_filename, '.');
+bool QpackOfflineDecoder::ParseInputFilename(
+ quiche::QuicheStringPiece input_filename) {
+ auto pieces = quiche::QuicheTextUtils::Split(input_filename, '.');
if (pieces.size() < 3) {
QUIC_LOG(ERROR) << "Not enough fields in input filename " << input_filename;
@@ -97,7 +100,8 @@ bool QpackOfflineDecoder::ParseInputFilename(QuicStringPiece input_filename) {
// Maximum allowed number of blocked streams.
uint64_t max_blocked_streams = 0;
- if (!QuicTextUtils::StringToUint64(*piece_it, &max_blocked_streams)) {
+ if (!quiche::QuicheTextUtils::StringToUint64(*piece_it,
+ &max_blocked_streams)) {
QUIC_LOG(ERROR) << "Error parsing part of input filename \"" << *piece_it
<< "\" as an integer.";
return false;
@@ -107,8 +111,8 @@ bool QpackOfflineDecoder::ParseInputFilename(QuicStringPiece input_filename) {
// Maximum Dynamic Table Capacity in bytes
uint64_t maximum_dynamic_table_capacity = 0;
- if (!QuicTextUtils::StringToUint64(*piece_it,
- &maximum_dynamic_table_capacity)) {
+ if (!quiche::QuicheTextUtils::StringToUint64(
+ *piece_it, &maximum_dynamic_table_capacity)) {
QUIC_LOG(ERROR) << "Error parsing part of input filename \"" << *piece_it
<< "\" as an integer.";
return false;
@@ -128,12 +132,12 @@ bool QpackOfflineDecoder::ParseInputFilename(QuicStringPiece input_filename) {
}
bool QpackOfflineDecoder::DecodeHeaderBlocksFromFile(
- QuicStringPiece input_filename) {
- // Store data in |input_data_storage|; use a QuicStringPiece to efficiently
- // keep track of remaining portion yet to be decoded.
+ quiche::QuicheStringPiece input_filename) {
+ // Store data in |input_data_storage|; use a quiche::QuicheStringPiece to
+ // efficiently keep track of remaining portion yet to be decoded.
std::string input_data_storage;
ReadFileContents(input_filename, &input_data_storage);
- QuicStringPiece input_data(input_data_storage);
+ quiche::QuicheStringPiece input_data(input_data_storage);
while (!input_data.empty()) {
// Parse stream_id and length.
@@ -156,7 +160,7 @@ bool QpackOfflineDecoder::DecodeHeaderBlocksFromFile(
}
// Parse data.
- QuicStringPiece data = input_data.substr(0, length);
+ quiche::QuicheStringPiece data = input_data.substr(0, length);
input_data = input_data.substr(length);
// Process data.
@@ -224,12 +228,14 @@ bool QpackOfflineDecoder::DecodeHeaderBlocksFromFile(
}
bool QpackOfflineDecoder::VerifyDecodedHeaderLists(
- QuicStringPiece expected_headers_filename) {
- // Store data in |expected_headers_data_storage|; use a QuicStringPiece to
- // efficiently keep track of remaining portion yet to be decoded.
+ quiche::QuicheStringPiece expected_headers_filename) {
+ // Store data in |expected_headers_data_storage|; use a
+ // quiche::QuicheStringPiece to efficiently keep track of remaining portion
+ // yet to be decoded.
std::string expected_headers_data_storage;
ReadFileContents(expected_headers_filename, &expected_headers_data_storage);
- QuicStringPiece expected_headers_data(expected_headers_data_storage);
+ quiche::QuicheStringPiece expected_headers_data(
+ expected_headers_data_storage);
while (!decoded_header_lists_.empty()) {
spdy::SpdyHeaderBlock decoded_header_list =
@@ -262,13 +268,14 @@ bool QpackOfflineDecoder::VerifyDecodedHeaderLists(
}
bool QpackOfflineDecoder::ReadNextExpectedHeaderList(
- QuicStringPiece* expected_headers_data,
+ quiche::QuicheStringPiece* expected_headers_data,
spdy::SpdyHeaderBlock* expected_header_list) {
while (true) {
- QuicStringPiece::size_type endline = expected_headers_data->find('\n');
+ quiche::QuicheStringPiece::size_type endline =
+ expected_headers_data->find('\n');
// Even last header list must be followed by an empty line.
- if (endline == QuicStringPiece::npos) {
+ if (endline == quiche::QuicheStringPiece::npos) {
QUIC_LOG(ERROR) << "Unexpected end of expected header list file.";
return false;
}
@@ -279,8 +286,9 @@ bool QpackOfflineDecoder::ReadNextExpectedHeaderList(
return true;
}
- QuicStringPiece header_field = expected_headers_data->substr(0, endline);
- auto pieces = QuicTextUtils::Split(header_field, '\t');
+ quiche::QuicheStringPiece header_field =
+ expected_headers_data->substr(0, endline);
+ auto pieces = quiche::QuicheTextUtils::Split(header_field, '\t');
if (pieces.size() != 2) {
QUIC_LOG(ERROR) << "Header key and value must be separated by TAB.";
@@ -308,9 +316,9 @@ bool QpackOfflineDecoder::CompareHeaderBlocks(
const char* kPseudoHeaderPrefix = ":";
for (spdy::SpdyHeaderBlock::iterator decoded_it = decoded_header_list.begin();
decoded_it != decoded_header_list.end();) {
- const QuicStringPiece key = decoded_it->first;
+ const quiche::QuicheStringPiece key = decoded_it->first;
if (key != kContentLength &&
- !QuicTextUtils::StartsWith(key, kPseudoHeaderPrefix)) {
+ !quiche::QuicheTextUtils::StartsWith(key, kPseudoHeaderPrefix)) {
++decoded_it;
continue;
}
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_offline_decoder.h b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_offline_decoder.h
index cb7dedd3aaf..f90b2c736eb 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_offline_decoder.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_offline_decoder.h
@@ -8,9 +8,9 @@
#include <list>
#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_decoder_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "net/third_party/quiche/src/spdy/core/spdy_header_block.h"
namespace quic {
@@ -29,11 +29,12 @@ class QpackOfflineDecoder : public QpackDecoder::EncoderStreamErrorDelegate {
// |expected_headers_filename|, and compare decoded header lists to expected
// ones. Returns true if there is an equal number of them and the
// corresponding ones match, false otherwise.
- bool DecodeAndVerifyOfflineData(QuicStringPiece input_filename,
- QuicStringPiece expected_headers_filename);
+ bool DecodeAndVerifyOfflineData(
+ quiche::QuicheStringPiece input_filename,
+ quiche::QuicheStringPiece expected_headers_filename);
// QpackDecoder::EncoderStreamErrorDelegate implementation:
- void OnEncoderStreamError(QuicStringPiece error_message) override;
+ void OnEncoderStreamError(quiche::QuicheStringPiece error_message) override;
private:
// Data structure to hold TestHeadersHandler and QpackProgressiveDecoder until
@@ -47,22 +48,24 @@ class QpackOfflineDecoder : public QpackDecoder::EncoderStreamErrorDelegate {
// Parse decoder parameters from |input_filename| and set up |qpack_decoder_|
// accordingly.
- bool ParseInputFilename(QuicStringPiece input_filename);
+ bool ParseInputFilename(quiche::QuicheStringPiece input_filename);
// Read encoded header blocks and encoder stream data from |input_filename|,
// pass them to |qpack_decoder_| for decoding, and add decoded header lists to
// |decoded_header_lists_|.
- bool DecodeHeaderBlocksFromFile(QuicStringPiece input_filename);
+ bool DecodeHeaderBlocksFromFile(quiche::QuicheStringPiece input_filename);
// Read expected header lists from |expected_headers_filename| and verify
// decoded header lists in |decoded_header_lists_| against them.
- bool VerifyDecodedHeaderLists(QuicStringPiece expected_headers_filename);
+ bool VerifyDecodedHeaderLists(
+ quiche::QuicheStringPiece expected_headers_filename);
// Parse next header list from |*expected_headers_data| into
// |*expected_header_list|, removing consumed data from the beginning of
// |*expected_headers_data|. Returns true on success, false if parsing fails.
- bool ReadNextExpectedHeaderList(QuicStringPiece* expected_headers_data,
- spdy::SpdyHeaderBlock* expected_header_list);
+ bool ReadNextExpectedHeaderList(
+ quiche::QuicheStringPiece* expected_headers_data,
+ spdy::SpdyHeaderBlock* expected_header_list);
// Compare two header lists. Allow for different orders of certain headers as
// described at
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h
index 08cab4e0b2c..074095048d7 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h
@@ -10,6 +10,7 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_stream_sender_delegate.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
@@ -31,14 +32,14 @@ class MockQpackStreamSenderDelegate : public QpackStreamSenderDelegate {
public:
~MockQpackStreamSenderDelegate() override = default;
- MOCK_METHOD1(WriteStreamData, void(QuicStringPiece data));
+ MOCK_METHOD1(WriteStreamData, void(quiche::QuicheStringPiece data));
};
class NoopQpackStreamSenderDelegate : public QpackStreamSenderDelegate {
public:
~NoopQpackStreamSenderDelegate() override = default;
- void WriteStreamData(QuicStringPiece /*data*/) override {}
+ void WriteStreamData(quiche::QuicheStringPiece /*data*/) override {}
};
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_buffered_packet_store_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_buffered_packet_store_peer.h
index e857dfbe786..625b1eb7f96 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_buffered_packet_store_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_buffered_packet_store_peer.h
@@ -8,7 +8,7 @@
#include <memory>
#include "net/third_party/quiche/src/quic/core/quic_alarm.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
+#include "net/third_party/quiche/src/quic/core/quic_clock.h"
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.cc
index 6278817caaf..20463ab4592 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.cc
@@ -69,16 +69,14 @@ void QuicConfigPeer::SetReceivedDisableConnectionMigration(QuicConfig* config) {
}
// static
-void QuicConfigPeer::SetReceivedMaxIncomingBidirectionalStreams(
- QuicConfig* config,
- uint32_t max_streams) {
- config->max_incoming_bidirectional_streams_.SetReceivedValue(max_streams);
+void QuicConfigPeer::SetReceivedMaxBidirectionalStreams(QuicConfig* config,
+ uint32_t max_streams) {
+ config->max_bidirectional_streams_.SetReceivedValue(max_streams);
}
// static
-void QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams(
- QuicConfig* config,
- uint32_t max_streams) {
- config->max_incoming_unidirectional_streams_.SetReceivedValue(max_streams);
+void QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(QuicConfig* config,
+ uint32_t max_streams) {
+ config->max_unidirectional_streams_.SetReceivedValue(max_streams);
}
// static
@@ -93,5 +91,20 @@ void QuicConfigPeer::SetReceivedStatelessResetToken(QuicConfig* config,
config->stateless_reset_token_.SetReceivedValue(token);
}
+// static
+void QuicConfigPeer::SetReceivedMaxPacketSize(QuicConfig* config,
+ uint32_t max_packet_size) {
+ config->max_packet_size_.SetReceivedValue(max_packet_size);
+}
+
+// static
+void QuicConfigPeer::ReceiveIdleNetworkTimeout(QuicConfig* config,
+ HelloType hello_type,
+ uint32_t idle_timeout_seconds) {
+ std::string error_details;
+ config->idle_network_timeout_seconds_.ReceiveValue(
+ idle_timeout_seconds, hello_type, &error_details);
+}
+
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.h
index e68d87d8502..b52bf42085b 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.h
@@ -45,16 +45,23 @@ class QuicConfigPeer {
static void SetReceivedDisableConnectionMigration(QuicConfig* config);
- static void SetReceivedMaxIncomingBidirectionalStreams(QuicConfig* config,
- uint32_t max_streams);
- static void SetReceivedMaxIncomingUnidirectionalStreams(QuicConfig* config,
- uint32_t max_streams);
+ static void SetReceivedMaxBidirectionalStreams(QuicConfig* config,
+ uint32_t max_streams);
+ static void SetReceivedMaxUnidirectionalStreams(QuicConfig* config,
+ uint32_t max_streams);
static void SetConnectionOptionsToSend(QuicConfig* config,
const QuicTagVector& options);
static void SetReceivedStatelessResetToken(QuicConfig* config,
QuicUint128 token);
+
+ static void SetReceivedMaxPacketSize(QuicConfig* config,
+ uint32_t max_packet_size);
+
+ static void ReceiveIdleNetworkTimeout(QuicConfig* config,
+ HelloType hello_type,
+ uint32_t idle_timeout_seconds);
};
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.cc
index 7b9264c31b8..6b6387f47c1 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.cc
@@ -10,6 +10,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_framer_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
@@ -50,6 +51,9 @@ QuicSentPacketManager* QuicConnectionPeer::GetSentPacketManager(
// static
QuicTime::Delta QuicConnectionPeer::GetNetworkTimeout(
QuicConnection* connection) {
+ if (connection->use_idle_network_detector_) {
+ return connection->idle_network_detector_.idle_network_timeout_;
+ }
return connection->idle_network_timeout_;
}
@@ -99,8 +103,9 @@ void QuicConnectionPeer::SwapCrypters(QuicConnection* connection,
}
// static
-void QuicConnectionPeer::SetCurrentPacket(QuicConnection* connection,
- QuicStringPiece current_packet) {
+void QuicConnectionPeer::SetCurrentPacket(
+ QuicConnection* connection,
+ quiche::QuicheStringPiece current_packet) {
connection->current_packet_data_ = current_packet.data();
connection->last_size_ = current_packet.size();
}
@@ -346,5 +351,35 @@ size_t QuicConnectionPeer::GetNumEncryptionLevels(QuicConnection* connection) {
return count;
}
+// static
+QuicNetworkBlackholeDetector& QuicConnectionPeer::GetBlackholeDetector(
+ QuicConnection* connection) {
+ return connection->blackhole_detector_;
+}
+
+// static
+QuicAlarm* QuicConnectionPeer::GetBlackholeDetectorAlarm(
+ QuicConnection* connection) {
+ return connection->blackhole_detector_.alarm_.get();
+}
+
+// static
+QuicTime QuicConnectionPeer::GetPathDegradingDeadline(
+ QuicConnection* connection) {
+ return connection->blackhole_detector_.path_degrading_deadline_;
+}
+
+// static
+QuicTime QuicConnectionPeer::GetBlackholeDetectionDeadline(
+ QuicConnection* connection) {
+ return connection->blackhole_detector_.blackhole_deadline_;
+}
+
+// static
+QuicAlarm* QuicConnectionPeer::GetIdleNetworkDetectorAlarm(
+ QuicConnection* connection) {
+ return connection->idle_network_detector_.alarm_.get();
+}
+
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h
index b7140ded5ed..d6d6b3cc3c0 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h
@@ -9,7 +9,7 @@
#include "net/third_party/quiche/src/quic/core/quic_connection_stats.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -69,7 +69,7 @@ class QuicConnectionPeer {
static void SwapCrypters(QuicConnection* connection, QuicFramer* framer);
static void SetCurrentPacket(QuicConnection* connection,
- QuicStringPiece current_packet);
+ quiche::QuicheStringPiece current_packet);
static QuicConnectionHelperInterface* GetHelper(QuicConnection* connection);
@@ -135,6 +135,17 @@ class QuicConnectionPeer {
const std::string& details);
static size_t GetNumEncryptionLevels(QuicConnection* connection);
+
+ static QuicNetworkBlackholeDetector& GetBlackholeDetector(
+ QuicConnection* connection);
+
+ static QuicAlarm* GetBlackholeDetectorAlarm(QuicConnection* connection);
+
+ static QuicTime GetPathDegradingDeadline(QuicConnection* connection);
+
+ static QuicTime GetBlackholeDetectionDeadline(QuicConnection* connection);
+
+ static QuicAlarm* GetIdleNetworkDetectorAlarm(QuicConnection* connection);
};
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_crypto_server_config_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_crypto_server_config_peer.cc
index be2d3386bb8..3893448931c 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_crypto_server_config_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_crypto_server_config_peer.cc
@@ -7,6 +7,7 @@
#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_random.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
@@ -52,7 +53,7 @@ std::string QuicCryptoServerConfigPeer::NewSourceAddressToken(
HandshakeFailureReason QuicCryptoServerConfigPeer::ValidateSourceAddressTokens(
std::string config_id,
- QuicStringPiece srct,
+ quiche::QuicheStringPiece srct,
const QuicIpAddress& ip,
QuicWallTime now,
CachedNetworkParameters* cached_network_params) {
@@ -69,7 +70,7 @@ HandshakeFailureReason QuicCryptoServerConfigPeer::ValidateSourceAddressTokens(
HandshakeFailureReason
QuicCryptoServerConfigPeer::ValidateSingleSourceAddressToken(
- QuicStringPiece token,
+ quiche::QuicheStringPiece token,
const QuicIpAddress& ip,
QuicWallTime now) {
SourceAddressTokens tokens;
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_crypto_server_config_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_crypto_server_config_peer.h
index baaa9b8bffb..270321f8ff1 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_crypto_server_config_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_crypto_server_config_peer.h
@@ -6,7 +6,7 @@
#define QUICHE_QUIC_TEST_TOOLS_QUIC_CRYPTO_SERVER_CONFIG_PEER_H_
#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
@@ -43,14 +43,14 @@ class QuicCryptoServerConfigPeer {
// Attempts to validate the tokens in |tokens|.
HandshakeFailureReason ValidateSourceAddressTokens(
std::string config_id,
- QuicStringPiece tokens,
+ quiche::QuicheStringPiece tokens,
const QuicIpAddress& ip,
QuicWallTime now,
CachedNetworkParameters* cached_network_params);
// Attempts to validate the single source address token in |token|.
HandshakeFailureReason ValidateSingleSourceAddressToken(
- QuicStringPiece token,
+ quiche::QuicheStringPiece token,
const QuicIpAddress& ip,
QuicWallTime now);
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_framer_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_framer_peer.cc
index d686d5a4097..cc94232f50d 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_framer_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_framer_peer.cc
@@ -57,252 +57,6 @@ void QuicFramerPeer::SetPerspective(QuicFramer* framer,
}
// static
-bool QuicFramerPeer::ProcessIetfStreamFrame(QuicFramer* framer,
- QuicDataReader* reader,
- uint8_t frame_type,
- QuicStreamFrame* frame) {
- return framer->ProcessIetfStreamFrame(reader, frame_type, frame);
-}
-
-// static
-bool QuicFramerPeer::AppendIetfStreamFrame(QuicFramer* framer,
- const QuicStreamFrame& frame,
- bool last_frame_in_packet,
- QuicDataWriter* writer) {
- return framer->AppendIetfStreamFrame(frame, last_frame_in_packet, writer);
-}
-
-// static
-bool QuicFramerPeer::ProcessCryptoFrame(QuicFramer* framer,
- QuicDataReader* reader,
- QuicCryptoFrame* frame) {
- return framer->ProcessCryptoFrame(reader, frame);
-}
-
-// static
-bool QuicFramerPeer::AppendCryptoFrame(QuicFramer* framer,
- const QuicCryptoFrame& frame,
- QuicDataWriter* writer) {
- return framer->AppendCryptoFrame(frame, writer);
-}
-
-// static
-bool QuicFramerPeer::ProcessIetfAckFrame(QuicFramer* framer,
- QuicDataReader* reader,
- uint64_t frame_type,
- QuicAckFrame* ack_frame) {
- return framer->ProcessIetfAckFrame(reader, frame_type, ack_frame);
-}
-
-// static
-bool QuicFramerPeer::AppendIetfAckFrameAndTypeByte(QuicFramer* framer,
- const QuicAckFrame& frame,
- QuicDataWriter* writer) {
- return framer->AppendIetfAckFrameAndTypeByte(frame, writer);
-}
-// static
-size_t QuicFramerPeer::GetIetfAckFrameSize(QuicFramer* framer,
- const QuicAckFrame& frame) {
- return framer->GetIetfAckFrameSize(frame);
-}
-
-// static
-bool QuicFramerPeer::AppendIetfConnectionCloseFrame(
- QuicFramer* framer,
- const QuicConnectionCloseFrame& frame,
- QuicDataWriter* writer) {
- return framer->AppendIetfConnectionCloseFrame(frame, writer);
-}
-
-// static
-bool QuicFramerPeer::ProcessIetfConnectionCloseFrame(
- QuicFramer* framer,
- QuicDataReader* reader,
- QuicConnectionCloseType type,
- QuicConnectionCloseFrame* frame) {
- return framer->ProcessIetfConnectionCloseFrame(reader, type, frame);
-}
-
-// static
-bool QuicFramerPeer::ProcessPathChallengeFrame(QuicFramer* framer,
- QuicDataReader* reader,
- QuicPathChallengeFrame* frame) {
- return framer->ProcessPathChallengeFrame(reader, frame);
-}
-
-// static
-bool QuicFramerPeer::ProcessPathResponseFrame(QuicFramer* framer,
- QuicDataReader* reader,
- QuicPathResponseFrame* frame) {
- return framer->ProcessPathResponseFrame(reader, frame);
-}
-
-// static
-bool QuicFramerPeer::AppendPathChallengeFrame(
- QuicFramer* framer,
- const QuicPathChallengeFrame& frame,
- QuicDataWriter* writer) {
- return framer->AppendPathChallengeFrame(frame, writer);
-}
-
-// static
-bool QuicFramerPeer::AppendPathResponseFrame(QuicFramer* framer,
- const QuicPathResponseFrame& frame,
- QuicDataWriter* writer) {
- return framer->AppendPathResponseFrame(frame, writer);
-}
-
-// static
-bool QuicFramerPeer::AppendIetfResetStreamFrame(QuicFramer* framer,
- const QuicRstStreamFrame& frame,
- QuicDataWriter* writer) {
- return framer->AppendIetfResetStreamFrame(frame, writer);
-}
-
-// static
-bool QuicFramerPeer::ProcessIetfResetStreamFrame(QuicFramer* framer,
- QuicDataReader* reader,
- QuicRstStreamFrame* frame) {
- return framer->ProcessIetfResetStreamFrame(reader, frame);
-}
-
-// static
-bool QuicFramerPeer::ProcessStopSendingFrame(
- QuicFramer* framer,
- QuicDataReader* reader,
- QuicStopSendingFrame* stop_sending_frame) {
- return framer->ProcessStopSendingFrame(reader, stop_sending_frame);
-}
-
-// static
-bool QuicFramerPeer::AppendStopSendingFrame(
- QuicFramer* framer,
- const QuicStopSendingFrame& stop_sending_frame,
- QuicDataWriter* writer) {
- return framer->AppendStopSendingFrame(stop_sending_frame, writer);
-}
-
-// static
-bool QuicFramerPeer::AppendMaxDataFrame(QuicFramer* framer,
- const QuicWindowUpdateFrame& frame,
- QuicDataWriter* writer) {
- return framer->AppendMaxDataFrame(frame, writer);
-}
-
-// static
-bool QuicFramerPeer::AppendMaxStreamDataFrame(
- QuicFramer* framer,
- const QuicWindowUpdateFrame& frame,
- QuicDataWriter* writer) {
- return framer->AppendMaxStreamDataFrame(frame, writer);
-}
-
-// static
-bool QuicFramerPeer::ProcessMaxDataFrame(QuicFramer* framer,
- QuicDataReader* reader,
- QuicWindowUpdateFrame* frame) {
- return framer->ProcessMaxDataFrame(reader, frame);
-}
-
-// static
-bool QuicFramerPeer::ProcessMaxStreamDataFrame(QuicFramer* framer,
- QuicDataReader* reader,
- QuicWindowUpdateFrame* frame) {
- return framer->ProcessMaxStreamDataFrame(reader, frame);
-}
-
-// static
-bool QuicFramerPeer::AppendMaxStreamsFrame(QuicFramer* framer,
- const QuicMaxStreamsFrame& frame,
- QuicDataWriter* writer) {
- return framer->AppendMaxStreamsFrame(frame, writer);
-}
-
-// static
-bool QuicFramerPeer::ProcessMaxStreamsFrame(QuicFramer* framer,
- QuicDataReader* reader,
- QuicMaxStreamsFrame* frame,
- uint64_t frame_type) {
- return framer->ProcessMaxStreamsFrame(reader, frame, frame_type);
-}
-
-// static
-bool QuicFramerPeer::AppendIetfBlockedFrame(QuicFramer* framer,
- const QuicBlockedFrame& frame,
- QuicDataWriter* writer) {
- return framer->AppendIetfBlockedFrame(frame, writer);
-}
-
-// static
-bool QuicFramerPeer::ProcessIetfBlockedFrame(QuicFramer* framer,
- QuicDataReader* reader,
- QuicBlockedFrame* frame) {
- return framer->ProcessIetfBlockedFrame(reader, frame);
-}
-
-// static
-bool QuicFramerPeer::AppendStreamBlockedFrame(QuicFramer* framer,
- const QuicBlockedFrame& frame,
- QuicDataWriter* writer) {
- return framer->AppendStreamBlockedFrame(frame, writer);
-}
-
-// static
-bool QuicFramerPeer::ProcessStreamBlockedFrame(QuicFramer* framer,
- QuicDataReader* reader,
- QuicBlockedFrame* frame) {
- return framer->ProcessStreamBlockedFrame(reader, frame);
-}
-
-// static
-bool QuicFramerPeer::AppendStreamsBlockedFrame(
- QuicFramer* framer,
- const QuicStreamsBlockedFrame& frame,
- QuicDataWriter* writer) {
- return framer->AppendStreamsBlockedFrame(frame, writer);
-}
-
-// static
-bool QuicFramerPeer::ProcessStreamsBlockedFrame(QuicFramer* framer,
- QuicDataReader* reader,
- QuicStreamsBlockedFrame* frame,
- uint64_t frame_type) {
- return framer->ProcessStreamsBlockedFrame(reader, frame, frame_type);
-}
-
-// static
-bool QuicFramerPeer::AppendNewConnectionIdFrame(
- QuicFramer* framer,
- const QuicNewConnectionIdFrame& frame,
- QuicDataWriter* writer) {
- return framer->AppendNewConnectionIdFrame(frame, writer);
-}
-
-// static
-bool QuicFramerPeer::ProcessNewConnectionIdFrame(
- QuicFramer* framer,
- QuicDataReader* reader,
- QuicNewConnectionIdFrame* frame) {
- return framer->ProcessNewConnectionIdFrame(reader, frame);
-}
-
-// static
-bool QuicFramerPeer::AppendRetireConnectionIdFrame(
- QuicFramer* framer,
- const QuicRetireConnectionIdFrame& frame,
- QuicDataWriter* writer) {
- return framer->AppendRetireConnectionIdFrame(frame, writer);
-}
-
-// static
-bool QuicFramerPeer::ProcessRetireConnectionIdFrame(
- QuicFramer* framer,
- QuicDataReader* reader,
- QuicRetireConnectionIdFrame* frame) {
- return framer->ProcessRetireConnectionIdFrame(reader, frame);
-}
-
-// static
void QuicFramerPeer::SwapCrypters(QuicFramer* framer1, QuicFramer* framer2) {
for (int i = ENCRYPTION_INITIAL; i < NUM_ENCRYPTION_LEVELS; i++) {
framer1->encrypter_[i].swap(framer2->encrypter_[i]);
@@ -334,16 +88,6 @@ QuicDecrypter* QuicFramerPeer::GetDecrypter(QuicFramer* framer,
}
// static
-size_t QuicFramerPeer::ComputeFrameLength(
- QuicFramer* framer,
- const QuicFrame& frame,
- bool last_frame_in_packet,
- QuicPacketNumberLength packet_number_length) {
- return framer->ComputeFrameLength(frame, last_frame_in_packet,
- packet_number_length);
-}
-
-// static
void QuicFramerPeer::SetFirstSendingPacketNumber(QuicFramer* framer,
uint64_t packet_number) {
*const_cast<QuicPacketNumber*>(&framer->first_sending_packet_number_) =
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_framer_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_framer_peer.h
index d462555a104..fdfa0df5450 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_framer_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_framer_peer.h
@@ -41,128 +41,6 @@ class QuicFramerPeer {
static QuicEncrypter* GetEncrypter(QuicFramer* framer, EncryptionLevel level);
static QuicDecrypter* GetDecrypter(QuicFramer* framer, EncryptionLevel level);
- // IETF defined frame append/process methods.
- static bool ProcessIetfStreamFrame(QuicFramer* framer,
- QuicDataReader* reader,
- uint8_t frame_type,
- QuicStreamFrame* frame);
- static bool AppendIetfStreamFrame(QuicFramer* framer,
- const QuicStreamFrame& frame,
- bool last_frame_in_packet,
- QuicDataWriter* writer);
- static bool ProcessCryptoFrame(QuicFramer* framer,
- QuicDataReader* reader,
- QuicCryptoFrame* frame);
- static bool AppendCryptoFrame(QuicFramer* framer,
- const QuicCryptoFrame& frame,
- QuicDataWriter* writer);
-
- static bool AppendIetfConnectionCloseFrame(
- QuicFramer* framer,
- const QuicConnectionCloseFrame& frame,
- QuicDataWriter* writer);
- static bool ProcessIetfConnectionCloseFrame(QuicFramer* framer,
- QuicDataReader* reader,
- QuicConnectionCloseType type,
- QuicConnectionCloseFrame* frame);
- static bool ProcessIetfAckFrame(QuicFramer* framer,
- QuicDataReader* reader,
- uint64_t frame_type,
- QuicAckFrame* ack_frame);
- static bool AppendIetfAckFrameAndTypeByte(QuicFramer* framer,
- const QuicAckFrame& frame,
- QuicDataWriter* writer);
- static size_t GetIetfAckFrameSize(QuicFramer* framer,
- const QuicAckFrame& frame);
- static bool AppendIetfResetStreamFrame(QuicFramer* framer,
- const QuicRstStreamFrame& frame,
- QuicDataWriter* writer);
- static bool ProcessIetfResetStreamFrame(QuicFramer* framer,
- QuicDataReader* reader,
- QuicRstStreamFrame* frame);
-
- static bool ProcessPathChallengeFrame(QuicFramer* framer,
- QuicDataReader* reader,
- QuicPathChallengeFrame* frame);
- static bool ProcessPathResponseFrame(QuicFramer* framer,
- QuicDataReader* reader,
- QuicPathResponseFrame* frame);
-
- static bool AppendPathChallengeFrame(QuicFramer* framer,
- const QuicPathChallengeFrame& frame,
- QuicDataWriter* writer);
- static bool AppendPathResponseFrame(QuicFramer* framer,
- const QuicPathResponseFrame& frame,
- QuicDataWriter* writer);
-
- static bool ProcessStopSendingFrame(QuicFramer* framer,
- QuicDataReader* reader,
- QuicStopSendingFrame* stop_sending_frame);
- static bool AppendStopSendingFrame(
- QuicFramer* framer,
- const QuicStopSendingFrame& stop_sending_frame,
- QuicDataWriter* writer);
-
- // Append/consume IETF-Format MAX_DATA and MAX_STREAM_DATA frames
- static bool AppendMaxDataFrame(QuicFramer* framer,
- const QuicWindowUpdateFrame& frame,
- QuicDataWriter* writer);
- static bool AppendMaxStreamDataFrame(QuicFramer* framer,
- const QuicWindowUpdateFrame& frame,
- QuicDataWriter* writer);
- static bool ProcessMaxDataFrame(QuicFramer* framer,
- QuicDataReader* reader,
- QuicWindowUpdateFrame* frame);
- static bool ProcessMaxStreamDataFrame(QuicFramer* framer,
- QuicDataReader* reader,
- QuicWindowUpdateFrame* frame);
- static bool AppendMaxStreamsFrame(QuicFramer* framer,
- const QuicMaxStreamsFrame& frame,
- QuicDataWriter* writer);
- static bool ProcessMaxStreamsFrame(QuicFramer* framer,
- QuicDataReader* reader,
- QuicMaxStreamsFrame* frame,
- uint64_t frame_type);
- static bool AppendIetfBlockedFrame(QuicFramer* framer,
- const QuicBlockedFrame& frame,
- QuicDataWriter* writer);
- static bool ProcessIetfBlockedFrame(QuicFramer* framer,
- QuicDataReader* reader,
- QuicBlockedFrame* frame);
-
- static bool AppendStreamBlockedFrame(QuicFramer* framer,
- const QuicBlockedFrame& frame,
- QuicDataWriter* writer);
- static bool ProcessStreamBlockedFrame(QuicFramer* framer,
- QuicDataReader* reader,
- QuicBlockedFrame* frame);
-
- static bool AppendStreamsBlockedFrame(QuicFramer* framer,
- const QuicStreamsBlockedFrame& frame,
- QuicDataWriter* writer);
- static bool ProcessStreamsBlockedFrame(QuicFramer* framer,
- QuicDataReader* reader,
- QuicStreamsBlockedFrame* frame,
- uint64_t frame_type);
-
- static bool AppendNewConnectionIdFrame(QuicFramer* framer,
- const QuicNewConnectionIdFrame& frame,
- QuicDataWriter* writer);
- static bool ProcessNewConnectionIdFrame(QuicFramer* framer,
- QuicDataReader* reader,
- QuicNewConnectionIdFrame* frame);
- static bool AppendRetireConnectionIdFrame(
- QuicFramer* framer,
- const QuicRetireConnectionIdFrame& frame,
- QuicDataWriter* writer);
- static bool ProcessRetireConnectionIdFrame(
- QuicFramer* framer,
- QuicDataReader* reader,
- QuicRetireConnectionIdFrame* frame);
- static size_t ComputeFrameLength(QuicFramer* framer,
- const QuicFrame& frame,
- bool last_frame_in_packet,
- QuicPacketNumberLength packet_number_length);
static void SetFirstSendingPacketNumber(QuicFramer* framer,
uint64_t packet_number);
static void SetExpectedServerConnectionIDLength(
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_interval_deque_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_interval_deque_peer.h
new file mode 100644
index 00000000000..e9a99ba02fc
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_interval_deque_peer.h
@@ -0,0 +1,35 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_TEST_TOOLS_QUIC_INTERVAL_DEQUE_PEER_H_
+#define QUICHE_QUIC_TEST_TOOLS_QUIC_INTERVAL_DEQUE_PEER_H_
+
+#include "net/third_party/quiche/src/quic/core/quic_interval_deque.h"
+
+namespace quic {
+
+namespace test {
+
+class QuicIntervalDequePeer {
+ public:
+ template <class T, class C>
+ static int32_t GetCachedIndex(QuicIntervalDeque<T, C>* interval_deque) {
+ if (!interval_deque->cached_index_.has_value()) {
+ return -1;
+ }
+ return interval_deque->cached_index_.value();
+ }
+
+ template <class T, class C>
+ static T* GetItem(QuicIntervalDeque<T, C>* interval_deque,
+ const std::size_t index) {
+ return &interval_deque->container_[index];
+ }
+};
+
+} // namespace test
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_TEST_TOOLS_QUIC_INTERVAL_DEQUE_PEER_H_
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.cc
index 7c8db91da7f..822401272e2 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.cc
@@ -144,5 +144,10 @@ QuicFramer* QuicPacketCreatorPeer::framer(QuicPacketCreator* creator) {
return creator->framer_;
}
+// static
+std::string QuicPacketCreatorPeer::GetRetryToken(QuicPacketCreator* creator) {
+ return creator->retry_token_;
+}
+
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.h
index 88587a212b5..bdadc2b9ad9 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.h
@@ -58,6 +58,7 @@ class QuicPacketCreatorPeer {
static EncryptionLevel GetEncryptionLevel(QuicPacketCreator* creator);
static QuicFramer* framer(QuicPacketCreator* creator);
+ static std::string GetRetryToken(QuicPacketCreator* creator);
};
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.cc
index cd8297a961e..f83189824d7 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.cc
@@ -102,26 +102,12 @@ void QuicSentPacketManagerPeer::MarkForRetransmission(
// static
QuicTime::Delta QuicSentPacketManagerPeer::GetRetransmissionDelay(
- const QuicSentPacketManager* sent_packet_manager,
- size_t consecutive_rto_count) {
- return sent_packet_manager->GetRetransmissionDelay(consecutive_rto_count);
-}
-
-// static
-QuicTime::Delta QuicSentPacketManagerPeer::GetRetransmissionDelay(
const QuicSentPacketManager* sent_packet_manager) {
return sent_packet_manager->GetRetransmissionDelay();
}
// static
QuicTime::Delta QuicSentPacketManagerPeer::GetTailLossProbeDelay(
- const QuicSentPacketManager* sent_packet_manager,
- size_t consecutive_tlp_count) {
- return sent_packet_manager->GetTailLossProbeDelay(consecutive_tlp_count);
-}
-
-// static
-QuicTime::Delta QuicSentPacketManagerPeer::GetTailLossProbeDelay(
const QuicSentPacketManager* sent_packet_manager) {
return sent_packet_manager->GetTailLossProbeDelay();
}
@@ -221,5 +207,12 @@ bool QuicSentPacketManagerPeer::AdaptiveTimeThresholdEnabled(
.use_adaptive_time_threshold();
}
+// static
+bool QuicSentPacketManagerPeer::UsePacketThresholdForRuntPackets(
+ QuicSentPacketManager* sent_packet_manager) {
+ return sent_packet_manager->uber_loss_algorithm_.general_loss_algorithms_[0]
+ .use_packet_threshold_for_runt_packets();
+}
+
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.h
index 3927189ee3f..d57c499c5a8 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.h
@@ -55,14 +55,8 @@ class QuicSentPacketManagerPeer {
TransmissionType transmission_type);
static QuicTime::Delta GetRetransmissionDelay(
- const QuicSentPacketManager* sent_packet_manager,
- size_t consecutive_rto_count);
- static QuicTime::Delta GetRetransmissionDelay(
const QuicSentPacketManager* sent_packet_manager);
static QuicTime::Delta GetTailLossProbeDelay(
- const QuicSentPacketManager* sent_packet_manager,
- size_t consecutive_tlp_count);
- static QuicTime::Delta GetTailLossProbeDelay(
const QuicSentPacketManager* sent_packet_manager);
static size_t GetNumRetransmittablePackets(
@@ -101,6 +95,9 @@ class QuicSentPacketManagerPeer {
static bool AdaptiveTimeThresholdEnabled(
QuicSentPacketManager* sent_packet_manager);
+
+ static bool UsePacketThresholdForRuntPackets(
+ QuicSentPacketManager* sent_packet_manager);
};
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_server_session_base_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_server_session_base_peer.h
index ab5b1f00f7f..a4feefebbe7 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_server_session_base_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_server_session_base_peer.h
@@ -19,7 +19,7 @@ class QuicServerSessionBasePeer {
return s->GetOrCreateStream(id);
}
static void SetCryptoStream(QuicServerSessionBase* s,
- QuicCryptoServerStream* crypto_stream) {
+ QuicCryptoServerStreamBase* crypto_stream) {
s->crypto_stream_.reset(crypto_stream);
}
static bool IsBandwidthResumptionEnabled(QuicServerSessionBase* s) {
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.cc
index f9e785d2c98..cbaf5d62be9 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.cc
@@ -75,10 +75,6 @@ void QuicSessionPeer::SetMaxOpenOutgoingStreams(QuicSession* session,
uint32_t max_streams) {
if (VersionHasIetfQuicFrames(session->transport_version())) {
QUIC_BUG << "SetmaxOpenOutgoingStreams deprecated for IETF QUIC";
- session->v99_streamid_manager_.SetMaxOpenOutgoingUnidirectionalStreams(
- max_streams);
- session->v99_streamid_manager_.SetMaxOpenOutgoingBidirectionalStreams(
- max_streams);
return;
}
session->stream_id_manager_.set_max_open_outgoing_streams(max_streams);
@@ -91,7 +87,7 @@ void QuicSessionPeer::SetMaxOpenOutgoingBidirectionalStreams(
DCHECK(VersionHasIetfQuicFrames(session->transport_version()))
<< "SetmaxOpenOutgoingBidirectionalStreams not supported for Google "
"QUIC";
- session->v99_streamid_manager_.SetMaxOpenOutgoingBidirectionalStreams(
+ session->v99_streamid_manager_.MaybeAllowNewOutgoingBidirectionalStreams(
max_streams);
}
// static
@@ -101,7 +97,7 @@ void QuicSessionPeer::SetMaxOpenOutgoingUnidirectionalStreams(
DCHECK(VersionHasIetfQuicFrames(session->transport_version()))
<< "SetmaxOpenOutgoingUnidirectionalStreams not supported for Google "
"QUIC";
- session->v99_streamid_manager_.SetMaxOpenOutgoingUnidirectionalStreams(
+ session->v99_streamid_manager_.MaybeAllowNewOutgoingUnidirectionalStreams(
max_streams);
}
@@ -237,5 +233,11 @@ void QuicSessionPeer::set_is_configured(QuicSession* session, bool value) {
session->is_configured_ = value;
}
+// static
+void QuicSessionPeer::SetPerspective(QuicSession* session,
+ Perspective perspective) {
+ session->perspective_ = perspective;
+}
+
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.h
index 446cd67b176..72caa9135b9 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.h
@@ -82,6 +82,7 @@ class QuicSessionPeer {
static PendingStream* GetPendingStream(QuicSession* session,
QuicStreamId stream_id);
static void set_is_configured(QuicSession* session, bool value);
+ static void SetPerspective(QuicSession* session, Perspective perspective);
};
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.cc
index cad9599f6fb..4730ef99e02 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.cc
@@ -32,9 +32,8 @@ void QuicSpdySessionPeer::SetHeadersStream(QuicSpdySession* session,
}
// static
-const spdy::SpdyFramer& QuicSpdySessionPeer::GetSpdyFramer(
- QuicSpdySession* session) {
- return session->spdy_framer_;
+spdy::SpdyFramer* QuicSpdySessionPeer::GetSpdyFramer(QuicSpdySession* session) {
+ return &session->spdy_framer_;
}
void QuicSpdySessionPeer::SetHpackEncoderDebugVisitor(
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h
index 1cfd45f252c..87eda44c0db 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h
@@ -28,7 +28,7 @@ class QuicSpdySessionPeer {
static QuicHeadersStream* GetHeadersStream(QuicSpdySession* session);
static void SetHeadersStream(QuicSpdySession* session,
QuicHeadersStream* headers_stream);
- static const spdy::SpdyFramer& GetSpdyFramer(QuicSpdySession* session);
+ static spdy::SpdyFramer* GetSpdyFramer(QuicSpdySession* session);
static void SetHpackEncoderDebugVisitor(
QuicSpdySession* session,
std::unique_ptr<QuicHpackDebugVisitor> visitor);
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_stream_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_stream_peer.h
index 6656df0acbb..9a216715c95 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_stream_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_stream_peer.h
@@ -8,7 +8,6 @@
#include "net/third_party/quiche/src/quic/core/quic_ack_listener_interface.h"
#include "net/third_party/quiche/src/quic/core/quic_interval_set.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h
index 9142348b771..f4b1de3165b 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h
@@ -10,7 +10,6 @@
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_stream_send_buffer.h"
#include "net/third_party/quiche/src/quic/core/quic_stream_sequencer.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_send_buffer_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_send_buffer_peer.cc
index 22e5e566c00..7257915ec2f 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_send_buffer_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_send_buffer_peer.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "net/third_party/quiche/src/quic/test_tools/quic_stream_send_buffer_peer.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_interval_deque_peer.h"
namespace quic {
@@ -18,22 +19,36 @@ void QuicStreamSendBufferPeer::SetStreamOffset(
// static
const BufferedSlice* QuicStreamSendBufferPeer::CurrentWriteSlice(
QuicStreamSendBuffer* send_buffer) {
- if (send_buffer->write_index_ == -1) {
+ auto wi = write_index(send_buffer);
+
+ if (wi == -1) {
return nullptr;
}
- return &send_buffer->buffered_slices_[send_buffer->write_index_];
+ return QuicIntervalDequePeer::GetItem(&send_buffer->interval_deque_, wi);
+}
+
+QuicStreamOffset QuicStreamSendBufferPeer::EndOffset(
+ QuicStreamSendBuffer* send_buffer) {
+ return send_buffer->current_end_offset_;
}
// static
QuicByteCount QuicStreamSendBufferPeer::TotalLength(
QuicStreamSendBuffer* send_buffer) {
QuicByteCount length = 0;
- for (const auto& slice : send_buffer->buffered_slices_) {
- length += slice.slice.length();
+ for (auto slice = send_buffer->interval_deque_.DataBegin();
+ slice != send_buffer->interval_deque_.DataEnd(); ++slice) {
+ length += slice->slice.length();
}
return length;
}
+// static
+int32_t QuicStreamSendBufferPeer::write_index(
+ QuicStreamSendBuffer* send_buffer) {
+ return QuicIntervalDequePeer::GetCachedIndex(&send_buffer->interval_deque_);
+}
+
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_send_buffer_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_send_buffer_peer.h
index 3adb173b91d..310cda91921 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_send_buffer_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_send_buffer_peer.h
@@ -19,11 +19,11 @@ class QuicStreamSendBufferPeer {
static const BufferedSlice* CurrentWriteSlice(
QuicStreamSendBuffer* send_buffer);
+ static QuicStreamOffset EndOffset(QuicStreamSendBuffer* send_buffer);
+
static QuicByteCount TotalLength(QuicStreamSendBuffer* send_buffer);
- static int32_t write_index(QuicStreamSendBuffer* send_buffer) {
- return send_buffer->write_index_;
- }
+ static int32_t write_index(QuicStreamSendBuffer* send_buffer);
};
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.cc
index ca5e95ab0f6..5ddc879af62 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.cc
@@ -20,7 +20,6 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_stack_trace.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_client_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
@@ -28,6 +27,8 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_stream_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/tools/quic_url.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
namespace test {
@@ -48,7 +49,7 @@ class RecordingProofVerifier : public ProofVerifier {
const uint16_t port,
const std::string& server_config,
QuicTransportVersion transport_version,
- QuicStringPiece chlo_hash,
+ quiche::QuicheStringPiece chlo_hash,
const std::vector<std::string>& certs,
const std::string& cert_sct,
const std::string& signature,
@@ -56,29 +57,11 @@ class RecordingProofVerifier : public ProofVerifier {
std::string* error_details,
std::unique_ptr<ProofVerifyDetails>* details,
std::unique_ptr<ProofVerifierCallback> callback) override {
- common_name_.clear();
- if (certs.empty()) {
- return QUIC_FAILURE;
+ QuicAsyncStatus process_certs_result = ProcessCerts(certs, cert_sct);
+ if (process_certs_result != QUIC_SUCCESS) {
+ return process_certs_result;
}
- const uint8_t* data;
- data = reinterpret_cast<const uint8_t*>(certs[0].data());
- bssl::UniquePtr<X509> cert(d2i_X509(nullptr, &data, certs[0].size()));
- if (!cert.get()) {
- return QUIC_FAILURE;
- }
-
- static const unsigned kMaxCommonNameLength = 256;
- char buf[kMaxCommonNameLength];
- X509_NAME* subject_name = X509_get_subject_name(cert.get());
- if (X509_NAME_get_text_by_NID(subject_name, NID_commonName, buf,
- sizeof(buf)) <= 0) {
- return QUIC_FAILURE;
- }
-
- common_name_ = buf;
- cert_sct_ = cert_sct;
-
if (!verifier_) {
return QUIC_SUCCESS;
}
@@ -91,14 +74,14 @@ class RecordingProofVerifier : public ProofVerifier {
QuicAsyncStatus VerifyCertChain(
const std::string& /*hostname*/,
- const std::vector<std::string>& /*certs*/,
+ const std::vector<std::string>& certs,
const std::string& /*ocsp_response*/,
- const std::string& /*cert_sct*/,
+ const std::string& cert_sct,
const ProofVerifyContext* /*context*/,
std::string* /*error_details*/,
std::unique_ptr<ProofVerifyDetails>* /*details*/,
std::unique_ptr<ProofVerifierCallback> /*callback*/) override {
- return QUIC_SUCCESS;
+ return ProcessCerts(certs, cert_sct);
}
std::unique_ptr<ProofVerifyContext> CreateDefaultContext() override {
@@ -110,6 +93,33 @@ class RecordingProofVerifier : public ProofVerifier {
const std::string& cert_sct() const { return cert_sct_; }
private:
+ QuicAsyncStatus ProcessCerts(const std::vector<std::string>& certs,
+ const std::string& cert_sct) {
+ common_name_.clear();
+ if (certs.empty()) {
+ return QUIC_FAILURE;
+ }
+
+ const uint8_t* data;
+ data = reinterpret_cast<const uint8_t*>(certs[0].data());
+ bssl::UniquePtr<X509> cert(d2i_X509(nullptr, &data, certs[0].size()));
+ if (!cert.get()) {
+ return QUIC_FAILURE;
+ }
+
+ static const unsigned kMaxCommonNameLength = 256;
+ char buf[kMaxCommonNameLength];
+ X509_NAME* subject_name = X509_get_subject_name(cert.get());
+ if (X509_NAME_get_text_by_NID(subject_name, NID_commonName, buf,
+ sizeof(buf)) <= 0) {
+ return QUIC_FAILURE;
+ }
+
+ common_name_ = buf;
+ cert_sct_ = cert_sct;
+ return QUIC_SUCCESS;
+ }
+
std::unique_ptr<ProofVerifier> verifier_;
std::string common_name_;
std::string cert_sct_;
@@ -399,7 +409,7 @@ void QuicTestClient::SendRequestsAndWaitForResponses(
ssize_t QuicTestClient::GetOrCreateStreamAndSendRequest(
const spdy::SpdyHeaderBlock* headers,
- QuicStringPiece body,
+ quiche::QuicheStringPiece body,
bool fin,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
if (headers) {
@@ -443,18 +453,18 @@ ssize_t QuicTestClient::GetOrCreateStreamAndSendRequest(
}
ssize_t QuicTestClient::SendMessage(const spdy::SpdyHeaderBlock& headers,
- QuicStringPiece body) {
+ quiche::QuicheStringPiece body) {
return SendMessage(headers, body, /*fin=*/true);
}
ssize_t QuicTestClient::SendMessage(const spdy::SpdyHeaderBlock& headers,
- QuicStringPiece body,
+ quiche::QuicheStringPiece body,
bool fin) {
return SendMessage(headers, body, fin, /*flush=*/true);
}
ssize_t QuicTestClient::SendMessage(const spdy::SpdyHeaderBlock& headers,
- QuicStringPiece body,
+ quiche::QuicheStringPiece body,
bool fin,
bool flush) {
// Always force creation of a stream for SendMessage.
@@ -476,7 +486,8 @@ ssize_t QuicTestClient::SendData(
const std::string& data,
bool last_data,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
- return GetOrCreateStreamAndSendRequest(nullptr, QuicStringPiece(data),
+ return GetOrCreateStreamAndSendRequest(nullptr,
+ quiche::QuicheStringPiece(data),
last_data, std::move(ack_listener));
}
@@ -670,8 +681,8 @@ bool QuicTestClient::WaitUntil(int timeout_ms, std::function<bool()> trigger) {
return true;
}
-ssize_t QuicTestClient::Send(const void* buffer, size_t size) {
- return SendData(std::string(static_cast<const char*>(buffer), size), false);
+ssize_t QuicTestClient::Send(quiche::QuicheStringPiece data) {
+ return SendData(std::string(data), false);
}
bool QuicTestClient::response_headers_complete() const {
@@ -845,7 +856,7 @@ void QuicTestClient::WaitForWriteToFlush() {
QuicTestClient::TestClientDataToResend::TestClientDataToResend(
std::unique_ptr<spdy::SpdyHeaderBlock> headers,
- QuicStringPiece body,
+ quiche::QuicheStringPiece body,
bool fin,
QuicTestClient* test_client,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener)
@@ -901,8 +912,8 @@ bool QuicTestClient::PopulateHeaderBlockFromUrl(
const std::string& uri,
spdy::SpdyHeaderBlock* headers) {
std::string url;
- if (QuicTextUtils::StartsWith(uri, "https://") ||
- QuicTextUtils::StartsWith(uri, "http://")) {
+ if (quiche::QuicheTextUtils::StartsWith(uri, "https://") ||
+ quiche::QuicheTextUtils::StartsWith(uri, "http://")) {
url = uri;
} else if (uri[0] == '/') {
url = "https://" + client_->server_id().host() + uri;
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.h
index cd5b09f7d77..f74974f4231 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.h
@@ -16,9 +16,9 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_epoll.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/tools/quic_client.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -127,19 +127,19 @@ class QuicTestClient : public QuicSpdyStream::Visitor,
// Sends a request containing |headers| and |body| and returns the number of
// bytes sent (the size of the serialized request headers and body).
ssize_t SendMessage(const spdy::SpdyHeaderBlock& headers,
- QuicStringPiece body);
+ quiche::QuicheStringPiece body);
// Sends a request containing |headers| and |body| with the fin bit set to
// |fin| and returns the number of bytes sent (the size of the serialized
// request headers and body).
ssize_t SendMessage(const spdy::SpdyHeaderBlock& headers,
- QuicStringPiece body,
+ quiche::QuicheStringPiece body,
bool fin);
// Sends a request containing |headers| and |body| with the fin bit set to
// |fin| and returns the number of bytes sent (the size of the serialized
// request headers and body). If |flush| is true, will wait for the message to
// be flushed before returning.
ssize_t SendMessage(const spdy::SpdyHeaderBlock& headers,
- QuicStringPiece body,
+ quiche::QuicheStringPiece body,
bool fin,
bool flush);
// Sends a request containing |headers| and |body|, waits for the response,
@@ -156,7 +156,7 @@ class QuicTestClient : public QuicSpdyStream::Visitor,
QuicSocketAddress local_address() const;
void ClearPerRequestState();
bool WaitUntil(int timeout_ms, std::function<bool()> trigger);
- ssize_t Send(const void* buffer, size_t size);
+ ssize_t Send(quiche::QuicheStringPiece data);
bool connected() const;
bool buffer_body() const;
void set_buffer_body(bool buffer_body);
@@ -249,7 +249,7 @@ class QuicTestClient : public QuicSpdyStream::Visitor,
// null, only the body will be sent on the stream.
ssize_t GetOrCreateStreamAndSendRequest(
const spdy::SpdyHeaderBlock* headers,
- QuicStringPiece body,
+ quiche::QuicheStringPiece body,
bool fin,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
@@ -324,7 +324,7 @@ class QuicTestClient : public QuicSpdyStream::Visitor,
public:
TestClientDataToResend(
std::unique_ptr<spdy::SpdyHeaderBlock> headers,
- QuicStringPiece body,
+ quiche::QuicheStringPiece body,
bool fin,
QuicTestClient* test_client,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_server.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_server.cc
index 81b54d47260..d85fe1fdeac 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_server.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_server.cc
@@ -12,6 +12,7 @@
#include "net/third_party/quiche/src/quic/tools/quic_simple_crypto_server_stream_helper.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_server_session.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -24,7 +25,7 @@ class CustomStreamSession : public QuicSimpleServerSession {
const ParsedQuicVersionVector& supported_versions,
QuicConnection* connection,
QuicSession::Visitor* visitor,
- QuicCryptoServerStream::Helper* helper,
+ QuicCryptoServerStreamBase::Helper* helper,
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache,
QuicTestServer::StreamFactory* stream_factory,
@@ -54,7 +55,7 @@ class CustomStreamSession : public QuicSimpleServerSession {
return QuicSimpleServerSession::CreateIncomingStream(id);
}
- QuicCryptoServerStreamBase* CreateQuicCryptoServerStream(
+ std::unique_ptr<QuicCryptoServerStreamBase> CreateQuicCryptoServerStream(
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache) override {
if (crypto_stream_factory_) {
@@ -76,7 +77,7 @@ class QuicTestDispatcher : public QuicSimpleDispatcher {
const QuicCryptoServerConfig* crypto_config,
QuicVersionManager* version_manager,
std::unique_ptr<QuicConnectionHelperInterface> helper,
- std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
+ std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
std::unique_ptr<QuicAlarmFactory> alarm_factory,
QuicSimpleServerBackend* quic_simple_server_backend,
uint8_t expected_server_connection_id_length)
@@ -92,10 +93,10 @@ class QuicTestDispatcher : public QuicSimpleDispatcher {
stream_factory_(nullptr),
crypto_stream_factory_(nullptr) {}
- QuicServerSessionBase* CreateQuicSession(
+ std::unique_ptr<QuicSession> CreateQuicSession(
QuicConnectionId id,
const QuicSocketAddress& client,
- QuicStringPiece alpn,
+ quiche::QuicheStringPiece alpn,
const ParsedQuicVersion& version) override {
QuicReaderMutexLock lock(&factory_lock_);
if (session_factory_ == nullptr && stream_factory_ == nullptr &&
@@ -107,9 +108,9 @@ class QuicTestDispatcher : public QuicSimpleDispatcher {
/* owns_writer= */ false, Perspective::IS_SERVER,
ParsedQuicVersionVector{version});
- QuicServerSessionBase* session = nullptr;
+ std::unique_ptr<QuicServerSessionBase> session;
if (stream_factory_ != nullptr || crypto_stream_factory_ != nullptr) {
- session = new CustomStreamSession(
+ session = std::make_unique<CustomStreamSession>(
config(), GetSupportedVersions(), connection, this, session_helper(),
crypto_config(), compressed_certs_cache(), stream_factory_,
crypto_stream_factory_, server_backend());
@@ -190,7 +191,7 @@ QuicDispatcher* QuicTestServer::CreateQuicDispatcher() {
&config(), &crypto_config(), version_manager(),
std::make_unique<QuicEpollConnectionHelper>(epoll_server(),
QuicAllocator::BUFFER_POOL),
- std::unique_ptr<QuicCryptoServerStream::Helper>(
+ std::unique_ptr<QuicCryptoServerStreamBase::Helper>(
new QuicSimpleCryptoServerStreamHelper()),
std::make_unique<QuicEpollAlarmFactory>(epoll_server()), server_backend(),
expected_server_connection_id_length());
@@ -216,7 +217,7 @@ ImmediateGoAwaySession::ImmediateGoAwaySession(
const QuicConfig& config,
QuicConnection* connection,
QuicSession::Visitor* visitor,
- QuicCryptoServerStream::Helper* helper,
+ QuicCryptoServerStreamBase::Helper* helper,
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache,
QuicSimpleServerBackend* quic_simple_server_backend)
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_server.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_server.h
index f9b677ab04a..d88337a623e 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_server.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_server.h
@@ -27,11 +27,11 @@ class QuicTestServer : public QuicServer {
virtual ~SessionFactory() {}
// Returns a new session owned by the caller.
- virtual QuicServerSessionBase* CreateSession(
+ virtual std::unique_ptr<QuicServerSessionBase> CreateSession(
const QuicConfig& config,
QuicConnection* connection,
QuicSession::Visitor* visitor,
- QuicCryptoServerStream::Helper* helper,
+ QuicCryptoServerStreamBase::Helper* helper,
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache,
QuicSimpleServerBackend* quic_simple_server_backend) = 0;
@@ -54,7 +54,7 @@ class QuicTestServer : public QuicServer {
virtual ~CryptoStreamFactory() {}
// Returns a new QuicCryptoServerStreamBase owned by the caller
- virtual QuicCryptoServerStreamBase* CreateCryptoStream(
+ virtual std::unique_ptr<QuicCryptoServerStreamBase> CreateCryptoStream(
const QuicCryptoServerConfig* crypto_config,
QuicServerSessionBase* session) = 0;
};
@@ -97,7 +97,7 @@ class ImmediateGoAwaySession : public QuicSimpleServerSession {
ImmediateGoAwaySession(const QuicConfig& config,
QuicConnection* connection,
QuicSession::Visitor* visitor,
- QuicCryptoServerStream::Helper* helper,
+ QuicCryptoServerStreamBase::Helper* helper,
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache,
QuicSimpleServerBackend* quic_simple_server_backend);
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.cc
index 4b10826660b..d8a043611d1 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.cc
@@ -17,17 +17,21 @@
#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
+#include "net/third_party/quiche/src/quic/core/quic_buffer_allocator.h"
#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
#include "net/third_party/quiche/src/quic/core/quic_framer.h"
#include "net/third_party/quiche/src/quic/core/quic_packet_creator.h"
+#include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "net/third_party/quiche/src/spdy/core/spdy_frame_builder.h"
using testing::_;
@@ -107,6 +111,22 @@ QuicAckFrame MakeAckFrameWithAckBlocks(size_t num_ack_blocks,
return ack;
}
+QuicAckFrame MakeAckFrameWithGaps(uint64_t gap_size,
+ size_t max_num_gaps,
+ uint64_t largest_acked) {
+ QuicAckFrame ack;
+ ack.largest_acked = QuicPacketNumber(largest_acked);
+ ack.packets.Add(QuicPacketNumber(largest_acked));
+ for (size_t i = 0; i < max_num_gaps; ++i) {
+ if (largest_acked <= gap_size) {
+ break;
+ }
+ largest_acked -= gap_size;
+ ack.packets.Add(QuicPacketNumber(largest_acked));
+ }
+ return ack;
+}
+
EncryptionLevel HeaderToEncryptionLevel(const QuicPacketHeader& header) {
if (header.form == IETF_QUIC_SHORT_HEADER_PACKET) {
return ENCRYPTION_FORWARD_SECURE;
@@ -160,11 +180,11 @@ std::unique_ptr<QuicPacket> BuildUnsizedDataPacket(
header.length_length);
}
-std::string Sha1Hash(QuicStringPiece data) {
+std::string Sha1Hash(quiche::QuicheStringPiece data) {
char buffer[SHA_DIGEST_LENGTH];
SHA1(reinterpret_cast<const uint8_t*>(data.data()), data.size(),
reinterpret_cast<uint8_t*>(buffer));
- return std::string(buffer, QUIC_ARRAYSIZE(buffer));
+ return std::string(buffer, QUICHE_ARRAYSIZE(buffer));
}
bool ClearControlFrame(const QuicFrame& frame) {
@@ -383,6 +403,11 @@ bool NoOpFramerVisitor::OnMessageFrame(const QuicMessageFrame& /*frame*/) {
return true;
}
+bool NoOpFramerVisitor::OnHandshakeDoneFrame(
+ const QuicHandshakeDoneFrame& /*frame*/) {
+ return true;
+}
+
bool NoOpFramerVisitor::IsValidStatelessResetToken(
QuicUint128 /*token*/) const {
return false;
@@ -548,12 +573,12 @@ MockQuicSession::MockQuicSession(QuicConnection* connection,
if (create_mock_crypto_stream) {
crypto_stream_ = std::make_unique<MockQuicCryptoStream>(this);
}
- ON_CALL(*this, WritevData(_, _, _, _, _))
+ ON_CALL(*this, WritevData(_, _, _, _, _, _))
.WillByDefault(testing::Return(QuicConsumedData(0, false)));
}
MockQuicSession::~MockQuicSession() {
- delete connection();
+ DeleteConnection();
}
QuicCryptoStream* MockQuicSession::GetMutableCryptoStream() {
@@ -568,14 +593,17 @@ void MockQuicSession::SetCryptoStream(QuicCryptoStream* crypto_stream) {
crypto_stream_.reset(crypto_stream);
}
-// static
-QuicConsumedData MockQuicSession::ConsumeData(QuicStream* stream,
- QuicStreamId /*id*/,
- size_t write_length,
- QuicStreamOffset offset,
- StreamSendingState state) {
+QuicConsumedData MockQuicSession::ConsumeData(
+ QuicStreamId id,
+ size_t write_length,
+ QuicStreamOffset offset,
+ StreamSendingState state,
+ TransmissionType /*type*/,
+ quiche::QuicheOptional<EncryptionLevel> /*level*/) {
if (write_length > 0) {
auto buf = std::make_unique<char[]>(write_length);
+ QuicStream* stream = GetOrCreateStream(id);
+ DCHECK(stream);
QuicDataWriter writer(write_length, buf.get(), quiche::HOST_BYTE_ORDER);
stream->WriteStreamData(offset, write_length, &writer);
} else {
@@ -593,7 +621,7 @@ bool MockQuicCryptoStream::encryption_established() const {
return false;
}
-bool MockQuicCryptoStream::handshake_confirmed() const {
+bool MockQuicCryptoStream::one_rtt_keys_available() const {
return false;
}
@@ -619,12 +647,12 @@ MockQuicSpdySession::MockQuicSpdySession(QuicConnection* connection,
crypto_stream_ = std::make_unique<MockQuicCryptoStream>(this);
}
- ON_CALL(*this, WritevData(_, _, _, _, _))
+ ON_CALL(*this, WritevData(_, _, _, _, _, _))
.WillByDefault(testing::Return(QuicConsumedData(0, false)));
}
MockQuicSpdySession::~MockQuicSpdySession() {
- delete connection();
+ DeleteConnection();
}
QuicCryptoStream* MockQuicSpdySession::GetMutableCryptoStream() {
@@ -639,6 +667,25 @@ void MockQuicSpdySession::SetCryptoStream(QuicCryptoStream* crypto_stream) {
crypto_stream_.reset(crypto_stream);
}
+QuicConsumedData MockQuicSpdySession::ConsumeData(
+ QuicStreamId id,
+ size_t write_length,
+ QuicStreamOffset offset,
+ StreamSendingState state,
+ TransmissionType /*type*/,
+ quiche::QuicheOptional<EncryptionLevel> /*level*/) {
+ if (write_length > 0) {
+ auto buf = std::make_unique<char[]>(write_length);
+ QuicStream* stream = GetOrCreateStream(id);
+ DCHECK(stream);
+ QuicDataWriter writer(write_length, buf.get(), quiche::HOST_BYTE_ORDER);
+ stream->WriteStreamData(offset, write_length, &writer);
+ } else {
+ DCHECK(state != NO_FIN);
+ }
+ return QuicConsumedData(write_length, state != NO_FIN);
+}
+
TestQuicSpdyServerSession::TestQuicSpdyServerSession(
QuicConnection* connection,
const QuicConfig& config,
@@ -657,31 +704,25 @@ TestQuicSpdyServerSession::TestQuicSpdyServerSession(
}
TestQuicSpdyServerSession::~TestQuicSpdyServerSession() {
- delete connection();
+ DeleteConnection();
}
-QuicCryptoServerStreamBase*
+std::unique_ptr<QuicCryptoServerStreamBase>
TestQuicSpdyServerSession::CreateQuicCryptoServerStream(
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache) {
- return new QuicCryptoServerStream(crypto_config, compressed_certs_cache, this,
- &helper_);
+ return CreateCryptoServerStream(crypto_config, compressed_certs_cache, this,
+ &helper_);
}
-void TestQuicSpdyServerSession::OnCryptoHandshakeEvent(
- CryptoHandshakeEvent event) {
- QuicSession::OnCryptoHandshakeEvent(event);
-}
-
-QuicCryptoServerStream* TestQuicSpdyServerSession::GetMutableCryptoStream() {
- return static_cast<QuicCryptoServerStream*>(
- QuicServerSessionBase::GetMutableCryptoStream());
+QuicCryptoServerStreamBase*
+TestQuicSpdyServerSession::GetMutableCryptoStream() {
+ return QuicServerSessionBase::GetMutableCryptoStream();
}
-const QuicCryptoServerStream* TestQuicSpdyServerSession::GetCryptoStream()
+const QuicCryptoServerStreamBase* TestQuicSpdyServerSession::GetCryptoStream()
const {
- return static_cast<const QuicCryptoServerStream*>(
- QuicServerSessionBase::GetCryptoStream());
+ return QuicServerSessionBase::GetCryptoStream();
}
TestQuicSpdyClientSession::TestQuicSpdyClientSession(
@@ -706,11 +747,6 @@ bool TestQuicSpdyClientSession::IsAuthorized(const std::string& /*authority*/) {
return true;
}
-void TestQuicSpdyClientSession::OnCryptoHandshakeEvent(
- CryptoHandshakeEvent event) {
- QuicSession::OnCryptoHandshakeEvent(event);
-}
-
QuicCryptoClientStream* TestQuicSpdyClientSession::GetMutableCryptoStream() {
return crypto_stream_.get();
}
@@ -748,7 +784,12 @@ MockPacketWriter::MockPacketWriter() {
MockPacketWriter::~MockPacketWriter() {}
-MockSendAlgorithm::MockSendAlgorithm() {}
+MockSendAlgorithm::MockSendAlgorithm() {
+ ON_CALL(*this, PacingRate(_))
+ .WillByDefault(testing::Return(QuicBandwidth::Zero()));
+ ON_CALL(*this, BandwidthEstimate())
+ .WillByDefault(testing::Return(QuicBandwidth::Zero()));
+}
MockSendAlgorithm::~MockSendAlgorithm() {}
@@ -764,50 +805,6 @@ MockNetworkChangeVisitor::MockNetworkChangeVisitor() {}
MockNetworkChangeVisitor::~MockNetworkChangeVisitor() {}
-namespace {
-
-std::string HexDumpWithMarks(const char* data,
- int length,
- const bool* marks,
- int mark_length) {
- static const char kHexChars[] = "0123456789abcdef";
- static const int kColumns = 4;
-
- const int kSizeLimit = 1024;
- if (length > kSizeLimit || mark_length > kSizeLimit) {
- QUIC_LOG(ERROR) << "Only dumping first " << kSizeLimit << " bytes.";
- length = std::min(length, kSizeLimit);
- mark_length = std::min(mark_length, kSizeLimit);
- }
-
- std::string hex;
- for (const char* row = data; length > 0;
- row += kColumns, length -= kColumns) {
- for (const char* p = row; p < row + 4; ++p) {
- if (p < row + length) {
- const bool mark =
- (marks && (p - data) < mark_length && marks[p - data]);
- hex += mark ? '*' : ' ';
- hex += kHexChars[(*p & 0xf0) >> 4];
- hex += kHexChars[*p & 0x0f];
- hex += mark ? '*' : ' ';
- } else {
- hex += " ";
- }
- }
- hex = hex + " ";
-
- for (const char* p = row; p < row + 4 && p < row + length; ++p) {
- hex += (*p >= 0x20 && *p <= 0x7f) ? (*p) : '.';
- }
-
- hex = hex + '\n';
- }
- return hex;
-}
-
-} // namespace
-
QuicIpAddress TestPeerIPAddress() {
return QuicIpAddress::Loopback4();
}
@@ -820,14 +817,6 @@ ParsedQuicVersion QuicVersionMin() {
return AllSupportedVersions().back();
}
-QuicTransportVersion QuicTransportVersionMax() {
- return AllSupportedTransportVersions().front();
-}
-
-QuicTransportVersion QuicTransportVersionMin() {
- return AllSupportedTransportVersions().back();
-}
-
QuicEncryptedPacket* ConstructEncryptedPacket(
QuicConnectionId destination_connection_id,
QuicConnectionId source_connection_id,
@@ -921,6 +910,7 @@ QuicEncryptedPacket* ConstructEncryptedPacket(
if (!versions) {
versions = &supported_versions;
}
+ EXPECT_FALSE(versions->empty());
ParsedQuicVersion version = (*versions)[0];
if (QuicVersionHasLongHeaderLengths(version.transport_version) &&
version_flag) {
@@ -940,7 +930,7 @@ QuicEncryptedPacket* ConstructEncryptedPacket(
if (!QuicVersionUsesCryptoFrames(version.transport_version)) {
QuicFrame frame(
QuicStreamFrame(QuicUtils::GetCryptoStreamId(version.transport_version),
- false, 0, QuicStringPiece(data)));
+ false, 0, quiche::QuicheStringPiece(data)));
frames.push_back(frame);
} else {
QuicFrame frame(new QuicCryptoFrame(level, 0, data));
@@ -1008,7 +998,8 @@ QuicEncryptedPacket* ConstructMisFramedEncryptedPacket(
header.retry_token_length_length = VARIABLE_LENGTH_INTEGER_LENGTH_1;
header.length_length = VARIABLE_LENGTH_INTEGER_LENGTH_2;
}
- QuicFrame frame(QuicStreamFrame(1, false, 0, QuicStringPiece(data)));
+ QuicFrame frame(
+ QuicStreamFrame(1, false, 0, quiche::QuicheStringPiece(data)));
QuicFrames frames;
frames.push_back(frame);
QuicFramer framer({version}, QuicTime::Zero(), perspective,
@@ -1048,37 +1039,6 @@ QuicEncryptedPacket* ConstructMisFramedEncryptedPacket(
return new QuicEncryptedPacket(buffer, encrypted_length, true);
}
-void CompareCharArraysWithHexError(const std::string& description,
- const char* actual,
- const int actual_len,
- const char* expected,
- const int expected_len) {
- EXPECT_EQ(actual_len, expected_len);
- const int min_len = std::min(actual_len, expected_len);
- const int max_len = std::max(actual_len, expected_len);
- std::unique_ptr<bool[]> marks(new bool[max_len]);
- bool identical = (actual_len == expected_len);
- for (int i = 0; i < min_len; ++i) {
- if (actual[i] != expected[i]) {
- marks[i] = true;
- identical = false;
- } else {
- marks[i] = false;
- }
- }
- for (int i = min_len; i < max_len; ++i) {
- marks[i] = true;
- }
- if (identical)
- return;
- ADD_FAILURE() << "Description:\n"
- << description << "\n\nExpected:\n"
- << HexDumpWithMarks(expected, expected_len, marks.get(),
- max_len)
- << "\nActual:\n"
- << HexDumpWithMarks(actual, actual_len, marks.get(), max_len);
-}
-
QuicConfig DefaultQuicConfig() {
QuicConfig config;
config.SetInitialMaxStreamDataBytesIncomingBidirectionalToSend(
@@ -1091,7 +1051,7 @@ QuicConfig DefaultQuicConfig() {
kInitialStreamFlowControlWindowForTest);
config.SetInitialSessionFlowControlWindowToSend(
kInitialSessionFlowControlWindowForTest);
- QuicConfigPeer::SetReceivedMaxIncomingBidirectionalStreams(
+ QuicConfigPeer::SetReceivedMaxBidirectionalStreams(
&config, kDefaultMaxStreamsPerConnection);
// Default enable NSTP.
// This is unnecessary for versions > 44
@@ -1104,13 +1064,6 @@ QuicConfig DefaultQuicConfig() {
return config;
}
-QuicTransportVersionVector SupportedTransportVersions(
- QuicTransportVersion version) {
- QuicTransportVersionVector versions;
- versions.push_back(version);
- return versions;
-}
-
ParsedQuicVersionVector SupportedVersions(ParsedQuicVersion version) {
ParsedQuicVersionVector versions;
versions.push_back(version);
@@ -1234,7 +1187,7 @@ StreamType DetermineStreamType(QuicStreamId id,
}
QuicMemSliceSpan MakeSpan(QuicBufferAllocator* allocator,
- QuicStringPiece message_data,
+ quiche::QuicheStringPiece message_data,
QuicMemSliceStorage* storage) {
if (message_data.length() == 0) {
*storage =
@@ -1247,5 +1200,12 @@ QuicMemSliceSpan MakeSpan(QuicBufferAllocator* allocator,
return storage->ToSpan();
}
+QuicMemSlice MemSliceFromString(quiche::QuicheStringPiece data) {
+ static SimpleBufferAllocator* allocator = new SimpleBufferAllocator();
+ QuicUniqueBufferPtr buffer = MakeUniqueBuffer(allocator, data.size());
+ memcpy(buffer.get(), data.data(), data.size());
+ return QuicMemSlice(std::move(buffer), data.size());
+}
+
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.h
index 7919ef30299..e30f484b067 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.h
@@ -17,18 +17,20 @@
#include "net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h"
#include "net/third_party/quiche/src/quic/core/http/quic_client_push_promise_index.h"
#include "net/third_party/quiche/src/quic/core/http/quic_server_session_base.h"
+#include "net/third_party/quiche/src/quic/core/http/quic_spdy_session.h"
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
#include "net/third_party/quiche/src/quic/core/quic_framer.h"
#include "net/third_party/quiche/src/quic/core/quic_packet_writer.h"
#include "net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h"
#include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice_storage.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_quic_session_visitor.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_random.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -63,14 +65,6 @@ ParsedQuicVersion QuicVersionMax();
// Lower limit on versions we support.
ParsedQuicVersion QuicVersionMin();
-// Upper limit on versions we support.
-// TODO(nharper): Remove this function when it is no longer used.
-QuicTransportVersion QuicTransportVersionMax();
-
-// Lower limit on versions we support.
-// TODO(nharper): Remove this function when it is no longer used.
-QuicTransportVersion QuicTransportVersionMin();
-
// Create an encrypted packet for testing.
// If versions == nullptr, uses &AllSupportedVersions().
// Note that the packet is encrypted with NullEncrypter, so to decrypt the
@@ -165,19 +159,9 @@ QuicEncryptedPacket* ConstructMisFramedEncryptedPacket(
ParsedQuicVersion version,
Perspective perspective);
-void CompareCharArraysWithHexError(const std::string& description,
- const char* actual,
- const int actual_len,
- const char* expected,
- const int expected_len);
-
// Returns QuicConfig set to default values.
QuicConfig DefaultQuicConfig();
-// Returns a version vector consisting of |version|.
-QuicTransportVersionVector SupportedTransportVersions(
- QuicTransportVersion version);
-
ParsedQuicVersionVector SupportedVersions(ParsedQuicVersion version);
struct QuicAckBlock {
@@ -205,6 +189,12 @@ QuicAckFrame InitAckFrame(QuicPacketNumber largest_acked);
QuicAckFrame MakeAckFrameWithAckBlocks(size_t num_ack_blocks,
uint64_t least_unacked);
+// Testing convenice method to construct a QuicAckFrame with |largest_acked|,
+// ack blocks of width 1 packet and |gap_size|.
+QuicAckFrame MakeAckFrameWithGaps(uint64_t gap_size,
+ size_t max_num_gaps,
+ uint64_t largest_acked);
+
// Returns the encryption level that corresponds to the header type in
// |header|. If the header is for GOOGLE_QUIC_PACKET instead of an
// IETF-invariants packet, this function returns ENCRYPTION_INITIAL.
@@ -225,7 +215,7 @@ std::unique_ptr<QuicPacket> BuildUnsizedDataPacket(
size_t packet_size);
// Compute SHA-1 hash of the supplied std::string.
-std::string Sha1Hash(QuicStringPiece data);
+std::string Sha1Hash(quiche::QuicheStringPiece data);
// Delete |frame| and return true.
bool ClearControlFrame(const QuicFrame& frame);
@@ -268,10 +258,12 @@ class MockFramerVisitor : public QuicFramerVisitorInterface {
MOCK_METHOD1(OnPublicResetPacket, void(const QuicPublicResetPacket& header));
MOCK_METHOD1(OnVersionNegotiationPacket,
void(const QuicVersionNegotiationPacket& packet));
- MOCK_METHOD3(OnRetryPacket,
+ MOCK_METHOD5(OnRetryPacket,
void(QuicConnectionId original_connection_id,
QuicConnectionId new_connection_id,
- QuicStringPiece retry_token));
+ quiche::QuicheStringPiece retry_token,
+ quiche::QuicheStringPiece retry_integrity_tag,
+ quiche::QuicheStringPiece retry_without_tag));
// The constructor sets this up to return true by default.
MOCK_METHOD1(OnUnauthenticatedHeader, bool(const QuicPacketHeader& header));
// The constructor sets this up to return true by default.
@@ -311,6 +303,7 @@ class MockFramerVisitor : public QuicFramerVisitorInterface {
MOCK_METHOD1(OnWindowUpdateFrame, bool(const QuicWindowUpdateFrame& frame));
MOCK_METHOD1(OnBlockedFrame, bool(const QuicBlockedFrame& frame));
MOCK_METHOD1(OnMessageFrame, bool(const QuicMessageFrame& frame));
+ MOCK_METHOD1(OnHandshakeDoneFrame, bool(const QuicHandshakeDoneFrame& frame));
MOCK_METHOD0(OnPacketComplete, void());
MOCK_CONST_METHOD1(IsValidStatelessResetToken, bool(QuicUint128));
MOCK_METHOD1(OnAuthenticatedIetfStatelessResetPacket,
@@ -330,7 +323,10 @@ class NoOpFramerVisitor : public QuicFramerVisitorInterface {
const QuicVersionNegotiationPacket& /*packet*/) override {}
void OnRetryPacket(QuicConnectionId /*original_connection_id*/,
QuicConnectionId /*new_connection_id*/,
- QuicStringPiece /*retry_token*/) override {}
+ quiche::QuicheStringPiece /*retry_token*/,
+ quiche::QuicheStringPiece /*retry_integrity_tag*/,
+ quiche::QuicheStringPiece /*retry_without_tag*/) override {
+ }
bool OnProtocolVersionMismatch(ParsedQuicVersion version) override;
bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override;
bool OnUnauthenticatedPublicHeader(const QuicPacketHeader& header) override;
@@ -366,6 +362,7 @@ class NoOpFramerVisitor : public QuicFramerVisitorInterface {
bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override;
bool OnBlockedFrame(const QuicBlockedFrame& frame) override;
bool OnMessageFrame(const QuicMessageFrame& frame) override;
+ bool OnHandshakeDoneFrame(const QuicHandshakeDoneFrame& frame) override;
void OnPacketComplete() override {}
bool IsValidStatelessResetToken(QuicUint128 token) const override;
void OnAuthenticatedIetfStatelessResetPacket(
@@ -386,7 +383,8 @@ class MockQuicConnectionVisitor : public QuicConnectionVisitorInterface {
MOCK_METHOD1(OnBlockedFrame, void(const QuicBlockedFrame& frame));
MOCK_METHOD1(OnRstStream, void(const QuicRstStreamFrame& frame));
MOCK_METHOD1(OnGoAway, void(const QuicGoAwayFrame& frame));
- MOCK_METHOD1(OnMessageReceived, void(QuicStringPiece message));
+ MOCK_METHOD1(OnMessageReceived, void(quiche::QuicheStringPiece message));
+ MOCK_METHOD0(OnHandshakeDoneReceived, void());
MOCK_METHOD2(OnConnectionClosed,
void(const QuicConnectionCloseFrame& frame,
ConnectionCloseSource source));
@@ -409,12 +407,14 @@ class MockQuicConnectionVisitor : public QuicConnectionVisitorInterface {
MOCK_METHOD0(OnAckNeedsRetransmittableFrame, void());
MOCK_METHOD0(SendPing, void());
MOCK_CONST_METHOD0(AllowSelfAddressChange, bool());
+ MOCK_CONST_METHOD0(GetHandshakeState, HandshakeState());
MOCK_METHOD0(OnForwardProgressConfirmed, void());
MOCK_METHOD1(OnMaxStreamsFrame, bool(const QuicMaxStreamsFrame& frame));
MOCK_METHOD1(OnStreamsBlockedFrame,
bool(const QuicStreamsBlockedFrame& frame));
MOCK_METHOD1(OnStopSendingFrame, void(const QuicStopSendingFrame& frame));
MOCK_METHOD1(OnPacketDecrypted, void(EncryptionLevel));
+ MOCK_METHOD0(OnOneRttPacketAcknowledged, void());
};
class MockQuicConnectionHelper : public QuicConnectionHelperInterface {
@@ -632,12 +632,13 @@ class MockQuicSession : public QuicSession {
MOCK_METHOD1(ShouldCreateIncomingStream2, bool(QuicStreamId id));
MOCK_METHOD0(ShouldCreateOutgoingBidirectionalStream, bool());
MOCK_METHOD0(ShouldCreateOutgoingUnidirectionalStream, bool());
- MOCK_METHOD5(WritevData,
- QuicConsumedData(QuicStream* stream,
- QuicStreamId id,
+ MOCK_METHOD6(WritevData,
+ QuicConsumedData(QuicStreamId id,
size_t write_length,
QuicStreamOffset offset,
- StreamSendingState state));
+ StreamSendingState state,
+ TransmissionType type,
+ quiche::QuicheOptional<EncryptionLevel> level));
MOCK_METHOD3(SendRstStream,
void(QuicStreamId stream_id,
@@ -645,29 +646,30 @@ class MockQuicSession : public QuicSession {
QuicStreamOffset bytes_written));
MOCK_METHOD2(OnStreamHeaders,
- void(QuicStreamId stream_id, QuicStringPiece headers_data));
+ void(QuicStreamId stream_id,
+ quiche::QuicheStringPiece headers_data));
MOCK_METHOD2(OnStreamHeadersPriority,
void(QuicStreamId stream_id, spdy::SpdyPriority priority));
MOCK_METHOD3(OnStreamHeadersComplete,
void(QuicStreamId stream_id, bool fin, size_t frame_len));
MOCK_CONST_METHOD0(ShouldKeepConnectionAlive, bool());
MOCK_METHOD2(SendStopSending, void(uint16_t code, QuicStreamId stream_id));
- MOCK_METHOD1(OnCryptoHandshakeEvent, void(QuicSession::CryptoHandshakeEvent));
MOCK_CONST_METHOD0(GetAlpnsToOffer, std::vector<std::string>());
MOCK_CONST_METHOD1(SelectAlpn,
- std::vector<QuicStringPiece>::const_iterator(
- const std::vector<QuicStringPiece>&));
- MOCK_METHOD1(OnAlpnSelected, void(QuicStringPiece));
+ std::vector<quiche::QuicheStringPiece>::const_iterator(
+ const std::vector<quiche::QuicheStringPiece>&));
+ MOCK_METHOD1(OnAlpnSelected, void(quiche::QuicheStringPiece));
using QuicSession::ActivateStream;
// Returns a QuicConsumedData that indicates all of |write_length| (and |fin|
// if set) has been consumed.
- static QuicConsumedData ConsumeData(QuicStream* stream,
- QuicStreamId id,
- size_t write_length,
- QuicStreamOffset offset,
- StreamSendingState state);
+ QuicConsumedData ConsumeData(QuicStreamId id,
+ size_t write_length,
+ QuicStreamOffset offset,
+ StreamSendingState state,
+ TransmissionType type,
+ quiche::QuicheOptional<EncryptionLevel> level);
void ReallySendRstStream(QuicStreamId id,
QuicRstStreamErrorCode error,
@@ -686,11 +688,14 @@ class MockQuicCryptoStream : public QuicCryptoStream {
~MockQuicCryptoStream() override;
bool encryption_established() const override;
- bool handshake_confirmed() const override;
+ bool one_rtt_keys_available() const override;
const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
const override;
CryptoMessageParser* crypto_message_parser() override;
void OnPacketDecrypted(EncryptionLevel /*level*/) override {}
+ void OnOneRttPacketAcknowledged() override {}
+ void OnHandshakeDoneReceived() override {}
+ HandshakeState GetHandshakeState() const override { return HANDSHAKE_START; }
private:
QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
@@ -728,12 +733,13 @@ class MockQuicSpdySession : public QuicSpdySession {
MOCK_METHOD1(ShouldCreateIncomingStream, bool(QuicStreamId id));
MOCK_METHOD0(ShouldCreateOutgoingBidirectionalStream, bool());
MOCK_METHOD0(ShouldCreateOutgoingUnidirectionalStream, bool());
- MOCK_METHOD5(WritevData,
- QuicConsumedData(QuicStream* stream,
- QuicStreamId id,
+ MOCK_METHOD6(WritevData,
+ QuicConsumedData(QuicStreamId id,
size_t write_length,
QuicStreamOffset offset,
- StreamSendingState state));
+ StreamSendingState state,
+ TransmissionType type,
+ quiche::QuicheOptional<EncryptionLevel> level));
MOCK_METHOD3(SendRstStream,
void(QuicStreamId stream_id,
@@ -741,7 +747,8 @@ class MockQuicSpdySession : public QuicSpdySession {
QuicStreamOffset bytes_written));
MOCK_METHOD2(OnStreamHeaders,
- void(QuicStreamId stream_id, QuicStringPiece headers_data));
+ void(QuicStreamId stream_id,
+ quiche::QuicheStringPiece headers_data));
MOCK_METHOD2(OnStreamHeadersPriority,
void(QuicStreamId stream_id,
const spdy::SpdyStreamPrecedence& precedence));
@@ -753,7 +760,8 @@ class MockQuicSpdySession : public QuicSpdySession {
size_t frame_len,
const QuicHeaderList& header_list));
MOCK_METHOD2(OnPromiseHeaders,
- void(QuicStreamId stream_id, QuicStringPiece headers_data));
+ void(QuicStreamId stream_id,
+ quiche::QuicheStringPiece headers_data));
MOCK_METHOD3(OnPromiseHeadersComplete,
void(QuicStreamId stream_id,
QuicStreamId promised_stream_id,
@@ -772,12 +780,58 @@ class MockQuicSpdySession : public QuicSpdySession {
OnStreamFrameData,
void(QuicStreamId stream_id, const char* data, size_t len, bool fin));
+ // Returns a QuicConsumedData that indicates all of |write_length| (and |fin|
+ // if set) has been consumed.
+ QuicConsumedData ConsumeData(QuicStreamId id,
+ size_t write_length,
+ QuicStreamOffset offset,
+ StreamSendingState state,
+ TransmissionType type,
+ quiche::QuicheOptional<EncryptionLevel> level);
+
using QuicSession::ActivateStream;
private:
std::unique_ptr<QuicCryptoStream> crypto_stream_;
};
+class MockHttp3DebugVisitor : public Http3DebugVisitor {
+ public:
+ MOCK_METHOD1(OnControlStreamCreated, void(QuicStreamId));
+ MOCK_METHOD1(OnQpackEncoderStreamCreated, void(QuicStreamId));
+ MOCK_METHOD1(OnQpackDecoderStreamCreated, void(QuicStreamId));
+ MOCK_METHOD1(OnPeerControlStreamCreated, void(QuicStreamId));
+ MOCK_METHOD1(OnPeerQpackEncoderStreamCreated, void(QuicStreamId));
+ MOCK_METHOD1(OnPeerQpackDecoderStreamCreated, void(QuicStreamId));
+
+ MOCK_METHOD1(OnCancelPushFrameReceived, void(const CancelPushFrame&));
+ MOCK_METHOD1(OnSettingsFrameReceived, void(const SettingsFrame&));
+ MOCK_METHOD1(OnGoAwayFrameReceived, void(const GoAwayFrame&));
+ MOCK_METHOD1(OnMaxPushIdFrameReceived, void(const MaxPushIdFrame&));
+ MOCK_METHOD1(OnPriorityUpdateFrameReceived, void(const PriorityUpdateFrame&));
+
+ MOCK_METHOD2(OnDataFrameReceived, void(QuicStreamId, QuicByteCount));
+ MOCK_METHOD2(OnHeadersFrameReceived, void(QuicStreamId, QuicByteCount));
+ MOCK_METHOD2(OnHeadersDecoded, void(QuicStreamId, QuicHeaderList));
+ MOCK_METHOD3(OnPushPromiseFrameReceived,
+ void(QuicStreamId, QuicStreamId, QuicByteCount));
+ MOCK_METHOD3(OnPushPromiseDecoded,
+ void(QuicStreamId, QuicStreamId, QuicHeaderList));
+ MOCK_METHOD3(OnUnknownFrameReceived,
+ void(QuicStreamId, uint64_t, QuicByteCount));
+
+ MOCK_METHOD1(OnSettingsFrameSent, void(const SettingsFrame&));
+ MOCK_METHOD1(OnGoAwayFrameSent, void(QuicStreamId));
+ MOCK_METHOD1(OnMaxPushIdFrameSent, void(const MaxPushIdFrame&));
+ MOCK_METHOD1(OnPriorityUpdateFrameSent, void(const PriorityUpdateFrame&));
+
+ MOCK_METHOD2(OnDataFrameSent, void(QuicStreamId, QuicByteCount));
+ MOCK_METHOD2(OnHeadersFrameSent,
+ void(QuicStreamId, const spdy::SpdyHeaderBlock&));
+ MOCK_METHOD3(OnPushPromiseFrameSent,
+ void(QuicStreamId, QuicStreamId, const spdy::SpdyHeaderBlock&));
+};
+
class TestQuicSpdyServerSession : public QuicServerSessionBase {
public:
// Takes ownership of |connection|.
@@ -796,18 +850,15 @@ class TestQuicSpdyServerSession : public QuicServerSessionBase {
MOCK_METHOD0(CreateOutgoingBidirectionalStream, QuicSpdyStream*());
MOCK_METHOD0(CreateOutgoingUnidirectionalStream, QuicSpdyStream*());
MOCK_CONST_METHOD1(SelectAlpn,
- std::vector<QuicStringPiece>::const_iterator(
- const std::vector<QuicStringPiece>&));
- QuicCryptoServerStreamBase* CreateQuicCryptoServerStream(
+ std::vector<quiche::QuicheStringPiece>::const_iterator(
+ const std::vector<quiche::QuicheStringPiece>&));
+ std::unique_ptr<QuicCryptoServerStreamBase> CreateQuicCryptoServerStream(
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache) override;
- // Override to not send max header list size.
- void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override;
+ QuicCryptoServerStreamBase* GetMutableCryptoStream() override;
- QuicCryptoServerStream* GetMutableCryptoStream() override;
-
- const QuicCryptoServerStream* GetCryptoStream() const override;
+ const QuicCryptoServerStreamBase* GetCryptoStream() const override;
MockQuicCryptoServerStreamHelper* helper() { return &helper_; }
@@ -868,8 +919,6 @@ class TestQuicSpdyClientSession : public QuicSpdyClientSessionBase {
MOCK_METHOD0(ShouldCreateOutgoingUnidirectionalStream, bool());
MOCK_CONST_METHOD0(GetAlpnsToOffer, std::vector<std::string>());
- // Override to not send max header list size.
- void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override;
QuicCryptoClientStream* GetMutableCryptoStream() override;
const QuicCryptoClientStream* GetCryptoStream() const override;
@@ -940,6 +989,7 @@ class MockSendAlgorithm : public SendAlgorithmInterface {
QuicPacketNumber,
QuicByteCount,
HasRetransmittableData));
+ MOCK_METHOD1(OnPacketNeutered, void(QuicPacketNumber));
MOCK_METHOD1(OnRetransmissionTimeout, void(bool));
MOCK_METHOD0(OnConnectionMigration, void());
MOCK_METHOD0(RevertRetransmissionTimeout, void());
@@ -969,7 +1019,6 @@ class MockLossAlgorithm : public LossDetectionInterface {
MockLossAlgorithm& operator=(const MockLossAlgorithm&) = delete;
~MockLossAlgorithm() override;
- MOCK_CONST_METHOD0(GetLossDetectionType, LossDetectionType());
MOCK_METHOD6(DetectLosses,
void(const QuicUnackedPacketMap& unacked_packets,
QuicTime time,
@@ -984,6 +1033,10 @@ class MockLossAlgorithm : public LossDetectionInterface {
QuicTime,
QuicPacketNumber,
QuicPacketNumber));
+
+ MOCK_METHOD0(OnConfigNegotiated, void());
+ MOCK_METHOD0(OnMinRttAvailable, void());
+ MOCK_METHOD0(OnConnectionClosed, void());
};
class MockAckListener : public QuicAckListenerInterface {
@@ -1024,6 +1077,8 @@ class MockQuicConnectionDebugVisitor : public QuicConnectionDebugVisitor {
MOCK_METHOD3(OnPacketSent,
void(const SerializedPacket&, TransmissionType, QuicTime));
+ MOCK_METHOD2(OnCoalescedPacketSent, void(const QuicCoalescedPacket&, size_t));
+
MOCK_METHOD0(OnPingSent, void());
MOCK_METHOD3(OnPacketReceived,
@@ -1071,8 +1126,12 @@ class MockQuicConnectionDebugVisitor : public QuicConnectionDebugVisitor {
MOCK_METHOD1(OnVersionNegotiationPacket,
void(const QuicVersionNegotiationPacket&));
- MOCK_METHOD3(OnRetryPacket,
- void(QuicConnectionId, QuicConnectionId, QuicStringPiece));
+ MOCK_METHOD5(OnRetryPacket,
+ void(QuicConnectionId,
+ QuicConnectionId,
+ quiche::QuicheStringPiece,
+ quiche::QuicheStringPiece,
+ quiche::QuicheStringPiece));
};
class MockReceivedPacketManager : public QuicReceivedPacketManager {
@@ -1210,7 +1269,7 @@ QuicHeaderList AsHeaderList(const T& container) {
}
// Utility function that stores |str|'s data in |iov|.
-inline void MakeIOVector(QuicStringPiece str, struct iovec* iov) {
+inline void MakeIOVector(quiche::QuicheStringPiece str, struct iovec* iov) {
iov->iov_base = const_cast<char*>(str.data());
iov->iov_len = static_cast<size_t>(str.size());
}
@@ -1240,9 +1299,13 @@ StreamType DetermineStreamType(QuicStreamId id,
// Utility function that stores message_data in |storage| and returns a
// QuicMemSliceSpan.
QuicMemSliceSpan MakeSpan(QuicBufferAllocator* allocator,
- QuicStringPiece message_data,
+ quiche::QuicheStringPiece message_data,
QuicMemSliceStorage* storage);
+// Creates a MemSlice using a singleton trivial buffer allocator. Performs a
+// copy.
+QuicMemSlice MemSliceFromString(quiche::QuicheStringPiece data);
+
// Used to compare ReceivedPacketInfo.
MATCHER_P(ReceivedPacketInfoEquals, info, "") {
return info.ToString() == arg.ToString();
@@ -1261,8 +1324,8 @@ MATCHER_P2(InRange, min, max, "") {
// EXPECT_THAT(stream_->connection_error()), IsError(QUIC_INTERNAL_ERROR));
MATCHER_P(IsError,
expected,
- QuicStrCat(negation ? "isn't equal to " : "is equal to ",
- QuicErrorCodeToString(expected))) {
+ quiche::QuicheStrCat(negation ? "isn't equal to " : "is equal to ",
+ QuicErrorCodeToString(expected))) {
*result_listener << QuicErrorCodeToString(arg);
return arg == expected;
}
@@ -1270,8 +1333,8 @@ MATCHER_P(IsError,
// Shorthand for IsError(QUIC_NO_ERROR).
// Example usage: EXPECT_THAT(stream_->connection_error(), IsQuicNoError());
MATCHER(IsQuicNoError,
- QuicStrCat(negation ? "isn't equal to " : "is equal to ",
- QuicErrorCodeToString(QUIC_NO_ERROR))) {
+ quiche::QuicheStrCat(negation ? "isn't equal to " : "is equal to ",
+ QuicErrorCodeToString(QUIC_NO_ERROR))) {
*result_listener << QuicErrorCodeToString(arg);
return arg == QUIC_NO_ERROR;
}
@@ -1281,8 +1344,8 @@ MATCHER(IsQuicNoError,
// EXPECT_THAT(stream_->stream_error(), IsStreamError(QUIC_INTERNAL_ERROR));
MATCHER_P(IsStreamError,
expected,
- QuicStrCat(negation ? "isn't equal to " : "is equal to ",
- QuicRstStreamErrorCodeToString(expected))) {
+ quiche::QuicheStrCat(negation ? "isn't equal to " : "is equal to ",
+ QuicRstStreamErrorCodeToString(expected))) {
*result_listener << QuicRstStreamErrorCodeToString(arg);
return arg == expected;
}
@@ -1290,8 +1353,9 @@ MATCHER_P(IsStreamError,
// Shorthand for IsStreamError(QUIC_STREAM_NO_ERROR). Example usage:
// EXPECT_THAT(stream_->stream_error(), IsQuicStreamNoError());
MATCHER(IsQuicStreamNoError,
- QuicStrCat(negation ? "isn't equal to " : "is equal to ",
- QuicRstStreamErrorCodeToString(QUIC_STREAM_NO_ERROR))) {
+ quiche::QuicheStrCat(
+ negation ? "isn't equal to " : "is equal to ",
+ QuicRstStreamErrorCodeToString(QUIC_STREAM_NO_ERROR))) {
*result_listener << QuicRstStreamErrorCodeToString(arg);
return arg == QUIC_STREAM_NO_ERROR;
}
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_transport_test_tools.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_transport_test_tools.h
index c6a8b46496e..e7e01f78377 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_transport_test_tools.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_transport_test_tools.h
@@ -14,13 +14,18 @@ namespace test {
class MockClientVisitor : public QuicTransportClientSession::ClientVisitor {
public:
+ MOCK_METHOD0(OnSessionReady, void());
MOCK_METHOD0(OnIncomingBidirectionalStreamAvailable, void());
MOCK_METHOD0(OnIncomingUnidirectionalStreamAvailable, void());
+ MOCK_METHOD1(OnDatagramReceived, void(quiche::QuicheStringPiece));
+ MOCK_METHOD0(OnCanCreateNewOutgoingBidirectionalStream, void());
+ MOCK_METHOD0(OnCanCreateNewOutgoingUnidirectionalStream, void());
};
class MockServerVisitor : public QuicTransportServerSession::ServerVisitor {
public:
MOCK_METHOD1(CheckOrigin, bool(url::Origin));
+ MOCK_METHOD1(ProcessPath, bool(const GURL&));
};
class MockStreamVisitor : public QuicTransportStream::Visitor {
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/send_algorithm_test_result.proto b/chromium/net/third_party/quiche/src/quic/test_tools/send_algorithm_test_result.proto
new file mode 100644
index 00000000000..a836c474ba0
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/send_algorithm_test_result.proto
@@ -0,0 +1,15 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package quic;
+
+message SendAlgorithmTestResult {
+ optional string test_name = 1;
+ optional uint64 random_seed = 2;
+ optional int64 simulated_duration_micros = 3;
+}
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/send_algorithm_test_utils.cc b/chromium/net/third_party/quiche/src/quic/test_tools/send_algorithm_test_utils.cc
new file mode 100644
index 00000000000..f5ca6ee026b
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/send_algorithm_test_utils.cc
@@ -0,0 +1,62 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/test_tools/send_algorithm_test_utils.h"
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test_output.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+
+namespace quic {
+namespace test {
+
+bool LoadSendAlgorithmTestResult(SendAlgorithmTestResult* result) {
+ std::string test_result_file_content;
+ if (!QuicLoadTestOutput(GetSendAlgorithmTestResultFilename(),
+ &test_result_file_content)) {
+ return false;
+ }
+ return result->ParseFromString(test_result_file_content);
+}
+
+void RecordSendAlgorithmTestResult(uint64_t random_seed,
+ int64_t simulated_duration_micros) {
+ SendAlgorithmTestResult result;
+ result.set_test_name(GetFullSendAlgorithmTestName());
+ result.set_random_seed(random_seed);
+ result.set_simulated_duration_micros(simulated_duration_micros);
+
+ QuicSaveTestOutput(GetSendAlgorithmTestResultFilename(),
+ result.SerializeAsString());
+}
+
+void CompareSendAlgorithmTestResult(int64_t actual_simulated_duration_micros) {
+ SendAlgorithmTestResult expected;
+ ASSERT_TRUE(LoadSendAlgorithmTestResult(&expected));
+ QUIC_LOG(INFO) << "Loaded expected test result: "
+ << expected.ShortDebugString();
+
+ EXPECT_GE(expected.simulated_duration_micros(),
+ actual_simulated_duration_micros);
+}
+
+std::string GetFullSendAlgorithmTestName() {
+ const auto* test_info =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+ const std::string type_param =
+ test_info->type_param() ? test_info->type_param() : "";
+ const std::string value_param =
+ test_info->value_param() ? test_info->value_param() : "";
+ return quiche::QuicheStrCat(test_info->test_suite_name(), ".",
+ test_info->name(), "_", type_param, "_",
+ value_param);
+}
+
+std::string GetSendAlgorithmTestResultFilename() {
+ return GetFullSendAlgorithmTestName() + ".test_result";
+}
+
+} // namespace test
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/send_algorithm_test_utils.h b/chromium/net/third_party/quiche/src/quic/test_tools/send_algorithm_test_utils.h
new file mode 100644
index 00000000000..c36218d0928
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/send_algorithm_test_utils.h
@@ -0,0 +1,29 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_TEST_TOOLS_SEND_ALGORITHM_TEST_UTILS_H_
+#define QUICHE_QUIC_TEST_TOOLS_SEND_ALGORITHM_TEST_UTILS_H_
+
+#include "net/third_party/quiche/src/quic/test_tools/send_algorithm_test_result.pb.h"
+
+namespace quic {
+namespace test {
+
+bool LoadSendAlgorithmTestResult(SendAlgorithmTestResult* result);
+
+void RecordSendAlgorithmTestResult(uint64_t random_seed,
+ int64_t simulated_duration_micros);
+
+// Load the expected test result with LoadSendAlgorithmTestResult(), and compare
+// it with the actual results provided in the arguments.
+void CompareSendAlgorithmTestResult(int64_t actual_simulated_duration_micros);
+
+std::string GetFullSendAlgorithmTestName();
+
+std::string GetSendAlgorithmTestResultFilename();
+
+} // namespace test
+} // namespace quic
+
+#endif // QUICHE_QUIC_TEST_TOOLS_SEND_ALGORITHM_TEST_UTILS_H_
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/server_thread.cc b/chromium/net/third_party/quiche/src/quic/test_tools/server_thread.cc
index ca159130a87..77a23a656fe 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/server_thread.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/server_thread.cc
@@ -15,6 +15,7 @@ namespace test {
ServerThread::ServerThread(QuicServer* server, const QuicSocketAddress& address)
: QuicThread("server_thread"),
server_(server),
+ clock_(server->epoll_server()),
address_(address),
port_(0),
initialized_(false) {}
@@ -68,6 +69,24 @@ void ServerThread::WaitForCryptoHandshakeConfirmed() {
confirmed_.WaitForNotification();
}
+bool ServerThread::WaitUntil(std::function<bool()> termination_predicate,
+ QuicTime::Delta timeout) {
+ const QuicTime deadline = clock_.Now() + timeout;
+ while (clock_.Now() < deadline) {
+ QuicNotification done_checking;
+ bool should_terminate = false;
+ Schedule([&] {
+ should_terminate = termination_predicate();
+ done_checking.Notify();
+ });
+ done_checking.WaitForNotification();
+ if (should_terminate) {
+ return true;
+ }
+ }
+ return false;
+}
+
void ServerThread::Pause() {
DCHECK(!pause_.HasBeenNotified());
pause_.Notify();
@@ -100,13 +119,13 @@ void ServerThread::MaybeNotifyOfHandshakeConfirmation() {
return;
}
QuicSession* session = dispatcher->session_map().begin()->second.get();
- if (session->IsCryptoHandshakeConfirmed()) {
+ if (session->OneRttKeysAvailable()) {
confirmed_.Notify();
}
}
void ServerThread::ExecuteScheduledActions() {
- QuicDeque<std::function<void()>> actions;
+ QuicCircularDeque<std::function<void()>> actions;
{
QuicWriterMutexLock lock(&scheduled_actions_lock_);
actions.swap(scheduled_actions_);
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/server_thread.h b/chromium/net/third_party/quiche/src/quic/test_tools/server_thread.h
index d430297f30b..31efed63c8a 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/server_thread.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/server_thread.h
@@ -39,6 +39,13 @@ class ServerThread : public QuicThread {
// Waits for the handshake to be confirmed for the first session created.
void WaitForCryptoHandshakeConfirmed();
+ // Wait until |termination_predicate| returns true in server thread, or
+ // reached |timeout|. Must be called from an external thread.
+ // Return whether the function returned after |termination_predicate| become
+ // true.
+ bool WaitUntil(std::function<bool()> termination_predicate,
+ QuicTime::Delta timeout);
+
// Pauses execution of the server until Resume() is called. May only be
// called once.
void Pause();
@@ -71,6 +78,7 @@ class ServerThread : public QuicThread {
QuicNotification quit_; // Notified when the server should quit.
std::unique_ptr<QuicServer> server_;
+ QuicEpollClock clock_;
QuicSocketAddress address_;
mutable QuicMutex port_lock_;
int port_ QUIC_GUARDED_BY(port_lock_);
@@ -78,7 +86,7 @@ class ServerThread : public QuicThread {
bool initialized_;
QuicMutex scheduled_actions_lock_;
- QuicDeque<std::function<void()>> scheduled_actions_
+ QuicCircularDeque<std::function<void()>> scheduled_actions_
QUIC_GUARDED_BY(scheduled_actions_lock_);
};
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simple_data_producer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/simple_data_producer.cc
index ad8b2c3573a..0d5fa5b37a6 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simple_data_producer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simple_data_producer.cc
@@ -10,6 +10,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -35,7 +36,7 @@ void SimpleDataProducer::SaveStreamData(QuicStreamId id,
void SimpleDataProducer::SaveCryptoData(EncryptionLevel level,
QuicStreamOffset offset,
- QuicStringPiece data) {
+ quiche::QuicheStringPiece data) {
auto key = std::make_pair(level, offset);
crypto_buffer_map_[key] = data;
}
@@ -64,7 +65,7 @@ bool SimpleDataProducer::WriteCryptoData(EncryptionLevel level,
return false;
}
return writer->WriteStringPiece(
- QuicStringPiece(it->second.data(), data_length));
+ quiche::QuicheStringPiece(it->second.data(), data_length));
}
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simple_data_producer.h b/chromium/net/third_party/quiche/src/quic/test_tools/simple_data_producer.h
index d51ec69be70..be0d8469fb6 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simple_data_producer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simple_data_producer.h
@@ -9,6 +9,7 @@
#include "net/third_party/quiche/src/quic/core/quic_stream_frame_data_producer.h"
#include "net/third_party/quiche/src/quic/core/quic_stream_send_buffer.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -35,7 +36,7 @@ class SimpleDataProducer : public QuicStreamFrameDataProducer {
void SaveCryptoData(EncryptionLevel level,
QuicStreamOffset offset,
- QuicStringPiece data);
+ quiche::QuicheStringPiece data);
// QuicStreamFrameDataProducer
WriteStreamDataResult WriteStreamData(QuicStreamId id,
@@ -62,7 +63,7 @@ class SimpleDataProducer : public QuicStreamFrameDataProducer {
using CryptoBufferMap =
QuicUnorderedMap<std::pair<EncryptionLevel, QuicStreamOffset>,
- QuicStringPiece,
+ quiche::QuicheStringPiece,
PairHash>;
SimpleBufferAllocator allocator_;
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simple_quic_framer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/simple_quic_framer.cc
index 588f3b66d43..3d2652fa7ed 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simple_quic_framer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simple_quic_framer.cc
@@ -10,7 +10,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace test {
@@ -41,7 +41,10 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
void OnRetryPacket(QuicConnectionId /*original_connection_id*/,
QuicConnectionId /*new_connection_id*/,
- QuicStringPiece /*retry_token*/) override {}
+ quiche::QuicheStringPiece /*retry_token*/,
+ quiche::QuicheStringPiece /*retry_integrity_tag*/,
+ quiche::QuicheStringPiece /*retry_without_tag*/) override {
+ }
bool OnUnauthenticatedPublicHeader(
const QuicPacketHeader& /*header*/) override {
@@ -75,7 +78,7 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
// TODO(ianswett): A pointer isn't necessary with emplace_back.
stream_frames_.push_back(std::make_unique<QuicStreamFrame>(
frame.stream_id, frame.fin, frame.offset,
- QuicStringPiece(*string_data)));
+ quiche::QuicheStringPiece(*string_data)));
return true;
}
@@ -85,7 +88,7 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
new std::string(frame.data_buffer, frame.data_length);
crypto_data_.push_back(QuicWrapUnique(string_data));
crypto_frames_.push_back(std::make_unique<QuicCryptoFrame>(
- frame.level, frame.offset, QuicStringPiece(*string_data)));
+ frame.level, frame.offset, quiche::QuicheStringPiece(*string_data)));
return true;
}
@@ -196,6 +199,11 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
return true;
}
+ bool OnHandshakeDoneFrame(const QuicHandshakeDoneFrame& frame) override {
+ handshake_done_frames_.push_back(frame);
+ return true;
+ }
+
void OnPacketComplete() override {}
bool IsValidStatelessResetToken(QuicUint128 /*token*/) const override {
@@ -286,6 +294,7 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
std::vector<QuicRetireConnectionIdFrame> retire_connection_id_frames_;
std::vector<QuicNewTokenFrame> new_token_frames_;
std::vector<QuicMessageFrame> message_frames_;
+ std::vector<QuicHandshakeDoneFrame> handshake_done_frames_;
std::vector<std::unique_ptr<std::string>> stream_data_;
std::vector<std::unique_ptr<std::string>> crypto_data_;
EncryptionLevel last_decrypted_level_;
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.cc b/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.cc
index 9e67c899f51..22fa55635b6 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.cc
@@ -300,6 +300,8 @@ void SimpleSessionNotifier::RetransmitFrames(const QuicFrames& frames,
for (const QuicFrame& frame : frames) {
if (frame.type == CRYPTO_FRAME) {
const StreamState& state = crypto_state_[frame.crypto_frame->level];
+ const EncryptionLevel current_encryption_level =
+ connection_->encryption_level();
QuicIntervalSet<QuicStreamOffset> retransmission(
frame.crypto_frame->offset,
frame.crypto_frame->offset + frame.crypto_frame->data_length);
@@ -307,11 +309,13 @@ void SimpleSessionNotifier::RetransmitFrames(const QuicFrames& frames,
for (const auto& interval : retransmission) {
QuicStreamOffset offset = interval.min();
QuicByteCount length = interval.max() - interval.min();
+ connection_->SetDefaultEncryptionLevel(frame.crypto_frame->level);
size_t consumed = connection_->SendCryptoData(frame.crypto_frame->level,
length, offset);
// CRYPTO frames should never be write blocked.
DCHECK_EQ(consumed, length);
}
+ connection_->SetDefaultEncryptionLevel(current_encryption_level);
}
if (frame.type != STREAM_FRAME) {
if (GetControlFrameId(frame) == kInvalidControlFrameId) {
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.h b/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.h
index b3d5d729e82..7366ed8df12 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.h
@@ -5,6 +5,7 @@
#ifndef QUICHE_QUIC_TEST_TOOLS_SIMPLE_SESSION_NOTIFIER_H_
#define QUICHE_QUIC_TEST_TOOLS_SIMPLE_SESSION_NOTIFIER_H_
+#include "net/third_party/quiche/src/quic/core/quic_circular_deque.h"
#include "net/third_party/quiche/src/quic/core/quic_interval_set.h"
#include "net/third_party/quiche/src/quic/core/session_notifier_interface.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
@@ -127,7 +128,7 @@ class SimpleSessionNotifier : public SessionNotifierInterface {
bool StreamHasBufferedData(QuicStreamId id) const;
- QuicDeque<QuicFrame> control_frames_;
+ QuicCircularDeque<QuicFrame> control_frames_;
QuicLinkedHashMap<QuicControlFrameId, bool> lost_control_frames_;
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/actor.h b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/actor.h
index 9e06a7ea0b0..17a21b5e811 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/actor.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/actor.h
@@ -7,8 +7,8 @@
#include <string>
+#include "net/third_party/quiche/src/quic/core/quic_clock.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
namespace quic {
namespace simulator {
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/alarm_factory.cc b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/alarm_factory.cc
index e748da5b0f4..723605fbd06 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/alarm_factory.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/alarm_factory.cc
@@ -5,7 +5,7 @@
#include "net/third_party/quiche/src/quic/test_tools/simulator/alarm_factory.h"
#include "net/third_party/quiche/src/quic/core/quic_alarm.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
namespace quic {
namespace simulator {
@@ -58,7 +58,7 @@ AlarmFactory::~AlarmFactory() {}
std::string AlarmFactory::GetNewAlarmName() {
++counter_;
- return QuicStringPrintf("%s (alarm %i)", name_.c_str(), counter_);
+ return quiche::QuicheStringPrintf("%s (alarm %i)", name_.c_str(), counter_);
}
QuicAlarm* AlarmFactory::CreateAlarm(QuicAlarm::Delegate* delegate) {
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/link.cc b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/link.cc
index 110933e1379..b10024a8665 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/link.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/link.cc
@@ -4,8 +4,8 @@
#include "net/third_party/quiche/src/quic/test_tools/simulator/link.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
namespace quic {
namespace simulator {
@@ -96,12 +96,12 @@ SymmetricLink::SymmetricLink(Simulator* simulator,
QuicBandwidth bandwidth,
QuicTime::Delta propagation_delay)
: a_to_b_link_(simulator,
- QuicStringPrintf("%s (A-to-B)", name.c_str()),
+ quiche::QuicheStringPrintf("%s (A-to-B)", name.c_str()),
sink_b,
bandwidth,
propagation_delay),
b_to_a_link_(simulator,
- QuicStringPrintf("%s (B-to-A)", name.c_str()),
+ quiche::QuicheStringPrintf("%s (B-to-A)", name.c_str()),
sink_a,
bandwidth,
propagation_delay) {}
@@ -111,9 +111,9 @@ SymmetricLink::SymmetricLink(Endpoint* endpoint_a,
QuicBandwidth bandwidth,
QuicTime::Delta propagation_delay)
: SymmetricLink(endpoint_a->simulator(),
- QuicStringPrintf("Link [%s]<->[%s]",
- endpoint_a->name().c_str(),
- endpoint_b->name().c_str()),
+ quiche::QuicheStringPrintf("Link [%s]<->[%s]",
+ endpoint_a->name().c_str(),
+ endpoint_b->name().c_str()),
endpoint_a->GetRxPort(),
endpoint_b->GetRxPort(),
bandwidth,
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/link.h b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/link.h
index 5621e1b259f..a832a7ee771 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/link.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/link.h
@@ -9,6 +9,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
#include "net/third_party/quiche/src/quic/core/quic_bandwidth.h"
+#include "net/third_party/quiche/src/quic/core/quic_circular_deque.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/actor.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/port.h"
@@ -60,7 +61,7 @@ class OneWayLink : public Actor, public ConstrainedPortInterface {
void ScheduleNextPacketDeparture();
UnconstrainedPortInterface* sink_;
- QuicDeque<QueuedPacket> packets_in_transit_;
+ QuicCircularDeque<QueuedPacket> packets_in_transit_;
QuicBandwidth bandwidth_;
const QuicTime::Delta propagation_delay_;
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.cc b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.cc
index 9f504359dbf..c908f982abd 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.cc
@@ -10,9 +10,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test_output.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"
@@ -52,6 +50,7 @@ QuicEndpoint::QuicEndpoint(Simulator* simulator,
std::make_unique<NullDecrypter>(perspective));
}
connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ connection_->OnHandshakeComplete();
if (perspective == Perspective::IS_SERVER) {
// Skip version negotiation.
test::QuicConnectionPeer::SetNegotiatedVersion(connection_.get());
@@ -201,6 +200,10 @@ bool QuicEndpoint::HasUnackedStreamData() const {
return false;
}
+HandshakeState QuicEndpoint::GetHandshakeState() const {
+ return HANDSHAKE_COMPLETE;
+}
+
WriteStreamDataResult QuicEndpoint::DataProducer::WriteStreamData(
QuicStreamId /*id*/,
QuicStreamOffset /*offset*/,
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.h b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.h
index c2d24ac5404..f3a9f029c85 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.h
@@ -17,6 +17,7 @@
#include "net/third_party/quiche/src/quic/test_tools/simulator/link.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/queue.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint_base.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
namespace simulator {
@@ -58,7 +59,8 @@ class QuicEndpoint : public QuicEndpointBase,
void OnBlockedFrame(const QuicBlockedFrame& /*frame*/) override {}
void OnRstStream(const QuicRstStreamFrame& /*frame*/) override {}
void OnGoAway(const QuicGoAwayFrame& /*frame*/) override {}
- void OnMessageReceived(QuicStringPiece /*message*/) override {}
+ void OnMessageReceived(quiche::QuicheStringPiece /*message*/) override {}
+ void OnHandshakeDoneReceived() override {}
void OnConnectionClosed(const QuicConnectionCloseFrame& /*frame*/,
ConnectionCloseSource /*source*/) override {}
void OnWriteBlocked() override {}
@@ -73,6 +75,7 @@ class QuicEndpoint : public QuicEndpointBase,
void OnAckNeedsRetransmittableFrame() override {}
void SendPing() override {}
bool AllowSelfAddressChange() const override;
+ HandshakeState GetHandshakeState() const override;
void OnForwardProgressConfirmed() override {}
bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& /*frame*/) override {
return true;
@@ -83,6 +86,7 @@ class QuicEndpoint : public QuicEndpointBase,
}
void OnStopSendingFrame(const QuicStopSendingFrame& /*frame*/) override {}
void OnPacketDecrypted(EncryptionLevel /*level*/) override {}
+ void OnOneRttPacketAcknowledged() override {}
// End QuicConnectionVisitorInterface implementation.
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint_base.cc b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint_base.cc
index 537a94737b4..21815d8fe31 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint_base.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint_base.cc
@@ -11,12 +11,11 @@
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test_output.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
namespace quic {
namespace simulator {
@@ -61,7 +60,7 @@ QuicEndpointBase::QuicEndpointBase(Simulator* simulator,
peer_name_(peer_name),
writer_(this),
nic_tx_queue_(simulator,
- QuicStringPrintf("%s (TX Queue)", name.c_str()),
+ quiche::QuicheStringPrintf("%s (TX Queue)", name.c_str()),
kMaxOutgoingPacketSize * kTxQueueSize),
connection_(nullptr),
write_blocked_count_(0),
@@ -74,10 +73,9 @@ QuicEndpointBase::~QuicEndpointBase() {
const char* perspective_prefix =
connection_->perspective() == Perspective::IS_CLIENT ? "C" : "S";
- std::string identifier =
- QuicStrCat(perspective_prefix, connection_->connection_id().ToString());
- QuicRecordTestOutput(identifier,
- trace_visitor_->trace()->SerializeAsString());
+ std::string identifier = quiche::QuicheStrCat(
+ perspective_prefix, connection_->connection_id().ToString());
+ QuicRecordTrace(identifier, trace_visitor_->trace()->SerializeAsString());
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/simulator.cc b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/simulator.cc
index fdb59dbc7bb..61ae9a3d739 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/simulator.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/simulator.cc
@@ -10,8 +10,10 @@
namespace quic {
namespace simulator {
-Simulator::Simulator()
- : random_generator_(nullptr),
+Simulator::Simulator() : Simulator(nullptr) {}
+
+Simulator::Simulator(QuicRandom* random_generator)
+ : random_generator_(random_generator),
alarm_factory_(this, "Default Alarm Manager"),
run_for_should_stop_(false),
enable_random_delays_(false) {
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/simulator.h b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/simulator.h
index e21dd501fe5..46f80778fd4 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/simulator.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/simulator.h
@@ -22,6 +22,7 @@ namespace simulator {
class Simulator : public QuicConnectionHelperInterface {
public:
Simulator();
+ explicit Simulator(QuicRandom* random_generator);
Simulator(const Simulator&) = delete;
Simulator& operator=(const Simulator&) = delete;
~Simulator() override;
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/switch.cc b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/switch.cc
index e9b57ec6171..dcfc2d851f4 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/switch.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/switch.cc
@@ -5,8 +5,8 @@
#include <cinttypes>
#include <utility>
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/switch.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
namespace quic {
namespace simulator {
@@ -17,8 +17,8 @@ Switch::Switch(Simulator* simulator,
QuicByteCount queue_capacity) {
for (size_t port_number = 1; port_number <= port_count; port_number++) {
ports_.emplace_back(simulator,
- QuicStrCat(name, " (port ", port_number, ")"), this,
- port_number, queue_capacity);
+ quiche::QuicheStrCat(name, " (port ", port_number, ")"),
+ this, port_number, queue_capacity);
}
}
@@ -34,7 +34,7 @@ Switch::Port::Port(Simulator* simulator,
port_number_(port_number),
connected_(false),
queue_(simulator,
- QuicStringPrintf("%s (queue)", name.c_str()),
+ quiche::QuicheStringPrintf("%s (queue)", name.c_str()),
queue_capacity) {}
void Switch::Port::AcceptPacket(std::unique_ptr<Packet> packet) {
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/switch.h b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/switch.h
index 6d3efc37423..dea8a860969 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/switch.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/switch.h
@@ -77,7 +77,7 @@ class Switch {
void DispatchPacket(SwitchPortNumber port_number,
std::unique_ptr<Packet> packet);
- // This can not be a QuicDeque since pointers into this are
+ // This can not be a QuicCircularDeque since pointers into this are
// assumed to be stable.
std::deque<Port> ports_;
QuicUnorderedMap<std::string, Port*> switching_table_;
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/traffic_policer.h b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/traffic_policer.h
index c2a3e9928a6..1696d5d884c 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/traffic_policer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/traffic_policer.h
@@ -5,7 +5,6 @@
#ifndef QUICHE_QUIC_TEST_TOOLS_SIMULATOR_TRAFFIC_POLICER_H_
#define QUICHE_QUIC_TEST_TOOLS_SIMULATOR_TRAFFIC_POLICER_H_
-#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/packet_filter.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/port.h"
diff --git a/chromium/net/third_party/quiche/src/quic/tools/fake_proof_verifier.h b/chromium/net/third_party/quiche/src/quic/tools/fake_proof_verifier.h
index ffeb6e95e72..a605e071992 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/fake_proof_verifier.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/fake_proof_verifier.h
@@ -6,6 +6,7 @@
#define QUICHE_QUIC_TOOLS_FAKE_PROOF_VERIFIER_H_
#include "net/third_party/quiche/src/quic/core/crypto/proof_verifier.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -18,7 +19,7 @@ class FakeProofVerifier : public ProofVerifier {
const uint16_t /*port*/,
const std::string& /*server_config*/,
QuicTransportVersion /*quic_version*/,
- QuicStringPiece /*chlo_hash*/,
+ quiche::QuicheStringPiece /*chlo_hash*/,
const std::vector<std::string>& /*certs*/,
const std::string& /*cert_sct*/,
const std::string& /*signature*/,
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_backend_response.h b/chromium/net/third_party/quiche/src/quic/tools/quic_backend_response.h
index f0b7b893889..6537987a381 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_backend_response.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_backend_response.h
@@ -6,6 +6,7 @@
#define QUICHE_QUIC_TOOLS_QUIC_BACKEND_RESPONSE_H_
#include "net/third_party/quiche/src/quic/tools/quic_url.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
namespace quic {
@@ -55,7 +56,9 @@ class QuicBackendResponse {
SpecialResponseType response_type() const { return response_type_; }
const spdy::SpdyHeaderBlock& headers() const { return headers_; }
const spdy::SpdyHeaderBlock& trailers() const { return trailers_; }
- const QuicStringPiece body() const { return QuicStringPiece(body_); }
+ const quiche::QuicheStringPiece body() const {
+ return quiche::QuicheStringPiece(body_);
+ }
void set_response_type(SpecialResponseType response_type) {
response_type_ = response_type;
@@ -67,7 +70,7 @@ class QuicBackendResponse {
void set_trailers(spdy::SpdyHeaderBlock trailers) {
trailers_ = std::move(trailers);
}
- void set_body(QuicStringPiece body) {
+ void set_body(quiche::QuicheStringPiece body) {
body_.assign(body.data(), body.size());
}
uint16_t stop_sending_code() const { return stop_sending_code_; }
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_client.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_client.cc
index 379cfac3c13..a9a932071f7 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_client.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_client.cc
@@ -26,13 +26,8 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
-#include "net/quic/platform/impl/quic_socket_utils.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_client_session.h"
-#ifndef SO_RXQ_OVFL
-#define SO_RXQ_OVFL 40
-#endif
-
namespace quic {
namespace tools {
@@ -89,6 +84,23 @@ QuicClient::QuicClient(QuicSocketAddress server_address,
std::move(proof_verifier),
std::move(session_cache)) {}
+QuicClient::QuicClient(QuicSocketAddress server_address,
+ const QuicServerId& server_id,
+ const ParsedQuicVersionVector& supported_versions,
+ const QuicConfig& config,
+ QuicEpollServer* epoll_server,
+ std::unique_ptr<ProofVerifier> proof_verifier,
+ std::unique_ptr<SessionCache> session_cache)
+ : QuicClient(
+ server_address,
+ server_id,
+ supported_versions,
+ config,
+ epoll_server,
+ QuicWrapUnique(new QuicClientEpollNetworkHelper(epoll_server, this)),
+ std::move(proof_verifier),
+ std::move(session_cache)) {}
+
QuicClient::QuicClient(
QuicSocketAddress server_address,
const QuicServerId& server_id,
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_client.h b/chromium/net/third_party/quiche/src/quic/tools/quic_client.h
index 10c61f378d0..7ce795d719c 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_client.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_client.h
@@ -49,6 +49,13 @@ class QuicClient : public QuicSpdyClientBase {
QuicEpollServer* epoll_server,
std::unique_ptr<ProofVerifier> proof_verifier,
std::unique_ptr<SessionCache> session_cache);
+ QuicClient(QuicSocketAddress server_address,
+ const QuicServerId& server_id,
+ const ParsedQuicVersionVector& supported_versions,
+ const QuicConfig& config,
+ QuicEpollServer* epoll_server,
+ std::unique_ptr<ProofVerifier> proof_verifier,
+ std::unique_ptr<SessionCache> session_cache);
// This will take ownership of a passed in network primitive.
QuicClient(QuicSocketAddress server_address,
const QuicServerId& server_id,
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_client_base.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_client_base.cc
index b6c33759b47..4b511849cb6 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_client_base.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_client_base.cc
@@ -10,7 +10,6 @@
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
namespace quic {
@@ -37,7 +36,8 @@ QuicClientBase::QuicClientBase(
num_sent_client_hellos_(0),
connection_error_(QUIC_NO_ERROR),
connected_or_attempting_connect_(false),
- network_helper_(std::move(network_helper)) {}
+ network_helper_(std::move(network_helper)),
+ connection_debug_visitor_(nullptr) {}
QuicClientBase::~QuicClientBase() = default;
@@ -72,19 +72,20 @@ bool QuicClientBase::Initialize() {
bool QuicClientBase::Connect() {
// Attempt multiple connects until the maximum number of client hellos have
// been sent.
+ int num_attempts = 0;
while (!connected() &&
- GetNumSentClientHellos() <= QuicCryptoClientStream::kMaxClientHellos) {
+ num_attempts <= QuicCryptoClientStream::kMaxClientHellos) {
StartConnect();
while (EncryptionBeingEstablished()) {
WaitForEvents();
}
ParsedQuicVersion version = UnsupportedQuicVersion();
- if (session() != nullptr &&
- !CanReconnectWithDifferentVersion(&version)) {
+ if (session() != nullptr && !CanReconnectWithDifferentVersion(&version)) {
// We've successfully created a session but we're not connected, and we
// cannot reconnect with a different version. Give up trying.
break;
}
+ num_attempts++;
}
return session()->connection()->connected();
}
@@ -115,6 +116,9 @@ void QuicClientBase::StartConnect() {
can_reconnect_with_different_version
? ParsedQuicVersionVector{mutual_version}
: supported_versions()));
+ if (connection_debug_visitor_ != nullptr) {
+ session()->connection()->set_debug_visitor(connection_debug_visitor_);
+ }
session()->connection()->set_client_connection_id(GetClientConnectionId());
if (initial_max_packet_length_ != 0) {
session()->connection()->SetMaxPacketLength(initial_max_packet_length_);
@@ -123,6 +127,10 @@ void QuicClientBase::StartConnect() {
// session.
set_writer(writer);
InitializeSession();
+ if (can_reconnect_with_different_version) {
+ // This is a reconnect using server supported |mutual_version|.
+ session()->connection()->SetVersionNegotiated();
+ }
set_connected_or_attempting_connect(true);
}
@@ -228,7 +236,7 @@ void QuicClientBase::WaitForStreamToClose(QuicStreamId id) {
bool QuicClientBase::WaitForCryptoHandshakeConfirmed() {
DCHECK(connected());
- while (connected() && !session_->IsCryptoHandshakeConfirmed()) {
+ while (connected() && !session_->OneRttKeysAvailable()) {
WaitForEvents();
}
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_client_base.h b/chromium/net/third_party/quiche/src/quic/tools/quic_client_base.h
index 8cb639bd58f..6c1e09a78d0 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_client_base.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_client_base.h
@@ -17,7 +17,7 @@
#include "net/third_party/quiche/src/quic/core/quic_config.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_macros.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -154,6 +154,18 @@ class QuicClientBase {
// The number of client hellos sent.
int GetNumSentClientHellos();
+ // Returns true if early data (0-RTT data) was sent and the server accepted
+ // it.
+ virtual bool EarlyDataAccepted() = 0;
+
+ // Returns true if the handshake was delayed one round trip by the server
+ // because the server wanted proof the client controls its source address
+ // before progressing further. In Google QUIC, this would be due to an
+ // inchoate REJ in the QUIC Crypto handshake; in IETF QUIC this would be due
+ // to a Retry packet.
+ // TODO(nharper): Consider a better name for this method.
+ virtual bool ReceivedInchoateReject() = 0;
+
// Gather the stats for the last session and update the stats for the overall
// connection.
void UpdateStats();
@@ -209,10 +221,15 @@ class QuicClientBase {
bool initialized() const { return initialized_; }
- void SetPreSharedKey(QuicStringPiece key) {
+ void SetPreSharedKey(quiche::QuicheStringPiece key) {
crypto_config_.set_pre_shared_key(key);
}
+ void set_connection_debug_visitor(
+ QuicConnectionDebugVisitor* connection_debug_visitor) {
+ connection_debug_visitor_ = connection_debug_visitor;
+ }
+
protected:
// TODO(rch): Move GetNumSentClientHellosFromSession and
// GetNumReceivedServerConfigUpdatesFromSession into a new/better
@@ -331,6 +348,10 @@ class QuicClientBase {
// The network helper used to create sockets and manage the event loop.
// Not owned by this class.
std::unique_ptr<NetworkHelper> network_helper_;
+
+ // The debug visitor set on the connection right after it is constructed.
+ // Not owned, must be valid for the lifetime of the QuicClientBase instance.
+ QuicConnectionDebugVisitor* connection_debug_visitor_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_client_epoll_network_helper.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_client_epoll_network_helper.cc
index 2f6d47d93c6..2a9ebbac0dd 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_client_epoll_network_helper.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_client_epoll_network_helper.cc
@@ -19,14 +19,10 @@
#include "net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_server_id.h"
+#include "net/third_party/quiche/src/quic/core/quic_udp_socket.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_system_event_loop.h"
-#include "net/quic/platform/impl/quic_socket_utils.h"
-
-#ifndef SO_RXQ_OVFL
-#define SO_RXQ_OVFL 40
-#endif
namespace quic {
@@ -81,7 +77,10 @@ bool QuicClientEpollNetworkHelper::CreateUDPSocketAndBind(
sockaddr_storage addr = client_address.generic_address();
int rc = bind(fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
if (rc < 0) {
- QUIC_LOG(ERROR) << "Bind failed: " << strerror(errno);
+ QUIC_LOG(ERROR) << "Bind failed: " << strerror(errno)
+ << " bind_to_address:" << bind_to_address
+ << ", bind_to_port:" << bind_to_port
+ << ", client_address:" << client_address;
return false;
}
@@ -91,7 +90,6 @@ bool QuicClientEpollNetworkHelper::CreateUDPSocketAndBind(
}
fd_address_map_[fd] = client_address;
-
epoll_server_->RegisterFD(fd, this, kEpollFlags);
return true;
}
@@ -131,9 +129,7 @@ void QuicClientEpollNetworkHelper::OnUnregistration(int /*fd*/,
void QuicClientEpollNetworkHelper::OnShutdown(QuicEpollServer* /*eps*/,
int /*fd*/) {}
-void QuicClientEpollNetworkHelper::OnEvent(int fd, QuicEpollEvent* event) {
- DCHECK_EQ(fd, GetLatestFD());
-
+void QuicClientEpollNetworkHelper::OnEvent(int /*fd*/, QuicEpollEvent* event) {
if (event->in_events & EPOLLIN) {
QUIC_DVLOG(1) << "Read packets on EPOLLIN";
int times_to_read = max_reads_per_epoll_loop_;
@@ -200,9 +196,16 @@ void QuicClientEpollNetworkHelper::ProcessPacket(
int QuicClientEpollNetworkHelper::CreateUDPSocket(
QuicSocketAddress server_address,
bool* overflow_supported) {
- return QuicSocketUtils::CreateUDPSocket(
- server_address,
- /*receive_buffer_size =*/kDefaultSocketReceiveBuffer,
- /*send_buffer_size =*/kDefaultSocketReceiveBuffer, overflow_supported);
+ QuicUdpSocketApi api;
+ int fd = api.Create(server_address.host().AddressFamilyToInt(),
+ /*receive_buffer_size =*/kDefaultSocketReceiveBuffer,
+ /*send_buffer_size =*/kDefaultSocketReceiveBuffer);
+ if (fd < 0) {
+ return fd;
+ }
+
+ *overflow_supported = api.EnableDroppedPacketCount(fd);
+ api.EnableReceiveTimestamp(fd);
+ return fd;
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_client_interop_test_bin.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_client_interop_test_bin.cc
index 8c9f6d16930..9745955799f 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_client_interop_test_bin.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_client_interop_test_bin.cc
@@ -18,6 +18,7 @@
#include "net/third_party/quiche/src/quic/tools/fake_proof_verifier.h"
#include "net/third_party/quiche/src/quic/tools/quic_client.h"
#include "net/third_party/quiche/src/quic/tools/quic_url.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
DEFINE_QUIC_COMMAND_LINE_FLAG(std::string,
host,
@@ -78,73 +79,125 @@ char MatrixLetter(Feature f) {
}
}
-// Attempts a resumption using |client| by disconnecting and reconnecting. If
-// resumption is successful, |features| is modified to add Feature::kResumption
-// to it, otherwise it is left unmodified.
-void AttemptResumption(QuicClient* client, std::set<Feature>* features) {
+class QuicClientInteropRunner : QuicConnectionDebugVisitor {
+ public:
+ QuicClientInteropRunner() {}
+
+ void InsertFeature(Feature feature) { features_.insert(feature); }
+
+ std::set<Feature> features() const { return features_; }
+
+ // Attempts a resumption using |client| by disconnecting and reconnecting. If
+ // resumption is successful, |features_| is modified to add
+ // Feature::kResumption to it, otherwise it is left unmodified.
+ void AttemptResumption(QuicClient* client);
+
+ void AttemptRequest(QuicSocketAddress addr,
+ std::string authority,
+ QuicServerId server_id,
+ ParsedQuicVersion version,
+ bool test_version_negotiation,
+ bool attempt_rebind);
+
+ void OnConnectionCloseFrame(const QuicConnectionCloseFrame& frame) override {
+ switch (frame.close_type) {
+ case GOOGLE_QUIC_CONNECTION_CLOSE:
+ QUIC_LOG(ERROR) << "Received unexpected GoogleQUIC connection close";
+ break;
+ case IETF_QUIC_TRANSPORT_CONNECTION_CLOSE:
+ if (frame.transport_error_code == NO_IETF_QUIC_ERROR) {
+ InsertFeature(Feature::kConnectionClose);
+ } else {
+ QUIC_LOG(ERROR) << "Received transport connection close "
+ << QuicIetfTransportErrorCodeString(
+ frame.transport_error_code);
+ }
+ break;
+ case IETF_QUIC_APPLICATION_CONNECTION_CLOSE:
+ if (frame.application_error_code == 0) {
+ InsertFeature(Feature::kConnectionClose);
+ } else {
+ QUIC_LOG(ERROR) << "Received application connection close "
+ << frame.application_error_code;
+ }
+ break;
+ }
+ }
+
+ void OnVersionNegotiationPacket(
+ const QuicVersionNegotiationPacket& /*packet*/) override {
+ InsertFeature(Feature::kVersionNegotiation);
+ }
+
+ private:
+ std::set<Feature> features_;
+};
+
+void QuicClientInteropRunner::AttemptResumption(QuicClient* client) {
client->Disconnect();
if (!client->Initialize()) {
QUIC_LOG(ERROR) << "Failed to reinitialize client";
return;
}
- if (!client->Connect() || !client->session()->IsCryptoHandshakeConfirmed()) {
+ if (!client->Connect() || !client->session()->OneRttKeysAvailable()) {
return;
}
if (static_cast<QuicCryptoClientStream*>(
test::QuicSessionPeer::GetMutableCryptoStream(client->session()))
->IsResumption()) {
- features->insert(Feature::kResumption);
+ InsertFeature(Feature::kResumption);
}
}
-std::set<Feature> AttemptRequest(QuicSocketAddress addr,
- std::string authority,
- QuicServerId server_id,
- bool test_version_negotiation,
- bool attempt_rebind) {
- ParsedQuicVersion version(PROTOCOL_TLS1_3, QUIC_VERSION_99);
+void QuicClientInteropRunner::AttemptRequest(QuicSocketAddress addr,
+ std::string authority,
+ QuicServerId server_id,
+ ParsedQuicVersion version,
+ bool test_version_negotiation,
+ bool attempt_rebind) {
ParsedQuicVersionVector versions = {version};
if (test_version_negotiation) {
versions.insert(versions.begin(), QuicVersionReservedForNegotiation());
}
- std::set<Feature> features;
auto proof_verifier = std::make_unique<FakeProofVerifier>();
auto session_cache = std::make_unique<test::SimpleSessionCache>();
QuicEpollServer epoll_server;
QuicEpollClock epoll_clock(&epoll_server);
+ QuicConfig config;
+ QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(20);
+ config.SetIdleNetworkTimeout(timeout, timeout);
auto client = std::make_unique<QuicClient>(
- addr, server_id, versions, &epoll_server, std::move(proof_verifier),
- std::move(session_cache));
+ addr, server_id, versions, config, &epoll_server,
+ std::move(proof_verifier), std::move(session_cache));
+ client->set_connection_debug_visitor(this);
if (!client->Initialize()) {
QUIC_LOG(ERROR) << "Failed to initialize client";
- return features;
+ return;
}
const bool connect_result = client->Connect();
QuicConnection* connection = client->session()->connection();
- if (connection != nullptr) {
- QuicConnectionStats client_stats = connection->GetStats();
- if (client_stats.retry_packet_processed) {
- features.insert(Feature::kRetry);
- }
- if (test_version_negotiation && connection->version() == version) {
- features.insert(Feature::kVersionNegotiation);
- }
+ if (connection == nullptr) {
+ QUIC_LOG(ERROR) << "No QuicConnection object";
+ return;
+ }
+ QuicConnectionStats client_stats = connection->GetStats();
+ if (client_stats.retry_packet_processed) {
+ InsertFeature(Feature::kRetry);
+ }
+ if (test_version_negotiation && connection->version() == version) {
+ InsertFeature(Feature::kVersionNegotiation);
}
if (test_version_negotiation && !connect_result) {
// Failed to negotiate version, retry without version negotiation.
- std::set<Feature> features_without_version_negotiation =
- AttemptRequest(addr, authority, server_id,
- /*test_version_negotiation=*/false, attempt_rebind);
-
- features.insert(features_without_version_negotiation.begin(),
- features_without_version_negotiation.end());
- return features;
+ AttemptRequest(addr, authority, server_id, version,
+ /*test_version_negotiation=*/false, attempt_rebind);
+ return;
}
- if (!client->session()->IsCryptoHandshakeConfirmed()) {
- return features;
+ if (!client->session()->OneRttKeysAvailable()) {
+ return;
}
- features.insert(Feature::kHandshake);
+ InsertFeature(Feature::kHandshake);
// Construct and send a request.
spdy::SpdyHeaderBlock header_block;
@@ -153,65 +206,44 @@ std::set<Feature> AttemptRequest(QuicSocketAddress addr,
header_block[":authority"] = authority;
header_block[":path"] = "/";
client->set_store_response(true);
- client->SendRequest(header_block, "", /*fin=*/true);
-
- const QuicTime request_start_time = epoll_clock.Now();
- static const auto request_timeout = QuicTime::Delta::FromSeconds(20);
- bool request_timed_out = false;
- while (client->WaitForEvents()) {
- if (epoll_clock.Now() - request_start_time >= request_timeout) {
- QUIC_LOG(ERROR) << "Timed out waiting for HTTP response";
- request_timed_out = true;
- break;
- }
+ client->SendRequestAndWaitForResponse(header_block, "", /*fin=*/true);
+
+ client_stats = connection->GetStats();
+ QuicSentPacketManager* sent_packet_manager =
+ test::QuicConnectionPeer::GetSentPacketManager(connection);
+ const bool received_forward_secure_ack =
+ sent_packet_manager != nullptr &&
+ sent_packet_manager->GetLargestAckedPacket(ENCRYPTION_FORWARD_SECURE)
+ .IsInitialized();
+ if (client_stats.stream_bytes_received > 0 && received_forward_secure_ack) {
+ InsertFeature(Feature::kStreamData);
}
- if (connection != nullptr) {
- QuicConnectionStats client_stats = connection->GetStats();
- QuicSentPacketManager* sent_packet_manager =
- test::QuicConnectionPeer::GetSentPacketManager(connection);
- const bool received_forward_secure_ack =
- sent_packet_manager != nullptr &&
- sent_packet_manager->GetLargestAckedPacket(ENCRYPTION_FORWARD_SECURE)
- .IsInitialized();
- if (client_stats.stream_bytes_received > 0 && received_forward_secure_ack) {
- features.insert(Feature::kStreamData);
- }
- }
-
- if (request_timed_out || !client->connected()) {
- return features;
+ if (!client->connected()) {
+ return;
}
if (client->latest_response_code() != -1) {
- features.insert(Feature::kHttp3);
+ InsertFeature(Feature::kHttp3);
if (client->client_session()->dynamic_table_entry_referenced()) {
- features.insert(Feature::kDynamicEntryReferenced);
+ InsertFeature(Feature::kDynamicEntryReferenced);
}
if (attempt_rebind) {
// Now make a second request after switching to a different client port.
if (client->ChangeEphemeralPort()) {
- client->SendRequest(header_block, "", /*fin=*/true);
-
- const QuicTime second_request_start_time = epoll_clock.Now();
- while (client->WaitForEvents()) {
- if (epoll_clock.Now() - second_request_start_time >=
- request_timeout) {
- // Rebinding does not work, retry without attempting it.
- std::set<Feature> features_without_rebind = AttemptRequest(
- addr, authority, server_id, test_version_negotiation,
- /*attempt_rebind=*/false);
- features.insert(features_without_rebind.begin(),
- features_without_rebind.end());
- return features;
- }
+ client->SendRequestAndWaitForResponse(header_block, "", /*fin=*/true);
+ if (!client->connected()) {
+ // Rebinding does not work, retry without attempting it.
+ AttemptRequest(addr, authority, server_id, version,
+ test_version_negotiation, /*attempt_rebind=*/false);
+ return;
}
- features.insert(Feature::kRebinding);
+ InsertFeature(Feature::kRebinding);
if (client->client_session()->dynamic_table_entry_referenced()) {
- features.insert(Feature::kDynamicEntryReferenced);
+ InsertFeature(Feature::kDynamicEntryReferenced);
}
} else {
QUIC_LOG(ERROR) << "Failed to change ephemeral port";
@@ -219,50 +251,48 @@ std::set<Feature> AttemptRequest(QuicSocketAddress addr,
}
}
- if (connection != nullptr && connection->connected()) {
- test::QuicConnectionPeer::SendConnectionClosePacket(
- connection, QUIC_NO_ERROR, "Graceful close");
- const QuicTime close_start_time = epoll_clock.Now();
- static const auto close_timeout = QuicTime::Delta::FromSeconds(10);
- while (client->connected()) {
- client->epoll_network_helper()->RunEventLoop();
- if (epoll_clock.Now() - close_start_time >= close_timeout) {
- QUIC_LOG(ERROR) << "Timed out waiting for connection close";
- AttemptResumption(client.get(), &features);
- return features;
- }
- }
- const QuicErrorCode received_error = client->session()->error();
- if (received_error == QUIC_NO_ERROR ||
- received_error == QUIC_PUBLIC_RESET) {
- features.insert(Feature::kConnectionClose);
- } else {
- QUIC_LOG(ERROR) << "Received error " << client->session()->error() << " "
- << client->session()->error_details();
- }
+ if (connection->connected()) {
+ connection->CloseConnection(
+ QUIC_NO_ERROR, "Graceful close",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ InsertFeature(Feature::kConnectionClose);
}
- AttemptResumption(client.get(), &features);
- return features;
+ AttemptResumption(client.get());
}
std::set<Feature> ServerSupport(std::string host, int port) {
// Enable IETF version support.
QuicVersionInitializeSupportForIetfDraft();
- QuicEnableVersion(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99));
+ ParsedQuicVersion version = UnsupportedQuicVersion();
+ for (const ParsedQuicVersion& vers : AllSupportedVersions()) {
+ // Find the first version that supports IETF QUIC.
+ if (vers.HasIetfQuicFrames() &&
+ vers.handshake_protocol == quic::PROTOCOL_TLS1_3) {
+ version = vers;
+ break;
+ }
+ }
+ CHECK_NE(version.transport_version, QUIC_VERSION_UNSUPPORTED);
+ QuicEnableVersion(version);
// Build the client, and try to connect.
- QuicSocketAddress addr = tools::LookupAddress(host, QuicStrCat(port));
+ QuicSocketAddress addr =
+ tools::LookupAddress(host, quiche::QuicheStrCat(port));
if (!addr.IsInitialized()) {
QUIC_LOG(ERROR) << "Failed to resolve " << host;
return std::set<Feature>();
}
QuicServerId server_id(host, port, false);
- std::string authority = QuicStrCat(host, ":", port);
+ std::string authority = quiche::QuicheStrCat(host, ":", port);
- return AttemptRequest(addr, authority, server_id,
+ QuicClientInteropRunner runner;
+
+ runner.AttemptRequest(addr, authority, server_id, version,
/*test_version_negotiation=*/true,
/*attempt_rebind=*/true);
+
+ return runner.features();
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_client_test.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_client_test.cc
index e460de495a2..b1923b67c7c 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_client_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_client_test.cc
@@ -12,12 +12,12 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_epoll.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_port_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test_loopback.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_client_peer.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
namespace test {
@@ -40,13 +40,13 @@ size_t NumOpenSocketFDs() {
std::unique_ptr<DIR, int (*)(DIR*)> fd_directory(opendir(kPathToFds),
closedir);
while ((file = readdir(fd_directory.get())) != nullptr) {
- QuicStringPiece name(file->d_name);
+ quiche::QuicheStringPiece name(file->d_name);
if (name == "." || name == "..") {
continue;
}
- std::string fd_path = ReadLink(QuicStrCat(kPathToFds, "/", name));
- if (QuicTextUtils::StartsWith(fd_path, "socket:")) {
+ std::string fd_path = ReadLink(quiche::QuicheStrCat(kPathToFds, "/", name));
+ if (quiche::QuicheTextUtils::StartsWith(fd_path, "socket:")) {
socket_count++;
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_epoll_client_factory.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_epoll_client_factory.cc
index 113958f548f..1751f4173ed 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_epoll_client_factory.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_epoll_client_factory.cc
@@ -13,6 +13,7 @@
#include "net/third_party/quiche/src/quic/core/quic_server_id.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
#include "net/third_party/quiche/src/quic/tools/quic_client.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
namespace quic {
@@ -23,7 +24,7 @@ std::unique_ptr<QuicSpdyClientBase> QuicEpollClientFactory::CreateClient(
ParsedQuicVersionVector versions,
std::unique_ptr<ProofVerifier> verifier) {
QuicSocketAddress addr =
- tools::LookupAddress(host_for_lookup, QuicStrCat(port));
+ tools::LookupAddress(host_for_lookup, quiche::QuicheStrCat(port));
if (!addr.IsInitialized()) {
QUIC_LOG(ERROR) << "Unable to resolve address: " << host_for_lookup;
return nullptr;
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.cc
index 38d25e53734..c7ac9127790 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.cc
@@ -11,7 +11,8 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_file_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
using spdy::kV3LowestPriority;
using spdy::SpdyHeaderBlock;
@@ -39,7 +40,7 @@ void QuicMemoryCacheBackend::ResourceFile::Read() {
if (file_contents_[pos - 1] == '\r') {
len -= 1;
}
- QuicStringPiece line(file_contents_.data() + start, len);
+ quiche::QuicheStringPiece line(file_contents_.data() + start, len);
start = pos + 1;
// Headers end with an empty line.
if (line.empty()) {
@@ -63,7 +64,8 @@ void QuicMemoryCacheBackend::ResourceFile::Read() {
return;
}
spdy_headers_.AppendValueOrAddHeader(
- QuicTextUtils::ToLower(line.substr(0, pos)), line.substr(pos + 2));
+ quiche::QuicheTextUtils::ToLower(line.substr(0, pos)),
+ line.substr(pos + 2));
}
// The connection header is prohibited in HTTP/2.
@@ -81,65 +83,71 @@ void QuicMemoryCacheBackend::ResourceFile::Read() {
// stuff as described in https://w3c.github.io/preload/.
it = spdy_headers_.find("x-push-url");
if (it != spdy_headers_.end()) {
- QuicStringPiece push_urls = it->second;
+ quiche::QuicheStringPiece push_urls = it->second;
size_t start = 0;
while (start < push_urls.length()) {
size_t pos = push_urls.find('\0', start);
if (pos == std::string::npos) {
- push_urls_.push_back(QuicStringPiece(push_urls.data() + start,
- push_urls.length() - start));
+ push_urls_.push_back(quiche::QuicheStringPiece(
+ push_urls.data() + start, push_urls.length() - start));
break;
}
- push_urls_.push_back(QuicStringPiece(push_urls.data() + start, pos));
+ push_urls_.push_back(
+ quiche::QuicheStringPiece(push_urls.data() + start, pos));
start += pos + 1;
}
}
- body_ = QuicStringPiece(file_contents_.data() + start,
- file_contents_.size() - start);
+ body_ = quiche::QuicheStringPiece(file_contents_.data() + start,
+ file_contents_.size() - start);
}
void QuicMemoryCacheBackend::ResourceFile::SetHostPathFromBase(
- QuicStringPiece base) {
+ quiche::QuicheStringPiece base) {
+ DCHECK(base[0] != '/') << base;
size_t path_start = base.find_first_of('/');
- DCHECK_LT(0UL, path_start);
- host_ = base.substr(0, path_start);
+ if (path_start == quiche::QuicheStringPiece::npos) {
+ host_ = std::string(base);
+ path_ = "";
+ return;
+ }
+
+ host_ = std::string(base.substr(0, path_start));
size_t query_start = base.find_first_of(',');
if (query_start > 0) {
- path_ = base.substr(path_start, query_start - 1);
+ path_ = std::string(base.substr(path_start, query_start - 1));
} else {
- path_ = base.substr(path_start);
+ path_ = std::string(base.substr(path_start));
}
}
-QuicStringPiece QuicMemoryCacheBackend::ResourceFile::RemoveScheme(
- QuicStringPiece url) {
- if (QuicTextUtils::StartsWith(url, "https://")) {
+quiche::QuicheStringPiece QuicMemoryCacheBackend::ResourceFile::RemoveScheme(
+ quiche::QuicheStringPiece url) {
+ if (quiche::QuicheTextUtils::StartsWith(url, "https://")) {
url.remove_prefix(8);
- } else if (QuicTextUtils::StartsWith(url, "http://")) {
+ } else if (quiche::QuicheTextUtils::StartsWith(url, "http://")) {
url.remove_prefix(7);
}
return url;
}
void QuicMemoryCacheBackend::ResourceFile::HandleXOriginalUrl() {
- QuicStringPiece url(x_original_url_);
- // Remove the protocol so we can add it below.
- url = RemoveScheme(url);
- SetHostPathFromBase(url);
+ quiche::QuicheStringPiece url(x_original_url_);
+ SetHostPathFromBase(RemoveScheme(url));
}
const QuicBackendResponse* QuicMemoryCacheBackend::GetResponse(
- QuicStringPiece host,
- QuicStringPiece path) const {
+ quiche::QuicheStringPiece host,
+ quiche::QuicheStringPiece path) const {
QuicWriterMutexLock lock(&response_mutex_);
auto it = responses_.find(GetKey(host, path));
if (it == responses_.end()) {
uint64_t ignored = 0;
if (generate_bytes_response_) {
- if (QuicTextUtils::StringToUint64(
- QuicStringPiece(path.data() + 1, path.size() - 1), &ignored)) {
+ if (quiche::QuicheTextUtils::StringToUint64(
+ quiche::QuicheStringPiece(path.data() + 1, path.size() - 1),
+ &ignored)) {
// The actual parsed length is ignored here and will be recomputed
// by the caller.
return generate_bytes_response_.get();
@@ -158,22 +166,23 @@ const QuicBackendResponse* QuicMemoryCacheBackend::GetResponse(
typedef QuicBackendResponse::ServerPushInfo ServerPushInfo;
typedef QuicBackendResponse::SpecialResponseType SpecialResponseType;
-void QuicMemoryCacheBackend::AddSimpleResponse(QuicStringPiece host,
- QuicStringPiece path,
+void QuicMemoryCacheBackend::AddSimpleResponse(quiche::QuicheStringPiece host,
+ quiche::QuicheStringPiece path,
int response_code,
- QuicStringPiece body) {
+ quiche::QuicheStringPiece body) {
SpdyHeaderBlock response_headers;
- response_headers[":status"] = QuicTextUtils::Uint64ToString(response_code);
+ response_headers[":status"] =
+ quiche::QuicheTextUtils::Uint64ToString(response_code);
response_headers["content-length"] =
- QuicTextUtils::Uint64ToString(body.length());
+ quiche::QuicheTextUtils::Uint64ToString(body.length());
AddResponse(host, path, std::move(response_headers), body);
}
void QuicMemoryCacheBackend::AddSimpleResponseWithServerPushResources(
- QuicStringPiece host,
- QuicStringPiece path,
+ quiche::QuicheStringPiece host,
+ quiche::QuicheStringPiece path,
int response_code,
- QuicStringPiece body,
+ quiche::QuicheStringPiece body,
std::list<ServerPushInfo> push_resources) {
AddSimpleResponse(host, path, response_code, body);
MaybeAddServerPushResources(host, path, push_resources);
@@ -184,48 +193,50 @@ void QuicMemoryCacheBackend::AddDefaultResponse(QuicBackendResponse* response) {
default_response_.reset(response);
}
-void QuicMemoryCacheBackend::AddResponse(QuicStringPiece host,
- QuicStringPiece path,
- SpdyHeaderBlock response_headers,
- QuicStringPiece response_body) {
+void QuicMemoryCacheBackend::AddResponse(
+ quiche::QuicheStringPiece host,
+ quiche::QuicheStringPiece path,
+ SpdyHeaderBlock response_headers,
+ quiche::QuicheStringPiece response_body) {
AddResponseImpl(host, path, QuicBackendResponse::REGULAR_RESPONSE,
std::move(response_headers), response_body, SpdyHeaderBlock(),
0);
}
-void QuicMemoryCacheBackend::AddResponse(QuicStringPiece host,
- QuicStringPiece path,
- SpdyHeaderBlock response_headers,
- QuicStringPiece response_body,
- SpdyHeaderBlock response_trailers) {
+void QuicMemoryCacheBackend::AddResponse(
+ quiche::QuicheStringPiece host,
+ quiche::QuicheStringPiece path,
+ SpdyHeaderBlock response_headers,
+ quiche::QuicheStringPiece response_body,
+ SpdyHeaderBlock response_trailers) {
AddResponseImpl(host, path, QuicBackendResponse::REGULAR_RESPONSE,
std::move(response_headers), response_body,
std::move(response_trailers), 0);
}
void QuicMemoryCacheBackend::AddSpecialResponse(
- QuicStringPiece host,
- QuicStringPiece path,
+ quiche::QuicheStringPiece host,
+ quiche::QuicheStringPiece path,
SpecialResponseType response_type) {
AddResponseImpl(host, path, response_type, SpdyHeaderBlock(), "",
SpdyHeaderBlock(), 0);
}
void QuicMemoryCacheBackend::AddSpecialResponse(
- QuicStringPiece host,
- QuicStringPiece path,
+ quiche::QuicheStringPiece host,
+ quiche::QuicheStringPiece path,
spdy::SpdyHeaderBlock response_headers,
- QuicStringPiece response_body,
+ quiche::QuicheStringPiece response_body,
SpecialResponseType response_type) {
AddResponseImpl(host, path, response_type, std::move(response_headers),
response_body, SpdyHeaderBlock(), 0);
}
void QuicMemoryCacheBackend::AddStopSendingResponse(
- QuicStringPiece host,
- QuicStringPiece path,
+ quiche::QuicheStringPiece host,
+ quiche::QuicheStringPiece path,
spdy::SpdyHeaderBlock response_headers,
- QuicStringPiece response_body,
+ quiche::QuicheStringPiece response_body,
uint16_t stop_sending_code) {
AddResponseImpl(host, path, SpecialResponseType::STOP_SENDING,
std::move(response_headers), response_body, SpdyHeaderBlock(),
@@ -249,10 +260,16 @@ bool QuicMemoryCacheBackend::InitializeBackend(
std::unique_ptr<ResourceFile> resource_file(new ResourceFile(filename));
// Tease apart filename into host and path.
- QuicStringPiece base(resource_file->file_name());
- base.remove_prefix(cache_directory.length());
+ std::string base(resource_file->file_name());
+ // Transform windows path separators to URL path separators.
+ for (size_t i = 0; i < base.length(); ++i) {
+ if (base[i] == '\\') {
+ base[i] = '/';
+ }
+ }
+ base.erase(0, cache_directory.length());
if (base[0] == '/') {
- base.remove_prefix(1);
+ base.erase(0, 1);
}
resource_file->SetHostPathFromBase(base);
@@ -346,13 +363,14 @@ QuicMemoryCacheBackend::~QuicMemoryCacheBackend() {
}
}
-void QuicMemoryCacheBackend::AddResponseImpl(QuicStringPiece host,
- QuicStringPiece path,
- SpecialResponseType response_type,
- SpdyHeaderBlock response_headers,
- QuicStringPiece response_body,
- SpdyHeaderBlock response_trailers,
- uint16_t stop_sending_code) {
+void QuicMemoryCacheBackend::AddResponseImpl(
+ quiche::QuicheStringPiece host,
+ quiche::QuicheStringPiece path,
+ SpecialResponseType response_type,
+ SpdyHeaderBlock response_headers,
+ quiche::QuicheStringPiece response_body,
+ SpdyHeaderBlock response_trailers,
+ uint16_t stop_sending_code) {
QuicWriterMutexLock lock(&response_mutex_);
DCHECK(!host.empty()) << "Host must be populated, e.g. \"www.google.com\"";
@@ -371,8 +389,9 @@ void QuicMemoryCacheBackend::AddResponseImpl(QuicStringPiece host,
responses_[key] = std::move(new_response);
}
-std::string QuicMemoryCacheBackend::GetKey(QuicStringPiece host,
- QuicStringPiece path) const {
+std::string QuicMemoryCacheBackend::GetKey(
+ quiche::QuicheStringPiece host,
+ quiche::QuicheStringPiece path) const {
std::string host_string = std::string(host);
size_t port = host_string.find(':');
if (port != std::string::npos)
@@ -381,8 +400,8 @@ std::string QuicMemoryCacheBackend::GetKey(QuicStringPiece host,
}
void QuicMemoryCacheBackend::MaybeAddServerPushResources(
- QuicStringPiece request_host,
- QuicStringPiece request_path,
+ quiche::QuicheStringPiece request_host,
+ quiche::QuicheStringPiece request_path,
std::list<ServerPushInfo> push_resources) {
std::string request_url = GetKey(request_host, request_path);
@@ -412,7 +431,7 @@ void QuicMemoryCacheBackend::MaybeAddServerPushResources(
}
if (!found_existing_response) {
// Add a server push response to responses map, if it is not in the map.
- QuicStringPiece body = push_resource.body;
+ quiche::QuicheStringPiece body = push_resource.body;
QUIC_DVLOG(1) << "Add response for push resource: host " << host
<< " path " << path;
AddResponse(host, path, push_resource.headers.Clone(), body);
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.h b/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.h
index f88d458e965..38d445c6006 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.h
@@ -13,10 +13,10 @@
#include "net/third_party/quiche/src/quic/core/http/spdy_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_mutex.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/tools/quic_backend_response.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_server_backend.h"
#include "net/third_party/quiche/src/quic/tools/quic_url.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
namespace quic {
@@ -40,34 +40,34 @@ class QuicMemoryCacheBackend : public QuicSimpleServerBackend {
void Read();
// |base| is |file_name_| with |cache_directory| prefix stripped.
- void SetHostPathFromBase(QuicStringPiece base);
+ void SetHostPathFromBase(quiche::QuicheStringPiece base);
const std::string& file_name() { return file_name_; }
- QuicStringPiece host() { return host_; }
+ quiche::QuicheStringPiece host() { return host_; }
- QuicStringPiece path() { return path_; }
+ quiche::QuicheStringPiece path() { return path_; }
const spdy::SpdyHeaderBlock& spdy_headers() { return spdy_headers_; }
- QuicStringPiece body() { return body_; }
+ quiche::QuicheStringPiece body() { return body_; }
- const std::vector<QuicStringPiece>& push_urls() { return push_urls_; }
+ const std::vector<quiche::QuicheStringPiece>& push_urls() {
+ return push_urls_;
+ }
- protected:
+ private:
void HandleXOriginalUrl();
- QuicStringPiece RemoveScheme(QuicStringPiece url);
+ quiche::QuicheStringPiece RemoveScheme(quiche::QuicheStringPiece url);
std::string file_name_;
std::string file_contents_;
- QuicStringPiece body_;
+ quiche::QuicheStringPiece body_;
spdy::SpdyHeaderBlock spdy_headers_;
- QuicStringPiece x_original_url_;
- std::vector<QuicStringPiece> push_urls_;
-
- private:
- QuicStringPiece host_;
- QuicStringPiece path_;
+ quiche::QuicheStringPiece x_original_url_;
+ std::vector<quiche::QuicheStringPiece> push_urls_;
+ std::string host_;
+ std::string path_;
};
QuicMemoryCacheBackend();
@@ -77,57 +77,57 @@ class QuicMemoryCacheBackend : public QuicSimpleServerBackend {
// Retrieve a response from this cache for a given host and path..
// If no appropriate response exists, nullptr is returned.
- const QuicBackendResponse* GetResponse(QuicStringPiece host,
- QuicStringPiece path) const;
+ const QuicBackendResponse* GetResponse(quiche::QuicheStringPiece host,
+ quiche::QuicheStringPiece path) const;
// Adds a simple response to the cache. The response headers will
// only contain the "content-length" header with the length of |body|.
- void AddSimpleResponse(QuicStringPiece host,
- QuicStringPiece path,
+ void AddSimpleResponse(quiche::QuicheStringPiece host,
+ quiche::QuicheStringPiece path,
int response_code,
- QuicStringPiece body);
+ quiche::QuicheStringPiece body);
// Add a simple response to the cache as AddSimpleResponse() does, and add
// some server push resources(resource path, corresponding response status and
// path) associated with it.
// Push resource implicitly come from the same host.
void AddSimpleResponseWithServerPushResources(
- QuicStringPiece host,
- QuicStringPiece path,
+ quiche::QuicheStringPiece host,
+ quiche::QuicheStringPiece path,
int response_code,
- QuicStringPiece body,
+ quiche::QuicheStringPiece body,
std::list<QuicBackendResponse::ServerPushInfo> push_resources);
// Add a response to the cache.
- void AddResponse(QuicStringPiece host,
- QuicStringPiece path,
+ void AddResponse(quiche::QuicheStringPiece host,
+ quiche::QuicheStringPiece path,
spdy::SpdyHeaderBlock response_headers,
- QuicStringPiece response_body);
+ quiche::QuicheStringPiece response_body);
// Add a response, with trailers, to the cache.
- void AddResponse(QuicStringPiece host,
- QuicStringPiece path,
+ void AddResponse(quiche::QuicheStringPiece host,
+ quiche::QuicheStringPiece path,
spdy::SpdyHeaderBlock response_headers,
- QuicStringPiece response_body,
+ quiche::QuicheStringPiece response_body,
spdy::SpdyHeaderBlock response_trailers);
// Simulate a special behavior at a particular path.
void AddSpecialResponse(
- QuicStringPiece host,
- QuicStringPiece path,
+ quiche::QuicheStringPiece host,
+ quiche::QuicheStringPiece path,
QuicBackendResponse::SpecialResponseType response_type);
void AddSpecialResponse(
- QuicStringPiece host,
- QuicStringPiece path,
+ quiche::QuicheStringPiece host,
+ quiche::QuicheStringPiece path,
spdy::SpdyHeaderBlock response_headers,
- QuicStringPiece response_body,
+ quiche::QuicheStringPiece response_body,
QuicBackendResponse::SpecialResponseType response_type);
- void AddStopSendingResponse(QuicStringPiece host,
- QuicStringPiece path,
+ void AddStopSendingResponse(quiche::QuicheStringPiece host,
+ quiche::QuicheStringPiece path,
spdy::SpdyHeaderBlock response_headers,
- QuicStringPiece response_body,
+ quiche::QuicheStringPiece response_body,
uint16_t stop_sending_code);
// Sets a default response in case of cache misses. Takes ownership of
@@ -154,21 +154,22 @@ class QuicMemoryCacheBackend : public QuicSimpleServerBackend {
QuicSimpleServerBackend::RequestHandler* quic_server_stream) override;
private:
- void AddResponseImpl(QuicStringPiece host,
- QuicStringPiece path,
+ void AddResponseImpl(quiche::QuicheStringPiece host,
+ quiche::QuicheStringPiece path,
QuicBackendResponse::SpecialResponseType response_type,
spdy::SpdyHeaderBlock response_headers,
- QuicStringPiece response_body,
+ quiche::QuicheStringPiece response_body,
spdy::SpdyHeaderBlock response_trailers,
uint16_t stop_sending_code);
- std::string GetKey(QuicStringPiece host, QuicStringPiece path) const;
+ std::string GetKey(quiche::QuicheStringPiece host,
+ quiche::QuicheStringPiece path) const;
// Add some server push urls with given responses for specified
// request if these push resources are not associated with this request yet.
void MaybeAddServerPushResources(
- QuicStringPiece request_host,
- QuicStringPiece request_path,
+ quiche::QuicheStringPiece request_host,
+ quiche::QuicheStringPiece request_path,
std::list<QuicBackendResponse::ServerPushInfo> push_resources);
// Check if push resource(push_host/push_path) associated with given request
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend_test.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend_test.cc
index 01ac334d1dd..e4b8d8e1f38 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend_test.cc
@@ -4,11 +4,12 @@
#include "net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_file_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/tools/quic_backend_response.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace quic {
namespace test {
@@ -61,7 +62,7 @@ TEST_F(QuicMemoryCacheBackendTest, AddResponse) {
spdy::SpdyHeaderBlock response_headers;
response_headers[":status"] = "200";
response_headers["content-length"] =
- QuicTextUtils::Uint64ToString(kResponseBody.size());
+ quiche::QuicheTextUtils::Uint64ToString(kResponseBody.size());
spdy::SpdyHeaderBlock response_trailers;
response_trailers["key-1"] = "value-1";
@@ -115,6 +116,32 @@ TEST_F(QuicMemoryCacheBackendTest, UsesOriginalUrl) {
EXPECT_LT(0U, response->body().length());
}
+TEST_F(QuicMemoryCacheBackendTest, UsesOriginalUrlOnly) {
+ // Tests that if the URL cannot be inferred correctly from the path
+ // because the directory does not include the hostname, that the
+ // X-Original-Url header's value will be used.
+ std::string dir;
+ std::string path = "map.html";
+ for (const std::string& file : ReadFileContents(CacheDirectory())) {
+ if (quiche::QuicheTextUtils::EndsWithIgnoreCase(file, "map.html")) {
+ dir = file;
+ dir.erase(dir.length() - path.length() - 1);
+ break;
+ }
+ }
+ ASSERT_NE("", dir);
+
+ cache_.InitializeBackend(dir);
+ const Response* response =
+ cache_.GetResponse("test.example.com", "/site_map.html");
+ ASSERT_TRUE(response);
+ ASSERT_TRUE(QuicContainsKey(response->headers(), ":status"));
+ EXPECT_EQ("200", response->headers().find(":status")->second);
+ // Connection headers are not valid in HTTP/2.
+ EXPECT_FALSE(QuicContainsKey(response->headers(), "connection"));
+ EXPECT_LT(0U, response->body().length());
+}
+
TEST_F(QuicMemoryCacheBackendTest, DefaultResponse) {
// Verify GetResponse returns nullptr when no default is set.
const Response* response = cache_.GetResponse("www.google.com", "/");
@@ -156,15 +183,16 @@ TEST_F(QuicMemoryCacheBackendTest, AddSimpleResponseWithServerPushResources) {
std::list<ServerPushInfo> push_resources;
std::string scheme = "http";
for (int i = 0; i < NumResources; ++i) {
- std::string path = "/server_push_src" + QuicTextUtils::Uint64ToString(i);
+ std::string path =
+ "/server_push_src" + quiche::QuicheTextUtils::Uint64ToString(i);
std::string url = scheme + "://" + request_host + path;
QuicUrl resource_url(url);
std::string body =
- QuicStrCat("This is server push response body for ", path);
+ quiche::QuicheStrCat("This is server push response body for ", path);
spdy::SpdyHeaderBlock response_headers;
response_headers[":status"] = "200";
response_headers["content-length"] =
- QuicTextUtils::Uint64ToString(body.size());
+ quiche::QuicheTextUtils::Uint64ToString(body.size());
push_resources.push_back(
ServerPushInfo(resource_url, response_headers.Clone(), i, body));
}
@@ -195,14 +223,15 @@ TEST_F(QuicMemoryCacheBackendTest, GetServerPushResourcesAndPushResponses) {
"404"};
std::list<ServerPushInfo> push_resources;
for (int i = 0; i < NumResources; ++i) {
- std::string path = "/server_push_src" + QuicTextUtils::Uint64ToString(i);
+ std::string path =
+ "/server_push_src" + quiche::QuicheTextUtils::Uint64ToString(i);
std::string url = scheme + "://" + request_host + path;
QuicUrl resource_url(url);
std::string body = "This is server push response body for " + path;
spdy::SpdyHeaderBlock response_headers;
response_headers[":status"] = push_response_status[i];
response_headers["content-length"] =
- QuicTextUtils::Uint64ToString(body.size());
+ quiche::QuicheTextUtils::Uint64ToString(body.size());
push_resources.push_back(
ServerPushInfo(resource_url, response_headers.Clone(), i, body));
}
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_packet_printer_bin.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_packet_printer_bin.cc
index 7738ea7938f..798b66e418e 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_packet_printer_bin.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_packet_printer_bin.cc
@@ -31,7 +31,8 @@
#include "net/third_party/quiche/src/quic/core/quic_framer.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
DEFINE_QUIC_COMMAND_LINE_FLAG(std::string,
quic_version,
@@ -64,7 +65,9 @@ class QuicPacketPrinter : public QuicFramerVisitorInterface {
}
void OnRetryPacket(QuicConnectionId /*original_connection_id*/,
QuicConnectionId /*new_connection_id*/,
- QuicStringPiece /*retry_token*/) override {
+ quiche::QuicheStringPiece /*retry_token*/,
+ quiche::QuicheStringPiece /*retry_integrity_tag*/,
+ quiche::QuicheStringPiece /*retry_without_tag*/) override {
std::cerr << "OnRetryPacket\n";
}
bool OnUnauthenticatedPublicHeader(
@@ -96,14 +99,16 @@ class QuicPacketPrinter : public QuicFramerVisitorInterface {
bool OnStreamFrame(const QuicStreamFrame& frame) override {
std::cerr << "OnStreamFrame: " << frame;
std::cerr << " data: { "
- << QuicTextUtils::HexEncode(frame.data_buffer, frame.data_length)
+ << quiche::QuicheTextUtils::HexEncode(frame.data_buffer,
+ frame.data_length)
<< " }\n";
return true;
}
bool OnCryptoFrame(const QuicCryptoFrame& frame) override {
std::cerr << "OnCryptoFrame: " << frame;
std::cerr << " data: { "
- << QuicTextUtils::HexEncode(frame.data_buffer, frame.data_length)
+ << quiche::QuicheTextUtils::HexEncode(frame.data_buffer,
+ frame.data_length)
<< " }\n";
return true;
}
@@ -198,6 +203,10 @@ class QuicPacketPrinter : public QuicFramerVisitorInterface {
std::cerr << "OnMessageFrame: " << frame;
return true;
}
+ bool OnHandshakeDoneFrame(const QuicHandshakeDoneFrame& frame) override {
+ std::cerr << "OnHandshakeDoneFrame: " << frame;
+ return true;
+ }
void OnPacketComplete() override { std::cerr << "OnPacketComplete\n"; }
bool IsValidStatelessResetToken(QuicUint128 /*token*/) const override {
std::cerr << "IsValidStatelessResetToken\n";
@@ -235,7 +244,7 @@ int main(int argc, char* argv[]) {
quic::QuicPrintCommandLineFlagHelp(usage);
return 1;
}
- std::string hex = quic::QuicTextUtils::HexDecode(args[1]);
+ std::string hex = quiche::QuicheTextUtils::HexDecode(args[1]);
quic::ParsedQuicVersionVector versions = quic::AllSupportedVersions();
// Fake a time since we're not actually generating acks.
quic::QuicTime start(quic::QuicTime::Zero());
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_reject_reason_decoder_bin.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_reject_reason_decoder_bin.cc
index de66774bab3..f7e3b75eaac 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_reject_reason_decoder_bin.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_reject_reason_decoder_bin.cc
@@ -10,7 +10,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
using quic::CryptoUtils;
using quic::HandshakeFailureReason;
@@ -27,7 +27,7 @@ int main(int argc, char* argv[]) {
}
uint32_t packed_error = 0;
- if (!quic::QuicTextUtils::StringToUint32(args[0], &packed_error)) {
+ if (!quiche::QuicheTextUtils::StringToUint32(args[0], &packed_error)) {
std::cerr << "Unable to parse: " << args[0] << "\n";
return 2;
}
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_server.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_server.cc
index 04cc9508aad..53fb95f0334 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_server.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_server.cc
@@ -16,6 +16,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
+#include "net/third_party/quiche/src/quic/core/quic_clock.h"
#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_data_reader.h"
#include "net/third_party/quiche/src/quic/core/quic_default_packet_writer.h"
@@ -24,19 +25,13 @@
#include "net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.h"
#include "net/third_party/quiche/src/quic/core/quic_packet_reader.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/quic/platform/impl/quic_epoll_clock.h"
-#include "net/quic/platform/impl/quic_socket_utils.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_crypto_server_stream_helper.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_server_backend.h"
-#ifndef SO_RXQ_OVFL
-#define SO_RXQ_OVFL 40
-#endif
-
namespace quic {
namespace {
@@ -118,15 +113,18 @@ void QuicServer::Initialize() {
QuicServer::~QuicServer() = default;
bool QuicServer::CreateUDPSocketAndListen(const QuicSocketAddress& address) {
- fd_ = QuicSocketUtils::CreateUDPSocket(
- address,
- /*receive_buffer_size =*/kDefaultSocketReceiveBuffer,
- /*send_buffer_size =*/kDefaultSocketReceiveBuffer, &overflow_supported_);
- if (fd_ < 0) {
+ QuicUdpSocketApi socket_api;
+ fd_ = socket_api.Create(address.host().AddressFamilyToInt(),
+ /*receive_buffer_size =*/kDefaultSocketReceiveBuffer,
+ /*send_buffer_size =*/kDefaultSocketReceiveBuffer);
+ if (fd_ == kQuicInvalidSocketFd) {
QUIC_LOG(ERROR) << "CreateSocket() failed: " << strerror(errno);
return false;
}
+ overflow_supported_ = socket_api.EnableDroppedPacketCount(fd_);
+ socket_api.EnableReceiveTimestamp(fd_);
+
sockaddr_storage addr = address.generic_address();
int rc = bind(fd_, reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
if (rc < 0) {
@@ -161,7 +159,7 @@ QuicDispatcher* QuicServer::CreateQuicDispatcher() {
&config_, &crypto_config_, &version_manager_,
std::unique_ptr<QuicEpollConnectionHelper>(new QuicEpollConnectionHelper(
&epoll_server_, QuicAllocator::BUFFER_POOL)),
- std::unique_ptr<QuicCryptoServerStream::Helper>(
+ std::unique_ptr<QuicCryptoServerStreamBase::Helper>(
new QuicSimpleCryptoServerStreamHelper()),
std::unique_ptr<QuicEpollAlarmFactory>(
new QuicEpollAlarmFactory(&epoll_server_)),
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_server.h b/chromium/net/third_party/quiche/src/quic/tools/quic_server.h
index 0b11be3c496..6059ea08746 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_server.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_server.h
@@ -18,11 +18,13 @@
#include "net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.h"
#include "net/third_party/quiche/src/quic/core/quic_framer.h"
#include "net/third_party/quiche/src/quic/core/quic_packet_writer.h"
+#include "net/third_party/quiche/src/quic/core/quic_udp_socket.h"
#include "net/third_party/quiche/src/quic/core/quic_version_manager.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_epoll.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_server_backend.h"
#include "net/third_party/quiche/src/quic/tools/quic_spdy_server_base.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -79,7 +81,7 @@ class QuicServer : public QuicSpdyServerBase,
crypto_config_.set_chlo_multiplier(multiplier);
}
- void SetPreSharedKey(QuicStringPiece key) {
+ void SetPreSharedKey(quiche::QuicheStringPiece key) {
crypto_config_.set_pre_shared_key(key);
}
@@ -89,6 +91,8 @@ class QuicServer : public QuicSpdyServerBase,
int port() { return port_; }
+ QuicEpollServer* epoll_server() { return &epoll_server_; }
+
protected:
virtual QuicPacketWriter* CreateWriter(int fd);
@@ -96,7 +100,6 @@ class QuicServer : public QuicSpdyServerBase,
const QuicConfig& config() const { return config_; }
const QuicCryptoServerConfig& crypto_config() const { return crypto_config_; }
- QuicEpollServer* epoll_server() { return &epoll_server_; }
QuicDispatcher* dispatcher() { return dispatcher_.get(); }
@@ -127,7 +130,7 @@ class QuicServer : public QuicSpdyServerBase,
int port_;
// Listening connection. Also used for outbound client communication.
- int fd_;
+ QuicUdpSocketFd fd_;
// If overflow_supported_ is true this will be the number of packets dropped
// during the lifetime of the server. This may overflow if enough packets
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_server_test.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_server_test.cc
index 8c894434dee..fb7955f2554 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_server_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_server_test.cc
@@ -8,7 +8,6 @@
#include "net/third_party/quiche/src/quic/core/quic_epoll_alarm_factory.h"
#include "net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_port_utils.h"
@@ -20,6 +19,7 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_server_peer.h"
#include "net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_crypto_server_stream_helper.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
namespace quic {
namespace test {
@@ -35,7 +35,7 @@ class MockQuicSimpleDispatcher : public QuicSimpleDispatcher {
const QuicCryptoServerConfig* crypto_config,
QuicVersionManager* version_manager,
std::unique_ptr<QuicConnectionHelperInterface> helper,
- std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
+ std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
std::unique_ptr<QuicAlarmFactory> alarm_factory,
QuicSimpleServerBackend* quic_simple_server_backend)
: QuicSimpleDispatcher(config,
@@ -71,7 +71,7 @@ class TestQuicServer : public QuicServer {
std::unique_ptr<QuicEpollConnectionHelper>(
new QuicEpollConnectionHelper(epoll_server(),
QuicAllocator::BUFFER_POOL)),
- std::unique_ptr<QuicCryptoServerStream::Helper>(
+ std::unique_ptr<QuicCryptoServerStreamBase::Helper>(
new QuicSimpleCryptoServerStreamHelper()),
std::unique_ptr<QuicEpollAlarmFactory>(
new QuicEpollAlarmFactory(epoll_server())),
@@ -136,9 +136,9 @@ TEST_F(QuicServerEpollInTest, ProcessBufferedCHLOsOnEpollin) {
ASSERT_LT(0, fd);
char buf[1024];
- memset(buf, 0, QUIC_ARRAYSIZE(buf));
+ memset(buf, 0, QUICHE_ARRAYSIZE(buf));
sockaddr_storage storage = server_address_.generic_address();
- int rc = sendto(fd, buf, QUIC_ARRAYSIZE(buf), 0,
+ int rc = sendto(fd, buf, QUICHE_ARRAYSIZE(buf), 0,
reinterpret_cast<sockaddr*>(&storage), sizeof(storage));
if (rc < 0) {
QUIC_DLOG(INFO) << errno << " " << strerror(errno);
@@ -164,7 +164,7 @@ class QuicServerDispatchPacketTest : public QuicTest {
std::unique_ptr<QuicEpollConnectionHelper>(
new QuicEpollConnectionHelper(&eps_,
QuicAllocator::BUFFER_POOL)),
- std::unique_ptr<QuicCryptoServerStream::Helper>(
+ std::unique_ptr<QuicCryptoServerStreamBase::Helper>(
new QuicSimpleCryptoServerStreamHelper()),
std::unique_ptr<QuicEpollAlarmFactory>(
new QuicEpollAlarmFactory(&eps_)),
@@ -202,7 +202,7 @@ TEST_F(QuicServerDispatchPacketTest, DispatchPacket) {
};
// clang-format on
QuicReceivedPacket encrypted_valid_packet(
- reinterpret_cast<char*>(valid_packet), QUIC_ARRAYSIZE(valid_packet),
+ reinterpret_cast<char*>(valid_packet), QUICHE_ARRAYSIZE(valid_packet),
QuicTime::Zero(), false);
EXPECT_CALL(dispatcher_, ProcessPacket(_, _, _)).Times(1);
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_crypto_server_stream_helper.h b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_crypto_server_stream_helper.h
index c4dcb08daee..02745cd8acc 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_crypto_server_stream_helper.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_crypto_server_stream_helper.h
@@ -6,14 +6,14 @@
#define QUICHE_QUIC_TOOLS_QUIC_SIMPLE_CRYPTO_SERVER_STREAM_HELPER_H_
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
-#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
+#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h"
namespace quic {
// Simple helper for server crypto streams which generates a new random
// connection ID for rejects.
class QuicSimpleCryptoServerStreamHelper
- : public QuicCryptoServerStream::Helper {
+ : public QuicCryptoServerStreamBase::Helper {
public:
QuicSimpleCryptoServerStreamHelper();
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.cc
index 0f4d4476848..e361511f5b3 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.cc
@@ -5,6 +5,7 @@
#include "net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_server_session.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -13,7 +14,7 @@ QuicSimpleDispatcher::QuicSimpleDispatcher(
const QuicCryptoServerConfig* crypto_config,
QuicVersionManager* version_manager,
std::unique_ptr<QuicConnectionHelperInterface> helper,
- std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
+ std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
std::unique_ptr<QuicAlarmFactory> alarm_factory,
QuicSimpleServerBackend* quic_simple_server_backend,
uint8_t expected_server_connection_id_length)
@@ -47,10 +48,10 @@ void QuicSimpleDispatcher::OnRstStreamReceived(
}
}
-QuicServerSessionBase* QuicSimpleDispatcher::CreateQuicSession(
+std::unique_ptr<QuicSession> QuicSimpleDispatcher::CreateQuicSession(
QuicConnectionId connection_id,
const QuicSocketAddress& client_address,
- QuicStringPiece /*alpn*/,
+ quiche::QuicheStringPiece /*alpn*/,
const ParsedQuicVersion& version) {
// The QuicServerSessionBase takes ownership of |connection| below.
QuicConnection* connection = new QuicConnection(
@@ -58,7 +59,7 @@ QuicServerSessionBase* QuicSimpleDispatcher::CreateQuicSession(
/* owns_writer= */ false, Perspective::IS_SERVER,
ParsedQuicVersionVector{version});
- QuicServerSessionBase* session = new QuicSimpleServerSession(
+ auto session = std::make_unique<QuicSimpleServerSession>(
config(), GetSupportedVersions(), connection, this, session_helper(),
crypto_config(), compressed_certs_cache(), quic_simple_server_backend_);
session->Initialize();
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.h b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.h
index 8a6cf85e6c5..dbb5fdf463c 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.h
@@ -8,6 +8,7 @@
#include "net/third_party/quiche/src/quic/core/http/quic_server_session_base.h"
#include "net/third_party/quiche/src/quic/core/quic_dispatcher.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_server_backend.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -18,7 +19,7 @@ class QuicSimpleDispatcher : public QuicDispatcher {
const QuicCryptoServerConfig* crypto_config,
QuicVersionManager* version_manager,
std::unique_ptr<QuicConnectionHelperInterface> helper,
- std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
+ std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
std::unique_ptr<QuicAlarmFactory> alarm_factory,
QuicSimpleServerBackend* quic_simple_server_backend,
uint8_t expected_server_connection_id_length);
@@ -30,10 +31,10 @@ class QuicSimpleDispatcher : public QuicDispatcher {
void OnRstStreamReceived(const QuicRstStreamFrame& frame) override;
protected:
- QuicServerSessionBase* CreateQuicSession(
+ std::unique_ptr<QuicSession> CreateQuicSession(
QuicConnectionId connection_id,
const QuicSocketAddress& client_address,
- QuicStringPiece alpn,
+ quiche::QuicheStringPiece alpn,
const ParsedQuicVersion& version) override;
QuicSimpleServerBackend* server_backend() {
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session.cc
index c60a9e229ee..5c83b4800fd 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session.cc
@@ -21,7 +21,7 @@ QuicSimpleServerSession::QuicSimpleServerSession(
const ParsedQuicVersionVector& supported_versions,
QuicConnection* connection,
QuicSession::Visitor* visitor,
- QuicCryptoServerStream::Helper* helper,
+ QuicCryptoServerStreamBase::Helper* helper,
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache,
QuicSimpleServerBackend* quic_simple_server_backend)
@@ -39,15 +39,15 @@ QuicSimpleServerSession::QuicSimpleServerSession(
}
QuicSimpleServerSession::~QuicSimpleServerSession() {
- delete connection();
+ DeleteConnection();
}
-QuicCryptoServerStreamBase*
+std::unique_ptr<QuicCryptoServerStreamBase>
QuicSimpleServerSession::CreateQuicCryptoServerStream(
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache) {
- return new QuicCryptoServerStream(crypto_config, compressed_certs_cache, this,
- stream_helper());
+ return CreateCryptoServerStream(crypto_config, compressed_certs_cache, this,
+ stream_helper());
}
void QuicSimpleServerSession::OnStreamFrame(const QuicStreamFrame& frame) {
@@ -74,10 +74,14 @@ void QuicSimpleServerSession::PromisePushResources(
for (QuicBackendResponse::ServerPushInfo resource : resources) {
spdy::SpdyHeaderBlock headers = SynthesizePushRequestHeaders(
request_url, resource, original_request_headers);
+ // TODO(b/136295430): Use sequential push IDs for IETF QUIC.
+ // TODO(bnc): If |highest_promised_stream_id_| is too large, it will always
+ // be skipped. Fix it by not incrementing if CanCreatePushStreamWithId()
+ // returns false.
highest_promised_stream_id_ +=
QuicUtils::StreamIdDelta(transport_version());
if (VersionUsesHttp3(transport_version()) &&
- highest_promised_stream_id_ > max_allowed_push_id()) {
+ !CanCreatePushStreamWithId(highest_promised_stream_id_)) {
return;
}
SendPushPromise(original_stream_id, highest_promised_stream_id_,
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session.h b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session.h
index d485e7c28dc..9942c7d80ad 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session.h
@@ -18,7 +18,7 @@
#include "net/third_party/quiche/src/quic/core/http/quic_server_session_base.h"
#include "net/third_party/quiche/src/quic/core/http/quic_spdy_session.h"
-#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
+#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/tools/quic_backend_response.h"
@@ -56,7 +56,7 @@ class QuicSimpleServerSession : public QuicServerSessionBase {
const ParsedQuicVersionVector& supported_versions,
QuicConnection* connection,
QuicSession::Visitor* visitor,
- QuicCryptoServerStream::Helper* helper,
+ QuicCryptoServerStreamBase::Helper* helper,
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache,
QuicSimpleServerBackend* quic_simple_server_backend);
@@ -94,7 +94,7 @@ class QuicSimpleServerSession : public QuicServerSessionBase {
const QuicRstStreamFrame& frame) override;
// QuicServerSessionBaseMethod:
- QuicCryptoServerStreamBase* CreateQuicCryptoServerStream(
+ std::unique_ptr<QuicCryptoServerStreamBase> CreateQuicCryptoServerStream(
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache) override;
@@ -147,7 +147,7 @@ class QuicSimpleServerSession : public QuicServerSessionBase {
// the queue also increases by 2 from previous one's. The front element's
// stream_id is always next_outgoing_stream_id_, and the last one is always
// highest_promised_stream_id_.
- QuicDeque<PromisedStreamInfo> promised_streams_;
+ QuicCircularDeque<PromisedStreamInfo> promised_streams_;
QuicSimpleServerBackend* quic_simple_server_backend_; // Not owned.
};
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session_test.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session_test.cc
index a548c6c906a..f9c28a701d0 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session_test.cc
@@ -16,13 +16,12 @@
#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
+#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_quic_session_visitor.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
@@ -36,8 +35,11 @@
#include "net/third_party/quiche/src/quic/tools/quic_backend_response.h"
#include "net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_server_stream.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
using testing::_;
+using testing::AnyNumber;
using testing::AtLeast;
using testing::InSequence;
using testing::Invoke;
@@ -58,7 +60,7 @@ const QuicByteCount kHeadersFramePayloadLength = 9;
class QuicSimpleServerSessionPeer {
public:
static void SetCryptoStream(QuicSimpleServerSession* s,
- QuicCryptoServerStream* crypto_stream) {
+ QuicCryptoServerStreamBase* crypto_stream) {
s->crypto_stream_.reset(crypto_stream);
}
@@ -82,8 +84,8 @@ class MockQuicCryptoServerStream : public QuicCryptoServerStream {
explicit MockQuicCryptoServerStream(
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache,
- QuicServerSessionBase* session,
- QuicCryptoServerStream::Helper* helper)
+ QuicSession* session,
+ QuicCryptoServerStreamBase::Helper* helper)
: QuicCryptoServerStream(crypto_config,
compressed_certs_cache,
session,
@@ -96,19 +98,46 @@ class MockQuicCryptoServerStream : public QuicCryptoServerStream {
MOCK_METHOD1(SendServerConfigUpdate,
void(const CachedNetworkParameters* cached_network_parameters));
- void set_encryption_established(bool has_established) {
- encryption_established_override_ = has_established;
- }
+ bool encryption_established() const override { return true; }
+};
- bool encryption_established() const override {
- return QuicCryptoServerStream::encryption_established() ||
- encryption_established_override_;
- }
+class MockTlsServerHandshaker : public TlsServerHandshaker {
+ public:
+ explicit MockTlsServerHandshaker(QuicSession* session,
+ SSL_CTX* ssl_ctx,
+ ProofSource* proof_source)
+ : TlsServerHandshaker(session, ssl_ctx, proof_source) {}
+ MockTlsServerHandshaker(const MockTlsServerHandshaker&) = delete;
+ MockTlsServerHandshaker& operator=(const MockTlsServerHandshaker&) = delete;
+ ~MockTlsServerHandshaker() override {}
+
+ MOCK_METHOD1(SendServerConfigUpdate,
+ void(const CachedNetworkParameters* cached_network_parameters));
- private:
- bool encryption_established_override_ = false;
+ bool encryption_established() const override { return true; }
};
+QuicCryptoServerStreamBase* CreateMockCryptoServerStream(
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache,
+ QuicSession* session,
+ QuicCryptoServerStreamBase::Helper* helper) {
+ switch (session->connection()->version().handshake_protocol) {
+ case PROTOCOL_QUIC_CRYPTO:
+ return new MockQuicCryptoServerStream(
+ crypto_config, compressed_certs_cache, session, helper);
+ case PROTOCOL_TLS1_3:
+ return new MockTlsServerHandshaker(session, crypto_config->ssl_ctx(),
+ crypto_config->proof_source());
+ case PROTOCOL_UNSUPPORTED:
+ break;
+ }
+ QUIC_BUG << "Unknown handshake protocol: "
+ << static_cast<int>(
+ session->connection()->version().handshake_protocol);
+ return nullptr;
+}
+
class MockQuicConnectionWithSendStreamData : public MockQuicConnection {
public:
MockQuicConnectionWithSendStreamData(
@@ -142,7 +171,7 @@ class MockQuicSimpleServerSession : public QuicSimpleServerSession {
const QuicConfig& config,
QuicConnection* connection,
QuicSession::Visitor* visitor,
- QuicCryptoServerStream::Helper* helper,
+ QuicCryptoServerStreamBase::Helper* helper,
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache,
QuicSimpleServerBackend* quic_simple_server_backend)
@@ -194,11 +223,10 @@ class QuicSimpleServerSessionTest
KeyExchangeSource::Default()),
compressed_certs_cache_(
QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) {
- SetQuicReloadableFlag(quic_supports_tls_handshake, true);
- config_.SetMaxIncomingBidirectionalStreamsToSend(kMaxStreamsForTest);
- QuicConfigPeer::SetReceivedMaxIncomingBidirectionalStreams(
- &config_, kMaxStreamsForTest);
- config_.SetMaxIncomingUnidirectionalStreamsToSend(kMaxStreamsForTest);
+ config_.SetMaxBidirectionalStreamsToSend(kMaxStreamsForTest);
+ QuicConfigPeer::SetReceivedMaxBidirectionalStreams(&config_,
+ kMaxStreamsForTest);
+ config_.SetMaxUnidirectionalStreamsToSend(kMaxStreamsForTest);
config_.SetInitialStreamFlowControlWindowToSend(
kInitialStreamFlowControlWindowForTest);
@@ -210,12 +238,12 @@ class QuicSimpleServerSessionTest
kInitialStreamFlowControlWindowForTest);
config_.SetInitialSessionFlowControlWindowToSend(
kInitialSessionFlowControlWindowForTest);
- if (VersionUsesHttp3(GetParam().transport_version)) {
- QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams(
+ if (VersionUsesHttp3(transport_version())) {
+ QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(
&config_, kMaxStreamsForTest + 3);
} else {
- QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams(
- &config_, kMaxStreamsForTest);
+ QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(&config_,
+ kMaxStreamsForTest);
}
ParsedQuicVersionVector supported_versions = SupportedVersions(GetParam());
@@ -230,10 +258,6 @@ class QuicSimpleServerSessionTest
QuicRandom::GetInstance(), &clock,
QuicCryptoServerConfig::ConfigOptions());
session_->Initialize();
- if (!GetQuicReloadableFlag(quic_version_negotiated_by_default_at_server)) {
- QuicSessionPeer::GetMutableCryptoStream(session_.get())
- ->OnSuccessfulVersionNegotiation(supported_versions.front());
- }
if (VersionHasIetfQuicFrames(transport_version())) {
EXPECT_CALL(*connection_, SendControlFrame(_))
@@ -244,17 +268,16 @@ class QuicSimpleServerSessionTest
}
QuicStreamId GetNthClientInitiatedBidirectionalId(int n) {
- return GetNthClientInitiatedBidirectionalStreamId(
- connection_->transport_version(), n);
+ return GetNthClientInitiatedBidirectionalStreamId(transport_version(), n);
}
QuicStreamId GetNthServerInitiatedUnidirectionalId(int n) {
return quic::test::GetNthServerInitiatedUnidirectionalStreamId(
- connection_->transport_version(), n);
+ transport_version(), n);
}
QuicTransportVersion transport_version() const {
- return connection_->transport_version();
+ return GetParam().transport_version;
}
void InjectStopSending(QuicStreamId stream_id,
@@ -298,7 +321,7 @@ TEST_P(QuicSimpleServerSessionTest, CloseStreamDueToReset) {
// Open a stream, then reset it.
// Send two bytes of payload to open it.
QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
- QuicStringPiece("HT"));
+ quiche::QuicheStringPiece("HT"));
session_->OnStreamFrame(data1);
EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams());
@@ -354,7 +377,7 @@ TEST_P(QuicSimpleServerSessionTest, NeverOpenStreamDueToReset) {
// Send two bytes of payload.
QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
- QuicStringPiece("HT"));
+ quiche::QuicheStringPiece("HT"));
session_->OnStreamFrame(data1);
// The stream should never be opened, now that the reset is received.
@@ -365,9 +388,9 @@ TEST_P(QuicSimpleServerSessionTest, NeverOpenStreamDueToReset) {
TEST_P(QuicSimpleServerSessionTest, AcceptClosedStream) {
// Send (empty) compressed headers followed by two bytes of data.
QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
- QuicStringPiece("\1\0\0\0\0\0\0\0HT"));
+ quiche::QuicheStringPiece("\1\0\0\0\0\0\0\0HT"));
QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(1), false, 0,
- QuicStringPiece("\2\0\0\0\0\0\0\0HT"));
+ quiche::QuicheStringPiece("\2\0\0\0\0\0\0\0HT"));
session_->OnStreamFrame(frame1);
session_->OnStreamFrame(frame2);
EXPECT_EQ(2u, session_->GetNumOpenIncomingStreams());
@@ -395,9 +418,9 @@ TEST_P(QuicSimpleServerSessionTest, AcceptClosedStream) {
// past the reset point of stream 3. As it's a closed stream we just drop the
// data on the floor, but accept the packet because it has data for stream 5.
QuicStreamFrame frame3(GetNthClientInitiatedBidirectionalId(0), false, 2,
- QuicStringPiece("TP"));
+ quiche::QuicheStringPiece("TP"));
QuicStreamFrame frame4(GetNthClientInitiatedBidirectionalId(1), false, 2,
- QuicStringPiece("TP"));
+ quiche::QuicheStringPiece("TP"));
session_->OnStreamFrame(frame3);
session_->OnStreamFrame(frame4);
// The stream should never be opened, now that the reset is received.
@@ -420,17 +443,6 @@ TEST_P(QuicSimpleServerSessionTest, CreateIncomingStreamDisconnected) {
EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenIncomingStreams());
}
-TEST_P(QuicSimpleServerSessionTest, CreateEvenIncomingDynamicStream) {
- // Tests that incoming stream creation fails when given stream id is even.
- size_t initial_num_open_stream = session_->GetNumOpenIncomingStreams();
- EXPECT_CALL(*connection_,
- CloseConnection(QUIC_INVALID_STREAM_ID,
- "Client created even numbered stream", _));
- QuicSimpleServerSessionPeer::CreateIncomingStream(
- session_.get(), GetNthServerInitiatedUnidirectionalId(0));
- EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenIncomingStreams());
-}
-
TEST_P(QuicSimpleServerSessionTest, CreateIncomingStream) {
QuicSpdyStream* stream = QuicSimpleServerSessionPeer::CreateIncomingStream(
session_.get(), GetNthClientInitiatedBidirectionalId(0));
@@ -479,26 +491,25 @@ TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamUptoLimit) {
// Receive some data to initiate a incoming stream which should not effect
// creating outgoing streams.
QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
- QuicStringPiece("HT"));
+ quiche::QuicheStringPiece("HT"));
session_->OnStreamFrame(data1);
EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams());
EXPECT_EQ(0u, session_->GetNumOpenOutgoingStreams());
- if (!VersionUsesHttp3(connection_->transport_version())) {
+ if (!VersionUsesHttp3(transport_version())) {
session_->UnregisterStreamPriority(
- QuicUtils::GetHeadersStreamId(connection_->transport_version()),
+ QuicUtils::GetHeadersStreamId(transport_version()),
/*is_static=*/true);
}
// Assume encryption already established.
QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), nullptr);
- MockQuicCryptoServerStream* crypto_stream =
- new MockQuicCryptoServerStream(&crypto_config_, &compressed_certs_cache_,
- session_.get(), &stream_helper_);
- crypto_stream->set_encryption_established(true);
+ QuicCryptoServerStreamBase* crypto_stream =
+ CreateMockCryptoServerStream(&crypto_config_, &compressed_certs_cache_,
+ session_.get(), &stream_helper_);
QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), crypto_stream);
- if (!VersionUsesHttp3(connection_->transport_version())) {
+ if (!VersionUsesHttp3(transport_version())) {
session_->RegisterStreamPriority(
- QuicUtils::GetHeadersStreamId(connection_->transport_version()),
+ QuicUtils::GetHeadersStreamId(transport_version()),
/*is_static=*/true,
spdy::SpdyStreamPrecedence(QuicStream::kDefaultPriority));
}
@@ -508,7 +519,7 @@ TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamUptoLimit) {
QuicSpdyStream* created_stream =
QuicSimpleServerSessionPeer::CreateOutgoingUnidirectionalStream(
session_.get());
- if (VersionUsesHttp3(connection_->transport_version())) {
+ if (VersionUsesHttp3(transport_version())) {
EXPECT_EQ(GetNthServerInitiatedUnidirectionalId(i + 3),
created_stream->id());
} else {
@@ -525,28 +536,33 @@ TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamUptoLimit) {
// Create peer initiated stream should have no problem.
QuicStreamFrame data2(GetNthClientInitiatedBidirectionalId(1), false, 0,
- QuicStringPiece("HT"));
+ quiche::QuicheStringPiece("HT"));
session_->OnStreamFrame(data2);
EXPECT_EQ(2u, session_->GetNumOpenIncomingStreams());
}
TEST_P(QuicSimpleServerSessionTest, OnStreamFrameWithEvenStreamId) {
QuicStreamFrame frame(GetNthServerInitiatedUnidirectionalId(0), false, 0,
- QuicStringPiece());
+ quiche::QuicheStringPiece());
EXPECT_CALL(*connection_,
CloseConnection(QUIC_INVALID_STREAM_ID,
"Client sent data on server push stream", _));
session_->OnStreamFrame(frame);
}
+// Tests that calling GetOrCreateStream() on an outgoing stream not promised yet
+// should result close connection.
TEST_P(QuicSimpleServerSessionTest, GetEvenIncomingError) {
- // Tests that calling GetOrCreateStream() on an outgoing stream not
- // promised yet should result close connection.
- EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID,
+ const size_t initial_num_open_stream = session_->GetNumOpenIncomingStreams();
+ const QuicErrorCode expected_error = VersionUsesHttp3(transport_version())
+ ? QUIC_HTTP_STREAM_WRONG_DIRECTION
+ : QUIC_INVALID_STREAM_ID;
+ EXPECT_CALL(*connection_, CloseConnection(expected_error,
"Data for nonexistent stream", _));
EXPECT_EQ(nullptr,
QuicSessionPeer::GetOrCreateStream(
session_.get(), GetNthServerInitiatedUnidirectionalId(3)));
+ EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenIncomingStreams());
}
// In order to test the case where server push stream creation goes beyond
@@ -565,7 +581,7 @@ class QuicSimpleServerSessionServerPushTest
QuicSimpleServerSessionServerPushTest() {
// Reset stream level flow control window to be 32KB.
if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
- if (VersionHasIetfQuicFrames(GetParam().transport_version)) {
+ if (VersionHasIetfQuicFrames(transport_version())) {
QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesUnidirectional(
&config_, kStreamFlowControlWindowSize);
} else {
@@ -592,10 +608,6 @@ class QuicSimpleServerSessionServerPushTest
config_, connection_, &owner_, &stream_helper_, &crypto_config_,
&compressed_certs_cache_, &memory_cache_backend_);
session_->Initialize();
- if (!GetQuicReloadableFlag(quic_version_negotiated_by_default_at_server)) {
- QuicSessionPeer::GetMutableCryptoStream(session_.get())
- ->OnSuccessfulVersionNegotiation(supported_versions.front());
- }
// Needed to make new session flow control window and server push work.
if (VersionHasIetfQuicFrames(transport_version())) {
@@ -605,25 +617,32 @@ class QuicSimpleServerSessionServerPushTest
}
session_->OnConfigNegotiated();
- if (!VersionUsesHttp3(connection_->transport_version())) {
+ if (!VersionUsesHttp3(transport_version())) {
session_->UnregisterStreamPriority(
- QuicUtils::GetHeadersStreamId(connection_->transport_version()),
+ QuicUtils::GetHeadersStreamId(transport_version()),
/*is_static=*/true);
}
QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), nullptr);
// Assume encryption already established.
- MockQuicCryptoServerStream* crypto_stream = new MockQuicCryptoServerStream(
- &crypto_config_, &compressed_certs_cache_, session_.get(),
- &stream_helper_);
+ QuicCryptoServerStreamBase* crypto_stream =
+ CreateMockCryptoServerStream(&crypto_config_, &compressed_certs_cache_,
+ session_.get(), &stream_helper_);
- crypto_stream->set_encryption_established(true);
QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), crypto_stream);
- if (!VersionUsesHttp3(connection_->transport_version())) {
+ if (!VersionUsesHttp3(transport_version())) {
session_->RegisterStreamPriority(
- QuicUtils::GetHeadersStreamId(connection_->transport_version()),
+ QuicUtils::GetHeadersStreamId(transport_version()),
/*is_static=*/true,
spdy::SpdyStreamPrecedence(QuicStream::kDefaultPriority));
}
+ if (VersionUsesHttp3(transport_version())) {
+ // Ignore writes on the control stream.
+ auto send_control_stream =
+ QuicSpdySessionPeer::GetSendControlStream(session_.get());
+ EXPECT_CALL(*connection_,
+ SendStreamData(send_control_stream->id(), _, _, NO_FIN))
+ .Times(AnyNumber());
+ }
}
// Given |num_resources|, create this number of fake push resources and push
@@ -647,19 +666,19 @@ class QuicSimpleServerSessionServerPushTest
QuicByteCount data_frame_header_length = 0;
for (unsigned int i = 1; i <= num_resources; ++i) {
QuicStreamId stream_id;
- if (VersionUsesHttp3(connection_->transport_version())) {
+ if (VersionUsesHttp3(transport_version())) {
stream_id = GetNthServerInitiatedUnidirectionalId(i + 2);
} else {
stream_id = GetNthServerInitiatedUnidirectionalId(i - 1);
}
- std::string path =
- partial_push_resource_path + QuicTextUtils::Uint64ToString(i);
+ std::string path = partial_push_resource_path +
+ quiche::QuicheTextUtils::Uint64ToString(i);
std::string url = scheme + "://" + resource_host + path;
QuicUrl resource_url = QuicUrl(url);
std::string body(body_size, 'a');
std::string data;
data_frame_header_length = 0;
- if (VersionUsesHttp3(connection_->transport_version())) {
+ if (VersionUsesHttp3(transport_version())) {
std::unique_ptr<char[]> buffer;
data_frame_header_length =
HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
@@ -682,13 +701,13 @@ class QuicSimpleServerSessionServerPushTest
// Since flow control window is smaller than response body, not the
// whole body will be sent.
QuicStreamOffset offset = 0;
- if (VersionUsesHttp3(connection_->transport_version())) {
+ if (VersionUsesHttp3(transport_version())) {
EXPECT_CALL(*connection_,
SendStreamData(stream_id, 1, offset, NO_FIN));
offset++;
}
- if (VersionUsesHttp3(connection_->transport_version())) {
+ if (VersionUsesHttp3(transport_version())) {
EXPECT_CALL(*connection_,
SendStreamData(stream_id, kHeadersFrameHeaderLength,
offset, NO_FIN));
@@ -698,7 +717,7 @@ class QuicSimpleServerSessionServerPushTest
offset, NO_FIN));
offset += kHeadersFramePayloadLength;
}
- if (VersionUsesHttp3(connection_->transport_version())) {
+ if (VersionUsesHttp3(transport_version())) {
EXPECT_CALL(*connection_,
SendStreamData(stream_id, data_frame_header_length,
offset, NO_FIN));
@@ -718,9 +737,9 @@ class QuicSimpleServerSessionServerPushTest
}
void MaybeConsumeHeadersStreamData() {
- if (!VersionUsesHttp3(connection_->transport_version())) {
+ if (!VersionUsesHttp3(transport_version())) {
QuicStreamId headers_stream_id =
- QuicUtils::GetHeadersStreamId(connection_->transport_version());
+ QuicUtils::GetHeadersStreamId(transport_version());
EXPECT_CALL(*connection_, SendStreamData(headers_stream_id, _, _, _))
.Times(AtLeast(1));
}
@@ -736,7 +755,10 @@ INSTANTIATE_TEST_SUITE_P(Tests,
// opened and send push response.
TEST_P(QuicSimpleServerSessionServerPushTest, TestPromisePushResources) {
MaybeConsumeHeadersStreamData();
- session_->SetMaxAllowedPushId(kMaxQuicStreamId);
+ if (VersionUsesHttp3(transport_version())) {
+ session_->EnableServerPush();
+ session_->OnMaxPushIdFrame(kMaxQuicStreamId);
+ }
size_t num_resources = kMaxStreamsForTest + 5;
PromisePushResources(num_resources);
EXPECT_EQ(kMaxStreamsForTest, session_->GetNumOpenOutgoingStreams());
@@ -747,11 +769,14 @@ TEST_P(QuicSimpleServerSessionServerPushTest, TestPromisePushResources) {
TEST_P(QuicSimpleServerSessionServerPushTest,
HandlePromisedPushRequestsAfterStreamDraining) {
MaybeConsumeHeadersStreamData();
- session_->SetMaxAllowedPushId(kMaxQuicStreamId);
+ if (VersionUsesHttp3(transport_version())) {
+ session_->EnableServerPush();
+ session_->OnMaxPushIdFrame(kMaxQuicStreamId);
+ }
size_t num_resources = kMaxStreamsForTest + 1;
QuicByteCount data_frame_header_length = PromisePushResources(num_resources);
QuicStreamId next_out_going_stream_id;
- if (VersionUsesHttp3(connection_->transport_version())) {
+ if (VersionUsesHttp3(transport_version())) {
next_out_going_stream_id =
GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest + 3);
} else {
@@ -762,12 +787,12 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
// After an open stream is marked draining, a new stream is expected to be
// created and a response sent on the stream.
QuicStreamOffset offset = 0;
- if (VersionUsesHttp3(connection_->transport_version())) {
+ if (VersionUsesHttp3(transport_version())) {
EXPECT_CALL(*connection_,
SendStreamData(next_out_going_stream_id, 1, offset, NO_FIN));
offset++;
}
- if (VersionUsesHttp3(connection_->transport_version())) {
+ if (VersionUsesHttp3(transport_version())) {
EXPECT_CALL(*connection_,
SendStreamData(next_out_going_stream_id,
kHeadersFrameHeaderLength, offset, NO_FIN));
@@ -777,7 +802,7 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
kHeadersFramePayloadLength, offset, NO_FIN));
offset += kHeadersFramePayloadLength;
}
- if (VersionUsesHttp3(connection_->transport_version())) {
+ if (VersionUsesHttp3(transport_version())) {
EXPECT_CALL(*connection_,
SendStreamData(next_out_going_stream_id,
data_frame_header_length, offset, NO_FIN));
@@ -801,7 +826,7 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
QuicMaxStreamsFrame(0, num_resources + 3, /*unidirectional=*/true));
}
- if (VersionUsesHttp3(connection_->transport_version())) {
+ if (VersionUsesHttp3(transport_version())) {
session_->StreamDraining(GetNthServerInitiatedUnidirectionalId(3));
} else {
session_->StreamDraining(GetNthServerInitiatedUnidirectionalId(0));
@@ -822,7 +847,10 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
return;
}
MaybeConsumeHeadersStreamData();
- session_->SetMaxAllowedPushId(kMaxQuicStreamId);
+ if (VersionUsesHttp3(transport_version())) {
+ session_->EnableServerPush();
+ session_->OnMaxPushIdFrame(kMaxQuicStreamId);
+ }
// Having two extra resources to be send later. One of them will be reset, so
// when opened stream become close, only one will become open.
@@ -838,7 +866,7 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
// Reset the last stream in the queue. It should be marked cancelled.
QuicStreamId stream_got_reset;
- if (VersionUsesHttp3(connection_->transport_version())) {
+ if (VersionUsesHttp3(transport_version())) {
stream_got_reset =
GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest + 4);
} else {
@@ -858,7 +886,7 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
// be created. But since one of them was marked cancelled due to RST frame,
// only one queued resource will be sent out.
QuicStreamId stream_not_reset;
- if (VersionUsesHttp3(connection_->transport_version())) {
+ if (VersionUsesHttp3(transport_version())) {
stream_not_reset =
GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest + 3);
} else {
@@ -867,7 +895,7 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
}
InSequence s;
QuicStreamOffset offset = 0;
- if (VersionUsesHttp3(connection_->transport_version())) {
+ if (VersionUsesHttp3(transport_version())) {
EXPECT_CALL(*connection_,
SendStreamData(stream_not_reset, 1, offset, NO_FIN));
offset++;
@@ -907,7 +935,10 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
TEST_P(QuicSimpleServerSessionServerPushTest,
CloseStreamToHandleMorePromisedStream) {
MaybeConsumeHeadersStreamData();
- session_->SetMaxAllowedPushId(kMaxQuicStreamId);
+ if (VersionUsesHttp3(transport_version())) {
+ session_->EnableServerPush();
+ session_->OnMaxPushIdFrame(kMaxQuicStreamId);
+ }
size_t num_resources = kMaxStreamsForTest + 1;
if (VersionHasIetfQuicFrames(transport_version())) {
// V99 will send out a stream-id-blocked frame when the we desired to exceed
@@ -918,7 +949,7 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
}
QuicByteCount data_frame_header_length = PromisePushResources(num_resources);
QuicStreamId stream_to_open;
- if (VersionUsesHttp3(connection_->transport_version())) {
+ if (VersionUsesHttp3(transport_version())) {
stream_to_open =
GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest + 3);
} else {
@@ -936,7 +967,7 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
OnStreamReset(stream_got_reset, QUIC_RST_ACKNOWLEDGEMENT));
}
QuicStreamOffset offset = 0;
- if (VersionUsesHttp3(connection_->transport_version())) {
+ if (VersionUsesHttp3(transport_version())) {
EXPECT_CALL(*connection_,
SendStreamData(stream_to_open, 1, offset, NO_FIN));
offset++;
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream.cc
index f821a5d373d..a6775ccd7a0 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream.cc
@@ -14,8 +14,9 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_server_session.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
using spdy::SpdyHeaderBlock;
@@ -182,7 +183,7 @@ void QuicSimpleServerStream::OnResponseBackendComplete(
if (response->response_type() == QuicBackendResponse::CLOSE_CONNECTION) {
QUIC_DVLOG(1) << "Special response: closing connection.";
- CloseConnectionWithDetails(QUIC_NO_ERROR, "Toy server forcing close");
+ OnUnrecoverableError(QUIC_NO_ERROR, "Toy server forcing close");
return;
}
@@ -265,14 +266,15 @@ void QuicSimpleServerStream::OnResponseBackendComplete(
if (response->response_type() == QuicBackendResponse::GENERATE_BYTES) {
QUIC_DVLOG(1) << "Stream " << id() << " sending a generate bytes response.";
std::string path = request_headers_[":path"].as_string().substr(1);
- if (!QuicTextUtils::StringToUint64(path, &generate_bytes_length_)) {
+ if (!quiche::QuicheTextUtils::StringToUint64(path,
+ &generate_bytes_length_)) {
QUIC_LOG(ERROR) << "Path is not a number.";
SendNotFoundResponse();
return;
}
SpdyHeaderBlock headers = response->headers().Clone();
headers["content-length"] =
- QuicTextUtils::Uint64ToString(generate_bytes_length_);
+ quiche::QuicheTextUtils::Uint64ToString(generate_bytes_length_);
WriteHeaders(std::move(headers), false, nullptr);
@@ -307,7 +309,7 @@ void QuicSimpleServerStream::SendNotFoundResponse() {
SpdyHeaderBlock headers;
headers[":status"] = "404";
headers["content-length"] =
- QuicTextUtils::Uint64ToString(strlen(kNotFoundResponseBody));
+ quiche::QuicheTextUtils::Uint64ToString(strlen(kNotFoundResponseBody));
SendHeadersAndBody(std::move(headers), kNotFoundResponseBody);
}
@@ -321,16 +323,16 @@ void QuicSimpleServerStream::SendErrorResponse(int resp_code) {
if (resp_code <= 0) {
headers[":status"] = "500";
} else {
- headers[":status"] = QuicTextUtils::Uint64ToString(resp_code);
+ headers[":status"] = quiche::QuicheTextUtils::Uint64ToString(resp_code);
}
headers["content-length"] =
- QuicTextUtils::Uint64ToString(strlen(kErrorResponseBody));
+ quiche::QuicheTextUtils::Uint64ToString(strlen(kErrorResponseBody));
SendHeadersAndBody(std::move(headers), kErrorResponseBody);
}
void QuicSimpleServerStream::SendIncompleteResponse(
SpdyHeaderBlock response_headers,
- QuicStringPiece body) {
+ quiche::QuicheStringPiece body) {
QUIC_DLOG(INFO) << "Stream " << id() << " writing headers (fin = false) : "
<< response_headers.DebugString();
WriteHeaders(std::move(response_headers), /*fin=*/false, nullptr);
@@ -344,14 +346,14 @@ void QuicSimpleServerStream::SendIncompleteResponse(
void QuicSimpleServerStream::SendHeadersAndBody(
SpdyHeaderBlock response_headers,
- QuicStringPiece body) {
+ quiche::QuicheStringPiece body) {
SendHeadersAndBodyAndTrailers(std::move(response_headers), body,
SpdyHeaderBlock());
}
void QuicSimpleServerStream::SendHeadersAndBodyAndTrailers(
SpdyHeaderBlock response_headers,
- QuicStringPiece body,
+ quiche::QuicheStringPiece body,
SpdyHeaderBlock response_trailers) {
// Send the headers, with a FIN if there's nothing else to send.
bool send_fin = (body.empty() && response_trailers.empty());
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream.h b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream.h
index 594ca028536..add4a12875d 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream.h
@@ -7,9 +7,9 @@
#include "net/third_party/quiche/src/quic/core/http/quic_spdy_server_stream_base.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/tools/quic_backend_response.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_server_backend.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
namespace quic {
@@ -77,12 +77,12 @@ class QuicSimpleServerStream : public QuicSpdyServerStreamBase,
// Sends the response header and body, but not the fin.
void SendIncompleteResponse(spdy::SpdyHeaderBlock response_headers,
- QuicStringPiece body);
+ quiche::QuicheStringPiece body);
void SendHeadersAndBody(spdy::SpdyHeaderBlock response_headers,
- QuicStringPiece body);
+ quiche::QuicheStringPiece body);
void SendHeadersAndBodyAndTrailers(spdy::SpdyHeaderBlock response_headers,
- QuicStringPiece body,
+ quiche::QuicheStringPiece body,
spdy::SpdyHeaderBlock response_trailers);
spdy::SpdyHeaderBlock* request_headers() { return &request_headers_; }
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream_test.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream_test.cc
index 50ca84fd188..06e886680a4 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream_test.cc
@@ -10,8 +10,8 @@
#include "net/third_party/quiche/src/quic/core/http/http_encoder.h"
#include "net/third_party/quiche/src/quic/core/http/spdy_utils.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
@@ -25,6 +25,9 @@
#include "net/third_party/quiche/src/quic/tools/quic_backend_response.h"
#include "net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_server_session.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_optional.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
using testing::_;
using testing::AnyNumber;
@@ -71,7 +74,7 @@ class TestStream : public QuicSimpleServerStream {
const std::string& body() const { return body_; }
int content_length() const { return content_length_; }
- QuicStringPiece GetHeader(QuicStringPiece key) const {
+ quiche::QuicheStringPiece GetHeader(quiche::QuicheStringPiece key) const {
auto it = request_headers_.find(key);
DCHECK(it != request_headers_.end());
return it->second;
@@ -108,8 +111,8 @@ class MockQuicSimpleServerSession : public QuicSimpleServerSession {
QuicSessionPeer::SetMaxOpenIncomingStreams(this, kMaxStreamsForTest);
QuicSessionPeer::SetMaxOpenOutgoingStreams(this, kMaxStreamsForTest);
}
- ON_CALL(*this, WritevData(_, _, _, _, _))
- .WillByDefault(Invoke(MockQuicSession::ConsumeData));
+ ON_CALL(*this, WritevData(_, _, _, _, _, _))
+ .WillByDefault(Invoke(this, &MockQuicSimpleServerSession::ConsumeData));
}
MockQuicSimpleServerSession(const MockQuicSimpleServerSession&) = delete;
@@ -121,12 +124,13 @@ class MockQuicSimpleServerSession : public QuicSimpleServerSession {
void(const QuicConnectionCloseFrame& frame,
ConnectionCloseSource source));
MOCK_METHOD1(CreateIncomingStream, QuicSpdyStream*(QuicStreamId id));
- MOCK_METHOD5(WritevData,
- QuicConsumedData(QuicStream* stream,
- QuicStreamId id,
+ MOCK_METHOD6(WritevData,
+ QuicConsumedData(QuicStreamId id,
size_t write_length,
QuicStreamOffset offset,
- StreamSendingState state));
+ StreamSendingState state,
+ TransmissionType type,
+ quiche::QuicheOptional<EncryptionLevel> level));
MOCK_METHOD4(OnStreamHeaderList,
void(QuicStreamId stream_id,
bool fin,
@@ -162,6 +166,25 @@ class MockQuicSimpleServerSession : public QuicSimpleServerSession {
MOCK_METHOD1(OnStopSendingReceived, void(const QuicStopSendingFrame& frame));
+ QuicConsumedData ConsumeData(
+ QuicStreamId id,
+ size_t write_length,
+ QuicStreamOffset offset,
+ StreamSendingState state,
+ TransmissionType /*type*/,
+ quiche::QuicheOptional<EncryptionLevel> /*level*/) {
+ if (write_length > 0) {
+ auto buf = std::make_unique<char[]>(write_length);
+ QuicStream* stream = GetOrCreateStream(id);
+ DCHECK(stream);
+ QuicDataWriter writer(write_length, buf.get(), quiche::HOST_BYTE_ORDER);
+ stream->WriteStreamData(offset, write_length, &writer);
+ } else {
+ DCHECK(state != NO_FIN);
+ }
+ return QuicConsumedData(write_length, state != NO_FIN);
+ }
+
spdy::SpdyHeaderBlock original_request_headers_;
};
@@ -218,8 +241,7 @@ class QuicSimpleServerStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
session_.config(), kMinimumFlowControlSendWindow);
QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesOutgoingBidirectional(
session_.config(), kMinimumFlowControlSendWindow);
- QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams(
- session_.config(), 10);
+ QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(session_.config(), 10);
session_.OnConfigNegotiated();
connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
}
@@ -256,8 +278,9 @@ INSTANTIATE_TEST_SUITE_P(Tests,
::testing::PrintToStringParamName());
TEST_P(QuicSimpleServerStreamTest, TestFraming) {
- EXPECT_CALL(session_, WritevData(_, _, _, _, _))
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
+ .WillRepeatedly(
+ Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_);
std::unique_ptr<char[]> buffer;
QuicByteCount header_length =
@@ -273,8 +296,9 @@ TEST_P(QuicSimpleServerStreamTest, TestFraming) {
}
TEST_P(QuicSimpleServerStreamTest, TestFramingOnePacket) {
- EXPECT_CALL(session_, WritevData(_, _, _, _, _))
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
+ .WillRepeatedly(
+ Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_);
std::unique_ptr<char[]> buffer;
@@ -291,8 +315,9 @@ TEST_P(QuicSimpleServerStreamTest, TestFramingOnePacket) {
}
TEST_P(QuicSimpleServerStreamTest, SendQuicRstStreamNoErrorInStopReading) {
- EXPECT_CALL(session_, WritevData(_, _, _, _, _))
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
+ .WillRepeatedly(
+ Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
EXPECT_FALSE(stream_->fin_received());
EXPECT_FALSE(stream_->rst_received());
@@ -311,9 +336,10 @@ TEST_P(QuicSimpleServerStreamTest, TestFramingExtraData) {
// We'll automatically write out an error (headers + body)
EXPECT_CALL(*stream_, WriteHeadersMock(false));
if (UsesHttp3()) {
- EXPECT_CALL(session_, WritevData(_, _, kDataFrameHeaderLength, _, NO_FIN));
+ EXPECT_CALL(session_,
+ WritevData(_, kDataFrameHeaderLength, _, NO_FIN, _, _));
}
- EXPECT_CALL(session_, WritevData(_, _, kErrorLength, _, FIN));
+ EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _, _));
EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(0);
@@ -362,9 +388,9 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithIllegalResponseStatus) {
InSequence s;
EXPECT_CALL(*stream_, WriteHeadersMock(false));
if (UsesHttp3()) {
- EXPECT_CALL(session_, WritevData(_, _, header_length, _, NO_FIN));
+ EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _, _));
}
- EXPECT_CALL(session_, WritevData(_, _, kErrorLength, _, FIN));
+ EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _, _));
stream_->DoSendResponse();
EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
@@ -395,9 +421,9 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithIllegalResponseStatus2) {
InSequence s;
EXPECT_CALL(*stream_, WriteHeadersMock(false));
if (UsesHttp3()) {
- EXPECT_CALL(session_, WritevData(_, _, header_length, _, NO_FIN));
+ EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _, _));
}
- EXPECT_CALL(session_, WritevData(_, _, kErrorLength, _, FIN));
+ EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _, _));
stream_->DoSendResponse();
EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
@@ -455,9 +481,9 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithValidHeaders) {
InSequence s;
EXPECT_CALL(*stream_, WriteHeadersMock(false));
if (UsesHttp3()) {
- EXPECT_CALL(session_, WritevData(_, _, header_length, _, NO_FIN));
+ EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _, _));
}
- EXPECT_CALL(session_, WritevData(_, _, body.length(), _, FIN));
+ EXPECT_CALL(session_, WritevData(_, body.length(), _, FIN, _, _));
stream_->DoSendResponse();
EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
@@ -497,9 +523,9 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithPushResources) {
_, _));
EXPECT_CALL(*stream_, WriteHeadersMock(false));
if (UsesHttp3()) {
- EXPECT_CALL(session_, WritevData(_, _, header_length, _, NO_FIN));
+ EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _, _));
}
- EXPECT_CALL(session_, WritevData(_, _, body.length(), _, FIN));
+ EXPECT_CALL(session_, WritevData(_, body.length(), _, FIN, _, _));
stream_->DoSendResponse();
EXPECT_EQ(*request_headers, session_.original_request_headers_);
}
@@ -553,11 +579,11 @@ TEST_P(QuicSimpleServerStreamTest, PushResponseOnServerInitiatedStream) {
EXPECT_CALL(*server_initiated_stream, WriteHeadersMock(false));
if (UsesHttp3()) {
- EXPECT_CALL(session_, WritevData(_, kServerInitiatedStreamId, header_length,
- _, NO_FIN));
+ EXPECT_CALL(session_, WritevData(kServerInitiatedStreamId, header_length, _,
+ NO_FIN, _, _));
}
EXPECT_CALL(session_,
- WritevData(_, kServerInitiatedStreamId, kBody.size(), _, FIN));
+ WritevData(kServerInitiatedStreamId, kBody.size(), _, FIN, _, _));
server_initiated_stream->PushResponse(std::move(headers));
EXPECT_EQ(kPath, server_initiated_stream->GetHeader(":path"));
EXPECT_EQ("GET", server_initiated_stream->GetHeader(":method"));
@@ -571,9 +597,10 @@ TEST_P(QuicSimpleServerStreamTest, TestSendErrorResponse) {
InSequence s;
EXPECT_CALL(*stream_, WriteHeadersMock(false));
if (UsesHttp3()) {
- EXPECT_CALL(session_, WritevData(_, _, kDataFrameHeaderLength, _, NO_FIN));
+ EXPECT_CALL(session_,
+ WritevData(_, kDataFrameHeaderLength, _, NO_FIN, _, _));
}
- EXPECT_CALL(session_, WritevData(_, _, kErrorLength, _, FIN));
+ EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _, _));
stream_->DoSendErrorResponse();
EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
@@ -585,11 +612,13 @@ TEST_P(QuicSimpleServerStreamTest, InvalidMultipleContentLength) {
spdy::SpdyHeaderBlock request_headers;
// \000 is a way to write the null byte when followed by a literal digit.
- header_list_.OnHeader("content-length", QuicStringPiece("11\00012", 5));
+ header_list_.OnHeader("content-length",
+ quiche::QuicheStringPiece("11\00012", 5));
EXPECT_CALL(*stream_, WriteHeadersMock(false));
- EXPECT_CALL(session_, WritevData(_, _, _, _, _))
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
+ .WillRepeatedly(
+ Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
stream_->OnStreamHeaderList(true, kFakeFrameLen, header_list_);
EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream_));
@@ -602,11 +631,13 @@ TEST_P(QuicSimpleServerStreamTest, InvalidLeadingNullContentLength) {
spdy::SpdyHeaderBlock request_headers;
// \000 is a way to write the null byte when followed by a literal digit.
- header_list_.OnHeader("content-length", QuicStringPiece("\00012", 3));
+ header_list_.OnHeader("content-length",
+ quiche::QuicheStringPiece("\00012", 3));
EXPECT_CALL(*stream_, WriteHeadersMock(false));
- EXPECT_CALL(session_, WritevData(_, _, _, _, _))
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
+ .WillRepeatedly(
+ Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
stream_->OnStreamHeaderList(true, kFakeFrameLen, header_list_);
EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream_));
@@ -617,7 +648,8 @@ TEST_P(QuicSimpleServerStreamTest, InvalidLeadingNullContentLength) {
TEST_P(QuicSimpleServerStreamTest, ValidMultipleContentLength) {
spdy::SpdyHeaderBlock request_headers;
// \000 is a way to write the null byte when followed by a literal digit.
- header_list_.OnHeader("content-length", QuicStringPiece("11\00011", 5));
+ header_list_.OnHeader("content-length",
+ quiche::QuicheStringPiece("11\00011", 5));
stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_);
@@ -639,8 +671,7 @@ TEST_P(QuicSimpleServerStreamTest,
// assumption on their number or size.
auto* qpack_decoder_stream =
QuicSpdySessionPeer::GetQpackDecoderSendStream(&session_);
- EXPECT_CALL(session_, WritevData(qpack_decoder_stream,
- qpack_decoder_stream->id(), _, _, _))
+ EXPECT_CALL(session_, WritevData(qpack_decoder_stream->id(), _, _, _, _, _))
.Times(AnyNumber());
}
EXPECT_CALL(session_, SendRstStream(_, QUIC_RST_ACKNOWLEDGEMENT, _)).Times(1);
@@ -681,7 +712,7 @@ TEST_P(QuicSimpleServerStreamTest, InvalidHeadersWithFin) {
0x54, 0x54, 0x50, 0x2f, // TTP/
0x31, 0x2e, 0x31, // 1.1
};
- QuicStringPiece data(arr, QUIC_ARRAYSIZE(arr));
+ quiche::QuicheStringPiece data(arr, QUICHE_ARRAYSIZE(arr));
QuicStreamFrame frame(stream_->id(), true, 0, data);
// Verify that we don't crash when we get a invalid headers in stream frame.
stream_->OnStreamFrame(frame);
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.cc
index 6b4cc8d042f..a944d6079df 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.cc
@@ -11,7 +11,8 @@
#include "net/third_party/quiche/src/quic/core/quic_server_id.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
using spdy::SpdyHeaderBlock;
@@ -24,7 +25,7 @@ void QuicSpdyClientBase::ClientQuicDataToResend::Resend() {
QuicSpdyClientBase::QuicDataToResend::QuicDataToResend(
std::unique_ptr<SpdyHeaderBlock> headers,
- QuicStringPiece body,
+ quiche::QuicheStringPiece body,
bool fin)
: headers_(std::move(headers)), body_(body), fin_(fin) {}
@@ -69,8 +70,9 @@ void QuicSpdyClientBase::InitializeSession() {
}
client_session()->Initialize();
client_session()->CryptoConnect();
- if (max_allowed_push_id_ > 0) {
- client_session()->SetMaxAllowedPushId(max_allowed_push_id_);
+ if (max_allowed_push_id_ > 0 &&
+ VersionUsesHttp3(client_session()->transport_version())) {
+ client_session()->SetMaxPushId(max_allowed_push_id_);
}
}
@@ -90,8 +92,8 @@ void QuicSpdyClientBase::OnClose(QuicSpdyStream* stream) {
auto status = response_headers.find(":status");
if (status == response_headers.end()) {
QUIC_LOG(ERROR) << "Missing :status response header";
- } else if (!QuicTextUtils::StringToInt(status->second,
- &latest_response_code_)) {
+ } else if (!quiche::QuicheTextUtils::StringToInt(status->second,
+ &latest_response_code_)) {
QUIC_LOG(ERROR) << "Invalid :status response header: " << status->second;
}
latest_response_headers_ = response_headers.DebugString();
@@ -113,13 +115,13 @@ std::unique_ptr<QuicSession> QuicSpdyClientBase::CreateQuicClientSession(
}
void QuicSpdyClientBase::SendRequest(const SpdyHeaderBlock& headers,
- QuicStringPiece body,
+ quiche::QuicheStringPiece body,
bool fin) {
if (GetQuicFlag(FLAGS_quic_client_convert_http_header_name_to_lowercase)) {
QUIC_CODE_COUNT(quic_client_convert_http_header_name_to_lowercase);
SpdyHeaderBlock sanitized_headers;
for (const auto& p : headers) {
- sanitized_headers[QuicTextUtils::ToLower(p.first)] = p.second;
+ sanitized_headers[quiche::QuicheTextUtils::ToLower(p.first)] = p.second;
}
SendRequestInternal(std::move(sanitized_headers), body, fin);
@@ -129,7 +131,7 @@ void QuicSpdyClientBase::SendRequest(const SpdyHeaderBlock& headers,
}
void QuicSpdyClientBase::SendRequestInternal(SpdyHeaderBlock sanitized_headers,
- QuicStringPiece body,
+ quiche::QuicheStringPiece body,
bool fin) {
QuicClientPushPromiseIndex::TryHandle* handle;
QuicAsyncStatus rv =
@@ -153,7 +155,7 @@ void QuicSpdyClientBase::SendRequestInternal(SpdyHeaderBlock sanitized_headers,
void QuicSpdyClientBase::SendRequestAndWaitForResponse(
const SpdyHeaderBlock& headers,
- QuicStringPiece body,
+ quiche::QuicheStringPiece body,
bool fin) {
SendRequest(headers, body, fin);
while (WaitForEvents()) {
@@ -178,7 +180,12 @@ QuicSpdyClientStream* QuicSpdyClientBase::CreateClientStream() {
if (!connected()) {
return nullptr;
}
-
+ if (VersionHasIetfQuicFrames(client_session()->transport_version())) {
+ // Process MAX_STREAMS from peer.
+ while (!client_session()->CanOpenNextOutgoingBidirectionalStream()) {
+ network_helper()->RunEventLoop();
+ }
+ }
auto* stream = static_cast<QuicSpdyClientStream*>(
client_session()->CreateOutgoingBidirectionalStream());
if (stream) {
@@ -189,6 +196,14 @@ QuicSpdyClientStream* QuicSpdyClientBase::CreateClientStream() {
return stream;
}
+bool QuicSpdyClientBase::EarlyDataAccepted() {
+ return client_session()->EarlyDataAccepted();
+}
+
+bool QuicSpdyClientBase::ReceivedInchoateReject() {
+ return client_session()->ReceivedInchoateReject();
+}
+
int QuicSpdyClientBase::GetNumSentClientHellosFromSession() {
return client_session()->GetNumSentClientHellos();
}
@@ -217,7 +232,7 @@ void QuicSpdyClientBase::ResendSavedData() {
}
void QuicSpdyClientBase::AddPromiseDataToResend(const SpdyHeaderBlock& headers,
- QuicStringPiece body,
+ quiche::QuicheStringPiece body,
bool fin) {
std::unique_ptr<SpdyHeaderBlock> new_headers(
new SpdyHeaderBlock(headers.Clone()));
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.h b/chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.h
index d95303855c4..c4381f7538f 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.h
@@ -16,8 +16,8 @@
#include "net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_config.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/tools/quic_client_base.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -47,7 +47,7 @@ class QuicSpdyClientBase : public QuicClientBase,
public:
// |headers| may be null, since it's possible to send data without headers.
QuicDataToResend(std::unique_ptr<spdy::SpdyHeaderBlock> headers,
- QuicStringPiece body,
+ quiche::QuicheStringPiece body,
bool fin);
QuicDataToResend(const QuicDataToResend&) = delete;
QuicDataToResend& operator=(const QuicDataToResend&) = delete;
@@ -60,7 +60,7 @@ class QuicSpdyClientBase : public QuicClientBase,
protected:
std::unique_ptr<spdy::SpdyHeaderBlock> headers_;
- QuicStringPiece body_;
+ quiche::QuicheStringPiece body_;
bool fin_;
};
@@ -86,12 +86,12 @@ class QuicSpdyClientBase : public QuicClientBase,
// Sends an HTTP request and does not wait for response before returning.
void SendRequest(const spdy::SpdyHeaderBlock& headers,
- QuicStringPiece body,
+ quiche::QuicheStringPiece body,
bool fin);
// Sends an HTTP request and waits for response before returning.
void SendRequestAndWaitForResponse(const spdy::SpdyHeaderBlock& headers,
- QuicStringPiece body,
+ quiche::QuicheStringPiece body,
bool fin);
// Sends a request simple GET for each URL in |url_list|, and then waits for
@@ -139,12 +139,16 @@ class QuicSpdyClientBase : public QuicClientBase,
bool drop_response_body() const { return drop_response_body_; }
// Set the max promise id for the client session.
+ // TODO(b/151641466): Rename this method.
void SetMaxAllowedPushId(QuicStreamId max) { max_allowed_push_id_ = max; }
// Disables the use of the QPACK dynamic table and of blocked streams.
// Must be called before InitializeSession().
void disable_qpack_dynamic_table() { disable_qpack_dynamic_table_ = true; }
+ bool EarlyDataAccepted() override;
+ bool ReceivedInchoateReject() override;
+
protected:
int GetNumSentClientHellosFromSession() override;
int GetNumReceivedServerConfigUpdatesFromSession() override;
@@ -159,7 +163,7 @@ class QuicSpdyClientBase : public QuicClientBase,
void ResendSavedData() override;
void AddPromiseDataToResend(const spdy::SpdyHeaderBlock& headers,
- QuicStringPiece body,
+ quiche::QuicheStringPiece body,
bool fin);
bool HasActiveRequests() override;
@@ -168,7 +172,7 @@ class QuicSpdyClientBase : public QuicClientBase,
class ClientQuicDataToResend : public QuicDataToResend {
public:
ClientQuicDataToResend(std::unique_ptr<spdy::SpdyHeaderBlock> headers,
- QuicStringPiece body,
+ quiche::QuicheStringPiece body,
bool fin,
QuicSpdyClientBase* client)
: QuicDataToResend(std::move(headers), body, fin), client_(client) {
@@ -187,7 +191,7 @@ class QuicSpdyClientBase : public QuicClientBase,
};
void SendRequestInternal(spdy::SpdyHeaderBlock sanitized_headers,
- QuicStringPiece body,
+ quiche::QuicheStringPiece body,
bool fin);
// Index of pending promised streams. Must outlive |session_|.
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.cc
index 41597359280..5733e0bb0d7 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.cc
@@ -54,18 +54,17 @@
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_default_proof_providers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_system_event_loop.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/tools/fake_proof_verifier.h"
#include "net/third_party/quiche/src/quic/tools/quic_url.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
namespace {
-using quic::QuicStringPiece;
-using quic::QuicTextUtils;
using quic::QuicUrl;
+using quiche::QuicheStringPiece;
+using quiche::QuicheTextUtils;
} // namespace
@@ -185,25 +184,29 @@ int QuicToyClient::SendRequestsAndPrintResponses(
quic::ParsedQuicVersionVector versions = quic::CurrentSupportedVersions();
- std::string quic_version_string = GetQuicFlag(FLAGS_quic_version);
if (GetQuicFlag(FLAGS_quic_ietf_draft)) {
quic::QuicVersionInitializeSupportForIetfDraft();
- versions = {{quic::PROTOCOL_TLS1_3, quic::QUIC_VERSION_99}};
- quic::QuicEnableVersion(versions[0]);
-
- } else if (!quic_version_string.empty()) {
- if (quic_version_string[0] == 'T') {
- // ParseQuicVersionString checks quic_supports_tls_handshake.
- SetQuicReloadableFlag(quic_supports_tls_handshake, true);
- }
- quic::ParsedQuicVersion parsed_quic_version =
- quic::ParseQuicVersionString(quic_version_string);
- if (parsed_quic_version.transport_version ==
- quic::QUIC_VERSION_UNSUPPORTED) {
- return 1;
+ versions = {};
+ for (const ParsedQuicVersion& version : AllSupportedVersions()) {
+ if (version.HasIetfQuicFrames() &&
+ version.handshake_protocol == quic::PROTOCOL_TLS1_3) {
+ versions.push_back(version);
+ }
}
- versions = {parsed_quic_version};
- quic::QuicEnableVersion(parsed_quic_version);
+ }
+
+ std::string quic_version_string = GetQuicFlag(FLAGS_quic_version);
+ if (!quic_version_string.empty()) {
+ versions = quic::ParseQuicVersionVectorString(quic_version_string);
+ }
+
+ if (versions.empty()) {
+ std::cerr << "No known version selected." << std::endl;
+ return 1;
+ }
+
+ for (const quic::ParsedQuicVersion& version : versions) {
+ quic::QuicEnableVersion(version);
}
if (GetQuicFlag(FLAGS_force_version_negotiation)) {
@@ -239,15 +242,15 @@ int QuicToyClient::SendRequestsAndPrintResponses(
if (!client->Connect()) {
quic::QuicErrorCode error = client->session()->error();
if (error == quic::QUIC_INVALID_VERSION) {
- std::cerr << "Server talks QUIC, but none of the versions supported by "
- << "this client: " << ParsedQuicVersionVectorToString(versions)
- << std::endl;
+ std::cerr << "Failed to negotiate version with " << host << ":" << port
+ << ". " << client->session()->error_details() << std::endl;
// 0: No error.
// 20: Failed to connect due to QUIC_INVALID_VERSION.
return GetQuicFlag(FLAGS_version_mismatch_ok) ? 0 : 20;
}
- std::cerr << "Failed to connect to " << host << ":" << port
- << ". Error: " << quic::QuicErrorCodeToString(error) << std::endl;
+ std::cerr << "Failed to connect to " << host << ":" << port << ". "
+ << quic::QuicErrorCodeToString(error) << " "
+ << client->session()->error_details() << std::endl;
return 1;
}
std::cerr << "Connected to " << host << ":" << port << std::endl;
@@ -257,7 +260,7 @@ int QuicToyClient::SendRequestsAndPrintResponses(
if (!GetQuicFlag(FLAGS_body_hex).empty()) {
DCHECK(GetQuicFlag(FLAGS_body).empty())
<< "Only set one of --body and --body_hex.";
- body = QuicTextUtils::HexDecode(GetQuicFlag(FLAGS_body_hex));
+ body = QuicheTextUtils::HexDecode(GetQuicFlag(FLAGS_body_hex));
}
// Construct a GET or POST request for supplied URL.
@@ -269,14 +272,14 @@ int QuicToyClient::SendRequestsAndPrintResponses(
// Append any additional headers supplied on the command line.
const std::string headers = GetQuicFlag(FLAGS_headers);
- for (QuicStringPiece sp : QuicTextUtils::Split(headers, ';')) {
- QuicTextUtils::RemoveLeadingAndTrailingWhitespace(&sp);
+ for (QuicheStringPiece sp : QuicheTextUtils::Split(headers, ';')) {
+ QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&sp);
if (sp.empty()) {
continue;
}
- std::vector<QuicStringPiece> kv = QuicTextUtils::Split(sp, ':');
- QuicTextUtils::RemoveLeadingAndTrailingWhitespace(&kv[0]);
- QuicTextUtils::RemoveLeadingAndTrailingWhitespace(&kv[1]);
+ std::vector<QuicheStringPiece> kv = QuicheTextUtils::Split(sp, ':');
+ QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&kv[0]);
+ QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&kv[1]);
header_block[kv[0]] = kv[1];
}
@@ -294,8 +297,8 @@ int QuicToyClient::SendRequestsAndPrintResponses(
if (!GetQuicFlag(FLAGS_body_hex).empty()) {
// Print the user provided hex, rather than binary body.
std::cout << "body:\n"
- << QuicTextUtils::HexDump(
- QuicTextUtils::HexDecode(GetQuicFlag(FLAGS_body_hex)))
+ << QuicheTextUtils::HexDump(QuicheTextUtils::HexDecode(
+ GetQuicFlag(FLAGS_body_hex)))
<< std::endl;
} else {
std::cout << "body: " << body << std::endl;
@@ -315,7 +318,7 @@ int QuicToyClient::SendRequestsAndPrintResponses(
if (!GetQuicFlag(FLAGS_body_hex).empty()) {
// Assume response is binary data.
std::cout << "body:\n"
- << QuicTextUtils::HexDump(response_body) << std::endl;
+ << QuicheTextUtils::HexDump(response_body) << std::endl;
} else {
std::cout << "body: " << response_body << std::endl;
}
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_toy_server.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_toy_server.cc
index 390dcf6aa0c..1f34849f9a3 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_toy_server.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_toy_server.cc
@@ -36,8 +36,15 @@ DEFINE_QUIC_COMMAND_LINE_FLAG(
DEFINE_QUIC_COMMAND_LINE_FLAG(bool,
quic_ietf_draft,
false,
- "Use the IETF draft version. This also enables "
- "required internal QUIC flags.");
+ "Only enable IETF draft versions. This also "
+ "enables required internal QUIC flags.");
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(
+ std::string,
+ quic_versions,
+ "",
+ "QUIC versions to enable, e.g. \"h3-25,h3-27\". If not set, then all "
+ "available versions are enabled.");
namespace quic {
@@ -62,10 +69,23 @@ int QuicToyServer::Start() {
ParsedQuicVersionVector supported_versions;
if (GetQuicFlag(FLAGS_quic_ietf_draft)) {
QuicVersionInitializeSupportForIetfDraft();
- supported_versions = {ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99)};
+ for (const ParsedQuicVersion& version : AllSupportedVersions()) {
+ // Add all versions that supports IETF QUIC.
+ if (version.HasIetfQuicFrames() &&
+ version.handshake_protocol == quic::PROTOCOL_TLS1_3) {
+ supported_versions.push_back(version);
+ }
+ }
} else {
supported_versions = AllSupportedVersions();
}
+ std::string versions_string = GetQuicFlag(FLAGS_quic_versions);
+ if (!versions_string.empty()) {
+ supported_versions = ParseQuicVersionVectorString(versions_string);
+ }
+ if (supported_versions.empty()) {
+ return 1;
+ }
for (const auto& version : supported_versions) {
QuicEnableVersion(version);
}
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.cc
index 9b1ea04cfe6..55a0674b3c0 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.cc
@@ -11,6 +11,7 @@
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -19,10 +20,9 @@ QuicTransportSimpleServerDispatcher::QuicTransportSimpleServerDispatcher(
const QuicCryptoServerConfig* crypto_config,
QuicVersionManager* version_manager,
std::unique_ptr<QuicConnectionHelperInterface> helper,
- std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
+ std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
std::unique_ptr<QuicAlarmFactory> alarm_factory,
uint8_t expected_server_connection_id_length,
- QuicTransportSimpleServerSession::Mode mode,
std::vector<url::Origin> accepted_origins)
: QuicDispatcher(config,
crypto_config,
@@ -31,23 +31,22 @@ QuicTransportSimpleServerDispatcher::QuicTransportSimpleServerDispatcher(
std::move(session_helper),
std::move(alarm_factory),
expected_server_connection_id_length),
- mode_(mode),
accepted_origins_(accepted_origins) {}
-QuicSession* QuicTransportSimpleServerDispatcher::CreateQuicSession(
+std::unique_ptr<QuicSession>
+QuicTransportSimpleServerDispatcher::CreateQuicSession(
QuicConnectionId server_connection_id,
const QuicSocketAddress& peer_address,
- QuicStringPiece /*alpn*/,
+ quiche::QuicheStringPiece /*alpn*/,
const ParsedQuicVersion& version) {
auto connection = std::make_unique<QuicConnection>(
server_connection_id, peer_address, helper(), alarm_factory(), writer(),
/*owns_writer=*/false, Perspective::IS_SERVER,
ParsedQuicVersionVector{version});
- QuicTransportSimpleServerSession* session =
- new QuicTransportSimpleServerSession(
- connection.release(), /*owns_connection=*/true, this, config(),
- GetSupportedVersions(), crypto_config(), compressed_certs_cache(),
- mode_, accepted_origins_);
+ auto session = std::make_unique<QuicTransportSimpleServerSession>(
+ connection.release(), /*owns_connection=*/true, this, config(),
+ GetSupportedVersions(), crypto_config(), compressed_certs_cache(),
+ accepted_origins_);
session->Initialize();
return session;
}
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.h b/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.h
index ea4eb8bf8ef..cc3f76eab53 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.h
@@ -8,6 +8,7 @@
#include "url/origin.h"
#include "net/third_party/quiche/src/quic/core/quic_dispatcher.h"
#include "net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -20,19 +21,18 @@ class QuicTransportSimpleServerDispatcher : public QuicDispatcher {
const QuicCryptoServerConfig* crypto_config,
QuicVersionManager* version_manager,
std::unique_ptr<QuicConnectionHelperInterface> helper,
- std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
+ std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
std::unique_ptr<QuicAlarmFactory> alarm_factory,
uint8_t expected_server_connection_id_length,
- QuicTransportSimpleServerSession::Mode mode,
std::vector<url::Origin> accepted_origins);
protected:
- QuicSession* CreateQuicSession(QuicConnectionId server_connection_id,
- const QuicSocketAddress& peer_address,
- QuicStringPiece alpn,
- const ParsedQuicVersion& version) override;
+ std::unique_ptr<QuicSession> CreateQuicSession(
+ QuicConnectionId server_connection_id,
+ const QuicSocketAddress& peer_address,
+ quiche::QuicheStringPiece alpn,
+ const ParsedQuicVersion& version) override;
- QuicTransportSimpleServerSession::Mode mode_;
std::vector<url::Origin> accepted_origins_;
};
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.cc
index 6e86ccab78d..49c86e52000 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.cc
@@ -8,12 +8,11 @@
#include "url/gurl.h"
#include "url/origin.h"
+#include "net/third_party/quiche/src/quic/core/quic_buffer_allocator.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_protocol.h"
#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h"
@@ -133,7 +132,6 @@ QuicTransportSimpleServerSession::QuicTransportSimpleServerSession(
const ParsedQuicVersionVector& supported_versions,
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache,
- Mode mode,
std::vector<url::Origin> accepted_origins)
: QuicTransportServerSession(connection,
owner,
@@ -142,14 +140,13 @@ QuicTransportSimpleServerSession::QuicTransportSimpleServerSession(
crypto_config,
compressed_certs_cache,
this),
- connection_(connection),
owns_connection_(owns_connection),
- mode_(mode),
+ mode_(DISCARD),
accepted_origins_(accepted_origins) {}
QuicTransportSimpleServerSession::~QuicTransportSimpleServerSession() {
if (owns_connection_) {
- delete connection_;
+ DeleteConnection();
}
}
@@ -202,6 +199,32 @@ bool QuicTransportSimpleServerSession::CheckOrigin(url::Origin origin) {
return false;
}
+bool QuicTransportSimpleServerSession::ProcessPath(const GURL& url) {
+ if (url.path() == "/discard") {
+ mode_ = DISCARD;
+ return true;
+ }
+ if (url.path() == "/echo") {
+ mode_ = ECHO;
+ return true;
+ }
+
+ QUIC_DLOG(WARNING) << "Unknown path requested: " << url.path();
+ return false;
+}
+
+void QuicTransportSimpleServerSession::OnMessageReceived(
+ quiche::QuicheStringPiece message) {
+ if (mode_ != ECHO) {
+ return;
+ }
+ QuicUniqueBufferPtr buffer = MakeUniqueBuffer(
+ connection()->helper()->GetStreamSendBufferAllocator(), message.size());
+ memcpy(buffer.get(), message.data(), message.size());
+ datagram_queue()->SendOrQueueDatagram(
+ QuicMemSlice(std::move(buffer), message.size()));
+}
+
void QuicTransportSimpleServerSession::MaybeEchoStreamsBack() {
while (!streams_to_echo_back_.empty() &&
CanOpenNextOutgoingUnidirectionalStream()) {
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.h b/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.h
index 11f82f2d272..7a5fb097cd9 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.h
@@ -44,13 +44,14 @@ class QuicTransportSimpleServerSession
const ParsedQuicVersionVector& supported_versions,
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache,
- Mode mode,
std::vector<url::Origin> accepted_origins);
~QuicTransportSimpleServerSession();
void OnIncomingDataStream(QuicTransportStream* stream) override;
void OnCanCreateNewOutgoingStream(bool unidirectional) override;
bool CheckOrigin(url::Origin origin) override;
+ bool ProcessPath(const GURL& url) override;
+ void OnMessageReceived(quiche::QuicheStringPiece message) override;
void EchoStreamBack(const std::string& data) {
streams_to_echo_back_.push_back(data);
@@ -60,11 +61,10 @@ class QuicTransportSimpleServerSession
private:
void MaybeEchoStreamsBack();
- QuicConnection* connection_;
const bool owns_connection_;
Mode mode_;
std::vector<url::Origin> accepted_origins_;
- QuicDeque<std::string> streams_to_echo_back_;
+ QuicCircularDeque<std::string> streams_to_echo_back_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_url.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_url.cc
index 4094ffebb7e..438847c35f8 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_url.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_url.cc
@@ -4,22 +4,24 @@
#include "net/third_party/quiche/src/quic/tools/quic_url.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
static constexpr size_t kMaxHostNameLength = 256;
-QuicUrl::QuicUrl(QuicStringPiece url) : url_(static_cast<std::string>(url)) {}
+QuicUrl::QuicUrl(quiche::QuicheStringPiece url)
+ : url_(static_cast<std::string>(url)) {}
-QuicUrl::QuicUrl(QuicStringPiece url, QuicStringPiece default_scheme)
+QuicUrl::QuicUrl(quiche::QuicheStringPiece url,
+ quiche::QuicheStringPiece default_scheme)
: QuicUrl(url) {
if (url_.has_scheme()) {
return;
}
- url_ = GURL(QuicStrCat(default_scheme, "://", url));
+ url_ = GURL(quiche::QuicheStrCat(default_scheme, "://", url));
}
std::string QuicUrl::ToString() const {
@@ -51,7 +53,7 @@ std::string QuicUrl::HostPort() const {
if (port == url::PORT_UNSPECIFIED) {
return host;
}
- return QuicStrCat(host, ":", port);
+ return quiche::QuicheStrCat(host, ":", port);
}
std::string QuicUrl::PathParamsQuery() const {
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_url.h b/chromium/net/third_party/quiche/src/quic/tools/quic_url.h
index da1b69db14d..4b057db3b3a 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_url.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_url.h
@@ -9,7 +9,7 @@
#include "url/gurl.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
namespace quic {
@@ -24,11 +24,12 @@ class QuicUrl {
// NOTE: If |url| doesn't have a scheme, it will have an empty scheme
// field. If that's not what you want, use the QuicUrlImpl(url,
// default_scheme) form below.
- explicit QuicUrl(QuicStringPiece url);
+ explicit QuicUrl(quiche::QuicheStringPiece url);
// Constructs a QuicUrlImpl from |url|, assuming that the scheme for the URL
// is |default_scheme| if there is no scheme specified in |url|.
- QuicUrl(QuicStringPiece url, QuicStringPiece default_scheme);
+ QuicUrl(quiche::QuicheStringPiece url,
+ quiche::QuicheStringPiece default_scheme);
// Returns false if the URL is not valid.
bool IsValid() const;
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_url_test.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_url_test.cc
index 608fdb107fc..8ffee252a7c 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_url_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_url_test.cc
@@ -6,7 +6,6 @@
#include <string>
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
namespace quic {