summaryrefslogtreecommitdiff
path: root/chromium/net/third_party
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2021-09-03 13:32:17 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2021-10-01 14:31:55 +0200
commit21ba0c5d4bf8fba15dddd97cd693bad2358b77fd (patch)
tree91be119f694044dfc1ff9fdc054459e925de9df0 /chromium/net/third_party
parent03c549e0392f92c02536d3f86d5e1d8dfa3435ac (diff)
downloadqtwebengine-chromium-21ba0c5d4bf8fba15dddd97cd693bad2358b77fd.tar.gz
BASELINE: Update Chromium to 92.0.4515.166
Change-Id: I42a050486714e9e54fc271f2a8939223a02ae364
Diffstat (limited to 'chromium/net/third_party')
-rw-r--r--chromium/net/third_party/nss/DIR_METADATA4
-rw-r--r--chromium/net/third_party/quiche/BUILD.gn1236
-rw-r--r--chromium/net/third_party/quiche/DIR_METADATA4
-rw-r--r--chromium/net/third_party/quiche/src/common/platform/api/quiche_prefetch.h (renamed from chromium/net/third_party/quiche/src/quic/platform/api/quic_prefetch.h)16
-rw-r--r--chromium/net/third_party/quiche/src/common/platform/api/quiche_test.h3
-rw-r--r--chromium/net/third_party/quiche/src/common/platform/api/quiche_test_helpers.h8
-rw-r--r--chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_prefetch_impl.h28
-rw-r--r--chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_sleep_impl.h22
-rw-r--r--chromium/net/third_party/quiche/src/common/quiche_circular_deque.h (renamed from chromium/net/third_party/quiche/src/quic/core/quic_circular_deque.h)100
-rw-r--r--chromium/net/third_party/quiche/src/common/quiche_circular_deque_test.cc (renamed from chromium/net/third_party/quiche/src/quic/core/quic_circular_deque_test.cc)179
-rw-r--r--chromium/net/third_party/quiche/src/common/quiche_data_reader.cc1
-rw-r--r--chromium/net/third_party/quiche/src/common/quiche_linked_hash_map.h (renamed from chromium/net/third_party/quiche/src/common/simple_linked_hash_map.h)84
-rw-r--r--chromium/net/third_party/quiche/src/common/quiche_linked_hash_map_test.cc (renamed from chromium/net/third_party/quiche/src/common/simple_linked_hash_map_test.cc)64
-rw-r--r--chromium/net/third_party/quiche/src/common/quiche_text_utils.cc77
-rw-r--r--chromium/net/third_party/quiche/src/common/quiche_text_utils.h (renamed from chromium/net/third_party/quiche/src/common/platform/api/quiche_text_utils.h)28
-rw-r--r--chromium/net/third_party/quiche/src/common/quiche_text_utils_test.cc (renamed from chromium/net/third_party/quiche/src/common/platform/api/quiche_text_utils_test.cc)16
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/adapter_impl_comparison_test.cc83
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/callback_visitor.cc215
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/callback_visitor.h92
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/callback_visitor_test.cc260
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/data_source.cc23
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/data_source.h53
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/data_source_test.cc40
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/http2_adapter.h9
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/http2_protocol.cc9
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/http2_protocol.h15
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/http2_session.h9
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/http2_util.cc33
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/http2_util.h1
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/http2_visitor_interface.h23
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/mock_http2_visitor.h9
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/mock_nghttp2_callbacks.cc123
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/mock_nghttp2_callbacks.h80
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter.cc149
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter.h97
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter_test.cc255
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_callbacks.cc30
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_callbacks.h5
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session.cc70
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session.h42
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session_test.cc295
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util.cc51
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util.h17
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter.cc77
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter.h7
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter_test.cc42
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session.cc231
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session.h141
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session_test.cc179
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/oghttp2_util.cc17
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/oghttp2_util.h16
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/recording_http2_visitor.cc155
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/recording_http2_visitor.h80
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/recording_http2_visitor_test.cc135
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/test_frame_sequence.cc23
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/test_frame_sequence.h7
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/test_utils.cc414
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/test_utils.h67
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/test_utils_test.cc69
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/window_manager.cc9
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/window_manager_test.cc6
-rw-r--r--chromium/net/third_party/quiche/src/http2/core/http2_priority_write_scheduler.h (renamed from chromium/net/third_party/quiche/src/spdy/core/http2_priority_write_scheduler.h)145
-rw-r--r--chromium/net/third_party/quiche/src/http2/core/http2_priority_write_scheduler_test.cc (renamed from chromium/net/third_party/quiche/src/spdy/core/http2_priority_write_scheduler_test.cc)53
-rw-r--r--chromium/net/third_party/quiche/src/http2/core/priority_write_scheduler.h (renamed from chromium/net/third_party/quiche/src/spdy/core/priority_write_scheduler.h)69
-rw-r--r--chromium/net/third_party/quiche/src/http2/core/priority_write_scheduler_test.cc (renamed from chromium/net/third_party/quiche/src/spdy/core/priority_write_scheduler_test.cc)86
-rw-r--r--chromium/net/third_party/quiche/src/http2/core/write_scheduler.h (renamed from chromium/net/third_party/quiche/src/spdy/core/write_scheduler.h)12
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc9
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables.h4
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_decoder_test.cc19
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_encoder_test.cc23
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder_test.cc5
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_example.cc3
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder_test.cc7
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_encoder_test.cc12
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_round_trip_test.cc3
-rw-r--r--chromium/net/third_party/quiche/src/http2/http2_constants.cc3
-rw-r--r--chromium/net/third_party/quiche/src/http2/http2_structures.cc5
-rw-r--r--chromium/net/third_party/quiche/src/http2/platform/api/http2_string_utils.h13
-rw-r--r--chromium/net/third_party/quiche/src/http2/platform/api/http2_string_utils_test.cc23
-rw-r--r--chromium/net/third_party/quiche/src/http2/test_tools/http2_random.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_base.cc16
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_base.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_buffer.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_gso_batch_writer_test.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/chlo_extractor.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.cc177
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_simulator_test.cc55
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_startup.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_encrypter_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_decrypter_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_encrypter_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aes_256_gcm_decrypter_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aes_256_gcm_encrypter_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/cert_compressor_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/certificate_view.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_decrypter_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_encrypter_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_tls_decrypter_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_tls_encrypter_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_message_printer_bin.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h13
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_server_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.cc17
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/proof_source.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.cc20
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.cc10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_new_token_frame.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_path_challenge_frame.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_path_response_frame.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/handshaker_delegate_interface.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/end_to_end_test.cc1036
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_decoder.cc100
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_decoder.h17
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_decoder_test.cc336
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_frames.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_header_list.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream_test.cc16
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream_test.cc30
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base_test.cc85
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_test.cc7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.cc33
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.h12
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session_test.cc73
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.cc7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_test.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/spdy_utils_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/web_transport_http3.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/packet_number_indexed_queue.h4
-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_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test.cc13
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table.cc295
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table.h355
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table_test.cc598
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.h12
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_chaos_protector.cc229
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_chaos_protector.h99
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_chaos_protector_test.cc207
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection.cc933
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection.h177
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_id.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_id_manager.cc60
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_id_manager.h28
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_id_manager_test.cc47
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_stats.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_stats.h14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_test.cc911
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream_test.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_datagram_queue.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.cc390
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_dispatcher_test.cc27
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_error_codes.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_flags_list.h178
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_framer.cc60
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_framer.h14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_framer_test.cc29
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_interval_deque.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_legacy_version_encapsulator.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_legacy_version_encapsulator_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_linux_socket_utils.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_linux_socket_utils_test.cc16
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.cc349
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.h51
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_creator_test.cc163
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packets.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_protocol_flags_list.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager_test.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_session.cc69
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_session.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer.cc11
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_test.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_test.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_tag.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.cc14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager_test.cc19
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.h11
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_utils.cc7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_versions.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_chlo_extractor.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.cc60
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker_test.cc31
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_handshaker.cc21
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_handshaker.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.cc328
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.h47
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker_test.cc72
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager_test.cc15
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_client_bin.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_client_session.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_compression_engine.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_server_backend.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_server_session.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_containers.h39
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_sleep.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_test.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/mock_tun_device.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device.cc77
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device.h10
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_interface.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger_test.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_test.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/platform/icmp_packet_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/platform/tcp_packet_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_session_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/web_transport_fingerprint_proof_verifier.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.cc7
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source_handle.cc22
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source_handle.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/mock_random.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/mock_random.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_peer.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_peer.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_header_table_peer.cc25
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_header_table_peer.h29
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_offline_decoder.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.cc49
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h19
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_dispatcher_peer.cc25
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_backend.cc93
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_time_wait_list_manager_peer.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_time_wait_list_manager_peer.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/server_thread.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/server_thread.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simple_data_producer.h12
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/link.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/queue.h4
-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/tools/quic_backend_response.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client_base.cc16
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client_epoll_network_helper.cc19
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_epoll_client_factory.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_epoll_client_factory.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.cc39
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.h13
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_packet_printer_bin.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_reject_reason_decoder_bin.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_backend.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session.cc33
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session.h13
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session_test.cc491
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream.cc12
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream_test.cc59
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.cc43
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_toy_server.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/web_transport_test_visitors.h91
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_constants.cc2
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.cc37
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter_test.cc28
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.cc29
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_entry.cc1
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.cc14
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.h5
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_output_stream.cc2
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_static_table.cc2
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.cc197
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.cc50
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.h19
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format_test.cc115
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_frame_builder.cc13
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_frame_builder.h6
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_framer.cc17
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_framer_test.cc93
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_header_block.cc30
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_header_storage.cc2
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_prefixed_buffer_reader.cc2
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_protocol.cc12
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_protocol.h3
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_protocol_test.cc28
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_protocol_test_utils.cc20
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_protocol_test_utils.h12
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_simple_arena.cc2
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_test_utils.cc4
-rw-r--r--chromium/net/third_party/quiche/src/spdy/platform/api/spdy_bug_tracker.h16
-rw-r--r--chromium/net/third_party/quiche/src/spdy/platform/api/spdy_containers.h6
-rw-r--r--chromium/net/third_party/quiche/src/spdy/platform/api/spdy_flag_utils.h19
-rw-r--r--chromium/net/third_party/quiche/src/spdy/platform/api/spdy_flags.h18
-rw-r--r--chromium/net/third_party/quiche/src/spdy/platform/api/spdy_logging.h23
-rw-r--r--chromium/net/third_party/quiche/src/spdy/platform/api/spdy_string_utils.h17
-rw-r--r--chromium/net/third_party/quiche/src/spdy/platform/api/spdy_string_utils_test.cc78
-rw-r--r--chromium/net/third_party/quiche/src/spdy/platform/api/spdy_test_helpers.h12
-rw-r--r--chromium/net/third_party/uri_template/DIR_METADATA4
336 files changed, 11287 insertions, 5466 deletions
diff --git a/chromium/net/third_party/nss/DIR_METADATA b/chromium/net/third_party/nss/DIR_METADATA
index 250c6d5b294..54e5bb81d80 100644
--- a/chromium/net/third_party/nss/DIR_METADATA
+++ b/chromium/net/third_party/nss/DIR_METADATA
@@ -1,10 +1,10 @@
# Metadata information for this directory.
#
# For more information on DIR_METADATA files, see:
-# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md
+# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md
#
# For the schema of this file, see Metadata message:
-# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto
+# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto
monorail {
component: "Internals>Network>SSL"
diff --git a/chromium/net/third_party/quiche/BUILD.gn b/chromium/net/third_party/quiche/BUILD.gn
index 7b567969912..41d2dfff1d9 100644
--- a/chromium/net/third_party/quiche/BUILD.gn
+++ b/chromium/net/third_party/quiche/BUILD.gn
@@ -29,619 +29,614 @@ source_set("quiche_public_deps") {
source_set("quiche") {
sources = [
+ "overrides/quiche_platform_impl/quic_mutex_impl.cc",
+ "overrides/quiche_platform_impl/quic_mutex_impl.h",
"overrides/quiche_platform_impl/quiche_export_impl.h",
+ "overrides/quiche_platform_impl/quiche_logging_impl.h",
+ "overrides/quiche_platform_impl/quiche_time_utils_impl.cc",
+ "overrides/quiche_platform_impl/quiche_time_utils_impl.h",
+ "src/common/platform/api/quiche_export.h",
+ "src/common/platform/api/quiche_flag_utils.h",
+ "src/common/platform/api/quiche_flags.h",
+ "src/common/platform/api/quiche_logging.h",
+ "src/common/platform/api/quiche_prefetch.h",
+ "src/common/platform/api/quiche_time_utils.h",
+ "src/common/platform/default/quiche_platform_impl/quiche_prefetch_impl.h",
+ "src/common/quiche_circular_deque.h",
+ "src/common/quiche_data_reader.cc",
+ "src/common/quiche_data_reader.h",
+ "src/common/quiche_data_writer.cc",
+ "src/common/quiche_data_writer.h",
+ "src/common/quiche_endian.h",
+ "src/common/quiche_linked_hash_map.h",
+ "src/common/quiche_text_utils.cc",
+ "src/common/quiche_text_utils.h",
+ "src/http2/core/http2_priority_write_scheduler.h",
+ "src/http2/core/priority_write_scheduler.h",
+ "src/http2/core/write_scheduler.h",
+ "src/http2/decoder/decode_buffer.cc",
+ "src/http2/decoder/decode_buffer.h",
+ "src/http2/decoder/decode_http2_structures.cc",
+ "src/http2/decoder/decode_http2_structures.h",
+ "src/http2/decoder/decode_status.cc",
+ "src/http2/decoder/decode_status.h",
+ "src/http2/decoder/frame_decoder_state.cc",
+ "src/http2/decoder/frame_decoder_state.h",
+ "src/http2/decoder/http2_frame_decoder.cc",
+ "src/http2/decoder/http2_frame_decoder.h",
+ "src/http2/decoder/http2_frame_decoder_listener.cc",
+ "src/http2/decoder/http2_frame_decoder_listener.h",
+ "src/http2/decoder/http2_structure_decoder.cc",
+ "src/http2/decoder/http2_structure_decoder.h",
+ "src/http2/decoder/payload_decoders/altsvc_payload_decoder.cc",
+ "src/http2/decoder/payload_decoders/altsvc_payload_decoder.h",
+ "src/http2/decoder/payload_decoders/continuation_payload_decoder.cc",
+ "src/http2/decoder/payload_decoders/continuation_payload_decoder.h",
+ "src/http2/decoder/payload_decoders/data_payload_decoder.cc",
+ "src/http2/decoder/payload_decoders/data_payload_decoder.h",
+ "src/http2/decoder/payload_decoders/goaway_payload_decoder.cc",
+ "src/http2/decoder/payload_decoders/goaway_payload_decoder.h",
+ "src/http2/decoder/payload_decoders/headers_payload_decoder.cc",
+ "src/http2/decoder/payload_decoders/headers_payload_decoder.h",
+ "src/http2/decoder/payload_decoders/ping_payload_decoder.cc",
+ "src/http2/decoder/payload_decoders/ping_payload_decoder.h",
+ "src/http2/decoder/payload_decoders/priority_payload_decoder.cc",
+ "src/http2/decoder/payload_decoders/priority_payload_decoder.h",
+ "src/http2/decoder/payload_decoders/priority_update_payload_decoder.cc",
+ "src/http2/decoder/payload_decoders/priority_update_payload_decoder.h",
+ "src/http2/decoder/payload_decoders/push_promise_payload_decoder.cc",
+ "src/http2/decoder/payload_decoders/push_promise_payload_decoder.h",
+ "src/http2/decoder/payload_decoders/rst_stream_payload_decoder.cc",
+ "src/http2/decoder/payload_decoders/rst_stream_payload_decoder.h",
+ "src/http2/decoder/payload_decoders/settings_payload_decoder.cc",
+ "src/http2/decoder/payload_decoders/settings_payload_decoder.h",
+ "src/http2/decoder/payload_decoders/unknown_payload_decoder.cc",
+ "src/http2/decoder/payload_decoders/unknown_payload_decoder.h",
+ "src/http2/decoder/payload_decoders/window_update_payload_decoder.cc",
+ "src/http2/decoder/payload_decoders/window_update_payload_decoder.h",
+ "src/http2/hpack/decoder/hpack_block_decoder.cc",
+ "src/http2/hpack/decoder/hpack_block_decoder.h",
+ "src/http2/hpack/decoder/hpack_decoder.cc",
+ "src/http2/hpack/decoder/hpack_decoder.h",
+ "src/http2/hpack/decoder/hpack_decoder_listener.cc",
+ "src/http2/hpack/decoder/hpack_decoder_listener.h",
+ "src/http2/hpack/decoder/hpack_decoder_state.cc",
+ "src/http2/hpack/decoder/hpack_decoder_state.h",
+ "src/http2/hpack/decoder/hpack_decoder_string_buffer.cc",
+ "src/http2/hpack/decoder/hpack_decoder_string_buffer.h",
+ "src/http2/hpack/decoder/hpack_decoder_tables.cc",
+ "src/http2/hpack/decoder/hpack_decoder_tables.h",
+ "src/http2/hpack/decoder/hpack_decoding_error.cc",
+ "src/http2/hpack/decoder/hpack_decoding_error.h",
+ "src/http2/hpack/decoder/hpack_entry_decoder.cc",
+ "src/http2/hpack/decoder/hpack_entry_decoder.h",
+ "src/http2/hpack/decoder/hpack_entry_decoder_listener.cc",
+ "src/http2/hpack/decoder/hpack_entry_decoder_listener.h",
+ "src/http2/hpack/decoder/hpack_entry_type_decoder.cc",
+ "src/http2/hpack/decoder/hpack_entry_type_decoder.h",
+ "src/http2/hpack/decoder/hpack_string_decoder.cc",
+ "src/http2/hpack/decoder/hpack_string_decoder.h",
+ "src/http2/hpack/decoder/hpack_string_decoder_listener.cc",
+ "src/http2/hpack/decoder/hpack_string_decoder_listener.h",
+ "src/http2/hpack/decoder/hpack_whole_entry_buffer.cc",
+ "src/http2/hpack/decoder/hpack_whole_entry_buffer.h",
+ "src/http2/hpack/decoder/hpack_whole_entry_listener.cc",
+ "src/http2/hpack/decoder/hpack_whole_entry_listener.h",
+ "src/http2/hpack/hpack_static_table_entries.inc",
+ "src/http2/hpack/http2_hpack_constants.cc",
+ "src/http2/hpack/http2_hpack_constants.h",
+ "src/http2/hpack/huffman/hpack_huffman_decoder.cc",
+ "src/http2/hpack/huffman/hpack_huffman_decoder.h",
+ "src/http2/hpack/huffman/hpack_huffman_encoder.cc",
+ "src/http2/hpack/huffman/hpack_huffman_encoder.h",
+ "src/http2/hpack/huffman/huffman_spec_tables.cc",
+ "src/http2/hpack/huffman/huffman_spec_tables.h",
+ "src/http2/hpack/varint/hpack_varint_decoder.cc",
+ "src/http2/hpack/varint/hpack_varint_decoder.h",
+ "src/http2/hpack/varint/hpack_varint_encoder.cc",
+ "src/http2/hpack/varint/hpack_varint_encoder.h",
+ "src/http2/http2_constants.cc",
+ "src/http2/http2_constants.h",
+ "src/http2/http2_structures.cc",
+ "src/http2/http2_structures.h",
+ "src/http2/platform/api/http2_bug_tracker.h",
+ "src/http2/platform/api/http2_containers.h",
+ "src/http2/platform/api/http2_estimate_memory_usage.h",
+ "src/http2/platform/api/http2_flag_utils.h",
+ "src/http2/platform/api/http2_flags.h",
+ "src/http2/platform/api/http2_logging.h",
+ "src/http2/platform/api/http2_macros.h",
+ "src/http2/platform/api/http2_string_utils.h",
+ "src/quic/core/congestion_control/bandwidth_sampler.cc",
+ "src/quic/core/congestion_control/bandwidth_sampler.h",
+ "src/quic/core/congestion_control/bbr2_drain.cc",
+ "src/quic/core/congestion_control/bbr2_drain.h",
+ "src/quic/core/congestion_control/bbr2_misc.cc",
+ "src/quic/core/congestion_control/bbr2_misc.h",
+ "src/quic/core/congestion_control/bbr2_probe_bw.cc",
+ "src/quic/core/congestion_control/bbr2_probe_bw.h",
+ "src/quic/core/congestion_control/bbr2_probe_rtt.cc",
+ "src/quic/core/congestion_control/bbr2_probe_rtt.h",
+ "src/quic/core/congestion_control/bbr2_sender.cc",
+ "src/quic/core/congestion_control/bbr2_sender.h",
+ "src/quic/core/congestion_control/bbr2_startup.cc",
+ "src/quic/core/congestion_control/bbr2_startup.h",
+ "src/quic/core/congestion_control/bbr_sender.cc",
+ "src/quic/core/congestion_control/bbr_sender.h",
+ "src/quic/core/congestion_control/cubic_bytes.cc",
+ "src/quic/core/congestion_control/cubic_bytes.h",
+ "src/quic/core/congestion_control/general_loss_algorithm.cc",
+ "src/quic/core/congestion_control/general_loss_algorithm.h",
+ "src/quic/core/congestion_control/hybrid_slow_start.cc",
+ "src/quic/core/congestion_control/hybrid_slow_start.h",
+ "src/quic/core/congestion_control/loss_detection_interface.h",
+ "src/quic/core/congestion_control/pacing_sender.cc",
+ "src/quic/core/congestion_control/pacing_sender.h",
+ "src/quic/core/congestion_control/prr_sender.cc",
+ "src/quic/core/congestion_control/prr_sender.h",
+ "src/quic/core/congestion_control/rtt_stats.cc",
+ "src/quic/core/congestion_control/rtt_stats.h",
+ "src/quic/core/congestion_control/send_algorithm_interface.cc",
+ "src/quic/core/congestion_control/send_algorithm_interface.h",
+ "src/quic/core/congestion_control/tcp_cubic_sender_bytes.cc",
+ "src/quic/core/congestion_control/tcp_cubic_sender_bytes.h",
+ "src/quic/core/congestion_control/uber_loss_algorithm.cc",
+ "src/quic/core/congestion_control/uber_loss_algorithm.h",
+ "src/quic/core/congestion_control/windowed_filter.h",
+ "src/quic/core/crypto/aead_base_decrypter.cc",
+ "src/quic/core/crypto/aead_base_decrypter.h",
+ "src/quic/core/crypto/aead_base_encrypter.cc",
+ "src/quic/core/crypto/aead_base_encrypter.h",
+ "src/quic/core/crypto/aes_128_gcm_12_decrypter.cc",
+ "src/quic/core/crypto/aes_128_gcm_12_decrypter.h",
+ "src/quic/core/crypto/aes_128_gcm_12_encrypter.cc",
+ "src/quic/core/crypto/aes_128_gcm_12_encrypter.h",
+ "src/quic/core/crypto/aes_128_gcm_decrypter.cc",
+ "src/quic/core/crypto/aes_128_gcm_decrypter.h",
+ "src/quic/core/crypto/aes_128_gcm_encrypter.cc",
+ "src/quic/core/crypto/aes_128_gcm_encrypter.h",
+ "src/quic/core/crypto/aes_256_gcm_decrypter.cc",
+ "src/quic/core/crypto/aes_256_gcm_decrypter.h",
+ "src/quic/core/crypto/aes_256_gcm_encrypter.cc",
+ "src/quic/core/crypto/aes_256_gcm_encrypter.h",
+ "src/quic/core/crypto/aes_base_decrypter.cc",
+ "src/quic/core/crypto/aes_base_decrypter.h",
+ "src/quic/core/crypto/aes_base_encrypter.cc",
+ "src/quic/core/crypto/aes_base_encrypter.h",
+ "src/quic/core/crypto/boring_utils.h",
+ "src/quic/core/crypto/cert_compressor.cc",
+ "src/quic/core/crypto/cert_compressor.h",
+ "src/quic/core/crypto/certificate_view.cc",
+ "src/quic/core/crypto/certificate_view.h",
+ "src/quic/core/crypto/chacha20_poly1305_decrypter.cc",
+ "src/quic/core/crypto/chacha20_poly1305_decrypter.h",
+ "src/quic/core/crypto/chacha20_poly1305_encrypter.cc",
+ "src/quic/core/crypto/chacha20_poly1305_encrypter.h",
+ "src/quic/core/crypto/chacha20_poly1305_tls_decrypter.cc",
+ "src/quic/core/crypto/chacha20_poly1305_tls_decrypter.h",
+ "src/quic/core/crypto/chacha20_poly1305_tls_encrypter.cc",
+ "src/quic/core/crypto/chacha20_poly1305_tls_encrypter.h",
+ "src/quic/core/crypto/chacha_base_decrypter.cc",
+ "src/quic/core/crypto/chacha_base_decrypter.h",
+ "src/quic/core/crypto/chacha_base_encrypter.cc",
+ "src/quic/core/crypto/chacha_base_encrypter.h",
+ "src/quic/core/crypto/channel_id.cc",
+ "src/quic/core/crypto/channel_id.h",
+ "src/quic/core/crypto/common_cert_set.cc",
+ "src/quic/core/crypto/common_cert_set.h",
+ "src/quic/core/crypto/crypto_framer.cc",
+ "src/quic/core/crypto/crypto_framer.h",
+ "src/quic/core/crypto/crypto_handshake.cc",
+ "src/quic/core/crypto/crypto_handshake.h",
+ "src/quic/core/crypto/crypto_handshake_message.cc",
+ "src/quic/core/crypto/crypto_handshake_message.h",
+ "src/quic/core/crypto/crypto_message_parser.h",
+ "src/quic/core/crypto/crypto_protocol.h",
+ "src/quic/core/crypto/crypto_secret_boxer.cc",
+ "src/quic/core/crypto/crypto_secret_boxer.h",
+ "src/quic/core/crypto/crypto_utils.cc",
+ "src/quic/core/crypto/crypto_utils.h",
+ "src/quic/core/crypto/curve25519_key_exchange.cc",
+ "src/quic/core/crypto/curve25519_key_exchange.h",
+ "src/quic/core/crypto/key_exchange.cc",
+ "src/quic/core/crypto/key_exchange.h",
+ "src/quic/core/crypto/null_decrypter.cc",
+ "src/quic/core/crypto/null_decrypter.h",
+ "src/quic/core/crypto/null_encrypter.cc",
+ "src/quic/core/crypto/null_encrypter.h",
+ "src/quic/core/crypto/p256_key_exchange.cc",
+ "src/quic/core/crypto/p256_key_exchange.h",
+ "src/quic/core/crypto/proof_source.cc",
+ "src/quic/core/crypto/proof_source.h",
+ "src/quic/core/crypto/proof_verifier.h",
+ "src/quic/core/crypto/quic_compressed_certs_cache.cc",
+ "src/quic/core/crypto/quic_compressed_certs_cache.h",
+ "src/quic/core/crypto/quic_crypter.cc",
+ "src/quic/core/crypto/quic_crypter.h",
+ "src/quic/core/crypto/quic_crypto_client_config.cc",
+ "src/quic/core/crypto/quic_crypto_client_config.h",
+ "src/quic/core/crypto/quic_crypto_proof.cc",
+ "src/quic/core/crypto/quic_crypto_proof.h",
+ "src/quic/core/crypto/quic_crypto_server_config.cc",
+ "src/quic/core/crypto/quic_crypto_server_config.h",
+ "src/quic/core/crypto/quic_decrypter.cc",
+ "src/quic/core/crypto/quic_decrypter.h",
+ "src/quic/core/crypto/quic_encrypter.cc",
+ "src/quic/core/crypto/quic_encrypter.h",
+ "src/quic/core/crypto/quic_hkdf.cc",
+ "src/quic/core/crypto/quic_hkdf.h",
+ "src/quic/core/crypto/quic_random.cc",
+ "src/quic/core/crypto/quic_random.h",
+ "src/quic/core/crypto/server_proof_verifier.h",
+ "src/quic/core/crypto/tls_client_connection.cc",
+ "src/quic/core/crypto/tls_client_connection.h",
+ "src/quic/core/crypto/tls_connection.cc",
+ "src/quic/core/crypto/tls_connection.h",
+ "src/quic/core/crypto/tls_server_connection.cc",
+ "src/quic/core/crypto/tls_server_connection.h",
+ "src/quic/core/crypto/transport_parameters.cc",
+ "src/quic/core/crypto/transport_parameters.h",
+ "src/quic/core/frames/quic_ack_frame.cc",
+ "src/quic/core/frames/quic_ack_frame.h",
+ "src/quic/core/frames/quic_ack_frequency_frame.cc",
+ "src/quic/core/frames/quic_ack_frequency_frame.h",
+ "src/quic/core/frames/quic_blocked_frame.cc",
+ "src/quic/core/frames/quic_blocked_frame.h",
+ "src/quic/core/frames/quic_connection_close_frame.cc",
+ "src/quic/core/frames/quic_connection_close_frame.h",
+ "src/quic/core/frames/quic_crypto_frame.cc",
+ "src/quic/core/frames/quic_crypto_frame.h",
+ "src/quic/core/frames/quic_frame.cc",
+ "src/quic/core/frames/quic_frame.h",
+ "src/quic/core/frames/quic_goaway_frame.cc",
+ "src/quic/core/frames/quic_goaway_frame.h",
+ "src/quic/core/frames/quic_handshake_done_frame.cc",
+ "src/quic/core/frames/quic_handshake_done_frame.h",
+ "src/quic/core/frames/quic_inlined_frame.h",
+ "src/quic/core/frames/quic_max_streams_frame.cc",
+ "src/quic/core/frames/quic_max_streams_frame.h",
+ "src/quic/core/frames/quic_message_frame.cc",
+ "src/quic/core/frames/quic_message_frame.h",
+ "src/quic/core/frames/quic_mtu_discovery_frame.h",
+ "src/quic/core/frames/quic_new_connection_id_frame.cc",
+ "src/quic/core/frames/quic_new_connection_id_frame.h",
+ "src/quic/core/frames/quic_new_token_frame.cc",
+ "src/quic/core/frames/quic_new_token_frame.h",
+ "src/quic/core/frames/quic_padding_frame.cc",
+ "src/quic/core/frames/quic_padding_frame.h",
+ "src/quic/core/frames/quic_path_challenge_frame.cc",
+ "src/quic/core/frames/quic_path_challenge_frame.h",
+ "src/quic/core/frames/quic_path_response_frame.cc",
+ "src/quic/core/frames/quic_path_response_frame.h",
+ "src/quic/core/frames/quic_ping_frame.cc",
+ "src/quic/core/frames/quic_ping_frame.h",
+ "src/quic/core/frames/quic_retire_connection_id_frame.cc",
+ "src/quic/core/frames/quic_retire_connection_id_frame.h",
+ "src/quic/core/frames/quic_rst_stream_frame.cc",
+ "src/quic/core/frames/quic_rst_stream_frame.h",
+ "src/quic/core/frames/quic_stop_sending_frame.cc",
+ "src/quic/core/frames/quic_stop_sending_frame.h",
+ "src/quic/core/frames/quic_stop_waiting_frame.cc",
+ "src/quic/core/frames/quic_stop_waiting_frame.h",
+ "src/quic/core/frames/quic_stream_frame.cc",
+ "src/quic/core/frames/quic_stream_frame.h",
+ "src/quic/core/frames/quic_streams_blocked_frame.cc",
+ "src/quic/core/frames/quic_streams_blocked_frame.h",
+ "src/quic/core/frames/quic_window_update_frame.cc",
+ "src/quic/core/frames/quic_window_update_frame.h",
+ "src/quic/core/handshaker_delegate_interface.h",
+ "src/quic/core/http/http_constants.cc",
+ "src/quic/core/http/http_constants.h",
+ "src/quic/core/http/http_decoder.cc",
+ "src/quic/core/http/http_decoder.h",
+ "src/quic/core/http/http_encoder.cc",
+ "src/quic/core/http/http_encoder.h",
+ "src/quic/core/http/http_frames.h",
+ "src/quic/core/http/quic_client_promised_info.cc",
+ "src/quic/core/http/quic_client_promised_info.h",
+ "src/quic/core/http/quic_client_push_promise_index.cc",
+ "src/quic/core/http/quic_client_push_promise_index.h",
+ "src/quic/core/http/quic_header_list.cc",
+ "src/quic/core/http/quic_header_list.h",
+ "src/quic/core/http/quic_headers_stream.cc",
+ "src/quic/core/http/quic_headers_stream.h",
+ "src/quic/core/http/quic_receive_control_stream.cc",
+ "src/quic/core/http/quic_receive_control_stream.h",
+ "src/quic/core/http/quic_send_control_stream.cc",
+ "src/quic/core/http/quic_send_control_stream.h",
+ "src/quic/core/http/quic_server_initiated_spdy_stream.cc",
+ "src/quic/core/http/quic_server_initiated_spdy_stream.h",
+ "src/quic/core/http/quic_server_session_base.cc",
+ "src/quic/core/http/quic_server_session_base.h",
+ "src/quic/core/http/quic_spdy_client_session.cc",
+ "src/quic/core/http/quic_spdy_client_session.h",
+ "src/quic/core/http/quic_spdy_client_session_base.cc",
+ "src/quic/core/http/quic_spdy_client_session_base.h",
+ "src/quic/core/http/quic_spdy_client_stream.cc",
+ "src/quic/core/http/quic_spdy_client_stream.h",
+ "src/quic/core/http/quic_spdy_session.cc",
+ "src/quic/core/http/quic_spdy_session.h",
+ "src/quic/core/http/quic_spdy_stream.cc",
+ "src/quic/core/http/quic_spdy_stream.h",
+ "src/quic/core/http/quic_spdy_stream_body_manager.cc",
+ "src/quic/core/http/quic_spdy_stream_body_manager.h",
+ "src/quic/core/http/spdy_server_push_utils.cc",
+ "src/quic/core/http/spdy_server_push_utils.h",
+ "src/quic/core/http/spdy_utils.cc",
+ "src/quic/core/http/spdy_utils.h",
+ "src/quic/core/http/web_transport_http3.cc",
+ "src/quic/core/http/web_transport_http3.h",
+ "src/quic/core/legacy_quic_stream_id_manager.cc",
+ "src/quic/core/legacy_quic_stream_id_manager.h",
+ "src/quic/core/packet_number_indexed_queue.h",
+ "src/quic/core/proto/cached_network_parameters_proto.h",
+ "src/quic/core/proto/crypto_server_config_proto.h",
+ "src/quic/core/proto/source_address_token_proto.h",
+ "src/quic/core/qpack/qpack_blocking_manager.cc",
+ "src/quic/core/qpack/qpack_blocking_manager.h",
+ "src/quic/core/qpack/qpack_decoded_headers_accumulator.cc",
+ "src/quic/core/qpack/qpack_decoded_headers_accumulator.h",
+ "src/quic/core/qpack/qpack_decoder.cc",
+ "src/quic/core/qpack/qpack_decoder.h",
+ "src/quic/core/qpack/qpack_decoder_stream_receiver.cc",
+ "src/quic/core/qpack/qpack_decoder_stream_receiver.h",
+ "src/quic/core/qpack/qpack_decoder_stream_sender.cc",
+ "src/quic/core/qpack/qpack_decoder_stream_sender.h",
+ "src/quic/core/qpack/qpack_encoder.cc",
+ "src/quic/core/qpack/qpack_encoder.h",
+ "src/quic/core/qpack/qpack_encoder_stream_receiver.cc",
+ "src/quic/core/qpack/qpack_encoder_stream_receiver.h",
+ "src/quic/core/qpack/qpack_encoder_stream_sender.cc",
+ "src/quic/core/qpack/qpack_encoder_stream_sender.h",
+ "src/quic/core/qpack/qpack_header_table.cc",
+ "src/quic/core/qpack/qpack_header_table.h",
+ "src/quic/core/qpack/qpack_index_conversions.cc",
+ "src/quic/core/qpack/qpack_index_conversions.h",
+ "src/quic/core/qpack/qpack_instruction_decoder.cc",
+ "src/quic/core/qpack/qpack_instruction_decoder.h",
+ "src/quic/core/qpack/qpack_instruction_encoder.cc",
+ "src/quic/core/qpack/qpack_instruction_encoder.h",
+ "src/quic/core/qpack/qpack_instructions.cc",
+ "src/quic/core/qpack/qpack_instructions.h",
+ "src/quic/core/qpack/qpack_progressive_decoder.cc",
+ "src/quic/core/qpack/qpack_progressive_decoder.h",
+ "src/quic/core/qpack/qpack_receive_stream.cc",
+ "src/quic/core/qpack/qpack_receive_stream.h",
+ "src/quic/core/qpack/qpack_required_insert_count.cc",
+ "src/quic/core/qpack/qpack_required_insert_count.h",
+ "src/quic/core/qpack/qpack_send_stream.cc",
+ "src/quic/core/qpack/qpack_send_stream.h",
+ "src/quic/core/qpack/qpack_static_table.cc",
+ "src/quic/core/qpack/qpack_static_table.h",
+ "src/quic/core/qpack/qpack_stream_receiver.h",
+ "src/quic/core/qpack/qpack_stream_sender_delegate.h",
+ "src/quic/core/qpack/value_splitting_header_list.cc",
+ "src/quic/core/qpack/value_splitting_header_list.h",
+ "src/quic/core/quic_ack_listener_interface.cc",
+ "src/quic/core/quic_ack_listener_interface.h",
+ "src/quic/core/quic_alarm.cc",
+ "src/quic/core/quic_alarm.h",
+ "src/quic/core/quic_alarm_factory.h",
+ "src/quic/core/quic_arena_scoped_ptr.h",
+ "src/quic/core/quic_bandwidth.cc",
+ "src/quic/core/quic_bandwidth.h",
+ "src/quic/core/quic_blocked_writer_interface.h",
+ "src/quic/core/quic_buffer_allocator.cc",
+ "src/quic/core/quic_buffer_allocator.h",
+ "src/quic/core/quic_chaos_protector.cc",
+ "src/quic/core/quic_chaos_protector.h",
+ "src/quic/core/quic_clock.cc",
+ "src/quic/core/quic_clock.h",
+ "src/quic/core/quic_coalesced_packet.cc",
+ "src/quic/core/quic_coalesced_packet.h",
+ "src/quic/core/quic_config.cc",
+ "src/quic/core/quic_config.h",
+ "src/quic/core/quic_connection.cc",
+ "src/quic/core/quic_connection.h",
+ "src/quic/core/quic_connection_id.cc",
+ "src/quic/core/quic_connection_id.h",
+ "src/quic/core/quic_connection_id_manager.cc",
+ "src/quic/core/quic_connection_id_manager.h",
+ "src/quic/core/quic_connection_stats.cc",
+ "src/quic/core/quic_connection_stats.h",
+ "src/quic/core/quic_constants.cc",
+ "src/quic/core/quic_constants.h",
+ "src/quic/core/quic_control_frame_manager.cc",
+ "src/quic/core/quic_control_frame_manager.h",
+ "src/quic/core/quic_crypto_client_handshaker.cc",
+ "src/quic/core/quic_crypto_client_handshaker.h",
+ "src/quic/core/quic_crypto_client_stream.cc",
+ "src/quic/core/quic_crypto_client_stream.h",
+ "src/quic/core/quic_crypto_handshaker.cc",
+ "src/quic/core/quic_crypto_handshaker.h",
+ "src/quic/core/quic_crypto_server_stream.cc",
+ "src/quic/core/quic_crypto_server_stream.h",
+ "src/quic/core/quic_crypto_server_stream_base.cc",
+ "src/quic/core/quic_crypto_server_stream_base.h",
+ "src/quic/core/quic_crypto_stream.cc",
+ "src/quic/core/quic_crypto_stream.h",
+ "src/quic/core/quic_data_reader.cc",
+ "src/quic/core/quic_data_reader.h",
+ "src/quic/core/quic_data_writer.cc",
+ "src/quic/core/quic_data_writer.h",
+ "src/quic/core/quic_datagram_queue.cc",
+ "src/quic/core/quic_datagram_queue.h",
"src/quic/core/quic_error_codes.cc",
"src/quic/core/quic_error_codes.h",
+ "src/quic/core/quic_flow_controller.cc",
+ "src/quic/core/quic_flow_controller.h",
+ "src/quic/core/quic_framer.cc",
+ "src/quic/core/quic_framer.h",
+ "src/quic/core/quic_idle_network_detector.cc",
+ "src/quic/core/quic_idle_network_detector.h",
+ "src/quic/core/quic_interval.h",
+ "src/quic/core/quic_interval_deque.h",
+ "src/quic/core/quic_interval_set.h",
+ "src/quic/core/quic_legacy_version_encapsulator.cc",
+ "src/quic/core/quic_legacy_version_encapsulator.h",
+ "src/quic/core/quic_lru_cache.h",
+ "src/quic/core/quic_mtu_discovery.cc",
+ "src/quic/core/quic_mtu_discovery.h",
+ "src/quic/core/quic_network_blackhole_detector.cc",
+ "src/quic/core/quic_network_blackhole_detector.h",
+ "src/quic/core/quic_one_block_arena.h",
+ "src/quic/core/quic_packet_creator.cc",
+ "src/quic/core/quic_packet_creator.h",
+ "src/quic/core/quic_packet_number.cc",
+ "src/quic/core/quic_packet_number.h",
+ "src/quic/core/quic_packet_writer.h",
+ "src/quic/core/quic_packets.cc",
+ "src/quic/core/quic_packets.h",
+ "src/quic/core/quic_path_validator.cc",
+ "src/quic/core/quic_path_validator.h",
+ "src/quic/core/quic_protocol_flags_list.h",
+ "src/quic/core/quic_received_packet_manager.cc",
+ "src/quic/core/quic_received_packet_manager.h",
+ "src/quic/core/quic_sent_packet_manager.cc",
+ "src/quic/core/quic_sent_packet_manager.h",
+ "src/quic/core/quic_server_id.cc",
+ "src/quic/core/quic_server_id.h",
+ "src/quic/core/quic_session.cc",
+ "src/quic/core/quic_session.h",
+ "src/quic/core/quic_simple_buffer_allocator.cc",
+ "src/quic/core/quic_simple_buffer_allocator.h",
+ "src/quic/core/quic_socket_address_coder.cc",
+ "src/quic/core/quic_socket_address_coder.h",
+ "src/quic/core/quic_stream.cc",
+ "src/quic/core/quic_stream.h",
+ "src/quic/core/quic_stream_frame_data_producer.h",
+ "src/quic/core/quic_stream_id_manager.cc",
+ "src/quic/core/quic_stream_id_manager.h",
+ "src/quic/core/quic_stream_send_buffer.cc",
+ "src/quic/core/quic_stream_send_buffer.h",
+ "src/quic/core/quic_stream_sequencer.cc",
+ "src/quic/core/quic_stream_sequencer.h",
+ "src/quic/core/quic_stream_sequencer_buffer.cc",
+ "src/quic/core/quic_stream_sequencer_buffer.h",
+ "src/quic/core/quic_sustained_bandwidth_recorder.cc",
+ "src/quic/core/quic_sustained_bandwidth_recorder.h",
+ "src/quic/core/quic_tag.cc",
+ "src/quic/core/quic_tag.h",
+ "src/quic/core/quic_time.cc",
+ "src/quic/core/quic_time.h",
+ "src/quic/core/quic_time_accumulator.h",
+ "src/quic/core/quic_transmission_info.cc",
+ "src/quic/core/quic_transmission_info.h",
+ "src/quic/core/quic_types.cc",
+ "src/quic/core/quic_types.h",
+ "src/quic/core/quic_unacked_packet_map.cc",
+ "src/quic/core/quic_unacked_packet_map.h",
+ "src/quic/core/quic_utils.cc",
+ "src/quic/core/quic_utils.h",
+ "src/quic/core/quic_version_manager.cc",
+ "src/quic/core/quic_version_manager.h",
+ "src/quic/core/quic_versions.cc",
+ "src/quic/core/quic_versions.h",
+ "src/quic/core/quic_write_blocked_list.cc",
+ "src/quic/core/quic_write_blocked_list.h",
+ "src/quic/core/session_notifier_interface.h",
+ "src/quic/core/stream_delegate_interface.h",
+ "src/quic/core/tls_client_handshaker.cc",
+ "src/quic/core/tls_client_handshaker.h",
+ "src/quic/core/tls_handshaker.cc",
+ "src/quic/core/tls_handshaker.h",
+ "src/quic/core/tls_server_handshaker.cc",
+ "src/quic/core/tls_server_handshaker.h",
+ "src/quic/core/uber_quic_stream_id_manager.cc",
+ "src/quic/core/uber_quic_stream_id_manager.h",
+ "src/quic/core/uber_received_packet_manager.cc",
+ "src/quic/core/uber_received_packet_manager.h",
+ "src/quic/core/web_transport_stream_adapter.cc",
+ "src/quic/core/web_transport_stream_adapter.h",
+ "src/quic/platform/api/quic_bug_tracker.h",
+ "src/quic/platform/api/quic_client_stats.h",
+ "src/quic/platform/api/quic_containers.h",
+ "src/quic/platform/api/quic_error_code_wrappers.h",
+ "src/quic/platform/api/quic_estimate_memory_usage.h",
+ "src/quic/platform/api/quic_export.h",
+ "src/quic/platform/api/quic_exported_stats.h",
+ "src/quic/platform/api/quic_file_utils.cc",
+ "src/quic/platform/api/quic_file_utils.h",
+ "src/quic/platform/api/quic_flag_utils.h",
+ "src/quic/platform/api/quic_flags.h",
+ "src/quic/platform/api/quic_hostname_utils.cc",
+ "src/quic/platform/api/quic_hostname_utils.h",
+ "src/quic/platform/api/quic_iovec.h",
+ "src/quic/platform/api/quic_ip_address.cc",
+ "src/quic/platform/api/quic_ip_address.h",
+ "src/quic/platform/api/quic_ip_address_family.h",
+ "src/quic/platform/api/quic_logging.h",
+ "src/quic/platform/api/quic_map_util.h",
+ "src/quic/platform/api/quic_mem_slice.h",
+ "src/quic/platform/api/quic_mem_slice_span.h",
+ "src/quic/platform/api/quic_mem_slice_storage.h",
+ "src/quic/platform/api/quic_mutex.cc",
+ "src/quic/platform/api/quic_mutex.h",
+ "src/quic/platform/api/quic_reference_counted.h",
+ "src/quic/platform/api/quic_server_stats.h",
+ "src/quic/platform/api/quic_sleep.h",
+ "src/quic/platform/api/quic_socket_address.cc",
+ "src/quic/platform/api/quic_socket_address.h",
+ "src/quic/platform/api/quic_stack_trace.h",
+ "src/quic/platform/api/quic_thread.h",
+ "src/quic/quic_transport/quic_transport_client_session.cc",
+ "src/quic/quic_transport/quic_transport_client_session.h",
+ "src/quic/quic_transport/quic_transport_protocol.h",
+ "src/quic/quic_transport/quic_transport_server_session.cc",
+ "src/quic/quic_transport/quic_transport_server_session.h",
+ "src/quic/quic_transport/quic_transport_session_interface.h",
+ "src/quic/quic_transport/quic_transport_stream.cc",
+ "src/quic/quic_transport/quic_transport_stream.h",
+ "src/quic/quic_transport/web_transport_fingerprint_proof_verifier.cc",
+ "src/quic/quic_transport/web_transport_fingerprint_proof_verifier.h",
+ "src/spdy/core/hpack/hpack_constants.cc",
+ "src/spdy/core/hpack/hpack_constants.h",
+ "src/spdy/core/hpack/hpack_decoder_adapter.cc",
+ "src/spdy/core/hpack/hpack_decoder_adapter.h",
+ "src/spdy/core/hpack/hpack_encoder.cc",
+ "src/spdy/core/hpack/hpack_encoder.h",
+ "src/spdy/core/hpack/hpack_entry.cc",
+ "src/spdy/core/hpack/hpack_entry.h",
+ "src/spdy/core/hpack/hpack_header_table.cc",
+ "src/spdy/core/hpack/hpack_header_table.h",
+ "src/spdy/core/hpack/hpack_output_stream.cc",
+ "src/spdy/core/hpack/hpack_output_stream.h",
+ "src/spdy/core/hpack/hpack_static_table.cc",
+ "src/spdy/core/hpack/hpack_static_table.h",
+ "src/spdy/core/http2_frame_decoder_adapter.cc",
+ "src/spdy/core/http2_frame_decoder_adapter.h",
+ "src/spdy/core/recording_headers_handler.cc",
+ "src/spdy/core/recording_headers_handler.h",
+ "src/spdy/core/spdy_alt_svc_wire_format.cc",
+ "src/spdy/core/spdy_alt_svc_wire_format.h",
+ "src/spdy/core/spdy_bitmasks.h",
+ "src/spdy/core/spdy_frame_builder.cc",
+ "src/spdy/core/spdy_frame_builder.h",
+ "src/spdy/core/spdy_frame_reader.cc",
+ "src/spdy/core/spdy_frame_reader.h",
+ "src/spdy/core/spdy_framer.cc",
+ "src/spdy/core/spdy_framer.h",
+ "src/spdy/core/spdy_header_block.cc",
+ "src/spdy/core/spdy_header_block.h",
+ "src/spdy/core/spdy_header_storage.cc",
+ "src/spdy/core/spdy_header_storage.h",
+ "src/spdy/core/spdy_headers_handler_interface.h",
+ "src/spdy/core/spdy_intrusive_list.h",
+ "src/spdy/core/spdy_no_op_visitor.cc",
+ "src/spdy/core/spdy_no_op_visitor.h",
+ "src/spdy/core/spdy_pinnable_buffer_piece.cc",
+ "src/spdy/core/spdy_pinnable_buffer_piece.h",
+ "src/spdy/core/spdy_prefixed_buffer_reader.cc",
+ "src/spdy/core/spdy_prefixed_buffer_reader.h",
+ "src/spdy/core/spdy_protocol.cc",
+ "src/spdy/core/spdy_protocol.h",
+ "src/spdy/core/spdy_simple_arena.cc",
+ "src/spdy/core/spdy_simple_arena.h",
+ "src/spdy/core/zero_copy_output_buffer.h",
+ "src/spdy/platform/api/spdy_containers.h",
+ "src/spdy/platform/api/spdy_estimate_memory_usage.h",
]
- if (!is_nacl) {
- sources += [
- "overrides/quiche_platform_impl/quic_mutex_impl.cc",
- "overrides/quiche_platform_impl/quic_mutex_impl.h",
- "overrides/quiche_platform_impl/quiche_logging_impl.h",
- "overrides/quiche_platform_impl/quiche_time_utils_impl.cc",
- "overrides/quiche_platform_impl/quiche_time_utils_impl.h",
- "src/common/platform/api/quiche_export.h",
- "src/common/platform/api/quiche_flag_utils.h",
- "src/common/platform/api/quiche_flags.h",
- "src/common/platform/api/quiche_logging.h",
- "src/common/platform/api/quiche_text_utils.h",
- "src/common/platform/api/quiche_time_utils.h",
- "src/common/quiche_data_reader.cc",
- "src/common/quiche_data_reader.h",
- "src/common/quiche_data_writer.cc",
- "src/common/quiche_data_writer.h",
- "src/common/quiche_endian.h",
- "src/common/simple_linked_hash_map.h",
- "src/http2/decoder/decode_buffer.cc",
- "src/http2/decoder/decode_buffer.h",
- "src/http2/decoder/decode_http2_structures.cc",
- "src/http2/decoder/decode_http2_structures.h",
- "src/http2/decoder/decode_status.cc",
- "src/http2/decoder/decode_status.h",
- "src/http2/decoder/frame_decoder_state.cc",
- "src/http2/decoder/frame_decoder_state.h",
- "src/http2/decoder/http2_frame_decoder.cc",
- "src/http2/decoder/http2_frame_decoder.h",
- "src/http2/decoder/http2_frame_decoder_listener.cc",
- "src/http2/decoder/http2_frame_decoder_listener.h",
- "src/http2/decoder/http2_structure_decoder.cc",
- "src/http2/decoder/http2_structure_decoder.h",
- "src/http2/decoder/payload_decoders/altsvc_payload_decoder.cc",
- "src/http2/decoder/payload_decoders/altsvc_payload_decoder.h",
- "src/http2/decoder/payload_decoders/continuation_payload_decoder.cc",
- "src/http2/decoder/payload_decoders/continuation_payload_decoder.h",
- "src/http2/decoder/payload_decoders/data_payload_decoder.cc",
- "src/http2/decoder/payload_decoders/data_payload_decoder.h",
- "src/http2/decoder/payload_decoders/goaway_payload_decoder.cc",
- "src/http2/decoder/payload_decoders/goaway_payload_decoder.h",
- "src/http2/decoder/payload_decoders/headers_payload_decoder.cc",
- "src/http2/decoder/payload_decoders/headers_payload_decoder.h",
- "src/http2/decoder/payload_decoders/ping_payload_decoder.cc",
- "src/http2/decoder/payload_decoders/ping_payload_decoder.h",
- "src/http2/decoder/payload_decoders/priority_payload_decoder.cc",
- "src/http2/decoder/payload_decoders/priority_payload_decoder.h",
- "src/http2/decoder/payload_decoders/priority_update_payload_decoder.cc",
- "src/http2/decoder/payload_decoders/priority_update_payload_decoder.h",
- "src/http2/decoder/payload_decoders/push_promise_payload_decoder.cc",
- "src/http2/decoder/payload_decoders/push_promise_payload_decoder.h",
- "src/http2/decoder/payload_decoders/rst_stream_payload_decoder.cc",
- "src/http2/decoder/payload_decoders/rst_stream_payload_decoder.h",
- "src/http2/decoder/payload_decoders/settings_payload_decoder.cc",
- "src/http2/decoder/payload_decoders/settings_payload_decoder.h",
- "src/http2/decoder/payload_decoders/unknown_payload_decoder.cc",
- "src/http2/decoder/payload_decoders/unknown_payload_decoder.h",
- "src/http2/decoder/payload_decoders/window_update_payload_decoder.cc",
- "src/http2/decoder/payload_decoders/window_update_payload_decoder.h",
- "src/http2/hpack/decoder/hpack_block_decoder.cc",
- "src/http2/hpack/decoder/hpack_block_decoder.h",
- "src/http2/hpack/decoder/hpack_decoder.cc",
- "src/http2/hpack/decoder/hpack_decoder.h",
- "src/http2/hpack/decoder/hpack_decoder_listener.cc",
- "src/http2/hpack/decoder/hpack_decoder_listener.h",
- "src/http2/hpack/decoder/hpack_decoder_state.cc",
- "src/http2/hpack/decoder/hpack_decoder_state.h",
- "src/http2/hpack/decoder/hpack_decoder_string_buffer.cc",
- "src/http2/hpack/decoder/hpack_decoder_string_buffer.h",
- "src/http2/hpack/decoder/hpack_decoder_tables.cc",
- "src/http2/hpack/decoder/hpack_decoder_tables.h",
- "src/http2/hpack/decoder/hpack_decoding_error.cc",
- "src/http2/hpack/decoder/hpack_decoding_error.h",
- "src/http2/hpack/decoder/hpack_entry_decoder.cc",
- "src/http2/hpack/decoder/hpack_entry_decoder.h",
- "src/http2/hpack/decoder/hpack_entry_decoder_listener.cc",
- "src/http2/hpack/decoder/hpack_entry_decoder_listener.h",
- "src/http2/hpack/decoder/hpack_entry_type_decoder.cc",
- "src/http2/hpack/decoder/hpack_entry_type_decoder.h",
- "src/http2/hpack/decoder/hpack_string_decoder.cc",
- "src/http2/hpack/decoder/hpack_string_decoder.h",
- "src/http2/hpack/decoder/hpack_string_decoder_listener.cc",
- "src/http2/hpack/decoder/hpack_string_decoder_listener.h",
- "src/http2/hpack/decoder/hpack_whole_entry_buffer.cc",
- "src/http2/hpack/decoder/hpack_whole_entry_buffer.h",
- "src/http2/hpack/decoder/hpack_whole_entry_listener.cc",
- "src/http2/hpack/decoder/hpack_whole_entry_listener.h",
- "src/http2/hpack/hpack_static_table_entries.inc",
- "src/http2/hpack/http2_hpack_constants.cc",
- "src/http2/hpack/http2_hpack_constants.h",
- "src/http2/hpack/huffman/hpack_huffman_decoder.cc",
- "src/http2/hpack/huffman/hpack_huffman_decoder.h",
- "src/http2/hpack/huffman/hpack_huffman_encoder.cc",
- "src/http2/hpack/huffman/hpack_huffman_encoder.h",
- "src/http2/hpack/huffman/huffman_spec_tables.cc",
- "src/http2/hpack/huffman/huffman_spec_tables.h",
- "src/http2/hpack/varint/hpack_varint_decoder.cc",
- "src/http2/hpack/varint/hpack_varint_decoder.h",
- "src/http2/hpack/varint/hpack_varint_encoder.cc",
- "src/http2/hpack/varint/hpack_varint_encoder.h",
- "src/http2/http2_constants.cc",
- "src/http2/http2_constants.h",
- "src/http2/http2_structures.cc",
- "src/http2/http2_structures.h",
- "src/http2/platform/api/http2_bug_tracker.h",
- "src/http2/platform/api/http2_containers.h",
- "src/http2/platform/api/http2_estimate_memory_usage.h",
- "src/http2/platform/api/http2_flag_utils.h",
- "src/http2/platform/api/http2_flags.h",
- "src/http2/platform/api/http2_logging.h",
- "src/http2/platform/api/http2_macros.h",
- "src/http2/platform/api/http2_string_utils.h",
- "src/quic/core/congestion_control/bandwidth_sampler.cc",
- "src/quic/core/congestion_control/bandwidth_sampler.h",
- "src/quic/core/congestion_control/bbr2_drain.cc",
- "src/quic/core/congestion_control/bbr2_drain.h",
- "src/quic/core/congestion_control/bbr2_misc.cc",
- "src/quic/core/congestion_control/bbr2_misc.h",
- "src/quic/core/congestion_control/bbr2_probe_bw.cc",
- "src/quic/core/congestion_control/bbr2_probe_bw.h",
- "src/quic/core/congestion_control/bbr2_probe_rtt.cc",
- "src/quic/core/congestion_control/bbr2_probe_rtt.h",
- "src/quic/core/congestion_control/bbr2_sender.cc",
- "src/quic/core/congestion_control/bbr2_sender.h",
- "src/quic/core/congestion_control/bbr2_startup.cc",
- "src/quic/core/congestion_control/bbr2_startup.h",
- "src/quic/core/congestion_control/bbr_sender.cc",
- "src/quic/core/congestion_control/bbr_sender.h",
- "src/quic/core/congestion_control/cubic_bytes.cc",
- "src/quic/core/congestion_control/cubic_bytes.h",
- "src/quic/core/congestion_control/general_loss_algorithm.cc",
- "src/quic/core/congestion_control/general_loss_algorithm.h",
- "src/quic/core/congestion_control/hybrid_slow_start.cc",
- "src/quic/core/congestion_control/hybrid_slow_start.h",
- "src/quic/core/congestion_control/loss_detection_interface.h",
- "src/quic/core/congestion_control/pacing_sender.cc",
- "src/quic/core/congestion_control/pacing_sender.h",
- "src/quic/core/congestion_control/prr_sender.cc",
- "src/quic/core/congestion_control/prr_sender.h",
- "src/quic/core/congestion_control/rtt_stats.cc",
- "src/quic/core/congestion_control/rtt_stats.h",
- "src/quic/core/congestion_control/send_algorithm_interface.cc",
- "src/quic/core/congestion_control/send_algorithm_interface.h",
- "src/quic/core/congestion_control/tcp_cubic_sender_bytes.cc",
- "src/quic/core/congestion_control/tcp_cubic_sender_bytes.h",
- "src/quic/core/congestion_control/uber_loss_algorithm.cc",
- "src/quic/core/congestion_control/uber_loss_algorithm.h",
- "src/quic/core/congestion_control/windowed_filter.h",
- "src/quic/core/crypto/aead_base_decrypter.cc",
- "src/quic/core/crypto/aead_base_decrypter.h",
- "src/quic/core/crypto/aead_base_encrypter.cc",
- "src/quic/core/crypto/aead_base_encrypter.h",
- "src/quic/core/crypto/aes_128_gcm_12_decrypter.cc",
- "src/quic/core/crypto/aes_128_gcm_12_decrypter.h",
- "src/quic/core/crypto/aes_128_gcm_12_encrypter.cc",
- "src/quic/core/crypto/aes_128_gcm_12_encrypter.h",
- "src/quic/core/crypto/aes_128_gcm_decrypter.cc",
- "src/quic/core/crypto/aes_128_gcm_decrypter.h",
- "src/quic/core/crypto/aes_128_gcm_encrypter.cc",
- "src/quic/core/crypto/aes_128_gcm_encrypter.h",
- "src/quic/core/crypto/aes_256_gcm_decrypter.cc",
- "src/quic/core/crypto/aes_256_gcm_decrypter.h",
- "src/quic/core/crypto/aes_256_gcm_encrypter.cc",
- "src/quic/core/crypto/aes_256_gcm_encrypter.h",
- "src/quic/core/crypto/aes_base_decrypter.cc",
- "src/quic/core/crypto/aes_base_decrypter.h",
- "src/quic/core/crypto/aes_base_encrypter.cc",
- "src/quic/core/crypto/aes_base_encrypter.h",
- "src/quic/core/crypto/boring_utils.h",
- "src/quic/core/crypto/cert_compressor.cc",
- "src/quic/core/crypto/cert_compressor.h",
- "src/quic/core/crypto/certificate_view.cc",
- "src/quic/core/crypto/certificate_view.h",
- "src/quic/core/crypto/chacha20_poly1305_decrypter.cc",
- "src/quic/core/crypto/chacha20_poly1305_decrypter.h",
- "src/quic/core/crypto/chacha20_poly1305_encrypter.cc",
- "src/quic/core/crypto/chacha20_poly1305_encrypter.h",
- "src/quic/core/crypto/chacha20_poly1305_tls_decrypter.cc",
- "src/quic/core/crypto/chacha20_poly1305_tls_decrypter.h",
- "src/quic/core/crypto/chacha20_poly1305_tls_encrypter.cc",
- "src/quic/core/crypto/chacha20_poly1305_tls_encrypter.h",
- "src/quic/core/crypto/chacha_base_decrypter.cc",
- "src/quic/core/crypto/chacha_base_decrypter.h",
- "src/quic/core/crypto/chacha_base_encrypter.cc",
- "src/quic/core/crypto/chacha_base_encrypter.h",
- "src/quic/core/crypto/channel_id.cc",
- "src/quic/core/crypto/channel_id.h",
- "src/quic/core/crypto/common_cert_set.cc",
- "src/quic/core/crypto/common_cert_set.h",
- "src/quic/core/crypto/crypto_framer.cc",
- "src/quic/core/crypto/crypto_framer.h",
- "src/quic/core/crypto/crypto_handshake.cc",
- "src/quic/core/crypto/crypto_handshake.h",
- "src/quic/core/crypto/crypto_handshake_message.cc",
- "src/quic/core/crypto/crypto_handshake_message.h",
- "src/quic/core/crypto/crypto_message_parser.h",
- "src/quic/core/crypto/crypto_protocol.h",
- "src/quic/core/crypto/crypto_secret_boxer.cc",
- "src/quic/core/crypto/crypto_secret_boxer.h",
- "src/quic/core/crypto/crypto_utils.cc",
- "src/quic/core/crypto/crypto_utils.h",
- "src/quic/core/crypto/curve25519_key_exchange.cc",
- "src/quic/core/crypto/curve25519_key_exchange.h",
- "src/quic/core/crypto/key_exchange.cc",
- "src/quic/core/crypto/key_exchange.h",
- "src/quic/core/crypto/null_decrypter.cc",
- "src/quic/core/crypto/null_decrypter.h",
- "src/quic/core/crypto/null_encrypter.cc",
- "src/quic/core/crypto/null_encrypter.h",
- "src/quic/core/crypto/p256_key_exchange.cc",
- "src/quic/core/crypto/p256_key_exchange.h",
- "src/quic/core/crypto/proof_source.cc",
- "src/quic/core/crypto/proof_source.h",
- "src/quic/core/crypto/proof_verifier.h",
- "src/quic/core/crypto/quic_compressed_certs_cache.cc",
- "src/quic/core/crypto/quic_compressed_certs_cache.h",
- "src/quic/core/crypto/quic_crypter.cc",
- "src/quic/core/crypto/quic_crypter.h",
- "src/quic/core/crypto/quic_crypto_client_config.cc",
- "src/quic/core/crypto/quic_crypto_client_config.h",
- "src/quic/core/crypto/quic_crypto_proof.cc",
- "src/quic/core/crypto/quic_crypto_proof.h",
- "src/quic/core/crypto/quic_crypto_server_config.cc",
- "src/quic/core/crypto/quic_crypto_server_config.h",
- "src/quic/core/crypto/quic_decrypter.cc",
- "src/quic/core/crypto/quic_decrypter.h",
- "src/quic/core/crypto/quic_encrypter.cc",
- "src/quic/core/crypto/quic_encrypter.h",
- "src/quic/core/crypto/quic_hkdf.cc",
- "src/quic/core/crypto/quic_hkdf.h",
- "src/quic/core/crypto/quic_random.cc",
- "src/quic/core/crypto/quic_random.h",
- "src/quic/core/crypto/server_proof_verifier.h",
- "src/quic/core/crypto/tls_client_connection.cc",
- "src/quic/core/crypto/tls_client_connection.h",
- "src/quic/core/crypto/tls_connection.cc",
- "src/quic/core/crypto/tls_connection.h",
- "src/quic/core/crypto/tls_server_connection.cc",
- "src/quic/core/crypto/tls_server_connection.h",
- "src/quic/core/crypto/transport_parameters.cc",
- "src/quic/core/crypto/transport_parameters.h",
- "src/quic/core/frames/quic_ack_frame.cc",
- "src/quic/core/frames/quic_ack_frame.h",
- "src/quic/core/frames/quic_ack_frequency_frame.cc",
- "src/quic/core/frames/quic_ack_frequency_frame.h",
- "src/quic/core/frames/quic_blocked_frame.cc",
- "src/quic/core/frames/quic_blocked_frame.h",
- "src/quic/core/frames/quic_connection_close_frame.cc",
- "src/quic/core/frames/quic_connection_close_frame.h",
- "src/quic/core/frames/quic_crypto_frame.cc",
- "src/quic/core/frames/quic_crypto_frame.h",
- "src/quic/core/frames/quic_frame.cc",
- "src/quic/core/frames/quic_frame.h",
- "src/quic/core/frames/quic_goaway_frame.cc",
- "src/quic/core/frames/quic_goaway_frame.h",
- "src/quic/core/frames/quic_handshake_done_frame.cc",
- "src/quic/core/frames/quic_handshake_done_frame.h",
- "src/quic/core/frames/quic_inlined_frame.h",
- "src/quic/core/frames/quic_max_streams_frame.cc",
- "src/quic/core/frames/quic_max_streams_frame.h",
- "src/quic/core/frames/quic_message_frame.cc",
- "src/quic/core/frames/quic_message_frame.h",
- "src/quic/core/frames/quic_mtu_discovery_frame.h",
- "src/quic/core/frames/quic_new_connection_id_frame.cc",
- "src/quic/core/frames/quic_new_connection_id_frame.h",
- "src/quic/core/frames/quic_new_token_frame.cc",
- "src/quic/core/frames/quic_new_token_frame.h",
- "src/quic/core/frames/quic_padding_frame.cc",
- "src/quic/core/frames/quic_padding_frame.h",
- "src/quic/core/frames/quic_path_challenge_frame.cc",
- "src/quic/core/frames/quic_path_challenge_frame.h",
- "src/quic/core/frames/quic_path_response_frame.cc",
- "src/quic/core/frames/quic_path_response_frame.h",
- "src/quic/core/frames/quic_ping_frame.cc",
- "src/quic/core/frames/quic_ping_frame.h",
- "src/quic/core/frames/quic_retire_connection_id_frame.cc",
- "src/quic/core/frames/quic_retire_connection_id_frame.h",
- "src/quic/core/frames/quic_rst_stream_frame.cc",
- "src/quic/core/frames/quic_rst_stream_frame.h",
- "src/quic/core/frames/quic_stop_sending_frame.cc",
- "src/quic/core/frames/quic_stop_sending_frame.h",
- "src/quic/core/frames/quic_stop_waiting_frame.cc",
- "src/quic/core/frames/quic_stop_waiting_frame.h",
- "src/quic/core/frames/quic_stream_frame.cc",
- "src/quic/core/frames/quic_stream_frame.h",
- "src/quic/core/frames/quic_streams_blocked_frame.cc",
- "src/quic/core/frames/quic_streams_blocked_frame.h",
- "src/quic/core/frames/quic_window_update_frame.cc",
- "src/quic/core/frames/quic_window_update_frame.h",
- "src/quic/core/handshaker_delegate_interface.h",
- "src/quic/core/http/http_constants.cc",
- "src/quic/core/http/http_constants.h",
- "src/quic/core/http/http_decoder.cc",
- "src/quic/core/http/http_decoder.h",
- "src/quic/core/http/http_encoder.cc",
- "src/quic/core/http/http_encoder.h",
- "src/quic/core/http/http_frames.h",
- "src/quic/core/http/quic_client_promised_info.cc",
- "src/quic/core/http/quic_client_promised_info.h",
- "src/quic/core/http/quic_client_push_promise_index.cc",
- "src/quic/core/http/quic_client_push_promise_index.h",
- "src/quic/core/http/quic_header_list.cc",
- "src/quic/core/http/quic_header_list.h",
- "src/quic/core/http/quic_headers_stream.cc",
- "src/quic/core/http/quic_headers_stream.h",
- "src/quic/core/http/quic_receive_control_stream.cc",
- "src/quic/core/http/quic_receive_control_stream.h",
- "src/quic/core/http/quic_send_control_stream.cc",
- "src/quic/core/http/quic_send_control_stream.h",
- "src/quic/core/http/quic_server_initiated_spdy_stream.cc",
- "src/quic/core/http/quic_server_initiated_spdy_stream.h",
- "src/quic/core/http/quic_server_session_base.cc",
- "src/quic/core/http/quic_server_session_base.h",
- "src/quic/core/http/quic_spdy_client_session.cc",
- "src/quic/core/http/quic_spdy_client_session.h",
- "src/quic/core/http/quic_spdy_client_session_base.cc",
- "src/quic/core/http/quic_spdy_client_session_base.h",
- "src/quic/core/http/quic_spdy_client_stream.cc",
- "src/quic/core/http/quic_spdy_client_stream.h",
- "src/quic/core/http/quic_spdy_session.cc",
- "src/quic/core/http/quic_spdy_session.h",
- "src/quic/core/http/quic_spdy_stream.cc",
- "src/quic/core/http/quic_spdy_stream.h",
- "src/quic/core/http/quic_spdy_stream_body_manager.cc",
- "src/quic/core/http/quic_spdy_stream_body_manager.h",
- "src/quic/core/http/spdy_server_push_utils.cc",
- "src/quic/core/http/spdy_server_push_utils.h",
- "src/quic/core/http/spdy_utils.cc",
- "src/quic/core/http/spdy_utils.h",
- "src/quic/core/http/web_transport_http3.cc",
- "src/quic/core/http/web_transport_http3.h",
- "src/quic/core/legacy_quic_stream_id_manager.cc",
- "src/quic/core/legacy_quic_stream_id_manager.h",
- "src/quic/core/packet_number_indexed_queue.h",
- "src/quic/core/proto/cached_network_parameters_proto.h",
- "src/quic/core/proto/crypto_server_config_proto.h",
- "src/quic/core/proto/source_address_token_proto.h",
- "src/quic/core/qpack/qpack_blocking_manager.cc",
- "src/quic/core/qpack/qpack_blocking_manager.h",
- "src/quic/core/qpack/qpack_decoded_headers_accumulator.cc",
- "src/quic/core/qpack/qpack_decoded_headers_accumulator.h",
- "src/quic/core/qpack/qpack_decoder.cc",
- "src/quic/core/qpack/qpack_decoder.h",
- "src/quic/core/qpack/qpack_decoder_stream_receiver.cc",
- "src/quic/core/qpack/qpack_decoder_stream_receiver.h",
- "src/quic/core/qpack/qpack_decoder_stream_sender.cc",
- "src/quic/core/qpack/qpack_decoder_stream_sender.h",
- "src/quic/core/qpack/qpack_encoder.cc",
- "src/quic/core/qpack/qpack_encoder.h",
- "src/quic/core/qpack/qpack_encoder_stream_receiver.cc",
- "src/quic/core/qpack/qpack_encoder_stream_receiver.h",
- "src/quic/core/qpack/qpack_encoder_stream_sender.cc",
- "src/quic/core/qpack/qpack_encoder_stream_sender.h",
- "src/quic/core/qpack/qpack_header_table.cc",
- "src/quic/core/qpack/qpack_header_table.h",
- "src/quic/core/qpack/qpack_index_conversions.cc",
- "src/quic/core/qpack/qpack_index_conversions.h",
- "src/quic/core/qpack/qpack_instruction_decoder.cc",
- "src/quic/core/qpack/qpack_instruction_decoder.h",
- "src/quic/core/qpack/qpack_instruction_encoder.cc",
- "src/quic/core/qpack/qpack_instruction_encoder.h",
- "src/quic/core/qpack/qpack_instructions.cc",
- "src/quic/core/qpack/qpack_instructions.h",
- "src/quic/core/qpack/qpack_progressive_decoder.cc",
- "src/quic/core/qpack/qpack_progressive_decoder.h",
- "src/quic/core/qpack/qpack_receive_stream.cc",
- "src/quic/core/qpack/qpack_receive_stream.h",
- "src/quic/core/qpack/qpack_required_insert_count.cc",
- "src/quic/core/qpack/qpack_required_insert_count.h",
- "src/quic/core/qpack/qpack_send_stream.cc",
- "src/quic/core/qpack/qpack_send_stream.h",
- "src/quic/core/qpack/qpack_static_table.cc",
- "src/quic/core/qpack/qpack_static_table.h",
- "src/quic/core/qpack/qpack_stream_receiver.h",
- "src/quic/core/qpack/qpack_stream_sender_delegate.h",
- "src/quic/core/qpack/value_splitting_header_list.cc",
- "src/quic/core/qpack/value_splitting_header_list.h",
- "src/quic/core/quic_ack_listener_interface.cc",
- "src/quic/core/quic_ack_listener_interface.h",
- "src/quic/core/quic_alarm.cc",
- "src/quic/core/quic_alarm.h",
- "src/quic/core/quic_alarm_factory.h",
- "src/quic/core/quic_arena_scoped_ptr.h",
- "src/quic/core/quic_bandwidth.cc",
- "src/quic/core/quic_bandwidth.h",
- "src/quic/core/quic_blocked_writer_interface.h",
- "src/quic/core/quic_buffer_allocator.cc",
- "src/quic/core/quic_buffer_allocator.h",
- "src/quic/core/quic_circular_deque.h",
- "src/quic/core/quic_clock.cc",
- "src/quic/core/quic_clock.h",
- "src/quic/core/quic_coalesced_packet.cc",
- "src/quic/core/quic_coalesced_packet.h",
- "src/quic/core/quic_config.cc",
- "src/quic/core/quic_config.h",
- "src/quic/core/quic_connection.cc",
- "src/quic/core/quic_connection.h",
- "src/quic/core/quic_connection_id.cc",
- "src/quic/core/quic_connection_id.h",
- "src/quic/core/quic_connection_id_manager.cc",
- "src/quic/core/quic_connection_id_manager.h",
- "src/quic/core/quic_connection_stats.cc",
- "src/quic/core/quic_connection_stats.h",
- "src/quic/core/quic_constants.cc",
- "src/quic/core/quic_constants.h",
- "src/quic/core/quic_control_frame_manager.cc",
- "src/quic/core/quic_control_frame_manager.h",
- "src/quic/core/quic_crypto_client_handshaker.cc",
- "src/quic/core/quic_crypto_client_handshaker.h",
- "src/quic/core/quic_crypto_client_stream.cc",
- "src/quic/core/quic_crypto_client_stream.h",
- "src/quic/core/quic_crypto_handshaker.cc",
- "src/quic/core/quic_crypto_handshaker.h",
- "src/quic/core/quic_crypto_server_stream.cc",
- "src/quic/core/quic_crypto_server_stream.h",
- "src/quic/core/quic_crypto_server_stream_base.cc",
- "src/quic/core/quic_crypto_server_stream_base.h",
- "src/quic/core/quic_crypto_stream.cc",
- "src/quic/core/quic_crypto_stream.h",
- "src/quic/core/quic_data_reader.cc",
- "src/quic/core/quic_data_reader.h",
- "src/quic/core/quic_data_writer.cc",
- "src/quic/core/quic_data_writer.h",
- "src/quic/core/quic_datagram_queue.cc",
- "src/quic/core/quic_datagram_queue.h",
- "src/quic/core/quic_flow_controller.cc",
- "src/quic/core/quic_flow_controller.h",
- "src/quic/core/quic_framer.cc",
- "src/quic/core/quic_framer.h",
- "src/quic/core/quic_idle_network_detector.cc",
- "src/quic/core/quic_idle_network_detector.h",
- "src/quic/core/quic_interval.h",
- "src/quic/core/quic_interval_deque.h",
- "src/quic/core/quic_interval_set.h",
- "src/quic/core/quic_legacy_version_encapsulator.cc",
- "src/quic/core/quic_legacy_version_encapsulator.h",
- "src/quic/core/quic_lru_cache.h",
- "src/quic/core/quic_mtu_discovery.cc",
- "src/quic/core/quic_mtu_discovery.h",
- "src/quic/core/quic_network_blackhole_detector.cc",
- "src/quic/core/quic_network_blackhole_detector.h",
- "src/quic/core/quic_one_block_arena.h",
- "src/quic/core/quic_packet_creator.cc",
- "src/quic/core/quic_packet_creator.h",
- "src/quic/core/quic_packet_number.cc",
- "src/quic/core/quic_packet_number.h",
- "src/quic/core/quic_packet_writer.h",
- "src/quic/core/quic_packets.cc",
- "src/quic/core/quic_packets.h",
- "src/quic/core/quic_path_validator.cc",
- "src/quic/core/quic_path_validator.h",
- "src/quic/core/quic_protocol_flags_list.h",
- "src/quic/core/quic_received_packet_manager.cc",
- "src/quic/core/quic_received_packet_manager.h",
- "src/quic/core/quic_sent_packet_manager.cc",
- "src/quic/core/quic_sent_packet_manager.h",
- "src/quic/core/quic_server_id.cc",
- "src/quic/core/quic_server_id.h",
- "src/quic/core/quic_session.cc",
- "src/quic/core/quic_session.h",
- "src/quic/core/quic_simple_buffer_allocator.cc",
- "src/quic/core/quic_simple_buffer_allocator.h",
- "src/quic/core/quic_socket_address_coder.cc",
- "src/quic/core/quic_socket_address_coder.h",
- "src/quic/core/quic_stream.cc",
- "src/quic/core/quic_stream.h",
- "src/quic/core/quic_stream_frame_data_producer.h",
- "src/quic/core/quic_stream_id_manager.cc",
- "src/quic/core/quic_stream_id_manager.h",
- "src/quic/core/quic_stream_send_buffer.cc",
- "src/quic/core/quic_stream_send_buffer.h",
- "src/quic/core/quic_stream_sequencer.cc",
- "src/quic/core/quic_stream_sequencer.h",
- "src/quic/core/quic_stream_sequencer_buffer.cc",
- "src/quic/core/quic_stream_sequencer_buffer.h",
- "src/quic/core/quic_sustained_bandwidth_recorder.cc",
- "src/quic/core/quic_sustained_bandwidth_recorder.h",
- "src/quic/core/quic_tag.cc",
- "src/quic/core/quic_tag.h",
- "src/quic/core/quic_time.cc",
- "src/quic/core/quic_time.h",
- "src/quic/core/quic_time_accumulator.h",
- "src/quic/core/quic_transmission_info.cc",
- "src/quic/core/quic_transmission_info.h",
- "src/quic/core/quic_types.cc",
- "src/quic/core/quic_types.h",
- "src/quic/core/quic_unacked_packet_map.cc",
- "src/quic/core/quic_unacked_packet_map.h",
- "src/quic/core/quic_utils.cc",
- "src/quic/core/quic_utils.h",
- "src/quic/core/quic_version_manager.cc",
- "src/quic/core/quic_version_manager.h",
- "src/quic/core/quic_versions.cc",
- "src/quic/core/quic_versions.h",
- "src/quic/core/quic_write_blocked_list.cc",
- "src/quic/core/quic_write_blocked_list.h",
- "src/quic/core/session_notifier_interface.h",
- "src/quic/core/stream_delegate_interface.h",
- "src/quic/core/tls_client_handshaker.cc",
- "src/quic/core/tls_client_handshaker.h",
- "src/quic/core/tls_handshaker.cc",
- "src/quic/core/tls_handshaker.h",
- "src/quic/core/tls_server_handshaker.cc",
- "src/quic/core/tls_server_handshaker.h",
- "src/quic/core/uber_quic_stream_id_manager.cc",
- "src/quic/core/uber_quic_stream_id_manager.h",
- "src/quic/core/uber_received_packet_manager.cc",
- "src/quic/core/uber_received_packet_manager.h",
- "src/quic/core/web_transport_stream_adapter.cc",
- "src/quic/core/web_transport_stream_adapter.h",
- "src/quic/platform/api/quic_bug_tracker.h",
- "src/quic/platform/api/quic_client_stats.h",
- "src/quic/platform/api/quic_containers.h",
- "src/quic/platform/api/quic_error_code_wrappers.h",
- "src/quic/platform/api/quic_estimate_memory_usage.h",
- "src/quic/platform/api/quic_export.h",
- "src/quic/platform/api/quic_exported_stats.h",
- "src/quic/platform/api/quic_file_utils.cc",
- "src/quic/platform/api/quic_file_utils.h",
- "src/quic/platform/api/quic_flag_utils.h",
- "src/quic/platform/api/quic_flags.h",
- "src/quic/platform/api/quic_hostname_utils.cc",
- "src/quic/platform/api/quic_hostname_utils.h",
- "src/quic/platform/api/quic_iovec.h",
- "src/quic/platform/api/quic_ip_address.cc",
- "src/quic/platform/api/quic_ip_address.h",
- "src/quic/platform/api/quic_ip_address_family.h",
- "src/quic/platform/api/quic_logging.h",
- "src/quic/platform/api/quic_map_util.h",
- "src/quic/platform/api/quic_mem_slice.h",
- "src/quic/platform/api/quic_mem_slice_span.h",
- "src/quic/platform/api/quic_mem_slice_storage.h",
- "src/quic/platform/api/quic_mutex.cc",
- "src/quic/platform/api/quic_mutex.h",
- "src/quic/platform/api/quic_prefetch.h",
- "src/quic/platform/api/quic_reference_counted.h",
- "src/quic/platform/api/quic_server_stats.h",
- "src/quic/platform/api/quic_sleep.h",
- "src/quic/platform/api/quic_socket_address.cc",
- "src/quic/platform/api/quic_socket_address.h",
- "src/quic/platform/api/quic_stack_trace.h",
- "src/quic/platform/api/quic_thread.h",
- "src/quic/quic_transport/quic_transport_client_session.cc",
- "src/quic/quic_transport/quic_transport_client_session.h",
- "src/quic/quic_transport/quic_transport_protocol.h",
- "src/quic/quic_transport/quic_transport_server_session.cc",
- "src/quic/quic_transport/quic_transport_server_session.h",
- "src/quic/quic_transport/quic_transport_session_interface.h",
- "src/quic/quic_transport/quic_transport_stream.cc",
- "src/quic/quic_transport/quic_transport_stream.h",
- "src/quic/quic_transport/web_transport_fingerprint_proof_verifier.cc",
- "src/quic/quic_transport/web_transport_fingerprint_proof_verifier.h",
- "src/spdy/core/hpack/hpack_constants.cc",
- "src/spdy/core/hpack/hpack_constants.h",
- "src/spdy/core/hpack/hpack_decoder_adapter.cc",
- "src/spdy/core/hpack/hpack_decoder_adapter.h",
- "src/spdy/core/hpack/hpack_encoder.cc",
- "src/spdy/core/hpack/hpack_encoder.h",
- "src/spdy/core/hpack/hpack_entry.cc",
- "src/spdy/core/hpack/hpack_entry.h",
- "src/spdy/core/hpack/hpack_header_table.cc",
- "src/spdy/core/hpack/hpack_header_table.h",
- "src/spdy/core/hpack/hpack_output_stream.cc",
- "src/spdy/core/hpack/hpack_output_stream.h",
- "src/spdy/core/hpack/hpack_static_table.cc",
- "src/spdy/core/hpack/hpack_static_table.h",
- "src/spdy/core/http2_frame_decoder_adapter.cc",
- "src/spdy/core/http2_frame_decoder_adapter.h",
- "src/spdy/core/http2_priority_write_scheduler.h",
- "src/spdy/core/priority_write_scheduler.h",
- "src/spdy/core/recording_headers_handler.cc",
- "src/spdy/core/recording_headers_handler.h",
- "src/spdy/core/spdy_alt_svc_wire_format.cc",
- "src/spdy/core/spdy_alt_svc_wire_format.h",
- "src/spdy/core/spdy_bitmasks.h",
- "src/spdy/core/spdy_frame_builder.cc",
- "src/spdy/core/spdy_frame_builder.h",
- "src/spdy/core/spdy_frame_reader.cc",
- "src/spdy/core/spdy_frame_reader.h",
- "src/spdy/core/spdy_framer.cc",
- "src/spdy/core/spdy_framer.h",
- "src/spdy/core/spdy_header_block.cc",
- "src/spdy/core/spdy_header_block.h",
- "src/spdy/core/spdy_header_storage.cc",
- "src/spdy/core/spdy_header_storage.h",
- "src/spdy/core/spdy_headers_handler_interface.h",
- "src/spdy/core/spdy_intrusive_list.h",
- "src/spdy/core/spdy_no_op_visitor.cc",
- "src/spdy/core/spdy_no_op_visitor.h",
- "src/spdy/core/spdy_pinnable_buffer_piece.cc",
- "src/spdy/core/spdy_pinnable_buffer_piece.h",
- "src/spdy/core/spdy_prefixed_buffer_reader.cc",
- "src/spdy/core/spdy_prefixed_buffer_reader.h",
- "src/spdy/core/spdy_protocol.cc",
- "src/spdy/core/spdy_protocol.h",
- "src/spdy/core/spdy_simple_arena.cc",
- "src/spdy/core/spdy_simple_arena.h",
- "src/spdy/core/write_scheduler.h",
- "src/spdy/core/zero_copy_output_buffer.h",
- "src/spdy/platform/api/spdy_bug_tracker.h",
- "src/spdy/platform/api/spdy_containers.h",
- "src/spdy/platform/api/spdy_estimate_memory_usage.h",
- "src/spdy/platform/api/spdy_flags.h",
- "src/spdy/platform/api/spdy_logging.h",
- "src/spdy/platform/api/spdy_string_utils.h",
- ]
- }
-
deps = [ "//net:net_deps" ]
public_deps = [ "//net:net_public_deps" ]
}
@@ -701,6 +696,7 @@ if (is_linux || is_chromeos) {
}
source_set("epoll_quic_tools_core") {
+ testonly = true
sources = [
"src/quic/core/quic_default_packet_writer.cc",
"src/quic/core/quic_default_packet_writer.h",
@@ -732,6 +728,7 @@ if (is_linux || is_chromeos) {
}
executable("epoll_quic_client") {
+ testonly = true
sources = [
"src/quic/tools/quic_client_bin.cc",
"src/quic/tools/quic_epoll_client_factory.cc",
@@ -744,12 +741,14 @@ if (is_linux || is_chromeos) {
"//net",
"//net:epoll_quic_tools",
"//net:epoll_server",
+ "//net:quic_test_tools",
"//net:simple_quic_tools",
"//third_party/boringssl",
]
}
executable("epoll_quic_server") {
+ testonly = true
sources = [
"src/quic/tools/quic_epoll_server_factory.cc",
"src/quic/tools/quic_epoll_server_factory.h",
@@ -779,6 +778,7 @@ if (is_linux || is_chromeos) {
}
source_set("masque_tools") {
+ testonly = true
sources = [
"src/quic/masque/masque_client_session.cc",
"src/quic/masque/masque_client_session.h",
@@ -813,6 +813,7 @@ if (is_linux || is_chromeos) {
}
executable("masque_client") {
+ testonly = true
sources = [ "src/quic/masque/masque_client_bin.cc" ]
deps = [
":masque_tools",
@@ -825,6 +826,7 @@ if (is_linux || is_chromeos) {
}
executable("masque_server") {
+ testonly = true
sources = [ "src/quic/masque/masque_server_bin.cc" ]
deps = [
":masque_tools",
@@ -907,8 +909,6 @@ source_set("quic_test_tools_core") {
"src/quic/test_tools/qpack/qpack_encoder_peer.h",
"src/quic/test_tools/qpack/qpack_encoder_test_utils.cc",
"src/quic/test_tools/qpack/qpack_encoder_test_utils.h",
- "src/quic/test_tools/qpack/qpack_header_table_peer.cc",
- "src/quic/test_tools/qpack/qpack_header_table_peer.h",
"src/quic/test_tools/qpack/qpack_offline_decoder.cc",
"src/quic/test_tools/qpack/qpack_offline_decoder.h",
"src/quic/test_tools/qpack/qpack_test_utils.cc",
@@ -1109,12 +1109,14 @@ source_set("simple_quic_tools_core") {
}
source_set("quic_client_core") {
+ testonly = true
sources = [
"src/quic/tools/quic_toy_client.cc",
"src/quic/tools/quic_toy_client.h",
]
deps = [
"//net",
+ "//net:quic_test_tools",
"//net:simple_quic_tools",
]
}
@@ -1183,11 +1185,14 @@ if (!is_ios) {
source_set("quiche_tests") {
testonly = true
sources = [
- "src/common/platform/api/quiche_text_utils_test.cc",
"src/common/platform/api/quiche_time_utils_test.cc",
+ "src/common/quiche_circular_deque_test.cc",
"src/common/quiche_data_writer_test.cc",
"src/common/quiche_endian_test.cc",
- "src/common/simple_linked_hash_map_test.cc",
+ "src/common/quiche_linked_hash_map_test.cc",
+ "src/common/quiche_text_utils_test.cc",
+ "src/http2/core/http2_priority_write_scheduler_test.cc",
+ "src/http2/core/priority_write_scheduler_test.cc",
"src/http2/decoder/decode_buffer_test.cc",
"src/http2/decoder/decode_http2_structures_test.cc",
"src/http2/decoder/frame_decoder_state_test_util.cc",
@@ -1246,7 +1251,6 @@ source_set("quiche_tests") {
"src/http2/http2_structures_test.cc",
"src/http2/http2_structures_test_util.cc",
"src/http2/http2_structures_test_util.h",
- "src/http2/platform/api/http2_string_utils_test.cc",
"src/http2/platform/api/http2_test_helpers.h",
"src/http2/test_tools/frame_parts.cc",
"src/http2/test_tools/frame_parts.h",
@@ -1344,7 +1348,7 @@ source_set("quiche_tests") {
"src/quic/core/quic_arena_scoped_ptr_test.cc",
"src/quic/core/quic_bandwidth_test.cc",
"src/quic/core/quic_buffered_packet_store_test.cc",
- "src/quic/core/quic_circular_deque_test.cc",
+ "src/quic/core/quic_chaos_protector_test.cc",
"src/quic/core/quic_coalesced_packet_test.cc",
"src/quic/core/quic_config_test.cc",
"src/quic/core/quic_connection_id_manager_test.cc",
@@ -1431,10 +1435,8 @@ source_set("quiche_tests") {
"src/spdy/core/hpack/hpack_output_stream_test.cc",
"src/spdy/core/hpack/hpack_round_trip_test.cc",
"src/spdy/core/hpack/hpack_static_table_test.cc",
- "src/spdy/core/http2_priority_write_scheduler_test.cc",
"src/spdy/core/mock_spdy_framer_visitor.cc",
"src/spdy/core/mock_spdy_framer_visitor.h",
- "src/spdy/core/priority_write_scheduler_test.cc",
"src/spdy/core/spdy_alt_svc_wire_format_test.cc",
"src/spdy/core/spdy_frame_builder_test.cc",
"src/spdy/core/spdy_frame_reader_test.cc",
@@ -1450,8 +1452,6 @@ source_set("quiche_tests") {
"src/spdy/core/spdy_simple_arena_test.cc",
"src/spdy/core/spdy_test_utils.cc",
"src/spdy/core/spdy_test_utils.h",
- "src/spdy/platform/api/spdy_string_utils_test.cc",
- "src/spdy/platform/api/spdy_test_helpers.h",
]
deps = [
diff --git a/chromium/net/third_party/quiche/DIR_METADATA b/chromium/net/third_party/quiche/DIR_METADATA
index 123352d107a..a745a9d91c3 100644
--- a/chromium/net/third_party/quiche/DIR_METADATA
+++ b/chromium/net/third_party/quiche/DIR_METADATA
@@ -1,10 +1,10 @@
# Metadata information for this directory.
#
# For more information on DIR_METADATA files, see:
-# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md
+# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md
#
# For the schema of this file, see Metadata message:
-# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto
+# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto
monorail {
component: "Internals>Network>QUIC"
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_prefetch.h b/chromium/net/third_party/quiche/src/common/platform/api/quiche_prefetch.h
index 49dbe4871e8..706a7090bea 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_prefetch.h
+++ b/chromium/net/third_party/quiche/src/common/platform/api/quiche_prefetch.h
@@ -2,12 +2,12 @@
// 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_PREFETCH_H_
-#define QUICHE_QUIC_PLATFORM_API_QUIC_PREFETCH_H_
+#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_PREFETCH_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_PREFETCH_H_
-#include "net/quic/platform/impl/quic_prefetch_impl.h"
+#include "quiche_platform_impl/quiche_prefetch_impl.h"
-namespace quic {
+namespace quiche {
// Move data into the cache before it is read, or "prefetch" it.
//
@@ -30,10 +30,10 @@ namespace quic {
// performance, so use them only when representative benchmarks show
// an improvement.
-inline void QuicPrefetchT0(const void* addr) {
- return QuicPrefetchT0Impl(addr);
+inline void QuichePrefetchT0(const void* addr) {
+ return QuichePrefetchT0Impl(addr);
}
-} // namespace quic
+} // namespace quiche
-#endif // QUICHE_QUIC_PLATFORM_API_QUIC_PREFETCH_H_
+#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_PREFETCH_H_
diff --git a/chromium/net/third_party/quiche/src/common/platform/api/quiche_test.h b/chromium/net/third_party/quiche/src/common/platform/api/quiche_test.h
index b5847529419..1af25df1ea5 100644
--- a/chromium/net/third_party/quiche/src/common/platform/api/quiche_test.h
+++ b/chromium/net/third_party/quiche/src/common/platform/api/quiche_test.h
@@ -12,4 +12,7 @@ using QuicheTest = quiche::test::QuicheTest;
template <class T>
using QuicheTestWithParam = quiche::test::QuicheTestWithParamImpl<T>;
+#define EXPECT_QUICHE_DEBUG_DEATH(condition, message) \
+ EXPECT_QUICHE_DEBUG_DEATH_IMPL(condition, message)
+
#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_H_
diff --git a/chromium/net/third_party/quiche/src/common/platform/api/quiche_test_helpers.h b/chromium/net/third_party/quiche/src/common/platform/api/quiche_test_helpers.h
new file mode 100644
index 00000000000..8e773a10a01
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/common/platform/api/quiche_test_helpers.h
@@ -0,0 +1,8 @@
+#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_HELPERS_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_HELPERS_H_
+
+#include "net/quiche/common/platform/impl/quiche_test_helpers_impl.h"
+
+#define EXPECT_QUICHE_BUG EXPECT_QUICHE_BUG_IMPL
+
+#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_HELPERS_H_
diff --git a/chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_prefetch_impl.h b/chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_prefetch_impl.h
new file mode 100644
index 00000000000..89454817d87
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_prefetch_impl.h
@@ -0,0 +1,28 @@
+// Copyright 2021 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_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_PREFETCH_IMPL_H_
+#define QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_PREFETCH_IMPL_H_
+
+#if defined(_MSC_VER)
+#include <intrin.h>
+#endif
+
+namespace quiche {
+
+inline void QuichePrefetchT0Impl(const void* addr) {
+#if !defined(DISABLE_BUILTIN_PREFETCH)
+#if defined(__GNUC__) || (defined(_M_ARM64) && defined(__clang__))
+ __builtin_prefetch(addr, 0, 3);
+#elif defined(_MSC_VER)
+ _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T0);
+#else
+ (void*)addr;
+#endif
+#endif // !defined(DISABLE_BUILTIN_PREFETCH)
+}
+
+} // namespace quiche
+
+#endif // QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_PREFETCH_IMPL_H_
diff --git a/chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_sleep_impl.h b/chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_sleep_impl.h
new file mode 100644
index 00000000000..125af37d877
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_sleep_impl.h
@@ -0,0 +1,22 @@
+#ifndef QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_SLEEP_IMPL_H_
+#define QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_SLEEP_IMPL_H_
+
+#include "quic/core/quic_time.h"
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Weverything"
+
+#include "absl/time/clock.h"
+#include "absl/time/time.h"
+
+#pragma clang diagnostic pop
+
+namespace quic {
+
+inline void QuicSleepImpl(QuicTime::Delta duration) {
+ absl::SleepFor(absl::Microseconds(duration.ToMicroseconds()));
+}
+
+} // namespace quic
+
+#endif // QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_SLEEP_IMPL_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_circular_deque.h b/chromium/net/third_party/quiche/src/common/quiche_circular_deque.h
index 44637abcbd6..42b22327f29 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_circular_deque.h
+++ b/chromium/net/third_party/quiche/src/common/quiche_circular_deque.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_CORE_QUIC_CIRCULAR_DEQUE_H_
-#define QUICHE_QUIC_CORE_QUIC_CIRCULAR_DEQUE_H_
+#ifndef QUICHE_COMMON_QUICHE_CIRCULAR_DEQUE_H_
+#define QUICHE_COMMON_QUICHE_CIRCULAR_DEQUE_H_
#include <algorithm>
#include <cstddef>
@@ -13,16 +13,16 @@
#include <ostream>
#include <type_traits>
-#include "quic/platform/api/quic_export.h"
-#include "quic/platform/api/quic_logging.h"
+#include "common/platform/api/quiche_export.h"
+#include "common/platform/api/quiche_logging.h"
-namespace quic {
+namespace quiche {
-// QuicCircularDeque is a STL-style container that is similar to std deque in
+// QuicheCircularDeque is a STL-style container that is similar to std::deque in
// API and std::vector in capacity management. The goal is to optimize a common
// QUIC use case where we keep adding new elements to the end and removing old
// elements from the beginning, under such scenarios, if the container's size()
-// remain relatively stable, QuicCircularDeque requires little to no memory
+// remain relatively stable, QuicheCircularDeque requires little to no memory
// allocations or deallocations.
//
// The implementation, as the name suggests, uses a flat circular buffer to hold
@@ -40,12 +40,12 @@ namespace quic {
template <typename T,
size_t MinCapacityIncrement = 3,
typename Allocator = std::allocator<T>>
-class QUIC_NO_EXPORT QuicCircularDeque {
+class QUICHE_NO_EXPORT QuicheCircularDeque {
using AllocatorTraits = std::allocator_traits<Allocator>;
// Pointee is either T or const T.
template <typename Pointee>
- class QUIC_NO_EXPORT basic_iterator {
+ class QUICHE_NO_EXPORT basic_iterator {
using size_type = typename AllocatorTraits::size_type;
public:
@@ -159,7 +159,7 @@ class QUIC_NO_EXPORT QuicCircularDeque {
}
private:
- basic_iterator(const QuicCircularDeque* deque, size_type index)
+ basic_iterator(const QuicheCircularDeque* deque, size_type index)
: deque_(deque), index_(index) {}
void Increment() {
@@ -191,8 +191,8 @@ class QUIC_NO_EXPORT QuicCircularDeque {
return index_ + deque_->data_capacity() - deque_->begin_;
}
- friend class QuicCircularDeque;
- const QuicCircularDeque* deque_ = nullptr;
+ friend class QuicheCircularDeque;
+ const QuicheCircularDeque* deque_ = nullptr;
size_type index_ = 0;
};
@@ -210,19 +210,19 @@ class QUIC_NO_EXPORT QuicCircularDeque {
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
- QuicCircularDeque() : QuicCircularDeque(allocator_type()) {}
- explicit QuicCircularDeque(const allocator_type& alloc)
+ QuicheCircularDeque() : QuicheCircularDeque(allocator_type()) {}
+ explicit QuicheCircularDeque(const allocator_type& alloc)
: allocator_and_data_(alloc) {}
- QuicCircularDeque(size_type count,
- const T& value,
- const Allocator& alloc = allocator_type())
+ QuicheCircularDeque(size_type count,
+ const T& value,
+ const Allocator& alloc = allocator_type())
: allocator_and_data_(alloc) {
resize(count, value);
}
- explicit QuicCircularDeque(size_type count,
- const Allocator& alloc = allocator_type())
+ explicit QuicheCircularDeque(size_type count,
+ const Allocator& alloc = allocator_type())
: allocator_and_data_(alloc) {
resize(count);
}
@@ -232,25 +232,26 @@ class QUIC_NO_EXPORT QuicCircularDeque {
typename = std::enable_if_t<std::is_base_of<
std::input_iterator_tag,
typename std::iterator_traits<InputIt>::iterator_category>::value>>
- QuicCircularDeque(InputIt first,
- InputIt last,
- const Allocator& alloc = allocator_type())
+ QuicheCircularDeque(InputIt first,
+ InputIt last,
+ const Allocator& alloc = allocator_type())
: allocator_and_data_(alloc) {
AssignRange(first, last);
}
- QuicCircularDeque(const QuicCircularDeque& other)
- : QuicCircularDeque(
+ QuicheCircularDeque(const QuicheCircularDeque& other)
+ : QuicheCircularDeque(
other,
AllocatorTraits::select_on_container_copy_construction(
other.allocator_and_data_.allocator())) {}
- QuicCircularDeque(const QuicCircularDeque& other, const allocator_type& alloc)
+ QuicheCircularDeque(const QuicheCircularDeque& other,
+ const allocator_type& alloc)
: allocator_and_data_(alloc) {
assign(other.begin(), other.end());
}
- QuicCircularDeque(QuicCircularDeque&& other)
+ QuicheCircularDeque(QuicheCircularDeque&& other)
: begin_(other.begin_),
end_(other.end_),
allocator_and_data_(std::move(other.allocator_and_data_)) {
@@ -259,16 +260,16 @@ class QUIC_NO_EXPORT QuicCircularDeque {
other.allocator_and_data_.data_capacity = 0;
}
- QuicCircularDeque(QuicCircularDeque&& other, const allocator_type& alloc)
+ QuicheCircularDeque(QuicheCircularDeque&& other, const allocator_type& alloc)
: allocator_and_data_(alloc) {
MoveRetainAllocator(std::move(other));
}
- QuicCircularDeque(std::initializer_list<T> init,
- const allocator_type& alloc = allocator_type())
- : QuicCircularDeque(init.begin(), init.end(), alloc) {}
+ QuicheCircularDeque(std::initializer_list<T> init,
+ const allocator_type& alloc = allocator_type())
+ : QuicheCircularDeque(init.begin(), init.end(), alloc) {}
- QuicCircularDeque& operator=(const QuicCircularDeque& other) {
+ QuicheCircularDeque& operator=(const QuicheCircularDeque& other) {
if (this == &other) {
return *this;
}
@@ -286,21 +287,21 @@ class QUIC_NO_EXPORT QuicCircularDeque {
return *this;
}
- QuicCircularDeque& operator=(QuicCircularDeque&& other) {
+ QuicheCircularDeque& operator=(QuicheCircularDeque&& other) {
if (this == &other) {
return *this;
}
if (AllocatorTraits::propagate_on_container_move_assignment::value) {
// Take over the storage of "other", along with its allocator.
- this->~QuicCircularDeque();
- new (this) QuicCircularDeque(std::move(other));
+ this->~QuicheCircularDeque();
+ new (this) QuicheCircularDeque(std::move(other));
} else {
MoveRetainAllocator(std::move(other));
}
return *this;
}
- ~QuicCircularDeque() { DestroyAndDeallocateAll(); }
+ ~QuicheCircularDeque() { DestroyAndDeallocateAll(); }
void assign(size_type count, const T& value) {
ClearRetainCapacity();
@@ -333,7 +334,7 @@ class QUIC_NO_EXPORT QuicCircularDeque {
}
const_reference at(size_type pos) const {
- return const_cast<QuicCircularDeque*>(this)->at(pos);
+ return const_cast<QuicheCircularDeque*>(this)->at(pos);
}
reference operator[](size_type pos) { return at(pos); }
@@ -346,7 +347,7 @@ class QUIC_NO_EXPORT QuicCircularDeque {
}
const_reference front() const {
- return const_cast<QuicCircularDeque*>(this)->front();
+ return const_cast<QuicheCircularDeque*>(this)->front();
}
reference back() {
@@ -355,7 +356,7 @@ class QUIC_NO_EXPORT QuicCircularDeque {
}
const_reference back() const {
- return const_cast<QuicCircularDeque*>(this)->back();
+ return const_cast<QuicheCircularDeque*>(this)->back();
}
iterator begin() { return iterator(this, begin_); }
@@ -460,7 +461,7 @@ class QUIC_NO_EXPORT QuicCircularDeque {
return num_elements_to_pop;
}
- void swap(QuicCircularDeque& other) {
+ void swap(QuicheCircularDeque& other) {
using std::swap;
swap(begin_, other.begin_);
swap(end_, other.end_);
@@ -479,7 +480,7 @@ class QUIC_NO_EXPORT QuicCircularDeque {
}
}
- friend void swap(QuicCircularDeque& lhs, QuicCircularDeque& rhs) {
+ friend void swap(QuicheCircularDeque& lhs, QuicheCircularDeque& rhs) {
lhs.swap(rhs);
}
@@ -487,18 +488,19 @@ class QUIC_NO_EXPORT QuicCircularDeque {
return allocator_and_data_.allocator();
}
- friend bool operator==(const QuicCircularDeque& lhs,
- const QuicCircularDeque& rhs) {
+ friend bool operator==(const QuicheCircularDeque& lhs,
+ const QuicheCircularDeque& rhs) {
return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}
- friend bool operator!=(const QuicCircularDeque& lhs,
- const QuicCircularDeque& rhs) {
+ friend bool operator!=(const QuicheCircularDeque& lhs,
+ const QuicheCircularDeque& rhs) {
return !(lhs == rhs);
}
- friend QUIC_NO_EXPORT std::ostream& operator<<(std::ostream& os,
- const QuicCircularDeque& dq) {
+ friend QUICHE_NO_EXPORT std::ostream& operator<<(
+ std::ostream& os,
+ const QuicheCircularDeque& dq) {
os << "{";
for (size_type pos = 0; pos != dq.size(); ++pos) {
if (pos != 0) {
@@ -511,7 +513,7 @@ class QUIC_NO_EXPORT QuicCircularDeque {
}
private:
- void MoveRetainAllocator(QuicCircularDeque&& other) {
+ void MoveRetainAllocator(QuicheCircularDeque&& other) {
if (get_allocator() == other.get_allocator()) {
// Take over the storage of "other", with which we share an allocator.
DestroyAndDeallocateAll();
@@ -752,6 +754,6 @@ class QUIC_NO_EXPORT QuicCircularDeque {
AllocatorAndData allocator_and_data_;
};
-} // namespace quic
+} // namespace quiche
-#endif // QUICHE_QUIC_CORE_QUIC_CIRCULAR_DEQUE_H_
+#endif // QUICHE_COMMON_QUICHE_CIRCULAR_DEQUE_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_circular_deque_test.cc b/chromium/net/third_party/quiche/src/common/quiche_circular_deque_test.cc
index 25aa78e709a..c15d904b850 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_circular_deque_test.cc
+++ b/chromium/net/third_party/quiche/src/common/quiche_circular_deque_test.cc
@@ -2,19 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "quic/core/quic_circular_deque.h"
+#include "common/quiche_circular_deque.h"
#include <cstddef>
#include <cstdint>
+#include <list>
#include <memory>
#include <type_traits>
-#include "quic/platform/api/quic_logging.h"
-#include "quic/platform/api/quic_test.h"
+#include "common/platform/api/quiche_logging.h"
+#include "common/platform/api/quiche_test.h"
using testing::ElementsAre;
-namespace quic {
+namespace quiche {
namespace test {
namespace {
@@ -106,10 +107,10 @@ void ShiftLeft(Deque* dq, bool emplace) {
}
}
-class QuicCircularDequeTest : public QuicTest {};
+class QuicheCircularDequeTest : public QuicheTest {};
-TEST_F(QuicCircularDequeTest, Empty) {
- QuicCircularDeque<int> dq;
+TEST_F(QuicheCircularDequeTest, Empty) {
+ QuicheCircularDeque<int> dq;
EXPECT_TRUE(dq.empty());
EXPECT_EQ(0u, dq.size());
dq.clear();
@@ -122,68 +123,69 @@ TEST_F(QuicCircularDequeTest, Empty) {
EXPECT_TRUE(dq.empty());
EXPECT_EQ(0u, dq.size());
- EXPECT_QUIC_DEBUG_DEATH(dq.front(), "");
- EXPECT_QUIC_DEBUG_DEATH(dq.back(), "");
- EXPECT_QUIC_DEBUG_DEATH(dq.at(0), "");
- EXPECT_QUIC_DEBUG_DEATH(dq[0], "");
+ EXPECT_QUICHE_DEBUG_DEATH(dq.front(), "");
+ EXPECT_QUICHE_DEBUG_DEATH(dq.back(), "");
+ EXPECT_QUICHE_DEBUG_DEATH(dq.at(0), "");
+ EXPECT_QUICHE_DEBUG_DEATH(dq[0], "");
}
-TEST_F(QuicCircularDequeTest, Constructor) {
- QuicCircularDeque<int> dq;
+TEST_F(QuicheCircularDequeTest, Constructor) {
+ QuicheCircularDeque<int> dq;
EXPECT_TRUE(dq.empty());
std::allocator<int> alloc;
- QuicCircularDeque<int> dq1(alloc);
+ QuicheCircularDeque<int> dq1(alloc);
EXPECT_TRUE(dq1.empty());
- QuicCircularDeque<int> dq2(8, 100, alloc);
+ QuicheCircularDeque<int> dq2(8, 100, alloc);
EXPECT_THAT(dq2, ElementsAre(100, 100, 100, 100, 100, 100, 100, 100));
- QuicCircularDeque<int> dq3(5, alloc);
+ QuicheCircularDeque<int> dq3(5, alloc);
EXPECT_THAT(dq3, ElementsAre(0, 0, 0, 0, 0));
- QuicCircularDeque<int> dq4_rand_iter(dq3.begin(), dq3.end(), alloc);
+ QuicheCircularDeque<int> dq4_rand_iter(dq3.begin(), dq3.end(), alloc);
EXPECT_THAT(dq4_rand_iter, ElementsAre(0, 0, 0, 0, 0));
EXPECT_EQ(dq4_rand_iter, dq3);
std::list<int> dq4_src = {4, 4, 4, 4};
- QuicCircularDeque<int> dq4_bidi_iter(dq4_src.begin(), dq4_src.end());
+ QuicheCircularDeque<int> dq4_bidi_iter(dq4_src.begin(), dq4_src.end());
EXPECT_THAT(dq4_bidi_iter, ElementsAre(4, 4, 4, 4));
- QuicCircularDeque<int> dq5(dq4_bidi_iter);
+ QuicheCircularDeque<int> dq5(dq4_bidi_iter);
EXPECT_THAT(dq5, ElementsAre(4, 4, 4, 4));
EXPECT_EQ(dq5, dq4_bidi_iter);
- QuicCircularDeque<int> dq6(dq5, alloc);
+ QuicheCircularDeque<int> dq6(dq5, alloc);
EXPECT_THAT(dq6, ElementsAre(4, 4, 4, 4));
EXPECT_EQ(dq6, dq5);
- QuicCircularDeque<int> dq7(std::move(*&dq6));
+ QuicheCircularDeque<int> dq7(std::move(*&dq6));
EXPECT_THAT(dq7, ElementsAre(4, 4, 4, 4));
EXPECT_TRUE(dq6.empty());
- QuicCircularDeque<int> dq8_equal_allocator(std::move(*&dq7), alloc);
+ QuicheCircularDeque<int> dq8_equal_allocator(std::move(*&dq7), alloc);
EXPECT_THAT(dq8_equal_allocator, ElementsAre(4, 4, 4, 4));
EXPECT_TRUE(dq7.empty());
- QuicCircularDeque<int, 3, CountingAllocator<int>> dq8_temp = {5, 6, 7, 8, 9};
- QuicCircularDeque<int, 3, CountingAllocator<int>> dq8_unequal_allocator(
+ QuicheCircularDeque<int, 3, CountingAllocator<int>> dq8_temp = {5, 6, 7, 8,
+ 9};
+ QuicheCircularDeque<int, 3, CountingAllocator<int>> dq8_unequal_allocator(
std::move(*&dq8_temp), CountingAllocator<int>());
EXPECT_THAT(dq8_unequal_allocator, ElementsAre(5, 6, 7, 8, 9));
EXPECT_TRUE(dq8_temp.empty());
- QuicCircularDeque<int> dq9({3, 4, 5, 6, 7}, alloc);
+ QuicheCircularDeque<int> dq9({3, 4, 5, 6, 7}, alloc);
EXPECT_THAT(dq9, ElementsAre(3, 4, 5, 6, 7));
}
-TEST_F(QuicCircularDequeTest, Assign) {
+TEST_F(QuicheCircularDequeTest, Assign) {
// assign()
- QuicCircularDeque<int, 3, CountingAllocator<int>> dq;
+ QuicheCircularDeque<int, 3, CountingAllocator<int>> dq;
dq.assign(7, 1);
EXPECT_THAT(dq, ElementsAre(1, 1, 1, 1, 1, 1, 1));
EXPECT_EQ(1u, dq.get_allocator().allocate_count());
- QuicCircularDeque<int, 3, CountingAllocator<int>> dq2;
+ QuicheCircularDeque<int, 3, CountingAllocator<int>> dq2;
dq2.assign(dq.begin(), dq.end());
EXPECT_THAT(dq2, ElementsAre(1, 1, 1, 1, 1, 1, 1));
EXPECT_EQ(1u, dq2.get_allocator().allocate_count());
@@ -194,7 +196,7 @@ TEST_F(QuicCircularDequeTest, Assign) {
// Assign from a non random access iterator.
std::list<int> dq3_src = {3, 3, 3, 3, 3};
- QuicCircularDeque<int, 3, CountingAllocator<int>> dq3;
+ QuicheCircularDeque<int, 3, CountingAllocator<int>> dq3;
dq3.assign(dq3_src.begin(), dq3_src.end());
EXPECT_THAT(dq3, ElementsAre(3, 3, 3, 3, 3));
EXPECT_LT(1u, dq3.get_allocator().allocate_count());
@@ -203,7 +205,7 @@ TEST_F(QuicCircularDequeTest, Assign) {
dq3 = *&dq3;
EXPECT_THAT(dq3, ElementsAre(3, 3, 3, 3, 3));
- QuicCircularDeque<
+ QuicheCircularDeque<
int, 3,
ConfigurableAllocator<int,
/*propagate_on_copy_assignment=*/std::true_type,
@@ -215,7 +217,7 @@ TEST_F(QuicCircularDequeTest, Assign) {
dq5 = dq4;
EXPECT_THAT(dq5, ElementsAre(3, 3, 3, 3, 3));
- QuicCircularDeque<
+ QuicheCircularDeque<
int, 3,
ConfigurableAllocator<int,
/*propagate_on_copy_assignment=*/std::false_type,
@@ -238,7 +240,7 @@ TEST_F(QuicCircularDequeTest, Assign) {
EXPECT_THAT(dq8, ElementsAre(3, 3, 3, 3, 3));
EXPECT_TRUE(dq3.empty());
- QuicCircularDeque<
+ QuicheCircularDeque<
int, 3,
ConfigurableAllocator<int,
/*propagate_on_copy_assignment=*/std::true_type,
@@ -252,7 +254,7 @@ TEST_F(QuicCircularDequeTest, Assign) {
EXPECT_THAT(dq9, ElementsAre(2, 2, 2, 2, 2, 2));
EXPECT_TRUE(dq10.empty());
- QuicCircularDeque<
+ QuicheCircularDeque<
int, 3,
ConfigurableAllocator<int,
/*propagate_on_copy_assignment=*/std::true_type,
@@ -267,13 +269,13 @@ TEST_F(QuicCircularDequeTest, Assign) {
EXPECT_TRUE(dq12.empty());
}
-TEST_F(QuicCircularDequeTest, Access) {
+TEST_F(QuicheCircularDequeTest, Access) {
// at()
// operator[]
// front()
// back()
- QuicCircularDeque<int, 3, CountingAllocator<int>> dq;
+ QuicheCircularDeque<int, 3, CountingAllocator<int>> dq;
dq.push_back(10);
EXPECT_EQ(dq.front(), 10);
EXPECT_EQ(dq.back(), 10);
@@ -369,15 +371,15 @@ TEST_F(QuicCircularDequeTest, Access) {
EXPECT_EQ(1u, dq.get_allocator().allocate_count());
}
-TEST_F(QuicCircularDequeTest, Iterate) {
- QuicCircularDeque<int> dq;
+TEST_F(QuicheCircularDequeTest, Iterate) {
+ QuicheCircularDeque<int> dq;
EXPECT_EQ(dq.begin(), dq.end());
EXPECT_EQ(dq.cbegin(), dq.cend());
EXPECT_EQ(dq.rbegin(), dq.rend());
EXPECT_EQ(dq.crbegin(), dq.crend());
dq.emplace_back(2);
- QuicCircularDeque<int>::const_iterator citer = dq.begin();
+ QuicheCircularDeque<int>::const_iterator citer = dq.begin();
EXPECT_NE(citer, dq.end());
EXPECT_EQ(*citer, 2);
++citer;
@@ -389,7 +391,7 @@ TEST_F(QuicCircularDequeTest, Iterate) {
EXPECT_EQ(*dq.crbegin(), 2);
dq.emplace_front(1);
- QuicCircularDeque<int>::const_reverse_iterator criter = dq.rbegin();
+ QuicheCircularDeque<int>::const_reverse_iterator criter = dq.rbegin();
EXPECT_NE(criter, dq.rend());
EXPECT_EQ(*criter, 2);
++criter;
@@ -407,42 +409,43 @@ TEST_F(QuicCircularDequeTest, Iterate) {
// Forward iterate.
int expected_value = 1;
- for (QuicCircularDeque<int>::iterator it = dq.begin(); it != dq.end(); ++it) {
+ for (QuicheCircularDeque<int>::iterator it = dq.begin(); it != dq.end();
+ ++it) {
EXPECT_EQ(expected_value++, *it);
}
expected_value = 1;
- for (QuicCircularDeque<int>::const_iterator it = dq.cbegin(); it != dq.cend();
- ++it) {
+ for (QuicheCircularDeque<int>::const_iterator it = dq.cbegin();
+ it != dq.cend(); ++it) {
EXPECT_EQ(expected_value++, *it);
}
// Reverse iterate.
expected_value = 3;
- for (QuicCircularDeque<int>::reverse_iterator it = dq.rbegin();
+ for (QuicheCircularDeque<int>::reverse_iterator it = dq.rbegin();
it != dq.rend(); ++it) {
EXPECT_EQ(expected_value--, *it);
}
expected_value = 3;
- for (QuicCircularDeque<int>::const_reverse_iterator it = dq.crbegin();
+ for (QuicheCircularDeque<int>::const_reverse_iterator it = dq.crbegin();
it != dq.crend(); ++it) {
EXPECT_EQ(expected_value--, *it);
}
}
-TEST_F(QuicCircularDequeTest, Iterator) {
+TEST_F(QuicheCircularDequeTest, Iterator) {
// Default constructed iterators of the same type compare equal.
- EXPECT_EQ(QuicCircularDeque<int>::iterator(),
- QuicCircularDeque<int>::iterator());
- EXPECT_EQ(QuicCircularDeque<int>::const_iterator(),
- QuicCircularDeque<int>::const_iterator());
- EXPECT_EQ(QuicCircularDeque<int>::reverse_iterator(),
- QuicCircularDeque<int>::reverse_iterator());
- EXPECT_EQ(QuicCircularDeque<int>::const_reverse_iterator(),
- QuicCircularDeque<int>::const_reverse_iterator());
-
- QuicCircularDeque<QuicCircularDeque<int>, 3> dqdq = {
+ EXPECT_EQ(QuicheCircularDeque<int>::iterator(),
+ QuicheCircularDeque<int>::iterator());
+ EXPECT_EQ(QuicheCircularDeque<int>::const_iterator(),
+ QuicheCircularDeque<int>::const_iterator());
+ EXPECT_EQ(QuicheCircularDeque<int>::reverse_iterator(),
+ QuicheCircularDeque<int>::reverse_iterator());
+ EXPECT_EQ(QuicheCircularDeque<int>::const_reverse_iterator(),
+ QuicheCircularDeque<int>::const_reverse_iterator());
+
+ QuicheCircularDeque<QuicheCircularDeque<int>, 3> dqdq = {
{1, 2}, {10, 20, 30}, {100, 200, 300, 400}};
// iter points to {1, 2}
@@ -494,8 +497,8 @@ TEST_F(QuicCircularDequeTest, Iterator) {
}
}
-TEST_F(QuicCircularDequeTest, Resize) {
- QuicCircularDeque<int, 3, CountingAllocator<int>> dq;
+TEST_F(QuicheCircularDequeTest, Resize) {
+ QuicheCircularDeque<int, 3, CountingAllocator<int>> dq;
dq.resize(8);
EXPECT_THAT(dq, ElementsAre(0, 0, 0, 0, 0, 0, 0, 0));
EXPECT_EQ(1u, dq.get_allocator().allocate_count());
@@ -503,7 +506,7 @@ TEST_F(QuicCircularDequeTest, Resize) {
dq.resize(10, 5);
EXPECT_THAT(dq, ElementsAre(0, 0, 0, 0, 0, 0, 0, 0, 5, 5));
- QuicCircularDeque<int, 3, CountingAllocator<int>> dq2 = dq;
+ QuicheCircularDeque<int, 3, CountingAllocator<int>> dq2 = dq;
for (size_t new_size = dq.size(); new_size != 0; --new_size) {
dq.resize(new_size);
@@ -575,7 +578,7 @@ class Foo {
};
} // namespace
-TEST_F(QuicCircularDequeTest, RelocateNonTriviallyCopyable) {
+TEST_F(QuicheCircularDequeTest, RelocateNonTriviallyCopyable) {
// When relocating non-trivially-copyable objects:
// - Move constructor is preferred, if available.
// - Copy constructor is used otherwise.
@@ -585,8 +588,8 @@ TEST_F(QuicCircularDequeTest, RelocateNonTriviallyCopyable) {
using MoveConstructible = std::unique_ptr<Foo>;
ASSERT_FALSE(std::is_trivially_copyable<MoveConstructible>::value);
ASSERT_TRUE(std::is_move_constructible<MoveConstructible>::value);
- QuicCircularDeque<MoveConstructible, 3,
- CountingAllocator<MoveConstructible>>
+ QuicheCircularDeque<MoveConstructible, 3,
+ CountingAllocator<MoveConstructible>>
dq1;
dq1.resize(3);
EXPECT_EQ(dq1.size(), dq1.capacity());
@@ -606,8 +609,8 @@ TEST_F(QuicCircularDequeTest, RelocateNonTriviallyCopyable) {
using NonMoveConstructible = Foo;
ASSERT_FALSE(std::is_trivially_copyable<NonMoveConstructible>::value);
ASSERT_FALSE(std::is_move_constructible<NonMoveConstructible>::value);
- QuicCircularDeque<NonMoveConstructible, 3,
- CountingAllocator<NonMoveConstructible>>
+ QuicheCircularDeque<NonMoveConstructible, 3,
+ CountingAllocator<NonMoveConstructible>>
dq2;
dq2.resize(3);
EXPECT_EQ(dq2.size(), dq2.capacity());
@@ -623,49 +626,49 @@ TEST_F(QuicCircularDequeTest, RelocateNonTriviallyCopyable) {
}
}
-TEST_F(QuicCircularDequeTest, PushPop) {
+TEST_F(QuicheCircularDequeTest, PushPop) {
// (push|pop|emplace)_(back|front)
{
- QuicCircularDeque<Foo, 4, CountingAllocator<Foo>> dq(4);
+ QuicheCircularDeque<Foo, 4, CountingAllocator<Foo>> dq(4);
for (size_t i = 0; i < dq.size(); ++i) {
dq[i].Set(i + 1);
}
- QUIC_LOG(INFO) << "dq initialized to " << dq;
+ QUICHE_LOG(INFO) << "dq initialized to " << dq;
EXPECT_THAT(dq, ElementsAre(Foo(1), Foo(2), Foo(3), Foo(4)));
ShiftLeft(&dq, false);
- QUIC_LOG(INFO) << "shift left once : " << dq;
+ QUICHE_LOG(INFO) << "shift left once : " << dq;
EXPECT_THAT(dq, ElementsAre(Foo(2), Foo(3), Foo(4), Foo(1)));
ShiftLeft(&dq, true);
- QUIC_LOG(INFO) << "shift left twice: " << dq;
+ QUICHE_LOG(INFO) << "shift left twice: " << dq;
EXPECT_THAT(dq, ElementsAre(Foo(3), Foo(4), Foo(1), Foo(2)));
ASSERT_GT(&dq.front(), &dq.back());
// dq destructs with wrapped data.
}
{
- QuicCircularDeque<Foo, 4, CountingAllocator<Foo>> dq1(4);
+ QuicheCircularDeque<Foo, 4, CountingAllocator<Foo>> dq1(4);
for (size_t i = 0; i < dq1.size(); ++i) {
dq1[i].Set(i + 1);
}
- QUIC_LOG(INFO) << "dq1 initialized to " << dq1;
+ QUICHE_LOG(INFO) << "dq1 initialized to " << dq1;
EXPECT_THAT(dq1, ElementsAre(Foo(1), Foo(2), Foo(3), Foo(4)));
ShiftRight(&dq1, false);
- QUIC_LOG(INFO) << "shift right once : " << dq1;
+ QUICHE_LOG(INFO) << "shift right once : " << dq1;
EXPECT_THAT(dq1, ElementsAre(Foo(4), Foo(1), Foo(2), Foo(3)));
ShiftRight(&dq1, true);
- QUIC_LOG(INFO) << "shift right twice: " << dq1;
+ QUICHE_LOG(INFO) << "shift right twice: " << dq1;
EXPECT_THAT(dq1, ElementsAre(Foo(3), Foo(4), Foo(1), Foo(2)));
ASSERT_GT(&dq1.front(), &dq1.back());
// dq1 destructs with wrapped data.
}
{ // Pop n elements from front.
- QuicCircularDeque<Foo, 4, CountingAllocator<Foo>> dq2(5);
+ QuicheCircularDeque<Foo, 4, CountingAllocator<Foo>> dq2(5);
for (size_t i = 0; i < dq2.size(); ++i) {
dq2[i].Set(i + 1);
}
@@ -679,7 +682,7 @@ TEST_F(QuicCircularDequeTest, PushPop) {
}
{ // Pop n elements from back.
- QuicCircularDeque<Foo, 4, CountingAllocator<Foo>> dq3(6);
+ QuicheCircularDeque<Foo, 4, CountingAllocator<Foo>> dq3(6);
for (size_t i = 0; i < dq3.size(); ++i) {
dq3[i].Set(i + 1);
}
@@ -700,11 +703,11 @@ TEST_F(QuicCircularDequeTest, PushPop) {
}
}
-TEST_F(QuicCircularDequeTest, Allocation) {
+TEST_F(QuicheCircularDequeTest, Allocation) {
CountingAllocator<int> alloc;
{
- QuicCircularDeque<int, 3, CountingAllocator<int>> dq(alloc);
+ QuicheCircularDeque<int, 3, CountingAllocator<int>> dq(alloc);
EXPECT_EQ(alloc, dq.get_allocator());
EXPECT_EQ(0u, dq.size());
EXPECT_EQ(0u, dq.capacity());
@@ -734,13 +737,13 @@ TEST_F(QuicCircularDequeTest, Allocation) {
} // namespace
} // namespace test
-} // namespace quic
+} // namespace quiche
-// Use a non-quic namespace to make sure swap can be used via ADL.
+// Use a non-quiche namespace to make sure swap can be used via ADL.
namespace {
template <typename T>
-using SwappableAllocator = quic::test::ConfigurableAllocator<
+using SwappableAllocator = quiche::test::ConfigurableAllocator<
T,
/*propagate_on_copy_assignment=*/std::true_type,
/*propagate_on_move_assignment=*/std::true_type,
@@ -748,7 +751,7 @@ using SwappableAllocator = quic::test::ConfigurableAllocator<
/*equality_result=*/true>;
template <typename T>
-using UnswappableEqualAllocator = quic::test::ConfigurableAllocator<
+using UnswappableEqualAllocator = quiche::test::ConfigurableAllocator<
T,
/*propagate_on_copy_assignment=*/std::true_type,
/*propagate_on_move_assignment=*/std::true_type,
@@ -756,19 +759,19 @@ using UnswappableEqualAllocator = quic::test::ConfigurableAllocator<
/*equality_result=*/true>;
template <typename T>
-using UnswappableUnequalAllocator = quic::test::ConfigurableAllocator<
+using UnswappableUnequalAllocator = quiche::test::ConfigurableAllocator<
T,
/*propagate_on_copy_assignment=*/std::true_type,
/*propagate_on_move_assignment=*/std::true_type,
/*propagate_on_swap=*/std::false_type,
/*equality_result=*/false>;
-using quic::test::QuicCircularDequeTest;
+using quiche::test::QuicheCircularDequeTest;
-TEST_F(QuicCircularDequeTest, Swap) {
+TEST_F(QuicheCircularDequeTest, Swap) {
using std::swap;
- quic::QuicCircularDeque<int64_t, 3, SwappableAllocator<int64_t>> dq1, dq2;
+ quiche::QuicheCircularDeque<int64_t, 3, SwappableAllocator<int64_t>> dq1, dq2;
dq1.push_back(10);
dq1.push_back(11);
dq2.push_back(20);
@@ -776,14 +779,16 @@ TEST_F(QuicCircularDequeTest, Swap) {
EXPECT_THAT(dq1, ElementsAre(20));
EXPECT_THAT(dq2, ElementsAre(10, 11));
- quic::QuicCircularDeque<char, 3, UnswappableEqualAllocator<char>> dq3, dq4;
+ quiche::QuicheCircularDeque<char, 3, UnswappableEqualAllocator<char>> dq3,
+ dq4;
dq3 = {1, 2, 3, 4, 5};
dq4 = {6, 7, 8, 9, 0};
swap(dq3, dq4);
EXPECT_THAT(dq3, ElementsAre(6, 7, 8, 9, 0));
EXPECT_THAT(dq4, ElementsAre(1, 2, 3, 4, 5));
- quic::QuicCircularDeque<int, 3, UnswappableUnequalAllocator<int>> dq5, dq6;
+ quiche::QuicheCircularDeque<int, 3, UnswappableUnequalAllocator<int>> dq5,
+ dq6;
dq6.push_front(4);
// Using UnswappableUnequalAllocator is ok as long as swap is not called.
@@ -791,6 +796,6 @@ TEST_F(QuicCircularDequeTest, Swap) {
EXPECT_THAT(dq5, ElementsAre(4));
// Undefined behavior to swap between two containers with unequal allocators.
- EXPECT_QUIC_DEBUG_DEATH(swap(dq5, dq6), "Undefined swap behavior");
+ EXPECT_QUICHE_DEBUG_DEATH(swap(dq5, dq6), "Undefined swap behavior");
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/common/quiche_data_reader.cc b/chromium/net/third_party/quiche/src/common/quiche_data_reader.cc
index c196b42d2bb..f20c752bcce 100644
--- a/chromium/net/third_party/quiche/src/common/quiche_data_reader.cc
+++ b/chromium/net/third_party/quiche/src/common/quiche_data_reader.cc
@@ -10,7 +10,6 @@
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "common/platform/api/quiche_logging.h"
-#include "common/platform/api/quiche_text_utils.h"
#include "common/quiche_endian.h"
namespace quiche {
diff --git a/chromium/net/third_party/quiche/src/common/simple_linked_hash_map.h b/chromium/net/third_party/quiche/src/common/quiche_linked_hash_map.h
index 17542a1dae6..a52863e40f5 100644
--- a/chromium/net/third_party/quiche/src/common/simple_linked_hash_map.h
+++ b/chromium/net/third_party/quiche/src/common/quiche_linked_hash_map.h
@@ -13,8 +13,8 @@
// mutations, except for an iterator pointing to an element that was just
// deleted.
-#ifndef QUICHE_COMMON_SIMPLE_LINKED_HASH_MAP_H_
-#define QUICHE_COMMON_SIMPLE_LINKED_HASH_MAP_H_
+#ifndef QUICHE_COMMON_QUICHE_LINKED_HASH_MAP_H_
+#define QUICHE_COMMON_QUICHE_LINKED_HASH_MAP_H_
#include <functional>
#include <list>
@@ -38,7 +38,7 @@ template <class Key,
class Value,
class Hash = std::hash<Key>,
class Eq = std::equal_to<Key>>
-class SimpleLinkedHashMap {
+class QuicheLinkedHashMap {
private:
typedef std::list<std::pair<Key, Value>> ListType;
typedef absl::node_hash_map<Key, typename ListType::iterator, Hash, Eq>
@@ -53,13 +53,13 @@ class SimpleLinkedHashMap {
typedef typename ListType::value_type value_type;
typedef typename ListType::size_type size_type;
- SimpleLinkedHashMap() = default;
- explicit SimpleLinkedHashMap(size_type bucket_count) : map_(bucket_count) {}
+ QuicheLinkedHashMap() = default;
+ explicit QuicheLinkedHashMap(size_type bucket_count) : map_(bucket_count) {}
- SimpleLinkedHashMap(const SimpleLinkedHashMap& other) = delete;
- SimpleLinkedHashMap& operator=(const SimpleLinkedHashMap& other) = delete;
- SimpleLinkedHashMap(SimpleLinkedHashMap&& other) = default;
- SimpleLinkedHashMap& operator=(SimpleLinkedHashMap&& other) = default;
+ QuicheLinkedHashMap(const QuicheLinkedHashMap& other) = delete;
+ QuicheLinkedHashMap& operator=(const QuicheLinkedHashMap& other) = delete;
+ QuicheLinkedHashMap(QuicheLinkedHashMap&& other) = default;
+ QuicheLinkedHashMap& operator=(QuicheLinkedHashMap&& other) = default;
// Returns an iterator to the first (insertion-ordered) element. Like a map,
// this can be dereferenced to a pair<Key, Value>.
@@ -127,7 +127,8 @@ class SimpleLinkedHashMap {
iterator erase(iterator position) {
typename MapType::iterator found = map_.find(position->first);
QUICHE_CHECK(found->second == position)
- << "Inconsisent iterator for map and list, or the iterator is invalid.";
+ << "Inconsistent iterator for map and list, or the iterator is "
+ "invalid.";
map_.erase(found);
return list_.erase(position);
@@ -172,49 +173,12 @@ class SimpleLinkedHashMap {
// Inserts an element into the map
std::pair<iterator, bool> insert(const std::pair<Key, Value>& pair) {
- // First make sure the map doesn't have a key with this value. If it does,
- // return a pair with an iterator to it, and false indicating that we
- // didn't insert anything.
- typename MapType::iterator found = map_.find(pair.first);
- if (found != map_.end()) {
- return std::make_pair(found->second, false);
- }
-
- // Otherwise, insert into the list first.
- list_.push_back(pair);
-
- // Obtain an iterator to the newly added element. We do -- instead of -
- // since list::iterator doesn't implement operator-().
- typename ListType::iterator last = list_.end();
- --last;
-
- QUICHE_CHECK(map_.insert(std::make_pair(pair.first, last)).second)
- << "Map and list are inconsistent";
-
- return std::make_pair(last, true);
+ return InsertInternal(pair);
}
// Inserts an element into the map
std::pair<iterator, bool> insert(std::pair<Key, Value>&& pair) {
- // First make sure the map doesn't have a key with this value. If it does,
- // return a pair with an iterator to it, and false indicating that we
- // didn't insert anything.
- typename MapType::iterator found = map_.find(pair.first);
- if (found != map_.end()) {
- return std::make_pair(found->second, false);
- }
-
- // Otherwise, insert into the list first.
- list_.push_back(std::move(pair));
-
- // Obtain an iterator to the newly added element. We do -- instead of -
- // since list::iterator doesn't implement operator-().
- typename ListType::iterator last = list_.end();
- --last;
-
- QUICHE_CHECK(map_.insert(std::make_pair(last->first, last)).second)
- << "Map and list are inconsistent";
- return std::make_pair(last, true);
+ return InsertInternal(std::move(pair));
}
// Derive size_ from map_, as list::size might be O(N).
@@ -234,12 +198,30 @@ class SimpleLinkedHashMap {
return {ins.first->second, true};
}
- void swap(SimpleLinkedHashMap& other) {
+ void swap(QuicheLinkedHashMap& other) {
map_.swap(other.map_);
list_.swap(other.list_);
}
private:
+ template <typename U>
+ std::pair<iterator, bool> InsertInternal(U&& pair) {
+ auto insert_result = map_.try_emplace(pair.first);
+ auto map_iter = insert_result.first;
+
+ // If the map already contains this key, return a pair with an iterator to
+ // it, and false indicating that we didn't insert anything.
+ if (!insert_result.second) {
+ return {map_iter->second, false};
+ }
+
+ // Otherwise, insert into the list, and set value in map.
+ auto list_iter = list_.insert(list_.end(), std::forward<U>(pair));
+ map_iter->second = list_iter;
+
+ return {list_iter, true};
+ }
+
// The map component, used for speedy lookups
MapType map_;
@@ -249,4 +231,4 @@ class SimpleLinkedHashMap {
} // namespace quiche
-#endif // QUICHE_COMMON_SIMPLE_LINKED_HASH_MAP_H_
+#endif // QUICHE_COMMON_QUICHE_LINKED_HASH_MAP_H_
diff --git a/chromium/net/third_party/quiche/src/common/simple_linked_hash_map_test.cc b/chromium/net/third_party/quiche/src/common/quiche_linked_hash_map_test.cc
index 1119f0d830f..dab608532ba 100644
--- a/chromium/net/third_party/quiche/src/common/simple_linked_hash_map_test.cc
+++ b/chromium/net/third_party/quiche/src/common/quiche_linked_hash_map_test.cc
@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Tests SimpleLinkedHashMap.
+// Tests QuicheLinkedHashMap.
-#include "common/simple_linked_hash_map.h"
+#include "common/quiche_linked_hash_map.h"
#include <memory>
#include <utility>
@@ -21,16 +21,16 @@ namespace test {
// Tests that move constructor works.
TEST(LinkedHashMapTest, Move) {
// Use unique_ptr as an example of a non-copyable type.
- SimpleLinkedHashMap<int, std::unique_ptr<int>> m;
+ QuicheLinkedHashMap<int, std::unique_ptr<int>> m;
m[2] = std::make_unique<int>(12);
m[3] = std::make_unique<int>(13);
- SimpleLinkedHashMap<int, std::unique_ptr<int>> n = std::move(m);
+ QuicheLinkedHashMap<int, std::unique_ptr<int>> n = std::move(m);
EXPECT_THAT(n,
UnorderedElementsAre(Pair(2, Pointee(12)), Pair(3, Pointee(13))));
}
TEST(LinkedHashMapTest, CanEmplaceMoveOnly) {
- SimpleLinkedHashMap<int, std::unique_ptr<int>> m;
+ QuicheLinkedHashMap<int, std::unique_ptr<int>> m;
struct Data {
int k, v;
};
@@ -55,7 +55,7 @@ struct NoCopy {
};
TEST(LinkedHashMapTest, CanEmplaceNoMoveNoCopy) {
- SimpleLinkedHashMap<int, NoCopy> m;
+ QuicheLinkedHashMap<int, NoCopy> m;
struct Data {
int k, v;
};
@@ -71,7 +71,7 @@ TEST(LinkedHashMapTest, CanEmplaceNoMoveNoCopy) {
}
TEST(LinkedHashMapTest, ConstKeys) {
- SimpleLinkedHashMap<int, int> m;
+ QuicheLinkedHashMap<int, int> m;
m.insert(std::make_pair(1, 2));
// Test that keys are const in iteration.
std::pair<int, int>& p = *m.begin();
@@ -80,14 +80,14 @@ TEST(LinkedHashMapTest, ConstKeys) {
// Tests that iteration from begin() to end() works
TEST(LinkedHashMapTest, Iteration) {
- SimpleLinkedHashMap<int, int> m;
+ QuicheLinkedHashMap<int, int> m;
EXPECT_TRUE(m.begin() == m.end());
m.insert(std::make_pair(2, 12));
m.insert(std::make_pair(1, 11));
m.insert(std::make_pair(3, 13));
- SimpleLinkedHashMap<int, int>::iterator i = m.begin();
+ QuicheLinkedHashMap<int, int>::iterator i = m.begin();
ASSERT_TRUE(m.begin() == i);
ASSERT_TRUE(m.end() != i);
EXPECT_EQ(2, i->first);
@@ -109,14 +109,14 @@ TEST(LinkedHashMapTest, Iteration) {
// Tests that reverse iteration from rbegin() to rend() works
TEST(LinkedHashMapTest, ReverseIteration) {
- SimpleLinkedHashMap<int, int> m;
+ QuicheLinkedHashMap<int, int> m;
EXPECT_TRUE(m.rbegin() == m.rend());
m.insert(std::make_pair(2, 12));
m.insert(std::make_pair(1, 11));
m.insert(std::make_pair(3, 13));
- SimpleLinkedHashMap<int, int>::reverse_iterator i = m.rbegin();
+ QuicheLinkedHashMap<int, int>::reverse_iterator i = m.rbegin();
ASSERT_TRUE(m.rbegin() == i);
ASSERT_TRUE(m.rend() != i);
EXPECT_EQ(3, i->first);
@@ -138,7 +138,7 @@ TEST(LinkedHashMapTest, ReverseIteration) {
// Tests that clear() works
TEST(LinkedHashMapTest, Clear) {
- SimpleLinkedHashMap<int, int> m;
+ QuicheLinkedHashMap<int, int> m;
m.insert(std::make_pair(2, 12));
m.insert(std::make_pair(1, 11));
m.insert(std::make_pair(3, 13));
@@ -156,7 +156,7 @@ TEST(LinkedHashMapTest, Clear) {
// Tests that size() works.
TEST(LinkedHashMapTest, Size) {
- SimpleLinkedHashMap<int, int> m;
+ QuicheLinkedHashMap<int, int> m;
EXPECT_EQ(0u, m.size());
m.insert(std::make_pair(2, 12));
EXPECT_EQ(1u, m.size());
@@ -170,7 +170,7 @@ TEST(LinkedHashMapTest, Size) {
// Tests empty()
TEST(LinkedHashMapTest, Empty) {
- SimpleLinkedHashMap<int, int> m;
+ QuicheLinkedHashMap<int, int> m;
ASSERT_TRUE(m.empty());
m.insert(std::make_pair(2, 12));
ASSERT_FALSE(m.empty());
@@ -179,7 +179,7 @@ TEST(LinkedHashMapTest, Empty) {
}
TEST(LinkedHashMapTest, Erase) {
- SimpleLinkedHashMap<int, int> m;
+ QuicheLinkedHashMap<int, int> m;
ASSERT_EQ(0u, m.size());
EXPECT_EQ(0u, m.erase(2)); // Nothing to erase yet
@@ -193,7 +193,7 @@ TEST(LinkedHashMapTest, Erase) {
}
TEST(LinkedHashMapTest, Erase2) {
- SimpleLinkedHashMap<int, int> m;
+ QuicheLinkedHashMap<int, int> m;
ASSERT_EQ(0u, m.size());
EXPECT_EQ(0u, m.erase(2)); // Nothing to erase yet
@@ -210,7 +210,7 @@ TEST(LinkedHashMapTest, Erase2) {
EXPECT_EQ(2u, m.size());
// Make sure we can still iterate over everything that's left.
- SimpleLinkedHashMap<int, int>::iterator it = m.begin();
+ QuicheLinkedHashMap<int, int>::iterator it = m.begin();
ASSERT_TRUE(it != m.end());
EXPECT_EQ(12, it->second);
++it;
@@ -232,7 +232,7 @@ TEST(LinkedHashMapTest, Erase2) {
// Test that erase(iter,iter) and erase(iter) compile and work.
TEST(LinkedHashMapTest, Erase3) {
- SimpleLinkedHashMap<int, int> m;
+ QuicheLinkedHashMap<int, int> m;
m.insert(std::make_pair(1, 11));
m.insert(std::make_pair(2, 12));
@@ -240,13 +240,13 @@ TEST(LinkedHashMapTest, Erase3) {
m.insert(std::make_pair(4, 14));
// Erase middle two
- SimpleLinkedHashMap<int, int>::iterator it2 = m.find(2);
- SimpleLinkedHashMap<int, int>::iterator it4 = m.find(4);
+ QuicheLinkedHashMap<int, int>::iterator it2 = m.find(2);
+ QuicheLinkedHashMap<int, int>::iterator it4 = m.find(4);
EXPECT_EQ(m.erase(it2, it4), m.find(4));
EXPECT_EQ(2u, m.size());
// Make sure we can still iterate over everything that's left.
- SimpleLinkedHashMap<int, int>::iterator it = m.begin();
+ QuicheLinkedHashMap<int, int>::iterator it = m.begin();
ASSERT_TRUE(it != m.end());
EXPECT_EQ(11, it->second);
++it;
@@ -267,9 +267,9 @@ TEST(LinkedHashMapTest, Erase3) {
}
TEST(LinkedHashMapTest, Insertion) {
- SimpleLinkedHashMap<int, int> m;
+ QuicheLinkedHashMap<int, int> m;
ASSERT_EQ(0u, m.size());
- std::pair<SimpleLinkedHashMap<int, int>::iterator, bool> result;
+ std::pair<QuicheLinkedHashMap<int, int>::iterator, bool> result;
result = m.insert(std::make_pair(2, 12));
ASSERT_EQ(1u, m.size());
@@ -284,7 +284,7 @@ TEST(LinkedHashMapTest, Insertion) {
EXPECT_EQ(11, result.first->second);
result = m.insert(std::make_pair(3, 13));
- SimpleLinkedHashMap<int, int>::iterator result_iterator = result.first;
+ QuicheLinkedHashMap<int, int>::iterator result_iterator = result.first;
ASSERT_EQ(3u, m.size());
EXPECT_TRUE(result.second);
EXPECT_EQ(3, result.first->first);
@@ -303,7 +303,7 @@ static std::pair<int, int> Pair(int i, int j) {
// Test front accessors.
TEST(LinkedHashMapTest, Front) {
- SimpleLinkedHashMap<int, int> m;
+ QuicheLinkedHashMap<int, int> m;
m.insert(std::make_pair(2, 12));
m.insert(std::make_pair(1, 11));
@@ -322,7 +322,7 @@ TEST(LinkedHashMapTest, Front) {
}
TEST(LinkedHashMapTest, Find) {
- SimpleLinkedHashMap<int, int> m;
+ QuicheLinkedHashMap<int, int> m;
EXPECT_TRUE(m.end() == m.find(1))
<< "We shouldn't find anything in an empty map.";
@@ -331,7 +331,7 @@ TEST(LinkedHashMapTest, Find) {
EXPECT_TRUE(m.end() == m.find(1))
<< "We shouldn't find an element that doesn't exist in the map.";
- std::pair<SimpleLinkedHashMap<int, int>::iterator, bool> result =
+ std::pair<QuicheLinkedHashMap<int, int>::iterator, bool> result =
m.insert(std::make_pair(1, 11));
ASSERT_TRUE(result.second);
ASSERT_TRUE(m.end() != result.first);
@@ -341,7 +341,7 @@ TEST(LinkedHashMapTest, Find) {
// Check that a follow-up insertion doesn't affect our original
m.insert(std::make_pair(3, 13));
- SimpleLinkedHashMap<int, int>::iterator it = m.find(1);
+ QuicheLinkedHashMap<int, int>::iterator it = m.find(1);
ASSERT_TRUE(m.end() != it);
EXPECT_EQ(11, it->second);
@@ -351,7 +351,7 @@ TEST(LinkedHashMapTest, Find) {
}
TEST(LinkedHashMapTest, Contains) {
- SimpleLinkedHashMap<int, int> m;
+ QuicheLinkedHashMap<int, int> m;
EXPECT_FALSE(m.contains(1)) << "An empty map shouldn't contain anything.";
@@ -369,8 +369,8 @@ TEST(LinkedHashMapTest, Contains) {
}
TEST(LinkedHashMapTest, Swap) {
- SimpleLinkedHashMap<int, int> m1;
- SimpleLinkedHashMap<int, int> m2;
+ QuicheLinkedHashMap<int, int> m1;
+ QuicheLinkedHashMap<int, int> m2;
m1.insert(std::make_pair(1, 1));
m1.insert(std::make_pair(2, 2));
m2.insert(std::make_pair(3, 3));
@@ -385,7 +385,7 @@ TEST(LinkedHashMapTest, CustomHashAndEquality) {
struct CustomIntHash {
size_t operator()(int x) const { return x; }
};
- SimpleLinkedHashMap<int, int, CustomIntHash> m;
+ QuicheLinkedHashMap<int, int, CustomIntHash> m;
m.insert(std::make_pair(1, 1));
EXPECT_TRUE(m.contains(1));
EXPECT_EQ(1, m[1]);
diff --git a/chromium/net/third_party/quiche/src/common/quiche_text_utils.cc b/chromium/net/third_party/quiche/src/common/quiche_text_utils.cc
new file mode 100644
index 00000000000..263c97e9db6
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/common/quiche_text_utils.cc
@@ -0,0 +1,77 @@
+// Copyright 2021 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 "common/quiche_text_utils.h"
+
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+
+namespace quiche {
+
+// static
+void QuicheTextUtils::Base64Encode(const uint8_t* data,
+ size_t data_len,
+ std::string* output) {
+ absl::Base64Escape(std::string(reinterpret_cast<const char*>(data), data_len),
+ output);
+ // Remove padding.
+ size_t len = output->size();
+ if (len >= 2) {
+ if ((*output)[len - 1] == '=') {
+ len--;
+ if ((*output)[len - 1] == '=') {
+ len--;
+ }
+ output->resize(len);
+ }
+ }
+}
+
+// static
+absl::optional<std::string> QuicheTextUtils::Base64Decode(
+ absl::string_view input) {
+ std::string output;
+ if (!absl::Base64Unescape(input, &output)) {
+ return absl::nullopt;
+ }
+ return output;
+}
+
+// static
+std::string QuicheTextUtils::HexDump(absl::string_view binary_data) {
+ const int kBytesPerLine = 16; // Maximum bytes dumped per line.
+ int offset = 0;
+ const char* p = binary_data.data();
+ int bytes_remaining = binary_data.size();
+ std::string output;
+ while (bytes_remaining > 0) {
+ const int line_bytes = std::min(bytes_remaining, kBytesPerLine);
+ absl::StrAppendFormat(&output, "0x%04x: ", offset);
+ for (int i = 0; i < kBytesPerLine; ++i) {
+ if (i < line_bytes) {
+ absl::StrAppendFormat(&output, "%02x",
+ static_cast<unsigned char>(p[i]));
+ } else {
+ absl::StrAppend(&output, " ");
+ }
+ if (i % 2) {
+ absl::StrAppend(&output, " ");
+ }
+ }
+ absl::StrAppend(&output, " ");
+ for (int i = 0; i < line_bytes; ++i) {
+ // Replace non-printable characters and 0x20 (space) with '.'
+ output += absl::ascii_isgraph(p[i]) ? p[i] : '.';
+ }
+
+ bytes_remaining -= line_bytes;
+ offset += line_bytes;
+ p += line_bytes;
+ absl::StrAppend(&output, "\n");
+ }
+ return output;
+}
+
+} // namespace quiche
diff --git a/chromium/net/third_party/quiche/src/common/platform/api/quiche_text_utils.h b/chromium/net/third_party/quiche/src/common/quiche_text_utils.h
index 42b4115a5de..c99d9e2ac02 100644
--- a/chromium/net/third_party/quiche/src/common/platform/api/quiche_text_utils.h
+++ b/chromium/net/third_party/quiche/src/common/quiche_text_utils.h
@@ -2,16 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_TEXT_UTILS_H_
-#define QUICHE_COMMON_PLATFORM_API_QUICHE_TEXT_UTILS_H_
+#ifndef QUICHE_COMMON_QUICHE_TEXT_UTILS_H_
+#define QUICHE_COMMON_QUICHE_TEXT_UTILS_H_
#include <string>
+#include "absl/strings/ascii.h"
#include "absl/strings/escaping.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "common/platform/api/quiche_export.h"
-#include "net/quiche/common/platform/impl/quiche_text_utils_impl.h"
namespace quiche {
@@ -20,47 +20,41 @@ class QUICHE_EXPORT QuicheTextUtils {
public:
// Returns a new string in which |data| has been converted to lower case.
static std::string ToLower(absl::string_view data) {
- return quiche::QuicheTextUtilsImpl::ToLower(data);
+ return absl::AsciiStrToLower(data);
}
// Removes leading and trailing whitespace from |data|.
static void RemoveLeadingAndTrailingWhitespace(absl::string_view* data) {
- quiche::QuicheTextUtilsImpl::RemoveLeadingAndTrailingWhitespace(data);
+ *data = absl::StripAsciiWhitespace(*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 quiche::QuicheTextUtilsImpl::Base64Encode(data, data_len, output);
- }
+ std::string* output);
// Decodes a base64-encoded |input|. Returns nullopt when the input is
// invalid.
- static absl::optional<std::string> Base64Decode(absl::string_view input) {
- return quiche::QuicheTextUtilsImpl::Base64Decode(input);
- }
+ static absl::optional<std::string> Base64Decode(absl::string_view input);
// 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(absl::string_view binary_data) {
- return quiche::QuicheTextUtilsImpl::HexDump(binary_data);
- }
+ static std::string HexDump(absl::string_view binary_data);
// Returns true if |data| contains any uppercase characters.
static bool ContainsUpperCase(absl::string_view data) {
- return quiche::QuicheTextUtilsImpl::ContainsUpperCase(data);
+ return std::any_of(data.begin(), data.end(), absl::ascii_isupper);
}
// Returns true if |data| contains only decimal digits.
static bool IsAllDigits(absl::string_view data) {
- return quiche::QuicheTextUtilsImpl::IsAllDigits(data);
+ return std::all_of(data.begin(), data.end(), absl::ascii_isdigit);
}
};
} // namespace quiche
-#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_TEXT_UTILS_H_
+#endif // QUICHE_COMMON_QUICHE_TEXT_UTILS_H_
diff --git a/chromium/net/third_party/quiche/src/common/platform/api/quiche_text_utils_test.cc b/chromium/net/third_party/quiche/src/common/quiche_text_utils_test.cc
index d6d1f4d443e..5c10cbf931a 100644
--- a/chromium/net/third_party/quiche/src/common/platform/api/quiche_text_utils_test.cc
+++ b/chromium/net/third_party/quiche/src/common/quiche_text_utils_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 "common/platform/api/quiche_text_utils.h"
+#include "common/quiche_text_utils.h"
#include <string>
@@ -12,9 +12,7 @@
namespace quiche {
namespace test {
-class QuicheTextUtilsTest : public QuicheTest {};
-
-TEST_F(QuicheTextUtilsTest, ToLower) {
+TEST(QuicheTextUtilsTest, ToLower) {
EXPECT_EQ("lower", quiche::QuicheTextUtils::ToLower("LOWER"));
EXPECT_EQ("lower", quiche::QuicheTextUtils::ToLower("lower"));
EXPECT_EQ("lower", quiche::QuicheTextUtils::ToLower("lOwEr"));
@@ -22,7 +20,7 @@ TEST_F(QuicheTextUtilsTest, ToLower) {
EXPECT_EQ("", quiche::QuicheTextUtils::ToLower(""));
}
-TEST_F(QuicheTextUtilsTest, RemoveLeadingAndTrailingWhitespace) {
+TEST(QuicheTextUtilsTest, RemoveLeadingAndTrailingWhitespace) {
std::string input;
for (auto* input : {"text", " text", " text", "text ", "text ", " text ",
@@ -33,7 +31,9 @@ TEST_F(QuicheTextUtilsTest, RemoveLeadingAndTrailingWhitespace) {
}
}
-TEST_F(QuicheTextUtilsTest, HexDump) {
+TEST(QuicheTextUtilsTest, HexDump) {
+ // Verify output for empty input.
+ EXPECT_EQ("", quiche::QuicheTextUtils::HexDump(absl::HexStringToBytes("")));
// Verify output of the HexDump method is as expected.
char packet[] = {
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x51, 0x55, 0x49, 0x43, 0x21,
@@ -62,7 +62,7 @@ TEST_F(QuicheTextUtilsTest, HexDump) {
quiche::QuicheTextUtils::HexDump(absl::HexStringToBytes("90aaff")));
}
-TEST_F(QuicheTextUtilsTest, Base64Encode) {
+TEST(QuicheTextUtilsTest, Base64Encode) {
std::string output;
std::string input = "Hello";
quiche::QuicheTextUtils::Base64Encode(
@@ -80,7 +80,7 @@ TEST_F(QuicheTextUtilsTest, Base64Encode) {
output);
}
-TEST_F(QuicheTextUtilsTest, ContainsUpperCase) {
+TEST(QuicheTextUtilsTest, ContainsUpperCase) {
EXPECT_FALSE(quiche::QuicheTextUtils::ContainsUpperCase("abc"));
EXPECT_FALSE(quiche::QuicheTextUtils::ContainsUpperCase(""));
EXPECT_FALSE(quiche::QuicheTextUtils::ContainsUpperCase("123"));
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/adapter_impl_comparison_test.cc b/chromium/net/third_party/quiche/src/http2/adapter/adapter_impl_comparison_test.cc
new file mode 100644
index 00000000000..11f03bb2ffe
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/adapter_impl_comparison_test.cc
@@ -0,0 +1,83 @@
+#include "http2/adapter/recording_http2_visitor.h"
+
+#include "http2/adapter/http2_protocol.h"
+#include "http2/adapter/nghttp2_adapter.h"
+#include "http2/adapter/oghttp2_adapter.h"
+#include "http2/adapter/test_frame_sequence.h"
+#include "common/platform/api/quiche_test.h"
+#include "spdy/core/spdy_protocol.h"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+namespace {
+
+TEST(AdapterImplComparisonTest, ClientHandlesFrames) {
+ RecordingHttp2Visitor nghttp2_visitor;
+ std::unique_ptr<NgHttp2Adapter> nghttp2_adapter =
+ NgHttp2Adapter::CreateClientAdapter(nghttp2_visitor);
+
+ RecordingHttp2Visitor oghttp2_visitor;
+ OgHttp2Adapter::Options options{.perspective = Perspective::kClient};
+ std::unique_ptr<OgHttp2Adapter> oghttp2_adapter =
+ OgHttp2Adapter::Create(oghttp2_visitor, options);
+
+ const std::string initial_frames = TestFrameSequence()
+ .ServerPreface()
+ .Ping(42)
+ .WindowUpdate(0, 1000)
+ .Serialize();
+
+ nghttp2_adapter->ProcessBytes(initial_frames);
+ oghttp2_adapter->ProcessBytes(initial_frames);
+
+ EXPECT_EQ(nghttp2_visitor.GetEventSequence(),
+ oghttp2_visitor.GetEventSequence());
+
+ // TODO(b/181586191): Consider consistent behavior for delivering events on
+ // non-existent streams between nghttp2_adapter and oghttp2_adapter.
+}
+
+TEST(AdapterImplComparisonTest, ServerHandlesFrames) {
+ RecordingHttp2Visitor nghttp2_visitor;
+ std::unique_ptr<NgHttp2Adapter> nghttp2_adapter =
+ NgHttp2Adapter::CreateServerAdapter(nghttp2_visitor);
+
+ RecordingHttp2Visitor oghttp2_visitor;
+ OgHttp2Adapter::Options options{.perspective = Perspective::kServer};
+ std::unique_ptr<OgHttp2Adapter> oghttp2_adapter =
+ OgHttp2Adapter::Create(oghttp2_visitor, options);
+
+ const std::string frames = TestFrameSequence()
+ .ClientPreface()
+ .Ping(42)
+ .WindowUpdate(0, 1000)
+ .Headers(1,
+ {{":method", "POST"},
+ {":scheme", "https"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}},
+ /*fin=*/false)
+ .WindowUpdate(1, 2000)
+ .Data(1, "This is the request body.")
+ .Headers(3,
+ {{":method", "GET"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/two"}},
+ /*fin=*/true)
+ .RstStream(3, Http2ErrorCode::CANCEL)
+ .Ping(47)
+ .Serialize();
+
+ nghttp2_adapter->ProcessBytes(frames);
+ oghttp2_adapter->ProcessBytes(frames);
+
+ EXPECT_EQ(nghttp2_visitor.GetEventSequence(),
+ oghttp2_visitor.GetEventSequence());
+}
+
+} // namespace
+} // namespace test
+} // namespace adapter
+} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/callback_visitor.cc b/chromium/net/third_party/quiche/src/http2/adapter/callback_visitor.cc
new file mode 100644
index 00000000000..eaf4b6169d2
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/callback_visitor.cc
@@ -0,0 +1,215 @@
+#include "http2/adapter/callback_visitor.h"
+
+#include "http2/adapter/nghttp2_util.h"
+#include "third_party/nghttp2/src/lib/includes/nghttp2/nghttp2.h"
+#include "common/quiche_endian.h"
+
+// This visitor implementation needs visibility into the
+// nghttp2_session_callbacks type. There's no public header, so we'll redefine
+// the struct here.
+struct nghttp2_session_callbacks {
+ nghttp2_send_callback send_callback;
+ nghttp2_recv_callback recv_callback;
+ nghttp2_on_frame_recv_callback on_frame_recv_callback;
+ nghttp2_on_invalid_frame_recv_callback on_invalid_frame_recv_callback;
+ nghttp2_on_data_chunk_recv_callback on_data_chunk_recv_callback;
+ nghttp2_before_frame_send_callback before_frame_send_callback;
+ nghttp2_on_frame_send_callback on_frame_send_callback;
+ nghttp2_on_frame_not_send_callback on_frame_not_send_callback;
+ nghttp2_on_stream_close_callback on_stream_close_callback;
+ nghttp2_on_begin_headers_callback on_begin_headers_callback;
+ nghttp2_on_header_callback on_header_callback;
+ nghttp2_on_header_callback2 on_header_callback2;
+ nghttp2_on_invalid_header_callback on_invalid_header_callback;
+ nghttp2_on_invalid_header_callback2 on_invalid_header_callback2;
+ nghttp2_select_padding_callback select_padding_callback;
+ nghttp2_data_source_read_length_callback read_length_callback;
+ nghttp2_on_begin_frame_callback on_begin_frame_callback;
+ nghttp2_send_data_callback send_data_callback;
+ nghttp2_pack_extension_callback pack_extension_callback;
+ nghttp2_unpack_extension_callback unpack_extension_callback;
+ nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback;
+ nghttp2_error_callback error_callback;
+ nghttp2_error_callback2 error_callback2;
+};
+
+namespace http2 {
+namespace adapter {
+
+void CallbackVisitor::OnConnectionError() {
+ QUICHE_LOG(FATAL) << "Not implemented";
+}
+
+void CallbackVisitor::OnFrameHeader(Http2StreamId stream_id,
+ size_t length,
+ uint8_t type,
+ uint8_t flags) {
+ // The general strategy is to clear |current_frame_| at the start of a new
+ // frame, accumulate frame information from the various callback events, then
+ // invoke the on_frame_recv_callback() with the accumulated frame data.
+ memset(&current_frame_, 0, sizeof(current_frame_));
+ current_frame_.hd.stream_id = stream_id;
+ current_frame_.hd.length = length;
+ current_frame_.hd.type = type;
+ current_frame_.hd.flags = flags;
+ callbacks_->on_begin_frame_callback(nullptr, &current_frame_.hd, user_data_);
+}
+
+void CallbackVisitor::OnSettingsStart() {}
+
+void CallbackVisitor::OnSetting(Http2Setting setting) {
+ settings_.push_back({.settings_id = setting.id, .value = setting.value});
+}
+
+void CallbackVisitor::OnSettingsEnd() {
+ current_frame_.settings.niv = settings_.size();
+ current_frame_.settings.iv = settings_.data();
+ callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
+ settings_.clear();
+}
+
+void CallbackVisitor::OnSettingsAck() {
+ // ACK is part of the flags, which were set in OnFrameHeader().
+ callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
+}
+
+void CallbackVisitor::OnBeginHeadersForStream(Http2StreamId stream_id) {
+ auto it = stream_map_.find(stream_id);
+ if (it == stream_map_.end()) {
+ auto p = stream_map_.insert({stream_id, absl::make_unique<StreamInfo>()});
+ it = p.first;
+ }
+ if (it->second->received_headers) {
+ // At least one headers frame has already been received.
+ current_frame_.headers.cat = NGHTTP2_HCAT_HEADERS;
+ } else {
+ switch (perspective_) {
+ case Perspective::kClient:
+ current_frame_.headers.cat = NGHTTP2_HCAT_RESPONSE;
+ break;
+ case Perspective::kServer:
+ current_frame_.headers.cat = NGHTTP2_HCAT_REQUEST;
+ break;
+ }
+ }
+ callbacks_->on_begin_headers_callback(nullptr, &current_frame_, user_data_);
+ it->second->received_headers = true;
+}
+
+void CallbackVisitor::OnHeaderForStream(Http2StreamId stream_id,
+ absl::string_view name,
+ absl::string_view value) {
+ callbacks_->on_header_callback(
+ nullptr, &current_frame_, ToUint8Ptr(name.data()), name.size(),
+ ToUint8Ptr(value.data()), value.size(), NGHTTP2_NV_FLAG_NONE, user_data_);
+}
+
+void CallbackVisitor::OnEndHeadersForStream(Http2StreamId stream_id) {
+ callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
+}
+
+void CallbackVisitor::OnBeginDataForStream(Http2StreamId stream_id,
+ size_t payload_length) {
+ // TODO(b/181586191): Interpret padding, subtract padding from
+ // |remaining_data_|.
+ remaining_data_ = payload_length;
+ if (remaining_data_ == 0) {
+ callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
+ }
+}
+
+void CallbackVisitor::OnDataForStream(Http2StreamId stream_id,
+ absl::string_view data) {
+ callbacks_->on_data_chunk_recv_callback(nullptr, current_frame_.hd.flags,
+ stream_id, ToUint8Ptr(data.data()),
+ data.size(), user_data_);
+ remaining_data_ -= data.size();
+ if (remaining_data_ == 0) {
+ callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
+ }
+}
+
+void CallbackVisitor::OnEndStream(Http2StreamId stream_id) {}
+
+void CallbackVisitor::OnRstStream(Http2StreamId stream_id,
+ Http2ErrorCode error_code) {
+ current_frame_.rst_stream.error_code = static_cast<uint32_t>(error_code);
+ callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
+}
+
+void CallbackVisitor::OnCloseStream(Http2StreamId stream_id,
+ Http2ErrorCode error_code) {
+ callbacks_->on_stream_close_callback(
+ nullptr, stream_id, static_cast<uint32_t>(error_code), user_data_);
+}
+
+void CallbackVisitor::OnPriorityForStream(Http2StreamId stream_id,
+ Http2StreamId parent_stream_id,
+ int weight,
+ bool exclusive) {
+ current_frame_.priority.pri_spec.stream_id = parent_stream_id;
+ current_frame_.priority.pri_spec.weight = weight;
+ current_frame_.priority.pri_spec.exclusive = exclusive;
+ callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
+}
+
+void CallbackVisitor::OnPing(Http2PingId ping_id, bool is_ack) {
+ uint64_t network_order_opaque_data =
+ quiche::QuicheEndian::HostToNet64(ping_id);
+ std::memcpy(current_frame_.ping.opaque_data, &network_order_opaque_data,
+ sizeof(network_order_opaque_data));
+ callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
+}
+
+void CallbackVisitor::OnPushPromiseForStream(Http2StreamId stream_id,
+ Http2StreamId promised_stream_id) {
+ QUICHE_LOG(FATAL) << "Not implemented";
+}
+
+void CallbackVisitor::OnGoAway(Http2StreamId last_accepted_stream_id,
+ Http2ErrorCode error_code,
+ absl::string_view opaque_data) {
+ current_frame_.goaway.last_stream_id = last_accepted_stream_id;
+ current_frame_.goaway.error_code = static_cast<uint32_t>(error_code);
+ current_frame_.goaway.opaque_data = ToUint8Ptr(opaque_data.data());
+ current_frame_.goaway.opaque_data_len = opaque_data.size();
+ callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
+}
+
+void CallbackVisitor::OnWindowUpdate(Http2StreamId stream_id,
+ int window_increment) {
+ current_frame_.window_update.window_size_increment = window_increment;
+ callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
+}
+
+void CallbackVisitor::OnReadyToSendDataForStream(Http2StreamId stream_id,
+ char* destination_buffer,
+ size_t length,
+ ssize_t* written,
+ bool* end_stream) {
+ QUICHE_LOG(FATAL) << "Not implemented";
+}
+
+void CallbackVisitor::OnReadyToSendMetadataForStream(Http2StreamId stream_id,
+ char* buffer,
+ size_t length,
+ ssize_t* written) {
+ QUICHE_LOG(FATAL) << "Not implemented";
+}
+
+void CallbackVisitor::OnBeginMetadataForStream(Http2StreamId stream_id,
+ size_t payload_length) {
+ QUICHE_LOG(FATAL) << "Not implemented";
+}
+
+void CallbackVisitor::OnMetadataForStream(Http2StreamId stream_id,
+ absl::string_view metadata) {
+ QUICHE_LOG(FATAL) << "Not implemented";
+}
+
+void CallbackVisitor::OnMetadataEndForStream(Http2StreamId stream_id) {
+ QUICHE_LOG(FATAL) << "Not implemented";
+}
+
+} // namespace adapter
+} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/callback_visitor.h b/chromium/net/third_party/quiche/src/http2/adapter/callback_visitor.h
new file mode 100644
index 00000000000..94746bf8edb
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/callback_visitor.h
@@ -0,0 +1,92 @@
+#ifndef QUICHE_HTTP2_ADAPTER_CALLBACK_VISITOR_H_
+#define QUICHE_HTTP2_ADAPTER_CALLBACK_VISITOR_H_
+
+#include <memory>
+#include <vector>
+
+#include "absl/container/flat_hash_map.h"
+#include "http2/adapter/http2_visitor_interface.h"
+#include "http2/adapter/nghttp2_util.h"
+#include "third_party/nghttp2/src/lib/includes/nghttp2/nghttp2.h"
+
+namespace http2 {
+namespace adapter {
+
+// This visitor implementation accepts a set of nghttp2 callbacks and a "user
+// data" pointer, and invokes the callbacks according to HTTP/2 events received.
+class CallbackVisitor : public Http2VisitorInterface {
+ public:
+ explicit CallbackVisitor(Perspective perspective,
+ nghttp2_session_callbacks_unique_ptr callbacks,
+ void* user_data)
+ : perspective_(perspective),
+ callbacks_(std::move(callbacks)),
+ user_data_(user_data) {}
+
+ void OnConnectionError() override;
+ void OnFrameHeader(Http2StreamId stream_id,
+ size_t length,
+ uint8_t type,
+ uint8_t flags) override;
+ void OnSettingsStart() override;
+ void OnSetting(Http2Setting setting) override;
+ void OnSettingsEnd() override;
+ void OnSettingsAck() override;
+ void OnBeginHeadersForStream(Http2StreamId stream_id) override;
+ void OnHeaderForStream(Http2StreamId stream_id,
+ absl::string_view name,
+ absl::string_view value) override;
+ void OnEndHeadersForStream(Http2StreamId stream_id) override;
+ void OnBeginDataForStream(Http2StreamId stream_id,
+ size_t payload_length) override;
+ void OnDataForStream(Http2StreamId stream_id,
+ absl::string_view data) override;
+ void OnEndStream(Http2StreamId stream_id) override;
+ void OnRstStream(Http2StreamId stream_id, Http2ErrorCode error_code) override;
+ void OnCloseStream(Http2StreamId stream_id,
+ Http2ErrorCode error_code) override;
+ void OnPriorityForStream(Http2StreamId stream_id,
+ Http2StreamId parent_stream_id,
+ int weight,
+ bool exclusive) override;
+ void OnPing(Http2PingId ping_id, bool is_ack) override;
+ void OnPushPromiseForStream(Http2StreamId stream_id,
+ Http2StreamId promised_stream_id) override;
+ void OnGoAway(Http2StreamId last_accepted_stream_id,
+ Http2ErrorCode error_code,
+ absl::string_view opaque_data) override;
+ void OnWindowUpdate(Http2StreamId stream_id, int window_increment) override;
+ void OnReadyToSendDataForStream(Http2StreamId stream_id,
+ char* destination_buffer,
+ size_t length,
+ ssize_t* written,
+ bool* end_stream) override;
+ void OnReadyToSendMetadataForStream(Http2StreamId stream_id,
+ char* buffer,
+ size_t length,
+ ssize_t* written) override;
+ void OnBeginMetadataForStream(Http2StreamId stream_id,
+ size_t payload_length) override;
+ void OnMetadataForStream(Http2StreamId stream_id,
+ absl::string_view metadata) override;
+ void OnMetadataEndForStream(Http2StreamId stream_id) override;
+
+ private:
+ Perspective perspective_;
+ nghttp2_session_callbacks_unique_ptr callbacks_;
+ void* user_data_;
+
+ nghttp2_frame current_frame_;
+ std::vector<nghttp2_settings_entry> settings_;
+ size_t remaining_data_ = 0;
+
+ struct StreamInfo {
+ bool received_headers = false;
+ };
+ absl::flat_hash_map<Http2StreamId, std::unique_ptr<StreamInfo>> stream_map_;
+};
+
+} // namespace adapter
+} // namespace http2
+
+#endif // QUICHE_HTTP2_ADAPTER_CALLBACK_VISITOR_H_
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/callback_visitor_test.cc b/chromium/net/third_party/quiche/src/http2/adapter/callback_visitor_test.cc
new file mode 100644
index 00000000000..4dfcb5fcddb
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/callback_visitor_test.cc
@@ -0,0 +1,260 @@
+#include "http2/adapter/callback_visitor.h"
+
+#include "http2/adapter/mock_nghttp2_callbacks.h"
+#include "http2/adapter/test_utils.h"
+#include "common/platform/api/quiche_test.h"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+namespace {
+
+using testing::_;
+
+enum FrameType {
+ DATA,
+ HEADERS,
+ PRIORITY,
+ RST_STREAM,
+ SETTINGS,
+ PUSH_PROMISE,
+ PING,
+ GOAWAY,
+ WINDOW_UPDATE,
+};
+
+// Tests connection-level events.
+TEST(ClientCallbackVisitorUnitTest, ConnectionFrames) {
+ testing::StrictMock<MockNghttp2Callbacks> callbacks;
+ CallbackVisitor visitor(Perspective::kClient,
+ MockNghttp2Callbacks::GetCallbacks(), &callbacks);
+
+ testing::InSequence seq;
+
+ // SETTINGS
+ EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(0, SETTINGS, _)));
+ visitor.OnFrameHeader(0, 0, SETTINGS, 0);
+
+ visitor.OnSettingsStart();
+ EXPECT_CALL(callbacks, OnFrameRecv(IsSettings(testing::IsEmpty())));
+ visitor.OnSettingsEnd();
+
+ // PING
+ EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(0, PING, _)));
+ visitor.OnFrameHeader(0, 8, PING, 0);
+
+ EXPECT_CALL(callbacks, OnFrameRecv(IsPing(42)));
+ visitor.OnPing(42, false);
+
+ // WINDOW_UPDATE
+ EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(0, WINDOW_UPDATE, _)));
+ visitor.OnFrameHeader(0, 4, WINDOW_UPDATE, 0);
+
+ EXPECT_CALL(callbacks, OnFrameRecv(IsWindowUpdate(1000)));
+ visitor.OnWindowUpdate(0, 1000);
+
+ // PING ack
+ EXPECT_CALL(callbacks,
+ OnBeginFrame(HasFrameHeader(0, PING, NGHTTP2_FLAG_ACK)));
+ visitor.OnFrameHeader(0, 8, PING, 1);
+
+ EXPECT_CALL(callbacks, OnFrameRecv(IsPingAck(247)));
+ visitor.OnPing(247, true);
+
+ // GOAWAY
+ EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(0, GOAWAY, 0)));
+ visitor.OnFrameHeader(0, 19, GOAWAY, 0);
+
+ EXPECT_CALL(callbacks, OnFrameRecv(IsGoAway(5, NGHTTP2_ENHANCE_YOUR_CALM,
+ "calm down!!")));
+ visitor.OnGoAway(5, Http2ErrorCode::ENHANCE_YOUR_CALM, "calm down!!");
+}
+
+TEST(ClientCallbackVisitorUnitTest, StreamFrames) {
+ testing::StrictMock<MockNghttp2Callbacks> callbacks;
+ CallbackVisitor visitor(Perspective::kClient,
+ MockNghttp2Callbacks::GetCallbacks(), &callbacks);
+
+ testing::InSequence seq;
+
+ // HEADERS on stream 1
+ EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(1, HEADERS, _)));
+ visitor.OnFrameHeader(1, 23, HEADERS, 4);
+
+ EXPECT_CALL(callbacks,
+ OnBeginHeaders(IsHeaders(1, _, NGHTTP2_HCAT_RESPONSE)));
+ visitor.OnBeginHeadersForStream(1);
+
+ EXPECT_CALL(callbacks, OnHeader(_, ":status", "200", _));
+ visitor.OnHeaderForStream(1, ":status", "200");
+
+ EXPECT_CALL(callbacks, OnHeader(_, "server", "my-fake-server", _));
+ visitor.OnHeaderForStream(1, "server", "my-fake-server");
+
+ EXPECT_CALL(callbacks,
+ OnHeader(_, "date", "Tue, 6 Apr 2021 12:54:01 GMT", _));
+ visitor.OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT");
+
+ EXPECT_CALL(callbacks, OnHeader(_, "trailer", "x-server-status", _));
+ visitor.OnHeaderForStream(1, "trailer", "x-server-status");
+
+ EXPECT_CALL(callbacks, OnFrameRecv(IsHeaders(1, _, NGHTTP2_HCAT_RESPONSE)));
+ visitor.OnEndHeadersForStream(1);
+
+ // DATA for stream 1
+ EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(1, DATA, 0)));
+ visitor.OnFrameHeader(1, 26, DATA, 0);
+
+ visitor.OnBeginDataForStream(1, 26);
+ EXPECT_CALL(callbacks, OnDataChunkRecv(0, 1, "This is the response body."));
+ EXPECT_CALL(callbacks, OnFrameRecv(IsData(1, _, 0)));
+ visitor.OnDataForStream(1, "This is the response body.");
+
+ // Trailers for stream 1, with a different nghttp2 "category".
+ EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(1, HEADERS, _)));
+ visitor.OnFrameHeader(1, 23, HEADERS, 4);
+
+ EXPECT_CALL(callbacks, OnBeginHeaders(IsHeaders(1, _, NGHTTP2_HCAT_HEADERS)));
+ visitor.OnBeginHeadersForStream(1);
+
+ EXPECT_CALL(callbacks, OnHeader(_, "x-server-status", "OK", _));
+ visitor.OnHeaderForStream(1, "x-server-status", "OK");
+
+ EXPECT_CALL(callbacks, OnFrameRecv(IsHeaders(1, _, NGHTTP2_HCAT_HEADERS)));
+ visitor.OnEndHeadersForStream(1);
+
+ // RST_STREAM on stream 3
+ EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(3, RST_STREAM, 0)));
+ visitor.OnFrameHeader(3, 4, RST_STREAM, 0);
+
+ EXPECT_CALL(callbacks, OnFrameRecv(IsRstStream(3, NGHTTP2_INTERNAL_ERROR)));
+ visitor.OnRstStream(3, Http2ErrorCode::INTERNAL_ERROR);
+
+ EXPECT_CALL(callbacks, OnStreamClose(3, NGHTTP2_INTERNAL_ERROR));
+ visitor.OnCloseStream(3, Http2ErrorCode::INTERNAL_ERROR);
+
+ // More stream close events
+ EXPECT_CALL(callbacks,
+ OnBeginFrame(HasFrameHeader(1, DATA, NGHTTP2_FLAG_END_STREAM)));
+ visitor.OnFrameHeader(1, 0, DATA, 1);
+
+ EXPECT_CALL(callbacks, OnFrameRecv(IsData(1, _, NGHTTP2_FLAG_END_STREAM)));
+ visitor.OnBeginDataForStream(1, 0);
+ visitor.OnEndStream(1);
+
+ EXPECT_CALL(callbacks, OnStreamClose(1, NGHTTP2_NO_ERROR));
+ visitor.OnCloseStream(1, Http2ErrorCode::NO_ERROR);
+
+ EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(5, RST_STREAM, _)));
+ visitor.OnFrameHeader(5, 4, RST_STREAM, 0);
+
+ EXPECT_CALL(callbacks, OnFrameRecv(IsRstStream(5, NGHTTP2_REFUSED_STREAM)));
+ visitor.OnRstStream(5, Http2ErrorCode::REFUSED_STREAM);
+
+ EXPECT_CALL(callbacks, OnStreamClose(5, NGHTTP2_REFUSED_STREAM));
+ visitor.OnCloseStream(5, Http2ErrorCode::REFUSED_STREAM);
+}
+
+TEST(ServerCallbackVisitorUnitTest, ConnectionFrames) {
+ testing::StrictMock<MockNghttp2Callbacks> callbacks;
+ CallbackVisitor visitor(Perspective::kServer,
+ MockNghttp2Callbacks::GetCallbacks(), &callbacks);
+
+ testing::InSequence seq;
+
+ // SETTINGS
+ EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(0, SETTINGS, _)));
+ visitor.OnFrameHeader(0, 0, SETTINGS, 0);
+
+ visitor.OnSettingsStart();
+ EXPECT_CALL(callbacks, OnFrameRecv(IsSettings(testing::IsEmpty())));
+ visitor.OnSettingsEnd();
+
+ // PING
+ EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(0, PING, _)));
+ visitor.OnFrameHeader(0, 8, PING, 0);
+
+ EXPECT_CALL(callbacks, OnFrameRecv(IsPing(42)));
+ visitor.OnPing(42, false);
+
+ // WINDOW_UPDATE
+ EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(0, WINDOW_UPDATE, _)));
+ visitor.OnFrameHeader(0, 4, WINDOW_UPDATE, 0);
+
+ EXPECT_CALL(callbacks, OnFrameRecv(IsWindowUpdate(1000)));
+ visitor.OnWindowUpdate(0, 1000);
+
+ // PING ack
+ EXPECT_CALL(callbacks,
+ OnBeginFrame(HasFrameHeader(0, PING, NGHTTP2_FLAG_ACK)));
+ visitor.OnFrameHeader(0, 8, PING, 1);
+
+ EXPECT_CALL(callbacks, OnFrameRecv(IsPingAck(247)));
+ visitor.OnPing(247, true);
+}
+
+TEST(ServerCallbackVisitorUnitTest, StreamFrames) {
+ testing::StrictMock<MockNghttp2Callbacks> callbacks;
+ CallbackVisitor visitor(Perspective::kServer,
+ MockNghttp2Callbacks::GetCallbacks(), &callbacks);
+
+ testing::InSequence seq;
+
+ // HEADERS on stream 1
+ EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(
+ 1, HEADERS, NGHTTP2_FLAG_END_HEADERS)));
+ visitor.OnFrameHeader(1, 23, HEADERS, 4);
+
+ EXPECT_CALL(callbacks, OnBeginHeaders(IsHeaders(1, NGHTTP2_FLAG_END_HEADERS,
+ NGHTTP2_HCAT_REQUEST)));
+ visitor.OnBeginHeadersForStream(1);
+
+ EXPECT_CALL(callbacks, OnHeader(_, ":method", "POST", _));
+ visitor.OnHeaderForStream(1, ":method", "POST");
+
+ EXPECT_CALL(callbacks, OnHeader(_, ":path", "/example/path", _));
+ visitor.OnHeaderForStream(1, ":path", "/example/path");
+
+ EXPECT_CALL(callbacks, OnHeader(_, ":scheme", "https", _));
+ visitor.OnHeaderForStream(1, ":scheme", "https");
+
+ EXPECT_CALL(callbacks, OnHeader(_, ":authority", "example.com", _));
+ visitor.OnHeaderForStream(1, ":authority", "example.com");
+
+ EXPECT_CALL(callbacks, OnHeader(_, "accept", "text/html", _));
+ visitor.OnHeaderForStream(1, "accept", "text/html");
+
+ EXPECT_CALL(callbacks, OnFrameRecv(IsHeaders(1, NGHTTP2_FLAG_END_HEADERS,
+ NGHTTP2_HCAT_REQUEST)));
+ visitor.OnEndHeadersForStream(1);
+
+ // DATA on stream 1
+ EXPECT_CALL(callbacks,
+ OnBeginFrame(HasFrameHeader(1, DATA, NGHTTP2_FLAG_END_STREAM)));
+ visitor.OnFrameHeader(1, 25, DATA, NGHTTP2_FLAG_END_STREAM);
+
+ visitor.OnBeginDataForStream(1, 25);
+ EXPECT_CALL(callbacks, OnDataChunkRecv(NGHTTP2_FLAG_END_STREAM, 1,
+ "This is the request body."));
+ EXPECT_CALL(callbacks, OnFrameRecv(IsData(1, _, NGHTTP2_FLAG_END_STREAM)));
+ visitor.OnDataForStream(1, "This is the request body.");
+ visitor.OnEndStream(1);
+
+ EXPECT_CALL(callbacks, OnStreamClose(1, NGHTTP2_NO_ERROR));
+ visitor.OnCloseStream(1, Http2ErrorCode::NO_ERROR);
+
+ // RST_STREAM on stream 3
+ EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(3, RST_STREAM, 0)));
+ visitor.OnFrameHeader(3, 4, RST_STREAM, 0);
+
+ EXPECT_CALL(callbacks, OnFrameRecv(IsRstStream(3, NGHTTP2_INTERNAL_ERROR)));
+ visitor.OnRstStream(3, Http2ErrorCode::INTERNAL_ERROR);
+
+ EXPECT_CALL(callbacks, OnStreamClose(3, NGHTTP2_INTERNAL_ERROR));
+ visitor.OnCloseStream(3, Http2ErrorCode::INTERNAL_ERROR);
+}
+
+} // namespace
+} // namespace test
+} // namespace adapter
+} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/data_source.cc b/chromium/net/third_party/quiche/src/http2/adapter/data_source.cc
new file mode 100644
index 00000000000..13f89d28581
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/data_source.cc
@@ -0,0 +1,23 @@
+#include "http2/adapter/data_source.h"
+
+namespace http2 {
+namespace adapter {
+
+StringDataSource::StringDataSource(std::string data)
+ : data_(std::move(data)), remaining_(data_) {
+ state_ = remaining_.empty() ? DONE : READY;
+}
+
+absl::string_view StringDataSource::NextData() const {
+ return remaining_;
+}
+
+void StringDataSource::Consume(size_t bytes) {
+ remaining_.remove_prefix(std::min(bytes, remaining_.size()));
+ if (remaining_.empty()) {
+ state_ = DONE;
+ }
+}
+
+} // namespace adapter
+} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/data_source.h b/chromium/net/third_party/quiche/src/http2/adapter/data_source.h
new file mode 100644
index 00000000000..e170104a597
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/data_source.h
@@ -0,0 +1,53 @@
+#ifndef QUICHE_HTTP2_ADAPTER_DATA_SOURCE_H_
+#define QUICHE_HTTP2_ADAPTER_DATA_SOURCE_H_
+
+#include <string>
+
+#include "absl/strings/string_view.h"
+
+namespace http2 {
+namespace adapter {
+
+// Represents a HTTP message body.
+class DataSource {
+ public:
+ virtual ~DataSource() {}
+
+ enum State {
+ // The source is not done, but cannot currently provide more data.
+ NOT_READY,
+ // The source can provide more data.
+ READY,
+ // The source is done.
+ DONE,
+ };
+
+ State state() const { return state_; }
+
+ // The next range of data provided by this data source.
+ virtual absl::string_view NextData() const = 0;
+
+ // Indicates that |bytes| bytes have been consumed by the caller.
+ virtual void Consume(size_t bytes) = 0;
+
+ protected:
+ State state_ = NOT_READY;
+};
+
+// A simple implementation constructible from a string_view or std::string.
+class StringDataSource : public DataSource {
+ public:
+ explicit StringDataSource(std::string data);
+
+ absl::string_view NextData() const override;
+ void Consume(size_t bytes) override;
+
+ private:
+ const std::string data_;
+ absl::string_view remaining_;
+};
+
+} // namespace adapter
+} // namespace http2
+
+#endif // QUICHE_HTTP2_ADAPTER_DATA_SOURCE_H_
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/data_source_test.cc b/chromium/net/third_party/quiche/src/http2/adapter/data_source_test.cc
new file mode 100644
index 00000000000..c290124b430
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/data_source_test.cc
@@ -0,0 +1,40 @@
+#include "http2/adapter/data_source.h"
+
+#include "common/platform/api/quiche_test.h"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+namespace {
+
+TEST(StringDataSourceTest, EmptyString) {
+ StringDataSource source("");
+
+ EXPECT_EQ(source.state(), DataSource::DONE);
+ EXPECT_THAT(source.NextData(), testing::IsEmpty());
+}
+
+TEST(StringDataSourceTest, PartialConsume) {
+ StringDataSource source("I'm a HTTP message body. Really!");
+
+ EXPECT_EQ(source.state(), DataSource::READY);
+ EXPECT_THAT(source.NextData(), testing::Not(testing::IsEmpty()));
+ source.Consume(6);
+ EXPECT_EQ(source.state(), DataSource::READY);
+ EXPECT_THAT(source.NextData(), testing::StartsWith("HTTP"));
+
+ source.Consume(0);
+ EXPECT_EQ(source.state(), DataSource::READY);
+ EXPECT_THAT(source.NextData(), testing::StartsWith("HTTP"));
+
+ // Consumes more than the remaining bytes available.
+ source.Consume(50);
+ EXPECT_THAT(source.NextData(), testing::IsEmpty())
+ << "next data: " << source.NextData();
+ EXPECT_EQ(source.state(), DataSource::DONE);
+}
+
+} // namespace
+} // namespace test
+} // namespace adapter
+} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/http2_adapter.h b/chromium/net/third_party/quiche/src/http2/adapter/http2_adapter.h
index 5ea6045af22..ef2ae0a5baf 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/http2_adapter.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/http2_adapter.h
@@ -19,11 +19,6 @@ namespace adapter {
// implementations.
class Http2Adapter {
public:
- enum class Perspective {
- kClient,
- kServer,
- };
-
Http2Adapter(const Http2Adapter&) = delete;
Http2Adapter& operator=(const Http2Adapter&) = delete;
@@ -79,6 +74,10 @@ class Http2Adapter {
virtual void MarkDataConsumedForStream(Http2StreamId stream_id,
size_t num_bytes) = 0;
+ // Submits a RST_STREAM for the given stream.
+ virtual void SubmitRst(Http2StreamId stream_id,
+ Http2ErrorCode error_code) = 0;
+
protected:
// Subclasses should expose a public factory method for constructing and
// initializing (via Initialize()) adapter instances.
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/http2_protocol.cc b/chromium/net/third_party/quiche/src/http2/adapter/http2_protocol.cc
index 18e8985ff4b..8d59aeedda0 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/http2_protocol.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/http2_protocol.cc
@@ -12,6 +12,15 @@ const char kHttp2AuthorityPseudoHeader[] = ":authority";
const char kHttp2PathPseudoHeader[] = ":path";
const char kHttp2StatusPseudoHeader[] = ":status";
+std::pair<absl::string_view, bool> GetStringView(const HeaderRep& rep) {
+ if (absl::holds_alternative<absl::string_view>(rep)) {
+ return std::make_pair(absl::get<absl::string_view>(rep), true);
+ } else {
+ absl::string_view view = absl::get<std::string>(rep);
+ return std::make_pair(view, false);
+ }
+}
+
absl::string_view Http2SettingsIdToString(uint16_t id) {
switch (id) {
case Http2KnownSettingsId::HEADER_TABLE_SIZE:
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/http2_protocol.h b/chromium/net/third_party/quiche/src/http2/adapter/http2_protocol.h
index 49e5f161620..1e1dd39a21a 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/http2_protocol.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/http2_protocol.h
@@ -8,6 +8,7 @@
#include "base/integral_types.h"
#include "absl/base/attributes.h"
#include "absl/strings/string_view.h"
+#include "absl/types/variant.h"
namespace http2 {
namespace adapter {
@@ -21,9 +22,16 @@ using Http2SettingsId = uint16_t;
// Represents the payload of an HTTP/2 PING frame.
using Http2PingId = uint64_t;
+// Represents a single header name or value.
+using HeaderRep = absl::variant<absl::string_view, std::string>;
+
+// Boolean return value is true if |rep| holds a string_view, which is assumed
+// to have an indefinite lifetime.
+std::pair<absl::string_view, bool> GetStringView(const HeaderRep& rep);
+
// Represents an HTTP/2 header field. A header field is a key-value pair with
// lowercase keys (as specified in RFC 7540 Section 8.1.2).
-using Header = std::pair<std::string, std::string>;
+using Header = std::pair<HeaderRep, HeaderRep>;
// Represents an HTTP/2 SETTINGS key-value parameter.
struct Http2Setting {
@@ -99,6 +107,11 @@ absl::string_view Http2SettingsIdToString(uint16_t id);
// Section 7 definitions.
absl::string_view Http2ErrorCodeToString(Http2ErrorCode error_code);
+enum class Perspective {
+ kClient,
+ kServer,
+};
+
} // namespace adapter
} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/http2_session.h b/chromium/net/third_party/quiche/src/http2/adapter/http2_session.h
index ddbed4477b5..0a6321c0ccc 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/http2_session.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/http2_session.h
@@ -26,15 +26,6 @@ class Http2Session {
virtual int GetRemoteWindowSize() const = 0;
};
-class Http2Options {
- public:
- Http2Options() = default;
- virtual ~Http2Options() {}
-
- // This method returns an opaque reference to the underlying type.
- virtual void* GetOptions() = 0;
-};
-
} // namespace adapter
} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/http2_util.cc b/chromium/net/third_party/quiche/src/http2/adapter/http2_util.cc
index 40deeb29332..e054a82e4ca 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/http2_util.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/http2_util.cc
@@ -36,5 +36,38 @@ spdy::SpdyErrorCode TranslateErrorCode(Http2ErrorCode code) {
}
}
+Http2ErrorCode TranslateErrorCode(spdy::SpdyErrorCode code) {
+ switch (code) {
+ case spdy::ERROR_CODE_NO_ERROR:
+ return Http2ErrorCode::NO_ERROR;
+ case spdy::ERROR_CODE_PROTOCOL_ERROR:
+ return Http2ErrorCode::PROTOCOL_ERROR;
+ case spdy::ERROR_CODE_INTERNAL_ERROR:
+ return Http2ErrorCode::INTERNAL_ERROR;
+ case spdy::ERROR_CODE_FLOW_CONTROL_ERROR:
+ return Http2ErrorCode::FLOW_CONTROL_ERROR;
+ case spdy::ERROR_CODE_SETTINGS_TIMEOUT:
+ return Http2ErrorCode::SETTINGS_TIMEOUT;
+ case spdy::ERROR_CODE_STREAM_CLOSED:
+ return Http2ErrorCode::STREAM_CLOSED;
+ case spdy::ERROR_CODE_FRAME_SIZE_ERROR:
+ return Http2ErrorCode::FRAME_SIZE_ERROR;
+ case spdy::ERROR_CODE_REFUSED_STREAM:
+ return Http2ErrorCode::REFUSED_STREAM;
+ case spdy::ERROR_CODE_CANCEL:
+ return Http2ErrorCode::CANCEL;
+ case spdy::ERROR_CODE_COMPRESSION_ERROR:
+ return Http2ErrorCode::COMPRESSION_ERROR;
+ case spdy::ERROR_CODE_CONNECT_ERROR:
+ return Http2ErrorCode::CONNECT_ERROR;
+ case spdy::ERROR_CODE_ENHANCE_YOUR_CALM:
+ return Http2ErrorCode::ENHANCE_YOUR_CALM;
+ case spdy::ERROR_CODE_INADEQUATE_SECURITY:
+ return Http2ErrorCode::INADEQUATE_SECURITY;
+ case spdy::ERROR_CODE_HTTP_1_1_REQUIRED:
+ return Http2ErrorCode::HTTP_1_1_REQUIRED;
+ }
+}
+
} // namespace adapter
} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/http2_util.h b/chromium/net/third_party/quiche/src/http2/adapter/http2_util.h
index e9ae2a59561..3ace28b2ce9 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/http2_util.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/http2_util.h
@@ -8,6 +8,7 @@ namespace http2 {
namespace adapter {
spdy::SpdyErrorCode TranslateErrorCode(Http2ErrorCode code);
+Http2ErrorCode TranslateErrorCode(spdy::SpdyErrorCode code);
} // namespace adapter
} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/http2_visitor_interface.h b/chromium/net/third_party/quiche/src/http2/adapter/http2_visitor_interface.h
index 765e9f43896..12729e75651 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/http2_visitor_interface.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/http2_visitor_interface.h
@@ -34,7 +34,7 @@ namespace adapter {
// - OnHeaderForStream()
// - OnEndHeadersForStream()
// - OnRstStream()
-// - OnAbortStream()
+// - OnCloseStream()
//
// Request closed mid-stream, e.g., with error code NO_ERROR:
// - OnBeginHeadersForStream()
@@ -43,8 +43,7 @@ namespace adapter {
// - OnRstStream()
// - OnCloseStream()
//
-// More details are at RFC 7540 (go/http2spec), and more examples are at
-// http://google3/net/http2/server/lib/internal/h2/nghttp2/nghttp2_server_adapter_test.cc.
+// More details are at RFC 7540 (go/http2spec).
class Http2VisitorInterface {
public:
Http2VisitorInterface(const Http2VisitorInterface&) = delete;
@@ -54,6 +53,12 @@ class Http2VisitorInterface {
// Called when a connection-level processing error has been encountered.
virtual void OnConnectionError() = 0;
+ // Called when the header for a frame is received.
+ virtual void OnFrameHeader(Http2StreamId stream_id,
+ size_t length,
+ uint8_t type,
+ uint8_t flags) {}
+
// Called when a non-ack SETTINGS frame is received.
virtual void OnSettingsStart() = 0;
@@ -97,18 +102,12 @@ class Http2VisitorInterface {
virtual void OnEndStream(Http2StreamId stream_id) = 0;
// Called when the connection receives a RST_STREAM for a stream. This call
- // will be followed by either OnCloseStream() or OnAbortStream().
+ // will be followed by either OnCloseStream().
virtual void OnRstStream(Http2StreamId stream_id,
Http2ErrorCode error_code) = 0;
- // Called when a stream is closed with error code NO_ERROR. Compare with
- // OnAbortStream().
- virtual void OnCloseStream(Http2StreamId stream_id) = 0;
-
- // Called when a stream is aborted, i.e., closed for the reason indicated by
- // the given |error_code|, where error_code != NO_ERROR. Compare with
- // OnCloseStream().
- virtual void OnAbortStream(Http2StreamId stream_id,
+ // Called when a stream is closed.
+ virtual void OnCloseStream(Http2StreamId stream_id,
Http2ErrorCode error_code) = 0;
// Called when the connection receives a PRIORITY frame.
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/mock_http2_visitor.h b/chromium/net/third_party/quiche/src/http2/adapter/mock_http2_visitor.h
index a5c83712fd7..171d40f443f 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/mock_http2_visitor.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/mock_http2_visitor.h
@@ -14,6 +14,11 @@ class MockHttp2Visitor : public Http2VisitorInterface {
MockHttp2Visitor() = default;
MOCK_METHOD(void, OnConnectionError, (), (override));
+ MOCK_METHOD(
+ void,
+ OnFrameHeader,
+ (Http2StreamId stream_id, size_t length, uint8_t type, uint8_t flags),
+ (override));
MOCK_METHOD(void, OnSettingsStart, (), (override));
MOCK_METHOD(void, OnSetting, (Http2Setting setting), (override));
MOCK_METHOD(void, OnSettingsEnd, (), (override));
@@ -52,10 +57,8 @@ class MockHttp2Visitor : public Http2VisitorInterface {
(Http2StreamId stream_id, Http2ErrorCode error_code),
(override));
- MOCK_METHOD(void, OnCloseStream, (Http2StreamId stream_id), (override));
-
MOCK_METHOD(void,
- OnAbortStream,
+ OnCloseStream,
(Http2StreamId stream_id, Http2ErrorCode error_code),
(override));
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/mock_nghttp2_callbacks.cc b/chromium/net/third_party/quiche/src/http2/adapter/mock_nghttp2_callbacks.cc
new file mode 100644
index 00000000000..4699a371add
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/mock_nghttp2_callbacks.cc
@@ -0,0 +1,123 @@
+#include "http2/adapter/mock_nghttp2_callbacks.h"
+
+#include "http2/adapter/nghttp2_util.h"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+
+/* static */
+nghttp2_session_callbacks_unique_ptr MockNghttp2Callbacks::GetCallbacks() {
+ nghttp2_session_callbacks* callbacks;
+ nghttp2_session_callbacks_new(&callbacks);
+
+ // All of the callback implementations below just delegate to the mock methods
+ // of |user_data|, which is assumed to be a MockNghttp2Callbacks*.
+ nghttp2_session_callbacks_set_send_callback(
+ callbacks,
+ [](nghttp2_session*, const uint8_t* data, size_t length, int flags,
+ void* user_data) -> ssize_t {
+ return static_cast<MockNghttp2Callbacks*>(user_data)->Send(data, length,
+ flags);
+ });
+
+ nghttp2_session_callbacks_set_send_data_callback(
+ callbacks,
+ [](nghttp2_session*, nghttp2_frame* frame, const uint8_t* framehd,
+ size_t length, nghttp2_data_source* source, void* user_data) -> int {
+ return static_cast<MockNghttp2Callbacks*>(user_data)->SendData(
+ frame, framehd, length, source);
+ });
+
+ nghttp2_session_callbacks_set_on_begin_headers_callback(
+ callbacks,
+ [](nghttp2_session*, const nghttp2_frame* frame, void* user_data) -> int {
+ return static_cast<MockNghttp2Callbacks*>(user_data)->OnBeginHeaders(
+ frame);
+ });
+
+ nghttp2_session_callbacks_set_on_header_callback(
+ callbacks,
+ [](nghttp2_session*, const nghttp2_frame* frame, const uint8_t* raw_name,
+ size_t name_length, const uint8_t* raw_value, size_t value_length,
+ uint8_t flags, void* user_data) -> int {
+ absl::string_view name = ToStringView(raw_name, name_length);
+ absl::string_view value = ToStringView(raw_value, value_length);
+ return static_cast<MockNghttp2Callbacks*>(user_data)->OnHeader(
+ frame, name, value, flags);
+ });
+
+ nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
+ callbacks,
+ [](nghttp2_session*, uint8_t flags, int32_t stream_id,
+ const uint8_t* data, size_t len, void* user_data) -> int {
+ absl::string_view chunk = ToStringView(data, len);
+ return static_cast<MockNghttp2Callbacks*>(user_data)->OnDataChunkRecv(
+ flags, stream_id, chunk);
+ });
+
+ nghttp2_session_callbacks_set_on_begin_frame_callback(
+ callbacks,
+ [](nghttp2_session*, const nghttp2_frame_hd* hd, void* user_data) -> int {
+ return static_cast<MockNghttp2Callbacks*>(user_data)->OnBeginFrame(hd);
+ });
+
+ nghttp2_session_callbacks_set_on_frame_recv_callback(
+ callbacks,
+ [](nghttp2_session*, const nghttp2_frame* frame, void* user_data) -> int {
+ return static_cast<MockNghttp2Callbacks*>(user_data)->OnFrameRecv(
+ frame);
+ });
+
+ nghttp2_session_callbacks_set_on_stream_close_callback(
+ callbacks,
+ [](nghttp2_session*, int32_t stream_id, uint32_t error_code,
+ void* user_data) -> int {
+ return static_cast<MockNghttp2Callbacks*>(user_data)->OnStreamClose(
+ stream_id, error_code);
+ });
+
+ nghttp2_session_callbacks_set_on_frame_send_callback(
+ callbacks,
+ [](nghttp2_session*, const nghttp2_frame* frame, void* user_data) -> int {
+ return static_cast<MockNghttp2Callbacks*>(user_data)->OnFrameSend(
+ frame);
+ });
+
+ nghttp2_session_callbacks_set_before_frame_send_callback(
+ callbacks,
+ [](nghttp2_session*, const nghttp2_frame* frame, void* user_data) -> int {
+ return static_cast<MockNghttp2Callbacks*>(user_data)->BeforeFrameSend(
+ frame);
+ });
+
+ nghttp2_session_callbacks_set_on_frame_not_send_callback(
+ callbacks,
+ [](nghttp2_session*, const nghttp2_frame* frame, int lib_error_code,
+ void* user_data) -> int {
+ return static_cast<MockNghttp2Callbacks*>(user_data)->OnFrameNotSend(
+ frame, lib_error_code);
+ });
+
+ nghttp2_session_callbacks_set_on_invalid_frame_recv_callback(
+ callbacks,
+ [](nghttp2_session*, const nghttp2_frame* frame, int error_code,
+ void* user_data) -> int {
+ return static_cast<MockNghttp2Callbacks*>(user_data)
+ ->OnInvalidFrameRecv(frame, error_code);
+ });
+
+ nghttp2_session_callbacks_set_error_callback2(
+ callbacks,
+ [](nghttp2_session* session, int lib_error_code, const char* msg,
+ size_t len, void* user_data) -> int {
+ return static_cast<MockNghttp2Callbacks*>(user_data)->OnErrorCallback2(
+ lib_error_code, msg, len);
+ });
+
+ return MakeCallbacksPtr(callbacks);
+}
+
+} // namespace test
+} // namespace adapter
+} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/mock_nghttp2_callbacks.h b/chromium/net/third_party/quiche/src/http2/adapter/mock_nghttp2_callbacks.h
new file mode 100644
index 00000000000..e2794575c8d
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/mock_nghttp2_callbacks.h
@@ -0,0 +1,80 @@
+#ifndef QUICHE_HTTP2_ADAPTER_MOCK_NGHTTP2_CALLBACKS_H_
+#define QUICHE_HTTP2_ADAPTER_MOCK_NGHTTP2_CALLBACKS_H_
+
+#include "absl/strings/string_view.h"
+#include "http2/adapter/nghttp2_util.h"
+#include "third_party/nghttp2/src/lib/includes/nghttp2/nghttp2.h"
+#include "common/platform/api/quiche_test.h"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+
+// This class provides a set of mock nghttp2 callbacks for use in unit test
+// expectations.
+class MockNghttp2Callbacks {
+ public:
+ MockNghttp2Callbacks() = default;
+
+ // The caller takes ownership of the |nghttp2_session_callbacks|.
+ static nghttp2_session_callbacks_unique_ptr GetCallbacks();
+
+ MOCK_METHOD(ssize_t,
+ Send,
+ (const uint8_t* data, size_t length, int flags),
+ ());
+
+ MOCK_METHOD(int,
+ SendData,
+ (nghttp2_frame * frame,
+ const uint8_t* framehd,
+ size_t length,
+ nghttp2_data_source* source),
+ ());
+
+ MOCK_METHOD(int, OnBeginHeaders, (const nghttp2_frame* frame), ());
+
+ MOCK_METHOD(int,
+ OnHeader,
+ (const nghttp2_frame* frame,
+ absl::string_view name,
+ absl::string_view value,
+ uint8_t flags),
+ ());
+
+ MOCK_METHOD(int,
+ OnDataChunkRecv,
+ (uint8_t flags, int32_t stream_id, absl::string_view data),
+ ());
+
+ MOCK_METHOD(int, OnBeginFrame, (const nghttp2_frame_hd* hd), ());
+
+ MOCK_METHOD(int, OnFrameRecv, (const nghttp2_frame* frame), ());
+
+ MOCK_METHOD(int, OnStreamClose, (int32_t stream_id, uint32_t error_code), ());
+
+ MOCK_METHOD(int, BeforeFrameSend, (const nghttp2_frame* frame), ());
+
+ MOCK_METHOD(int, OnFrameSend, (const nghttp2_frame* frame), ());
+
+ MOCK_METHOD(int,
+ OnFrameNotSend,
+ (const nghttp2_frame* frame, int lib_error_code),
+ ());
+
+ MOCK_METHOD(int,
+ OnInvalidFrameRecv,
+ (const nghttp2_frame* frame, int error_code),
+ ());
+
+ MOCK_METHOD(int,
+ OnErrorCallback2,
+ (int lib_error_code, const char* msg, size_t len),
+ ());
+};
+
+} // namespace test
+} // namespace adapter
+} // namespace http2
+
+#endif // QUICHE_HTTP2_ADAPTER_MOCK_NGHTTP2_CALLBACKS_H_
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter.cc b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter.cc
new file mode 100644
index 00000000000..878c040ef72
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter.cc
@@ -0,0 +1,149 @@
+#include "http2/adapter/nghttp2_adapter.h"
+
+#include "absl/algorithm/container.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "http2/adapter/nghttp2_callbacks.h"
+#include "third_party/nghttp2/src/lib/includes/nghttp2/nghttp2.h"
+#include "common/platform/api/quiche_logging.h"
+#include "common/quiche_endian.h"
+
+namespace http2 {
+namespace adapter {
+
+/* static */
+std::unique_ptr<NgHttp2Adapter> NgHttp2Adapter::CreateClientAdapter(
+ Http2VisitorInterface& visitor) {
+ auto adapter = new NgHttp2Adapter(visitor, Perspective::kClient);
+ adapter->Initialize();
+ return absl::WrapUnique(adapter);
+}
+
+/* static */
+std::unique_ptr<NgHttp2Adapter> NgHttp2Adapter::CreateServerAdapter(
+ Http2VisitorInterface& visitor) {
+ auto adapter = new NgHttp2Adapter(visitor, Perspective::kServer);
+ adapter->Initialize();
+ return absl::WrapUnique(adapter);
+}
+
+ssize_t NgHttp2Adapter::ProcessBytes(absl::string_view bytes) {
+ const ssize_t processed_bytes = session_->ProcessBytes(bytes);
+ if (processed_bytes < 0) {
+ visitor_.OnConnectionError();
+ }
+ return processed_bytes;
+}
+
+void NgHttp2Adapter::SubmitSettings(absl::Span<const Http2Setting> settings) {
+ // Submit SETTINGS, converting each Http2Setting to an nghttp2_settings_entry.
+ std::vector<nghttp2_settings_entry> nghttp2_settings;
+ absl::c_transform(settings, std::back_inserter(nghttp2_settings),
+ [](const Http2Setting& setting) {
+ return nghttp2_settings_entry{setting.id, setting.value};
+ });
+ nghttp2_submit_settings(session_->raw_ptr(), NGHTTP2_FLAG_NONE,
+ nghttp2_settings.data(), nghttp2_settings.size());
+}
+
+void NgHttp2Adapter::SubmitPriorityForStream(Http2StreamId stream_id,
+ Http2StreamId parent_stream_id,
+ int weight,
+ bool exclusive) {
+ nghttp2_priority_spec priority_spec;
+ nghttp2_priority_spec_init(&priority_spec, parent_stream_id, weight,
+ static_cast<int>(exclusive));
+ nghttp2_submit_priority(session_->raw_ptr(), NGHTTP2_FLAG_NONE, stream_id,
+ &priority_spec);
+}
+
+void NgHttp2Adapter::SubmitPing(Http2PingId ping_id) {
+ uint8_t opaque_data[8] = {};
+ Http2PingId ping_id_to_serialize = quiche::QuicheEndian::HostToNet64(ping_id);
+ std::memcpy(opaque_data, &ping_id_to_serialize, sizeof(Http2PingId));
+ nghttp2_submit_ping(session_->raw_ptr(), NGHTTP2_FLAG_NONE, opaque_data);
+}
+
+void NgHttp2Adapter::SubmitGoAway(Http2StreamId last_accepted_stream_id,
+ Http2ErrorCode error_code,
+ absl::string_view opaque_data) {
+ nghttp2_submit_goaway(session_->raw_ptr(), NGHTTP2_FLAG_NONE,
+ last_accepted_stream_id,
+ static_cast<uint32_t>(error_code),
+ ToUint8Ptr(opaque_data.data()), opaque_data.size());
+}
+
+void NgHttp2Adapter::SubmitWindowUpdate(Http2StreamId stream_id,
+ int window_increment) {
+ nghttp2_submit_window_update(session_->raw_ptr(), NGHTTP2_FLAG_NONE,
+ stream_id, window_increment);
+}
+
+void NgHttp2Adapter::SubmitMetadata(Http2StreamId stream_id,
+ bool end_metadata) {
+ QUICHE_LOG(DFATAL) << "Not implemented";
+}
+
+std::string NgHttp2Adapter::GetBytesToWrite(absl::optional<size_t> max_bytes) {
+ ssize_t num_bytes = 0;
+ std::string result;
+ do {
+ const uint8_t* data = nullptr;
+ num_bytes = nghttp2_session_mem_send(session_->raw_ptr(), &data);
+ if (num_bytes > 0) {
+ absl::StrAppend(
+ &result,
+ absl::string_view(reinterpret_cast<const char*>(data), num_bytes));
+ } else if (num_bytes < 0) {
+ visitor_.OnConnectionError();
+ }
+ } while (num_bytes > 0);
+ return result;
+}
+
+int NgHttp2Adapter::GetPeerConnectionWindow() const {
+ return session_->GetRemoteWindowSize();
+}
+
+void NgHttp2Adapter::MarkDataConsumedForStream(Http2StreamId stream_id,
+ size_t num_bytes) {
+ int rc = session_->Consume(stream_id, num_bytes);
+ if (rc != 0) {
+ QUICHE_LOG(ERROR) << "Error " << rc << " marking " << num_bytes
+ << " bytes consumed for stream " << stream_id;
+ }
+}
+
+void NgHttp2Adapter::SubmitRst(Http2StreamId stream_id,
+ Http2ErrorCode error_code) {
+ int status =
+ nghttp2_submit_rst_stream(session_->raw_ptr(), NGHTTP2_FLAG_NONE,
+ stream_id, static_cast<uint32_t>(error_code));
+ if (status < 0) {
+ QUICHE_LOG(WARNING) << "Reset stream failed: " << stream_id
+ << " with status code " << status;
+ }
+}
+
+NgHttp2Adapter::NgHttp2Adapter(Http2VisitorInterface& visitor,
+ Perspective perspective)
+ : Http2Adapter(visitor), visitor_(visitor), perspective_(perspective) {}
+
+NgHttp2Adapter::~NgHttp2Adapter() {}
+
+void NgHttp2Adapter::Initialize() {
+ nghttp2_option* options;
+ nghttp2_option_new(&options);
+ // Set some common options for compatibility.
+ nghttp2_option_set_no_closed_streams(options, 1);
+ nghttp2_option_set_no_auto_window_update(options, 1);
+ nghttp2_option_set_max_send_header_block_length(options, 0x2000000);
+ nghttp2_option_set_max_outbound_ack(options, 10000);
+
+ session_ =
+ absl::make_unique<NgHttp2Session>(perspective_, callbacks::Create(),
+ options, static_cast<void*>(&visitor_));
+}
+
+} // namespace adapter
+} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter.h b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter.h
new file mode 100644
index 00000000000..13c2ffcc3f4
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter.h
@@ -0,0 +1,97 @@
+#ifndef QUICHE_HTTP2_ADAPTER_NGHTTP2_ADAPTER_H_
+#define QUICHE_HTTP2_ADAPTER_NGHTTP2_ADAPTER_H_
+
+#include "http2/adapter/http2_adapter.h"
+#include "http2/adapter/http2_protocol.h"
+#include "http2/adapter/nghttp2_session.h"
+#include "http2/adapter/nghttp2_util.h"
+
+namespace http2 {
+namespace adapter {
+
+class NgHttp2Adapter : public Http2Adapter {
+ public:
+ ~NgHttp2Adapter() override;
+
+ // Creates an adapter that functions as a client.
+ static std::unique_ptr<NgHttp2Adapter> CreateClientAdapter(
+ Http2VisitorInterface& visitor);
+
+ // Creates an adapter that functions as a server.
+ static std::unique_ptr<NgHttp2Adapter> CreateServerAdapter(
+ Http2VisitorInterface& visitor);
+
+ // Processes the incoming |bytes| as HTTP/2 and invokes callbacks on the
+ // |visitor_| as appropriate.
+ ssize_t ProcessBytes(absl::string_view bytes) override;
+
+ // Submits the |settings| to be written to the peer, e.g., as part of the
+ // HTTP/2 connection preface.
+ void SubmitSettings(absl::Span<const Http2Setting> settings) override;
+
+ // Submits a PRIORITY frame for the given stream.
+ void SubmitPriorityForStream(Http2StreamId stream_id,
+ Http2StreamId parent_stream_id,
+ int weight,
+ bool exclusive) override;
+
+ // Submits a PING on the connection. Note that nghttp2 automatically submits
+ // PING acks upon receiving non-ack PINGs from the peer, so callers only use
+ // this method to originate PINGs. See nghttp2_option_set_no_auto_ping_ack().
+ void SubmitPing(Http2PingId ping_id) override;
+
+ // Submits a GOAWAY on the connection. Note that |last_accepted_stream_id|
+ // refers to stream IDs initiated by the peer. For client-side, this last
+ // stream ID must be even (or 0); for server-side, this last stream ID must be
+ // odd (or 0).
+ // TODO(birenroy): Add a graceful shutdown behavior to the API.
+ void SubmitGoAway(Http2StreamId last_accepted_stream_id,
+ Http2ErrorCode error_code,
+ absl::string_view opaque_data) override;
+
+ // Submits a WINDOW_UPDATE for the given stream (a |stream_id| of 0 indicates
+ // a connection-level WINDOW_UPDATE).
+ void SubmitWindowUpdate(Http2StreamId stream_id,
+ int window_increment) override;
+
+ // Submits a METADATA frame for the given stream (a |stream_id| of 0 indicates
+ // connection-level METADATA). If |end_metadata|, the frame will also have the
+ // END_METADATA flag set.
+ void SubmitMetadata(Http2StreamId stream_id, bool end_metadata) override;
+
+ // Returns serialized bytes for writing to the wire. Writes should be
+ // submitted to Nghttp2Adapter first, so that Nghttp2Adapter has data to
+ // serialize and return in this method.
+ std::string GetBytesToWrite(absl::optional<size_t> max_bytes) override;
+
+ // Returns the connection-level flow control window for the peer.
+ int GetPeerConnectionWindow() const override;
+
+ // Marks the given amount of data as consumed for the given stream, which
+ // enables the nghttp2 layer to trigger WINDOW_UPDATEs as appropriate.
+ void MarkDataConsumedForStream(Http2StreamId stream_id,
+ size_t num_bytes) override;
+
+ // Submits a RST_STREAM with the desired |error_code|.
+ void SubmitRst(Http2StreamId stream_id, Http2ErrorCode error_code) override;
+
+ // TODO(b/181586191): Temporary accessor until equivalent functionality is
+ // available in this adapter class.
+ NgHttp2Session& session() { return *session_; }
+
+ private:
+ NgHttp2Adapter(Http2VisitorInterface& visitor, Perspective perspective);
+
+ // Performs any necessary initialization of the underlying HTTP/2 session,
+ // such as preparing initial SETTINGS.
+ void Initialize();
+
+ std::unique_ptr<NgHttp2Session> session_;
+ Http2VisitorInterface& visitor_;
+ Perspective perspective_;
+};
+
+} // namespace adapter
+} // namespace http2
+
+#endif // QUICHE_HTTP2_ADAPTER_NGHTTP2_ADAPTER_H_
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter_test.cc b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter_test.cc
new file mode 100644
index 00000000000..3aec115dbeb
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter_test.cc
@@ -0,0 +1,255 @@
+#include "http2/adapter/nghttp2_adapter.h"
+
+#include "http2/adapter/mock_http2_visitor.h"
+#include "http2/adapter/test_frame_sequence.h"
+#include "http2/adapter/test_utils.h"
+#include "common/platform/api/quiche_test.h"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+namespace {
+
+using testing::_;
+
+enum FrameType {
+ DATA,
+ HEADERS,
+ PRIORITY,
+ RST_STREAM,
+ SETTINGS,
+ PUSH_PROMISE,
+ PING,
+ GOAWAY,
+ WINDOW_UPDATE,
+};
+
+TEST(NgHttp2AdapterTest, ClientConstruction) {
+ testing::StrictMock<MockHttp2Visitor> visitor;
+ auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
+ ASSERT_NE(nullptr, adapter);
+ EXPECT_TRUE(adapter->session().want_read());
+ EXPECT_FALSE(adapter->session().want_write());
+}
+
+TEST(NgHttp2AdapterTest, ClientHandlesFrames) {
+ testing::StrictMock<MockHttp2Visitor> visitor;
+ auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
+ std::string serialized = adapter->GetBytesToWrite(absl::nullopt);
+ EXPECT_THAT(serialized, testing::StrEq(spdy::kHttp2ConnectionHeaderPrefix));
+
+ const std::string initial_frames = TestFrameSequence()
+ .ServerPreface()
+ .Ping(42)
+ .WindowUpdate(0, 1000)
+ .Serialize();
+ testing::InSequence s;
+
+ // Server preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+
+ EXPECT_CALL(visitor, OnFrameHeader(0, 8, PING, 0));
+ EXPECT_CALL(visitor, OnPing(42, false));
+ EXPECT_CALL(visitor, OnFrameHeader(0, 4, WINDOW_UPDATE, 0));
+ EXPECT_CALL(visitor, OnWindowUpdate(0, 1000));
+
+ const ssize_t initial_result = adapter->ProcessBytes(initial_frames);
+ EXPECT_EQ(initial_frames.size(), initial_result);
+
+ EXPECT_EQ(adapter->GetPeerConnectionWindow(),
+ kDefaultInitialStreamWindowSize + 1000);
+ // Some bytes should have been serialized.
+ serialized = adapter->GetBytesToWrite(absl::nullopt);
+ EXPECT_THAT(serialized, EqualsFrames({spdy::SpdyFrameType::SETTINGS,
+ spdy::SpdyFrameType::PING}));
+
+ const std::vector<const Header> headers1 =
+ ToHeaders({{":method", "GET"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}});
+ const auto nvs1 = GetNghttp2Nvs(headers1);
+
+ const std::vector<const Header> headers2 =
+ ToHeaders({{":method", "GET"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/two"}});
+ const auto nvs2 = GetNghttp2Nvs(headers2);
+
+ const std::vector<const Header> headers3 =
+ ToHeaders({{":method", "GET"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/three"}});
+ const auto nvs3 = GetNghttp2Nvs(headers3);
+
+ const int32_t stream_id1 =
+ nghttp2_submit_request(adapter->session().raw_ptr(), nullptr, nvs1.data(),
+ nvs1.size(), nullptr, nullptr);
+ ASSERT_GT(stream_id1, 0);
+ QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
+
+ const int32_t stream_id2 =
+ nghttp2_submit_request(adapter->session().raw_ptr(), nullptr, nvs2.data(),
+ nvs2.size(), nullptr, nullptr);
+ ASSERT_GT(stream_id2, 0);
+ QUICHE_LOG(INFO) << "Created stream: " << stream_id2;
+
+ const int32_t stream_id3 =
+ nghttp2_submit_request(adapter->session().raw_ptr(), nullptr, nvs3.data(),
+ nvs3.size(), nullptr, nullptr);
+ ASSERT_GT(stream_id3, 0);
+ QUICHE_LOG(INFO) << "Created stream: " << stream_id3;
+
+ serialized = adapter->GetBytesToWrite(absl::nullopt);
+ EXPECT_THAT(serialized, EqualsFrames({spdy::SpdyFrameType::HEADERS,
+ spdy::SpdyFrameType::HEADERS,
+ spdy::SpdyFrameType::HEADERS}));
+
+ const std::string stream_frames =
+ TestFrameSequence()
+ .Headers(1,
+ {{":status", "200"},
+ {"server", "my-fake-server"},
+ {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
+ /*fin=*/false)
+ .Data(1, "This is the response body.")
+ .RstStream(3, Http2ErrorCode::INTERNAL_ERROR)
+ .GoAway(5, Http2ErrorCode::ENHANCE_YOUR_CALM, "calm down!!")
+ .Serialize();
+
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, "server", "my-fake-server"));
+ EXPECT_CALL(visitor,
+ OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+ EXPECT_CALL(visitor, OnFrameHeader(1, 26, DATA, 0));
+ EXPECT_CALL(visitor, OnBeginDataForStream(1, 26));
+ EXPECT_CALL(visitor, OnDataForStream(1, "This is the response body."));
+ EXPECT_CALL(visitor, OnFrameHeader(3, 4, RST_STREAM, 0));
+ EXPECT_CALL(visitor, OnRstStream(3, Http2ErrorCode::INTERNAL_ERROR));
+ EXPECT_CALL(visitor, OnCloseStream(3, Http2ErrorCode::INTERNAL_ERROR));
+ EXPECT_CALL(visitor, OnFrameHeader(0, 19, GOAWAY, 0));
+ EXPECT_CALL(visitor,
+ OnGoAway(5, Http2ErrorCode::ENHANCE_YOUR_CALM, "calm down!!"));
+ const ssize_t stream_result = adapter->ProcessBytes(stream_frames);
+ EXPECT_EQ(stream_frames.size(), stream_result);
+
+ // Even though the client recieved a GOAWAY, streams 1 and 5 are still active.
+ EXPECT_TRUE(adapter->session().want_read());
+
+ EXPECT_CALL(visitor, OnFrameHeader(1, 0, DATA, 1));
+ EXPECT_CALL(visitor, OnBeginDataForStream(1, 0));
+ EXPECT_CALL(visitor, OnEndStream(1));
+ EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::NO_ERROR));
+ EXPECT_CALL(visitor, OnFrameHeader(5, 4, RST_STREAM, 0));
+ EXPECT_CALL(visitor, OnRstStream(5, Http2ErrorCode::REFUSED_STREAM));
+ EXPECT_CALL(visitor, OnCloseStream(5, Http2ErrorCode::REFUSED_STREAM));
+ adapter->ProcessBytes(TestFrameSequence()
+ .Data(1, "", true)
+ .RstStream(5, Http2ErrorCode::REFUSED_STREAM)
+ .Serialize());
+ // After receiving END_STREAM for 1 and RST_STREAM for 5, the session no
+ // longer expects reads.
+ EXPECT_FALSE(adapter->session().want_read());
+
+ // Client will not have anything else to write.
+ EXPECT_FALSE(adapter->session().want_write());
+ serialized = adapter->GetBytesToWrite(absl::nullopt);
+ EXPECT_THAT(serialized, testing::IsEmpty());
+}
+
+TEST(NgHttp2AdapterTest, ServerConstruction) {
+ testing::StrictMock<MockHttp2Visitor> visitor;
+ auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
+ ASSERT_NE(nullptr, adapter);
+ EXPECT_TRUE(adapter->session().want_read());
+ EXPECT_FALSE(adapter->session().want_write());
+}
+
+TEST(NgHttp2AdapterTest, ServerHandlesFrames) {
+ testing::StrictMock<MockHttp2Visitor> visitor;
+ auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
+
+ const std::string frames = TestFrameSequence()
+ .ClientPreface()
+ .Ping(42)
+ .WindowUpdate(0, 1000)
+ .Headers(1,
+ {{":method", "POST"},
+ {":scheme", "https"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}},
+ /*fin=*/false)
+ .WindowUpdate(1, 2000)
+ .Data(1, "This is the request body.")
+ .Headers(3,
+ {{":method", "GET"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/two"}},
+ /*fin=*/true)
+ .RstStream(3, Http2ErrorCode::CANCEL)
+ .Ping(47)
+ .Serialize();
+ testing::InSequence s;
+
+ // Client preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+
+ EXPECT_CALL(visitor, OnFrameHeader(0, 8, PING, 0));
+ EXPECT_CALL(visitor, OnPing(42, false));
+ EXPECT_CALL(visitor, OnFrameHeader(0, 4, WINDOW_UPDATE, 0));
+ EXPECT_CALL(visitor, OnWindowUpdate(0, 1000));
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "POST"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+ EXPECT_CALL(visitor, OnFrameHeader(1, 4, WINDOW_UPDATE, 0));
+ EXPECT_CALL(visitor, OnWindowUpdate(1, 2000));
+ EXPECT_CALL(visitor, OnFrameHeader(1, 25, DATA, 0));
+ EXPECT_CALL(visitor, OnBeginDataForStream(1, 25));
+ EXPECT_CALL(visitor, OnDataForStream(1, "This is the request body."));
+ EXPECT_CALL(visitor, OnFrameHeader(3, _, HEADERS, 5));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(3));
+ EXPECT_CALL(visitor, OnHeaderForStream(3, ":method", "GET"));
+ EXPECT_CALL(visitor, OnHeaderForStream(3, ":scheme", "http"));
+ EXPECT_CALL(visitor, OnHeaderForStream(3, ":authority", "example.com"));
+ EXPECT_CALL(visitor, OnHeaderForStream(3, ":path", "/this/is/request/two"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(3));
+ EXPECT_CALL(visitor, OnEndStream(3));
+ EXPECT_CALL(visitor, OnFrameHeader(3, 4, RST_STREAM, 0));
+ EXPECT_CALL(visitor, OnRstStream(3, Http2ErrorCode::CANCEL));
+ EXPECT_CALL(visitor, OnCloseStream(3, Http2ErrorCode::CANCEL));
+ EXPECT_CALL(visitor, OnFrameHeader(0, 8, PING, 0));
+ EXPECT_CALL(visitor, OnPing(47, false));
+
+ const ssize_t result = adapter->ProcessBytes(frames);
+ EXPECT_EQ(frames.size(), result);
+
+ EXPECT_EQ(adapter->GetPeerConnectionWindow(),
+ kDefaultInitialStreamWindowSize + 1000);
+
+ EXPECT_TRUE(adapter->session().want_write());
+ // Some bytes should have been serialized.
+ std::string serialized = adapter->GetBytesToWrite(absl::nullopt);
+ // SETTINGS ack, two PING acks.
+ EXPECT_THAT(serialized, EqualsFrames({spdy::SpdyFrameType::SETTINGS,
+ spdy::SpdyFrameType::PING,
+ spdy::SpdyFrameType::PING}));
+}
+
+} // namespace
+} // namespace test
+} // namespace adapter
+} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_callbacks.cc b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_callbacks.cc
index 337f230b796..8774873c95f 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_callbacks.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_callbacks.cc
@@ -14,11 +14,14 @@
namespace http2 {
namespace adapter {
+namespace callbacks {
int OnBeginFrame(nghttp2_session* /* session */,
const nghttp2_frame_hd* header,
void* user_data) {
auto* visitor = static_cast<Http2VisitorInterface*>(user_data);
+ visitor->OnFrameHeader(header->stream_id, header->length, header->type,
+ header->flags);
if (header->type == NGHTTP2_DATA) {
visitor->OnBeginDataForStream(header->stream_id, header->length);
}
@@ -30,6 +33,8 @@ int OnFrameReceived(nghttp2_session* /* session */,
void* user_data) {
auto* visitor = static_cast<Http2VisitorInterface*>(user_data);
const Http2StreamId stream_id = frame->hd.stream_id;
+ QUICHE_VLOG(2) << "Frame " << static_cast<int>(frame->hd.type)
+ << " for stream " << stream_id;
switch (frame->hd.type) {
// The beginning of the DATA frame is handled in OnBeginFrame(), and the
// beginning of the header block is handled in client/server-specific
@@ -158,11 +163,7 @@ int OnStreamClosed(nghttp2_session* /* session */,
uint32_t error_code,
void* user_data) {
auto* visitor = static_cast<Http2VisitorInterface*>(user_data);
- if (error_code == static_cast<uint32_t>(Http2ErrorCode::NO_ERROR)) {
- visitor->OnCloseStream(stream_id);
- } else {
- visitor->OnAbortStream(stream_id, ToHttp2ErrorCode(error_code));
- }
+ visitor->OnCloseStream(stream_id, ToHttp2ErrorCode(error_code));
return 0;
}
@@ -185,5 +186,24 @@ ssize_t OnReadyToReadDataForStream(nghttp2_session* /* session */,
return bytes_to_send;
}
+nghttp2_session_callbacks_unique_ptr Create() {
+ nghttp2_session_callbacks* callbacks;
+ nghttp2_session_callbacks_new(&callbacks);
+
+ nghttp2_session_callbacks_set_on_begin_frame_callback(callbacks,
+ &OnBeginFrame);
+ nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
+ &OnFrameReceived);
+ nghttp2_session_callbacks_set_on_begin_headers_callback(callbacks,
+ &OnBeginHeaders);
+ nghttp2_session_callbacks_set_on_header_callback2(callbacks, &OnHeader);
+ nghttp2_session_callbacks_set_on_data_chunk_recv_callback(callbacks,
+ &OnDataChunk);
+ nghttp2_session_callbacks_set_on_stream_close_callback(callbacks,
+ &OnStreamClosed);
+ return MakeCallbacksPtr(callbacks);
+}
+
+} // namespace callbacks
} // namespace adapter
} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_callbacks.h b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_callbacks.h
index 7e6ce7c38d2..5fbaee041c5 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_callbacks.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_callbacks.h
@@ -2,10 +2,12 @@
#define QUICHE_HTTP2_ADAPTER_NGHTTP2_CALLBACKS_H_
#include "http2/adapter/http2_protocol.h"
+#include "http2/adapter/nghttp2_util.h"
#include "third_party/nghttp2/src/lib/includes/nghttp2/nghttp2.h"
namespace http2 {
namespace adapter {
+namespace callbacks {
// The following functions are nghttp2 callbacks that Nghttp2Adapter sets at the
// beginning of its lifetime. It is expected that |user_data| holds an
@@ -46,6 +48,9 @@ ssize_t OnReadyToReadDataForStream(nghttp2_session* session,
nghttp2_data_source* source,
void* user_data);
+nghttp2_session_callbacks_unique_ptr Create();
+
+} // namespace callbacks
} // namespace adapter
} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session.cc b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session.cc
new file mode 100644
index 00000000000..d434b06e0f5
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session.cc
@@ -0,0 +1,70 @@
+#include "http2/adapter/nghttp2_session.h"
+
+#include "common/platform/api/quiche_logging.h"
+
+namespace http2 {
+namespace adapter {
+namespace {
+
+void DeleteOptions(nghttp2_option* options) {
+ if (options) {
+ nghttp2_option_del(options);
+ }
+}
+
+} // namespace
+
+NgHttp2Session::NgHttp2Session(Perspective perspective,
+ nghttp2_session_callbacks_unique_ptr callbacks,
+ nghttp2_option* options,
+ void* userdata)
+ : session_(MakeSessionPtr(nullptr)),
+ options_(options, DeleteOptions),
+ perspective_(perspective) {
+ nghttp2_session* session;
+ switch (perspective) {
+ case Perspective::kClient:
+ nghttp2_session_client_new2(&session, callbacks.get(), userdata,
+ options_.get());
+ break;
+ case Perspective::kServer:
+ nghttp2_session_server_new2(&session, callbacks.get(), userdata,
+ options_.get());
+ break;
+ }
+ session_.reset(session);
+}
+
+NgHttp2Session::~NgHttp2Session() {
+ // Can't invoke want_read() or want_write(), as they are virtual methods.
+ const bool pending_reads = nghttp2_session_want_read(session_.get()) != 0;
+ const bool pending_writes = nghttp2_session_want_write(session_.get()) != 0;
+ QUICHE_LOG_IF(WARNING, pending_reads || pending_writes)
+ << "Shutting down connection with pending reads: " << pending_reads
+ << " or pending writes: " << pending_writes;
+}
+
+ssize_t NgHttp2Session::ProcessBytes(absl::string_view bytes) {
+ return nghttp2_session_mem_recv(
+ session_.get(), reinterpret_cast<const uint8_t*>(bytes.data()),
+ bytes.size());
+}
+
+int NgHttp2Session::Consume(Http2StreamId stream_id, size_t num_bytes) {
+ return nghttp2_session_consume(session_.get(), stream_id, num_bytes);
+}
+
+bool NgHttp2Session::want_read() const {
+ return nghttp2_session_want_read(session_.get()) != 0;
+}
+
+bool NgHttp2Session::want_write() const {
+ return nghttp2_session_want_write(session_.get()) != 0;
+}
+
+int NgHttp2Session::GetRemoteWindowSize() const {
+ return nghttp2_session_get_remote_window_size(session_.get());
+}
+
+} // namespace adapter
+} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session.h b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session.h
new file mode 100644
index 00000000000..d446a07c75b
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session.h
@@ -0,0 +1,42 @@
+#ifndef QUICHE_HTTP2_ADAPTER_NGHTTP2_SESSION_H_
+#define QUICHE_HTTP2_ADAPTER_NGHTTP2_SESSION_H_
+
+#include "http2/adapter/http2_session.h"
+#include "http2/adapter/nghttp2_util.h"
+#include "third_party/nghttp2/src/lib/includes/nghttp2/nghttp2.h"
+
+namespace http2 {
+namespace adapter {
+
+// A C++ wrapper around common nghttp2_session operations.
+class NgHttp2Session : public Http2Session {
+ public:
+ // Takes ownership of |options|.
+ NgHttp2Session(Perspective perspective,
+ nghttp2_session_callbacks_unique_ptr callbacks,
+ nghttp2_option* options,
+ void* userdata);
+ ~NgHttp2Session() override;
+
+ ssize_t ProcessBytes(absl::string_view bytes) override;
+
+ int Consume(Http2StreamId stream_id, size_t num_bytes) override;
+
+ bool want_read() const override;
+ bool want_write() const override;
+ int GetRemoteWindowSize() const override;
+
+ nghttp2_session* raw_ptr() const { return session_.get(); }
+
+ private:
+ using OptionsDeleter = void (&)(nghttp2_option*);
+
+ nghttp2_session_unique_ptr session_;
+ std::unique_ptr<nghttp2_option, OptionsDeleter> options_;
+ Perspective perspective_;
+};
+
+} // namespace adapter
+} // namespace http2
+
+#endif // QUICHE_HTTP2_ADAPTER_NGHTTP2_SESSION_H_
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session_test.cc b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session_test.cc
new file mode 100644
index 00000000000..169d2f20dd0
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session_test.cc
@@ -0,0 +1,295 @@
+#include "http2/adapter/nghttp2_session.h"
+
+#include "http2/adapter/mock_http2_visitor.h"
+#include "http2/adapter/nghttp2_callbacks.h"
+#include "http2/adapter/nghttp2_util.h"
+#include "http2/adapter/test_frame_sequence.h"
+#include "http2/adapter/test_utils.h"
+#include "common/platform/api/quiche_test.h"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+namespace {
+
+using testing::_;
+
+enum FrameType {
+ DATA,
+ HEADERS,
+ PRIORITY,
+ RST_STREAM,
+ SETTINGS,
+ PUSH_PROMISE,
+ PING,
+ GOAWAY,
+ WINDOW_UPDATE,
+};
+
+ssize_t SaveSessionOutput(nghttp2_session* /* session*/,
+ const uint8_t* data,
+ size_t length,
+ int /* flags */,
+ void* user_data) {
+ auto visitor = static_cast<DataSavingVisitor*>(user_data);
+ visitor->Save(ToStringView(data, length));
+ return length;
+}
+
+class NgHttp2SessionTest : public testing::Test {
+ public:
+ nghttp2_option* CreateOptions() {
+ nghttp2_option* options;
+ nghttp2_option_new(&options);
+ nghttp2_option_set_no_auto_window_update(options, 1);
+ return options;
+ }
+
+ nghttp2_session_callbacks_unique_ptr CreateCallbacks() {
+ nghttp2_session_callbacks_unique_ptr callbacks = callbacks::Create();
+ nghttp2_session_callbacks_set_send_callback(callbacks.get(),
+ &SaveSessionOutput);
+ return callbacks;
+ }
+
+ DataSavingVisitor visitor_;
+};
+
+TEST_F(NgHttp2SessionTest, ClientConstruction) {
+ NgHttp2Session session(Perspective::kClient, CreateCallbacks(),
+ CreateOptions(), &visitor_);
+ EXPECT_TRUE(session.want_read());
+ EXPECT_FALSE(session.want_write());
+ EXPECT_EQ(session.GetRemoteWindowSize(), kDefaultInitialStreamWindowSize);
+ EXPECT_NE(session.raw_ptr(), nullptr);
+}
+
+TEST_F(NgHttp2SessionTest, ClientHandlesFrames) {
+ NgHttp2Session session(Perspective::kClient, CreateCallbacks(),
+ CreateOptions(), &visitor_);
+
+ ASSERT_EQ(0, nghttp2_session_send(session.raw_ptr()));
+ ASSERT_GT(visitor_.data().size(), 0);
+
+ const std::string initial_frames = TestFrameSequence()
+ .ServerPreface()
+ .Ping(42)
+ .WindowUpdate(0, 1000)
+ .Serialize();
+ testing::InSequence s;
+
+ // Server preface (empty SETTINGS)
+ EXPECT_CALL(visitor_, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor_, OnSettingsStart());
+ EXPECT_CALL(visitor_, OnSettingsEnd());
+
+ EXPECT_CALL(visitor_, OnFrameHeader(0, 8, PING, 0));
+ EXPECT_CALL(visitor_, OnPing(42, false));
+ EXPECT_CALL(visitor_, OnFrameHeader(0, 4, WINDOW_UPDATE, 0));
+ EXPECT_CALL(visitor_, OnWindowUpdate(0, 1000));
+
+ const ssize_t initial_result = session.ProcessBytes(initial_frames);
+ EXPECT_EQ(initial_frames.size(), initial_result);
+
+ EXPECT_EQ(session.GetRemoteWindowSize(),
+ kDefaultInitialStreamWindowSize + 1000);
+ ASSERT_EQ(0, nghttp2_session_send(session.raw_ptr()));
+ // Some bytes should have been serialized.
+ absl::string_view serialized = visitor_.data();
+ ASSERT_THAT(serialized,
+ testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
+ serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
+ EXPECT_THAT(serialized, EqualsFrames({spdy::SpdyFrameType::SETTINGS,
+ spdy::SpdyFrameType::PING}));
+ visitor_.Clear();
+
+ const std::vector<const Header> headers1 =
+ ToHeaders({{":method", "GET"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}});
+ const auto nvs1 = GetNghttp2Nvs(headers1);
+
+ const std::vector<const Header> headers2 =
+ ToHeaders({{":method", "GET"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/two"}});
+ const auto nvs2 = GetNghttp2Nvs(headers2);
+
+ const std::vector<const Header> headers3 =
+ ToHeaders({{":method", "GET"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/three"}});
+ const auto nvs3 = GetNghttp2Nvs(headers3);
+
+ const int32_t stream_id1 = nghttp2_submit_request(
+ session.raw_ptr(), nullptr, nvs1.data(), nvs1.size(), nullptr, nullptr);
+ ASSERT_GT(stream_id1, 0);
+ QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
+
+ const int32_t stream_id2 = nghttp2_submit_request(
+ session.raw_ptr(), nullptr, nvs2.data(), nvs2.size(), nullptr, nullptr);
+ ASSERT_GT(stream_id2, 0);
+ QUICHE_LOG(INFO) << "Created stream: " << stream_id2;
+
+ const int32_t stream_id3 = nghttp2_submit_request(
+ session.raw_ptr(), nullptr, nvs3.data(), nvs3.size(), nullptr, nullptr);
+ ASSERT_GT(stream_id3, 0);
+ QUICHE_LOG(INFO) << "Created stream: " << stream_id3;
+
+ ASSERT_EQ(0, nghttp2_session_send(session.raw_ptr()));
+ serialized = visitor_.data();
+ EXPECT_THAT(serialized, EqualsFrames({spdy::SpdyFrameType::HEADERS,
+ spdy::SpdyFrameType::HEADERS,
+ spdy::SpdyFrameType::HEADERS}));
+ visitor_.Clear();
+
+ const std::string stream_frames =
+ TestFrameSequence()
+ .Headers(1,
+ {{":status", "200"},
+ {"server", "my-fake-server"},
+ {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
+ /*fin=*/false)
+ .Data(1, "This is the response body.")
+ .RstStream(3, Http2ErrorCode::INTERNAL_ERROR)
+ .GoAway(5, Http2ErrorCode::ENHANCE_YOUR_CALM, "calm down!!")
+ .Serialize();
+
+ EXPECT_CALL(visitor_, OnFrameHeader(1, _, HEADERS, 4));
+ EXPECT_CALL(visitor_, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor_, OnHeaderForStream(1, ":status", "200"));
+ EXPECT_CALL(visitor_, OnHeaderForStream(1, "server", "my-fake-server"));
+ EXPECT_CALL(visitor_,
+ OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT"));
+ EXPECT_CALL(visitor_, OnEndHeadersForStream(1));
+ EXPECT_CALL(visitor_, OnFrameHeader(1, 26, DATA, 0));
+ EXPECT_CALL(visitor_, OnBeginDataForStream(1, 26));
+ EXPECT_CALL(visitor_, OnDataForStream(1, "This is the response body."));
+ EXPECT_CALL(visitor_, OnFrameHeader(3, 4, RST_STREAM, 0));
+ EXPECT_CALL(visitor_, OnRstStream(3, Http2ErrorCode::INTERNAL_ERROR));
+ EXPECT_CALL(visitor_, OnCloseStream(3, Http2ErrorCode::INTERNAL_ERROR));
+ EXPECT_CALL(visitor_, OnFrameHeader(0, 19, GOAWAY, 0));
+ EXPECT_CALL(visitor_,
+ OnGoAway(5, Http2ErrorCode::ENHANCE_YOUR_CALM, "calm down!!"));
+ const ssize_t stream_result = session.ProcessBytes(stream_frames);
+ EXPECT_EQ(stream_frames.size(), stream_result);
+
+ // Even though the client recieved a GOAWAY, streams 1 and 5 are still active.
+ EXPECT_TRUE(session.want_read());
+
+ EXPECT_CALL(visitor_, OnFrameHeader(1, 0, DATA, 1));
+ EXPECT_CALL(visitor_, OnBeginDataForStream(1, 0));
+ EXPECT_CALL(visitor_, OnEndStream(1));
+ EXPECT_CALL(visitor_, OnCloseStream(1, Http2ErrorCode::NO_ERROR));
+ EXPECT_CALL(visitor_, OnFrameHeader(5, 4, RST_STREAM, 0));
+ EXPECT_CALL(visitor_, OnRstStream(5, Http2ErrorCode::REFUSED_STREAM));
+ EXPECT_CALL(visitor_, OnCloseStream(5, Http2ErrorCode::REFUSED_STREAM));
+ session.ProcessBytes(TestFrameSequence()
+ .Data(1, "", true)
+ .RstStream(5, Http2ErrorCode::REFUSED_STREAM)
+ .Serialize());
+ // After receiving END_STREAM for 1 and RST_STREAM for 5, the session no
+ // longer expects reads.
+ EXPECT_FALSE(session.want_read());
+
+ // Client will not have anything else to write.
+ EXPECT_FALSE(session.want_write());
+ ASSERT_EQ(0, nghttp2_session_send(session.raw_ptr()));
+ serialized = visitor_.data();
+ EXPECT_EQ(serialized.size(), 0);
+}
+
+TEST_F(NgHttp2SessionTest, ServerConstruction) {
+ NgHttp2Session session(Perspective::kServer, CreateCallbacks(),
+ CreateOptions(), &visitor_);
+ EXPECT_TRUE(session.want_read());
+ EXPECT_FALSE(session.want_write());
+ EXPECT_EQ(session.GetRemoteWindowSize(), kDefaultInitialStreamWindowSize);
+ EXPECT_NE(session.raw_ptr(), nullptr);
+}
+
+TEST_F(NgHttp2SessionTest, ServerHandlesFrames) {
+ NgHttp2Session session(Perspective::kServer, CreateCallbacks(),
+ CreateOptions(), &visitor_);
+
+ const std::string frames = TestFrameSequence()
+ .ClientPreface()
+ .Ping(42)
+ .WindowUpdate(0, 1000)
+ .Headers(1,
+ {{":method", "POST"},
+ {":scheme", "https"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}},
+ /*fin=*/false)
+ .WindowUpdate(1, 2000)
+ .Data(1, "This is the request body.")
+ .Headers(3,
+ {{":method", "GET"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/two"}},
+ /*fin=*/true)
+ .RstStream(3, Http2ErrorCode::CANCEL)
+ .Ping(47)
+ .Serialize();
+ testing::InSequence s;
+
+ // Client preface (empty SETTINGS)
+ EXPECT_CALL(visitor_, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor_, OnSettingsStart());
+ EXPECT_CALL(visitor_, OnSettingsEnd());
+
+ EXPECT_CALL(visitor_, OnFrameHeader(0, 8, PING, 0));
+ EXPECT_CALL(visitor_, OnPing(42, false));
+ EXPECT_CALL(visitor_, OnFrameHeader(0, 4, WINDOW_UPDATE, 0));
+ EXPECT_CALL(visitor_, OnWindowUpdate(0, 1000));
+ EXPECT_CALL(visitor_, OnFrameHeader(1, _, HEADERS, 4));
+ EXPECT_CALL(visitor_, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor_, OnHeaderForStream(1, ":method", "POST"));
+ EXPECT_CALL(visitor_, OnHeaderForStream(1, ":scheme", "https"));
+ EXPECT_CALL(visitor_, OnHeaderForStream(1, ":authority", "example.com"));
+ EXPECT_CALL(visitor_, OnHeaderForStream(1, ":path", "/this/is/request/one"));
+ EXPECT_CALL(visitor_, OnEndHeadersForStream(1));
+ EXPECT_CALL(visitor_, OnFrameHeader(1, 4, WINDOW_UPDATE, 0));
+ EXPECT_CALL(visitor_, OnWindowUpdate(1, 2000));
+ EXPECT_CALL(visitor_, OnFrameHeader(1, 25, DATA, 0));
+ EXPECT_CALL(visitor_, OnBeginDataForStream(1, 25));
+ EXPECT_CALL(visitor_, OnDataForStream(1, "This is the request body."));
+ EXPECT_CALL(visitor_, OnFrameHeader(3, _, HEADERS, 5));
+ EXPECT_CALL(visitor_, OnBeginHeadersForStream(3));
+ EXPECT_CALL(visitor_, OnHeaderForStream(3, ":method", "GET"));
+ EXPECT_CALL(visitor_, OnHeaderForStream(3, ":scheme", "http"));
+ EXPECT_CALL(visitor_, OnHeaderForStream(3, ":authority", "example.com"));
+ EXPECT_CALL(visitor_, OnHeaderForStream(3, ":path", "/this/is/request/two"));
+ EXPECT_CALL(visitor_, OnEndHeadersForStream(3));
+ EXPECT_CALL(visitor_, OnEndStream(3));
+ EXPECT_CALL(visitor_, OnFrameHeader(3, 4, RST_STREAM, 0));
+ EXPECT_CALL(visitor_, OnRstStream(3, Http2ErrorCode::CANCEL));
+ EXPECT_CALL(visitor_, OnCloseStream(3, Http2ErrorCode::CANCEL));
+ EXPECT_CALL(visitor_, OnFrameHeader(0, 8, PING, 0));
+ EXPECT_CALL(visitor_, OnPing(47, false));
+
+ const ssize_t result = session.ProcessBytes(frames);
+ EXPECT_EQ(frames.size(), result);
+
+ EXPECT_EQ(session.GetRemoteWindowSize(),
+ kDefaultInitialStreamWindowSize + 1000);
+
+ EXPECT_TRUE(session.want_write());
+ ASSERT_EQ(0, nghttp2_session_send(session.raw_ptr()));
+ // Some bytes should have been serialized.
+ absl::string_view serialized = visitor_.data();
+ // SETTINGS ack, two PING acks.
+ EXPECT_THAT(serialized, EqualsFrames({spdy::SpdyFrameType::SETTINGS,
+ spdy::SpdyFrameType::PING,
+ spdy::SpdyFrameType::PING}));
+}
+
+} // namespace
+} // namespace test
+} // namespace adapter
+} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util.cc b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util.cc
index e1341481ae5..8d23a55278a 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util.cc
@@ -10,6 +10,31 @@
namespace http2 {
namespace adapter {
+namespace {
+
+void DeleteCallbacks(nghttp2_session_callbacks* callbacks) {
+ if (callbacks) {
+ nghttp2_session_callbacks_del(callbacks);
+ }
+}
+
+void DeleteSession(nghttp2_session* session) {
+ if (session) {
+ nghttp2_session_del(session);
+ }
+}
+
+} // namespace
+
+nghttp2_session_callbacks_unique_ptr MakeCallbacksPtr(
+ nghttp2_session_callbacks* callbacks) {
+ return nghttp2_session_callbacks_unique_ptr(callbacks, DeleteCallbacks);
+}
+
+nghttp2_session_unique_ptr MakeSessionPtr(nghttp2_session* session) {
+ return nghttp2_session_unique_ptr(session, DeleteSession);
+}
+
uint8_t* ToUint8Ptr(char* str) { return reinterpret_cast<uint8_t*>(str); }
uint8_t* ToUint8Ptr(const char* str) {
return const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(str));
@@ -25,16 +50,30 @@ absl::string_view ToStringView(uint8_t* pointer, size_t length) {
return absl::string_view(reinterpret_cast<const char*>(pointer), length);
}
-std::vector<nghttp2_nv> GetRequestNghttp2Nvs(absl::Span<const Header> headers) {
+absl::string_view ToStringView(const uint8_t* pointer, size_t length) {
+ return absl::string_view(reinterpret_cast<const char*>(pointer), length);
+}
+
+std::vector<nghttp2_nv> GetNghttp2Nvs(absl::Span<const Header> headers) {
const int num_headers = headers.size();
auto nghttp2_nvs = std::vector<nghttp2_nv>(num_headers);
for (int i = 0; i < num_headers; ++i) {
nghttp2_nv header;
- header.name = ToUint8Ptr(&headers[i].first[0]);
- header.namelen = headers[i].first.size();
- header.value = ToUint8Ptr(&headers[i].second[0]);
- header.valuelen = headers[i].second.size();
- header.flags = NGHTTP2_FLAG_NONE;
+ uint8_t flags = NGHTTP2_NV_FLAG_NONE;
+
+ const auto [name, no_copy_name] = GetStringView(headers[i].first);
+ header.name = ToUint8Ptr(name.data());
+ header.namelen = name.size();
+ if (no_copy_name) {
+ flags |= NGHTTP2_NV_FLAG_NO_COPY_NAME;
+ }
+ const auto [value, no_copy_value] = GetStringView(headers[i].second);
+ header.value = ToUint8Ptr(value.data());
+ header.valuelen = value.size();
+ if (no_copy_value) {
+ flags |= NGHTTP2_NV_FLAG_NO_COPY_VALUE;
+ }
+ header.flags = flags;
nghttp2_nvs.push_back(std::move(header));
}
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util.h b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util.h
index 3fcbfcd068c..e2c3e7a37c7 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util.h
@@ -20,15 +20,28 @@ inline constexpr int kStreamCallbackFailureStatus =
NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
inline constexpr int kCancelStatus = NGHTTP2_ERR_CANCEL;
+using CallbacksDeleter = void (&)(nghttp2_session_callbacks*);
+using SessionDeleter = void (&)(nghttp2_session*);
+
+using nghttp2_session_callbacks_unique_ptr =
+ std::unique_ptr<nghttp2_session_callbacks, CallbacksDeleter>;
+using nghttp2_session_unique_ptr =
+ std::unique_ptr<nghttp2_session, SessionDeleter>;
+
+nghttp2_session_callbacks_unique_ptr MakeCallbacksPtr(
+ nghttp2_session_callbacks* callbacks);
+nghttp2_session_unique_ptr MakeSessionPtr(nghttp2_session* session);
+
uint8_t* ToUint8Ptr(char* str);
uint8_t* ToUint8Ptr(const char* str);
absl::string_view ToStringView(nghttp2_rcbuf* rc_buffer);
absl::string_view ToStringView(uint8_t* pointer, size_t length);
+absl::string_view ToStringView(const uint8_t* pointer, size_t length);
-// Returns the nghttp2 header structure from the given request |headers|, which
+// Returns the nghttp2 header structure from the given |headers|, which
// must have the correct pseudoheaders preceding other headers.
-std::vector<nghttp2_nv> GetRequestNghttp2Nvs(absl::Span<const Header> headers);
+std::vector<nghttp2_nv> GetNghttp2Nvs(absl::Span<const Header> headers);
// Returns the nghttp2 header structure from the given response |headers|, with
// the :status pseudoheader first based on the given |response_code|. The
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter.cc b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter.cc
index 7b7d2a2229b..9f287facb9f 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter.cc
@@ -1,12 +1,9 @@
#include "http2/adapter/oghttp2_adapter.h"
-#include <list>
-
#include "absl/memory/memory.h"
#include "absl/strings/str_cat.h"
#include "http2/adapter/http2_util.h"
-#include "http2/adapter/window_manager.h"
-#include "spdy/core/spdy_framer.h"
+#include "common/platform/api/quiche_bug_tracker.h"
#include "spdy/core/spdy_protocol.h"
namespace http2 {
@@ -23,70 +20,6 @@ using spdy::SpdyWindowUpdateIR;
} // namespace
-struct StreamState {
- WindowManager window_manager;
-};
-
-class OgHttp2Adapter::OgHttp2Session : public Http2Session {
- public:
- OgHttp2Session(Http2VisitorInterface& /*visitor*/, Options /*options*/) {}
- ~OgHttp2Session() override {}
-
- ssize_t ProcessBytes(absl::string_view bytes) override {
- SPDY_BUG(oghttp2_process_bytes) << "Not implemented";
- return 0;
- }
-
- int Consume(Http2StreamId stream_id, size_t num_bytes) override {
- auto it = stream_map_.find(stream_id);
- if (it == stream_map_.end()) {
- // TODO(b/181586191): LOG_ERROR rather than SPDY_BUG.
- SPDY_BUG(stream_consume_notfound)
- << "Stream " << stream_id << " not found";
- } else {
- it->second.window_manager.MarkDataFlushed(num_bytes);
- }
- return 0; // Remove?
- }
-
- bool want_read() const override { return false; }
- bool want_write() const override {
- return !frames_.empty() || !serialized_prefix_.empty();
- }
- int GetRemoteWindowSize() const override {
- SPDY_BUG(peer_window_not_updated) << "Not implemented";
- return peer_window_;
- }
-
- void EnqueueFrame(std::unique_ptr<spdy::SpdyFrameIR> frame) {
- frames_.push_back(std::move(frame));
- }
-
- std::string GetBytesToWrite(absl::optional<size_t> max_bytes) {
- const size_t serialized_max =
- max_bytes ? max_bytes.value() : std::numeric_limits<size_t>::max();
- std::string serialized = std::move(serialized_prefix_);
- while (serialized.size() < serialized_max && !frames_.empty()) {
- spdy::SpdySerializedFrame frame =
- framer_.SerializeFrame(*frames_.front());
- absl::StrAppend(&serialized, absl::string_view(frame));
- frames_.pop_front();
- }
- if (serialized.size() > serialized_max) {
- serialized_prefix_ = serialized.substr(serialized_max);
- serialized.resize(serialized_max);
- }
- return serialized;
- }
-
- private:
- spdy::SpdyFramer framer_{spdy::SpdyFramer::ENABLE_COMPRESSION};
- absl::flat_hash_map<Http2StreamId, StreamState> stream_map_;
- std::list<std::unique_ptr<SpdyFrameIR>> frames_;
- std::string serialized_prefix_;
- int peer_window_ = 65535;
-};
-
/* static */
std::unique_ptr<OgHttp2Adapter> OgHttp2Adapter::Create(
Http2VisitorInterface& visitor,
@@ -135,7 +68,7 @@ void OgHttp2Adapter::SubmitWindowUpdate(Http2StreamId stream_id,
}
void OgHttp2Adapter::SubmitMetadata(Http2StreamId stream_id, bool fin) {
- SPDY_BUG(oghttp2_submit_metadata) << "Not implemented";
+ QUICHE_BUG(oghttp2_submit_metadata) << "Not implemented";
}
std::string OgHttp2Adapter::GetBytesToWrite(absl::optional<size_t> max_bytes) {
@@ -151,6 +84,12 @@ void OgHttp2Adapter::MarkDataConsumedForStream(Http2StreamId stream_id,
session_->Consume(stream_id, num_bytes);
}
+void OgHttp2Adapter::SubmitRst(Http2StreamId stream_id,
+ Http2ErrorCode error_code) {
+ session_->EnqueueFrame(absl::make_unique<spdy::SpdyRstStreamIR>(
+ stream_id, TranslateErrorCode(error_code)));
+}
+
const Http2Session& OgHttp2Adapter::session() const {
return *session_;
}
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter.h b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter.h
index 1f32cfc6ddd..572ba04e9fc 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter.h
@@ -5,15 +5,14 @@
#include "http2/adapter/http2_adapter.h"
#include "http2/adapter/http2_session.h"
+#include "http2/adapter/oghttp2_session.h"
namespace http2 {
namespace adapter {
class OgHttp2Adapter : public Http2Adapter {
public:
- struct Options {
- Perspective context;
- };
+ using Options = OgHttp2Session::Options;
static std::unique_ptr<OgHttp2Adapter> Create(Http2VisitorInterface& visitor,
Options options);
@@ -37,13 +36,13 @@ class OgHttp2Adapter : public Http2Adapter {
int GetPeerConnectionWindow() const override;
void MarkDataConsumedForStream(Http2StreamId stream_id,
size_t num_bytes) override;
+ void SubmitRst(Http2StreamId stream_id, Http2ErrorCode error_code) override;
const Http2Session& session() const;
private:
OgHttp2Adapter(Http2VisitorInterface& visitor, Options options);
- class OgHttp2Session;
std::unique_ptr<OgHttp2Session> session_;
};
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter_test.cc b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter_test.cc
index 3c04c06d7ec..4c849f6fd6d 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter_test.cc
@@ -1,9 +1,10 @@
#include "http2/adapter/oghttp2_adapter.h"
#include "http2/adapter/mock_http2_visitor.h"
+#include "http2/adapter/test_frame_sequence.h"
#include "http2/adapter/test_utils.h"
#include "common/platform/api/quiche_test.h"
-#include "spdy/platform/api/spdy_test_helpers.h"
+#include "common/platform/api/quiche_test_helpers.h"
namespace http2 {
namespace adapter {
@@ -13,7 +14,7 @@ namespace {
class OgHttp2AdapterTest : public testing::Test {
protected:
void SetUp() override {
- OgHttp2Adapter::Options options;
+ OgHttp2Adapter::Options options{.perspective = Perspective::kServer};
adapter_ = OgHttp2Adapter::Create(http2_visitor_, options);
}
@@ -22,27 +23,32 @@ class OgHttp2AdapterTest : public testing::Test {
};
TEST_F(OgHttp2AdapterTest, ProcessBytes) {
- EXPECT_SPDY_BUG(adapter_->ProcessBytes("fake data"), "Not implemented");
+ testing::InSequence seq;
+ EXPECT_CALL(http2_visitor_, OnFrameHeader(0, 0, 4, 0));
+ EXPECT_CALL(http2_visitor_, OnSettingsStart());
+ EXPECT_CALL(http2_visitor_, OnSettingsEnd());
+ EXPECT_CALL(http2_visitor_, OnFrameHeader(0, 8, 6, 0));
+ EXPECT_CALL(http2_visitor_, OnPing(17, false));
+ adapter_->ProcessBytes(
+ TestFrameSequence().ClientPreface().Ping(17).Serialize());
}
TEST_F(OgHttp2AdapterTest, SubmitMetadata) {
- EXPECT_SPDY_BUG(adapter_->SubmitMetadata(3, true), "Not implemented");
+ EXPECT_QUICHE_BUG(adapter_->SubmitMetadata(3, true), "Not implemented");
}
TEST_F(OgHttp2AdapterTest, GetPeerConnectionWindow) {
- int peer_window = 0;
- EXPECT_SPDY_BUG(peer_window = adapter_->GetPeerConnectionWindow(),
- "Not implemented");
+ const int peer_window = adapter_->GetPeerConnectionWindow();
EXPECT_GT(peer_window, 0);
}
TEST_F(OgHttp2AdapterTest, MarkDataConsumedForStream) {
- EXPECT_SPDY_BUG(adapter_->MarkDataConsumedForStream(1, 11),
- "Stream 1 not found");
+ EXPECT_QUICHE_BUG(adapter_->MarkDataConsumedForStream(1, 11),
+ "Stream 1 not found");
}
TEST_F(OgHttp2AdapterTest, TestSerialize) {
- EXPECT_FALSE(adapter_->session().want_read());
+ EXPECT_TRUE(adapter_->session().want_read());
EXPECT_FALSE(adapter_->session().want_write());
adapter_->SubmitSettings(
@@ -50,16 +56,18 @@ TEST_F(OgHttp2AdapterTest, TestSerialize) {
EXPECT_TRUE(adapter_->session().want_write());
adapter_->SubmitPriorityForStream(3, 1, 255, true);
+ adapter_->SubmitRst(3, Http2ErrorCode::CANCEL);
adapter_->SubmitPing(42);
adapter_->SubmitGoAway(13, Http2ErrorCode::NO_ERROR, "");
adapter_->SubmitWindowUpdate(3, 127);
EXPECT_TRUE(adapter_->session().want_write());
- EXPECT_THAT(adapter_->GetBytesToWrite(absl::nullopt),
- ContainsFrames(
- {spdy::SpdyFrameType::SETTINGS, spdy::SpdyFrameType::PRIORITY,
- spdy::SpdyFrameType::PING, spdy::SpdyFrameType::GOAWAY,
- spdy::SpdyFrameType::WINDOW_UPDATE}));
+ EXPECT_THAT(
+ adapter_->GetBytesToWrite(absl::nullopt),
+ EqualsFrames(
+ {spdy::SpdyFrameType::SETTINGS, spdy::SpdyFrameType::PRIORITY,
+ spdy::SpdyFrameType::RST_STREAM, spdy::SpdyFrameType::PING,
+ spdy::SpdyFrameType::GOAWAY, spdy::SpdyFrameType::WINDOW_UPDATE}));
EXPECT_FALSE(adapter_->session().want_write());
}
@@ -78,8 +86,8 @@ TEST_F(OgHttp2AdapterTest, TestPartialSerialize) {
EXPECT_FALSE(adapter_->session().want_write());
EXPECT_THAT(
absl::StrCat(first_part, second_part),
- ContainsFrames({spdy::SpdyFrameType::SETTINGS,
- spdy::SpdyFrameType::GOAWAY, spdy::SpdyFrameType::PING}));
+ EqualsFrames({spdy::SpdyFrameType::SETTINGS, spdy::SpdyFrameType::GOAWAY,
+ spdy::SpdyFrameType::PING}));
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session.cc b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session.cc
new file mode 100644
index 00000000000..2222fed4b6b
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session.cc
@@ -0,0 +1,231 @@
+#include "http2/adapter/oghttp2_session.h"
+
+#include "absl/strings/escaping.h"
+
+namespace http2 {
+namespace adapter {
+
+void OgHttp2Session::PassthroughHeadersHandler::OnHeaderBlockStart() {
+ visitor_.OnBeginHeadersForStream(stream_id_);
+}
+
+void OgHttp2Session::PassthroughHeadersHandler::OnHeader(
+ absl::string_view key,
+ absl::string_view value) {
+ visitor_.OnHeaderForStream(stream_id_, key, value);
+}
+
+void OgHttp2Session::PassthroughHeadersHandler::OnHeaderBlockEnd(
+ size_t /* uncompressed_header_bytes */,
+ size_t /* compressed_header_bytes */) {
+ visitor_.OnEndHeadersForStream(stream_id_);
+}
+
+OgHttp2Session::OgHttp2Session(Http2VisitorInterface& visitor, Options options)
+ : visitor_(visitor), headers_handler_(visitor), options_(options) {
+ decoder_.set_visitor(this);
+ if (options_.perspective == Perspective::kServer) {
+ remaining_preface_ = {spdy::kHttp2ConnectionHeaderPrefix,
+ spdy::kHttp2ConnectionHeaderPrefixSize};
+ }
+}
+
+OgHttp2Session::~OgHttp2Session() {}
+
+ssize_t OgHttp2Session::ProcessBytes(absl::string_view bytes) {
+ ssize_t preface_consumed = 0;
+ if (!remaining_preface_.empty()) {
+ QUICHE_VLOG(2) << "Preface bytes remaining: " << remaining_preface_.size();
+ // decoder_ does not understand the client connection preface.
+ size_t min_size = std::min(remaining_preface_.size(), bytes.size());
+ if (!absl::StartsWith(remaining_preface_, bytes.substr(0, min_size))) {
+ // Preface doesn't match!
+ QUICHE_DLOG(INFO) << "Preface doesn't match! Expected: ["
+ << absl::CEscape(remaining_preface_) << "], actual: ["
+ << absl::CEscape(bytes) << "]";
+ visitor_.OnConnectionError();
+ return -1;
+ }
+ remaining_preface_.remove_prefix(min_size);
+ bytes.remove_prefix(min_size);
+ if (!remaining_preface_.empty()) {
+ QUICHE_VLOG(2) << "Preface bytes remaining: "
+ << remaining_preface_.size();
+ return min_size;
+ }
+ preface_consumed = min_size;
+ }
+ ssize_t result = decoder_.ProcessInput(bytes.data(), bytes.size());
+ return result < 0 ? result : result + preface_consumed;
+}
+
+int OgHttp2Session::Consume(Http2StreamId stream_id, size_t num_bytes) {
+ auto it = stream_map_.find(stream_id);
+ if (it == stream_map_.end()) {
+ // TODO(b/181586191): LOG_ERROR rather than QUICHE_BUG.
+ QUICHE_BUG(stream_consume_notfound)
+ << "Stream " << stream_id << " not found";
+ } else {
+ it->second.window_manager.MarkDataFlushed(num_bytes);
+ }
+ return 0; // Remove?
+}
+
+void OgHttp2Session::EnqueueFrame(std::unique_ptr<spdy::SpdyFrameIR> frame) {
+ frames_.push_back(std::move(frame));
+}
+
+std::string OgHttp2Session::GetBytesToWrite(absl::optional<size_t> max_bytes) {
+ const size_t serialized_max =
+ max_bytes ? max_bytes.value() : std::numeric_limits<size_t>::max();
+ std::string serialized = std::move(serialized_prefix_);
+ while (serialized.size() < serialized_max && !frames_.empty()) {
+ spdy::SpdySerializedFrame frame = framer_.SerializeFrame(*frames_.front());
+ absl::StrAppend(&serialized, absl::string_view(frame));
+ frames_.pop_front();
+ }
+ if (serialized.size() > serialized_max) {
+ serialized_prefix_ = serialized.substr(serialized_max);
+ serialized.resize(serialized_max);
+ }
+ return serialized;
+}
+
+void OgHttp2Session::OnError(http2::Http2DecoderAdapter::SpdyFramerError error,
+ std::string detailed_error) {
+ QUICHE_VLOG(1) << "Error: "
+ << http2::Http2DecoderAdapter::SpdyFramerErrorToString(error)
+ << " details: " << detailed_error;
+ visitor_.OnConnectionError();
+}
+
+void OgHttp2Session::OnCommonHeader(spdy::SpdyStreamId stream_id,
+ size_t length,
+ uint8_t type,
+ uint8_t flags) {
+ visitor_.OnFrameHeader(stream_id, length, type, flags);
+}
+
+void OgHttp2Session::OnDataFrameHeader(spdy::SpdyStreamId stream_id,
+ size_t length,
+ bool fin) {
+ visitor_.OnBeginDataForStream(stream_id, length);
+}
+
+void OgHttp2Session::OnStreamFrameData(spdy::SpdyStreamId stream_id,
+ const char* data,
+ size_t len) {
+ visitor_.OnDataForStream(stream_id, absl::string_view(data, len));
+}
+
+void OgHttp2Session::OnStreamEnd(spdy::SpdyStreamId stream_id) {
+ visitor_.OnEndStream(stream_id);
+}
+
+void OgHttp2Session::OnStreamPadLength(spdy::SpdyStreamId /*stream_id*/,
+ size_t /*value*/) {
+ // TODO(181586191): handle padding
+}
+
+void OgHttp2Session::OnStreamPadding(spdy::SpdyStreamId stream_id, size_t len) {
+ // TODO(181586191): handle padding
+}
+
+spdy::SpdyHeadersHandlerInterface* OgHttp2Session::OnHeaderFrameStart(
+ spdy::SpdyStreamId stream_id) {
+ headers_handler_.set_stream_id(stream_id);
+ return &headers_handler_;
+}
+
+void OgHttp2Session::OnHeaderFrameEnd(spdy::SpdyStreamId stream_id) {
+ headers_handler_.set_stream_id(0);
+}
+
+void OgHttp2Session::OnRstStream(spdy::SpdyStreamId stream_id,
+ spdy::SpdyErrorCode error_code) {
+ visitor_.OnRstStream(stream_id, TranslateErrorCode(error_code));
+ visitor_.OnCloseStream(stream_id, TranslateErrorCode(error_code));
+}
+
+void OgHttp2Session::OnSettings() {
+ visitor_.OnSettingsStart();
+}
+
+void OgHttp2Session::OnSetting(spdy::SpdySettingsId id, uint32_t value) {
+ visitor_.OnSetting({id, value});
+}
+
+void OgHttp2Session::OnSettingsEnd() {
+ visitor_.OnSettingsEnd();
+}
+
+void OgHttp2Session::OnSettingsAck() {
+ visitor_.OnSettingsAck();
+}
+
+void OgHttp2Session::OnPing(spdy::SpdyPingId unique_id, bool is_ack) {
+ visitor_.OnPing(unique_id, is_ack);
+}
+
+void OgHttp2Session::OnGoAway(spdy::SpdyStreamId last_accepted_stream_id,
+ spdy::SpdyErrorCode error_code) {
+ received_goaway_ = true;
+ visitor_.OnGoAway(last_accepted_stream_id, TranslateErrorCode(error_code),
+ "");
+}
+
+bool OgHttp2Session::OnGoAwayFrameData(const char* goaway_data, size_t len) {
+ // Opaque data is currently ignored.
+ return true;
+}
+
+void OgHttp2Session::OnHeaders(spdy::SpdyStreamId stream_id,
+ bool has_priority,
+ int weight,
+ spdy::SpdyStreamId parent_stream_id,
+ bool exclusive,
+ bool fin,
+ bool end) {}
+
+void OgHttp2Session::OnWindowUpdate(spdy::SpdyStreamId stream_id,
+ int delta_window_size) {
+ if (stream_id == 0) {
+ peer_window_ += delta_window_size;
+ } else {
+ auto it = stream_map_.find(stream_id);
+ if (it == stream_map_.end()) {
+ QUICHE_VLOG(1) << "Stream " << stream_id << " not found!";
+ } else {
+ it->second.send_window += delta_window_size;
+ }
+ }
+ visitor_.OnWindowUpdate(stream_id, delta_window_size);
+}
+
+void OgHttp2Session::OnPushPromise(spdy::SpdyStreamId stream_id,
+ spdy::SpdyStreamId promised_stream_id,
+ bool end) {}
+
+void OgHttp2Session::OnContinuation(spdy::SpdyStreamId stream_id, bool end) {}
+
+void OgHttp2Session::OnAltSvc(spdy::SpdyStreamId /*stream_id*/,
+ absl::string_view /*origin*/,
+ const spdy::SpdyAltSvcWireFormat::
+ AlternativeServiceVector& /*altsvc_vector*/) {
+}
+
+void OgHttp2Session::OnPriority(spdy::SpdyStreamId stream_id,
+ spdy::SpdyStreamId parent_stream_id,
+ int weight,
+ bool exclusive) {}
+
+void OgHttp2Session::OnPriorityUpdate(spdy::SpdyStreamId prioritized_stream_id,
+ absl::string_view priority_field_value) {}
+
+bool OgHttp2Session::OnUnknownFrame(spdy::SpdyStreamId stream_id,
+ uint8_t frame_type) {
+ return true;
+}
+
+} // namespace adapter
+} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session.h b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session.h
new file mode 100644
index 00000000000..b0bc28b7002
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session.h
@@ -0,0 +1,141 @@
+#ifndef QUICHE_HTTP2_ADAPTER_OGHTTP2_SESSION_H_
+#define QUICHE_HTTP2_ADAPTER_OGHTTP2_SESSION_H_
+
+#include <list>
+
+#include "http2/adapter/http2_session.h"
+#include "http2/adapter/http2_util.h"
+#include "http2/adapter/http2_visitor_interface.h"
+#include "http2/adapter/window_manager.h"
+#include "common/platform/api/quiche_bug_tracker.h"
+#include "spdy/core/http2_frame_decoder_adapter.h"
+#include "spdy/core/spdy_framer.h"
+
+namespace http2 {
+namespace adapter {
+
+// This class manages state associated with a single multiplexed HTTP/2 session.
+class OgHttp2Session : public Http2Session,
+ public spdy::SpdyFramerVisitorInterface {
+ public:
+ struct Options {
+ Perspective perspective = Perspective::kClient;
+ };
+
+ OgHttp2Session(Http2VisitorInterface& visitor, Options /*options*/);
+ ~OgHttp2Session() override;
+
+ // Enqueues a frame for transmission to the peer.
+ void EnqueueFrame(std::unique_ptr<spdy::SpdyFrameIR> frame);
+
+ // If |want_write()| returns true, this method will return a non-empty string
+ // containing serialized HTTP/2 frames to write to the peer.
+ std::string GetBytesToWrite(absl::optional<size_t> max_bytes);
+
+ // From Http2Session.
+ ssize_t ProcessBytes(absl::string_view bytes) override;
+ int Consume(Http2StreamId stream_id, size_t num_bytes) override;
+ bool want_read() const override { return !received_goaway_; }
+ bool want_write() const override {
+ return !frames_.empty() || !serialized_prefix_.empty();
+ }
+ int GetRemoteWindowSize() const override {
+ return peer_window_;
+ }
+
+ // From SpdyFramerVisitorInterface
+ void OnError(http2::Http2DecoderAdapter::SpdyFramerError error,
+ std::string detailed_error) override;
+ void OnCommonHeader(spdy::SpdyStreamId /*stream_id*/,
+ size_t /*length*/,
+ uint8_t /*type*/,
+ uint8_t /*flags*/) override;
+ void OnDataFrameHeader(spdy::SpdyStreamId stream_id,
+ size_t length,
+ bool fin) override;
+ void OnStreamFrameData(spdy::SpdyStreamId stream_id,
+ const char* data,
+ size_t len) override;
+ void OnStreamEnd(spdy::SpdyStreamId stream_id) override;
+ void OnStreamPadLength(spdy::SpdyStreamId /*stream_id*/,
+ size_t /*value*/) override;
+ void OnStreamPadding(spdy::SpdyStreamId stream_id, size_t len) override;
+ spdy::SpdyHeadersHandlerInterface* OnHeaderFrameStart(
+ spdy::SpdyStreamId stream_id) override;
+ void OnHeaderFrameEnd(spdy::SpdyStreamId stream_id) override;
+ void OnRstStream(spdy::SpdyStreamId stream_id,
+ spdy::SpdyErrorCode error_code) override;
+ void OnSettings() override;
+ void OnSetting(spdy::SpdySettingsId id, uint32_t value) override;
+ void OnSettingsEnd() override;
+ void OnSettingsAck() override;
+ void OnPing(spdy::SpdyPingId unique_id, bool is_ack) override;
+ void OnGoAway(spdy::SpdyStreamId last_accepted_stream_id,
+ spdy::SpdyErrorCode error_code) override;
+ bool OnGoAwayFrameData(const char* goaway_data, size_t len);
+ void OnHeaders(spdy::SpdyStreamId stream_id,
+ bool has_priority,
+ int weight,
+ spdy::SpdyStreamId parent_stream_id,
+ bool exclusive,
+ bool fin,
+ bool end) override;
+ void OnWindowUpdate(spdy::SpdyStreamId stream_id,
+ int delta_window_size) override;
+ void OnPushPromise(spdy::SpdyStreamId stream_id,
+ spdy::SpdyStreamId promised_stream_id,
+ bool end) override;
+ void OnContinuation(spdy::SpdyStreamId stream_id, bool end) override;
+ void OnAltSvc(spdy::SpdyStreamId /*stream_id*/,
+ absl::string_view /*origin*/,
+ const spdy::SpdyAltSvcWireFormat::
+ AlternativeServiceVector& /*altsvc_vector*/);
+ void OnPriority(spdy::SpdyStreamId stream_id,
+ spdy::SpdyStreamId parent_stream_id,
+ int weight,
+ bool exclusive) override;
+ void OnPriorityUpdate(spdy::SpdyStreamId prioritized_stream_id,
+ absl::string_view priority_field_value) override;
+ bool OnUnknownFrame(spdy::SpdyStreamId stream_id,
+ uint8_t frame_type) override;
+
+ private:
+ struct StreamState {
+ WindowManager window_manager;
+ int32_t send_window = 65535;
+ bool half_closed_local = false;
+ bool half_closed_remote = false;
+ };
+
+ class PassthroughHeadersHandler : public spdy::SpdyHeadersHandlerInterface {
+ public:
+ explicit PassthroughHeadersHandler(Http2VisitorInterface& visitor)
+ : visitor_(visitor) {}
+ void set_stream_id(Http2StreamId stream_id) { stream_id_ = stream_id; }
+ void OnHeaderBlockStart() override;
+ void OnHeader(absl::string_view key, absl::string_view value) override;
+ void OnHeaderBlockEnd(size_t /* uncompressed_header_bytes */,
+ size_t /* compressed_header_bytes */) override;
+
+ private:
+ Http2VisitorInterface& visitor_;
+ Http2StreamId stream_id_ = 0;
+ };
+
+ Http2VisitorInterface& visitor_;
+ spdy::SpdyFramer framer_{spdy::SpdyFramer::ENABLE_COMPRESSION};
+ http2::Http2DecoderAdapter decoder_;
+ absl::flat_hash_map<Http2StreamId, StreamState> stream_map_;
+ std::list<std::unique_ptr<spdy::SpdyFrameIR>> frames_;
+ PassthroughHeadersHandler headers_handler_;
+ std::string serialized_prefix_;
+ absl::string_view remaining_preface_;
+ int peer_window_ = 65535;
+ Options options_;
+ bool received_goaway_ = false;
+};
+
+} // namespace adapter
+} // namespace http2
+
+#endif // QUICHE_HTTP2_ADAPTER_OGHTTP2_SESSION_H_
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session_test.cc b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session_test.cc
new file mode 100644
index 00000000000..ab155697d5d
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session_test.cc
@@ -0,0 +1,179 @@
+#include "http2/adapter/oghttp2_session.h"
+
+#include "http2/adapter/mock_http2_visitor.h"
+#include "http2/adapter/test_frame_sequence.h"
+#include "common/platform/api/quiche_test.h"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+namespace {
+
+using testing::_;
+
+enum FrameType {
+ DATA,
+ HEADERS,
+ PRIORITY,
+ RST_STREAM,
+ SETTINGS,
+ PUSH_PROMISE,
+ PING,
+ GOAWAY,
+ WINDOW_UPDATE,
+};
+
+} // namespace
+
+TEST(OgHttp2SessionTest, ClientConstruction) {
+ testing::StrictMock<MockHttp2Visitor> visitor;
+ OgHttp2Session session(
+ visitor, OgHttp2Session::Options{.perspective = Perspective::kClient});
+ EXPECT_TRUE(session.want_read());
+ EXPECT_FALSE(session.want_write());
+ EXPECT_EQ(session.GetRemoteWindowSize(), kDefaultInitialStreamWindowSize);
+}
+
+TEST(OgHttp2SessionTest, ClientHandlesFrames) {
+ testing::StrictMock<MockHttp2Visitor> visitor;
+ OgHttp2Session session(
+ visitor, OgHttp2Session::Options{.perspective = Perspective::kClient});
+
+ const std::string initial_frames = TestFrameSequence()
+ .ServerPreface()
+ .Ping(42)
+ .WindowUpdate(0, 1000)
+ .Serialize();
+ testing::InSequence s;
+
+ // Server preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+
+ EXPECT_CALL(visitor, OnFrameHeader(0, 8, PING, 0));
+ EXPECT_CALL(visitor, OnPing(42, false));
+ EXPECT_CALL(visitor, OnFrameHeader(0, 4, WINDOW_UPDATE, 0));
+ EXPECT_CALL(visitor, OnWindowUpdate(0, 1000));
+
+ const ssize_t initial_result = session.ProcessBytes(initial_frames);
+ EXPECT_EQ(initial_frames.size(), initial_result);
+
+ EXPECT_EQ(session.GetRemoteWindowSize(),
+ kDefaultInitialStreamWindowSize + 1000);
+
+ // Should OgHttp2Session require that streams 1 and 3 have been created?
+
+ const std::string stream_frames =
+ TestFrameSequence()
+ .Headers(1,
+ {{":status", "200"},
+ {"server", "my-fake-server"},
+ {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
+ /*fin=*/false)
+ .Data(1, "This is the response body.")
+ .RstStream(3, Http2ErrorCode::INTERNAL_ERROR)
+ .GoAway(5, Http2ErrorCode::ENHANCE_YOUR_CALM, "calm down!!")
+ .Serialize();
+
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, "server", "my-fake-server"));
+ EXPECT_CALL(visitor,
+ OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+ EXPECT_CALL(visitor, OnFrameHeader(1, 26, DATA, 0));
+ EXPECT_CALL(visitor, OnBeginDataForStream(1, 26));
+ EXPECT_CALL(visitor, OnDataForStream(1, "This is the response body."));
+ EXPECT_CALL(visitor, OnFrameHeader(3, 4, RST_STREAM, 0));
+ EXPECT_CALL(visitor, OnRstStream(3, Http2ErrorCode::INTERNAL_ERROR));
+ EXPECT_CALL(visitor, OnCloseStream(3, Http2ErrorCode::INTERNAL_ERROR));
+ EXPECT_CALL(visitor, OnFrameHeader(0, 19, GOAWAY, 0));
+ EXPECT_CALL(visitor, OnGoAway(5, Http2ErrorCode::ENHANCE_YOUR_CALM, ""));
+ const ssize_t stream_result = session.ProcessBytes(stream_frames);
+ EXPECT_EQ(stream_frames.size(), stream_result);
+}
+
+TEST(OgHttp2SessionTest, ServerConstruction) {
+ testing::StrictMock<MockHttp2Visitor> visitor;
+ OgHttp2Session session(
+ visitor, OgHttp2Session::Options{.perspective = Perspective::kServer});
+ EXPECT_TRUE(session.want_read());
+ EXPECT_FALSE(session.want_write());
+ EXPECT_EQ(session.GetRemoteWindowSize(), kDefaultInitialStreamWindowSize);
+}
+
+TEST(OgHttp2SessionTest, ServerHandlesFrames) {
+ testing::StrictMock<MockHttp2Visitor> visitor;
+ OgHttp2Session session(
+ visitor, OgHttp2Session::Options{.perspective = Perspective::kServer});
+
+ const std::string frames = TestFrameSequence()
+ .ClientPreface()
+ .Ping(42)
+ .WindowUpdate(0, 1000)
+ .Headers(1,
+ {{":method", "POST"},
+ {":scheme", "https"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}},
+ /*fin=*/false)
+ .WindowUpdate(1, 2000)
+ .Data(1, "This is the request body.")
+ .Headers(3,
+ {{":method", "GET"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/two"}},
+ /*fin=*/true)
+ .RstStream(3, Http2ErrorCode::CANCEL)
+ .Ping(47)
+ .Serialize();
+ testing::InSequence s;
+
+ // Client preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+
+ EXPECT_CALL(visitor, OnFrameHeader(0, 8, PING, 0));
+ EXPECT_CALL(visitor, OnPing(42, false));
+ EXPECT_CALL(visitor, OnFrameHeader(0, 4, WINDOW_UPDATE, 0));
+ EXPECT_CALL(visitor, OnWindowUpdate(0, 1000));
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "POST"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+ EXPECT_CALL(visitor, OnFrameHeader(1, 4, WINDOW_UPDATE, 0));
+ EXPECT_CALL(visitor, OnWindowUpdate(1, 2000));
+ EXPECT_CALL(visitor, OnFrameHeader(1, 25, DATA, 0));
+ EXPECT_CALL(visitor, OnBeginDataForStream(1, 25));
+ EXPECT_CALL(visitor, OnDataForStream(1, "This is the request body."));
+ EXPECT_CALL(visitor, OnFrameHeader(3, _, HEADERS, 5));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(3));
+ EXPECT_CALL(visitor, OnHeaderForStream(3, ":method", "GET"));
+ EXPECT_CALL(visitor, OnHeaderForStream(3, ":scheme", "http"));
+ EXPECT_CALL(visitor, OnHeaderForStream(3, ":authority", "example.com"));
+ EXPECT_CALL(visitor, OnHeaderForStream(3, ":path", "/this/is/request/two"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(3));
+ EXPECT_CALL(visitor, OnEndStream(3));
+ EXPECT_CALL(visitor, OnFrameHeader(3, 4, RST_STREAM, 0));
+ EXPECT_CALL(visitor, OnRstStream(3, Http2ErrorCode::CANCEL));
+ EXPECT_CALL(visitor, OnCloseStream(3, Http2ErrorCode::CANCEL));
+ EXPECT_CALL(visitor, OnFrameHeader(0, 8, PING, 0));
+ EXPECT_CALL(visitor, OnPing(47, false));
+
+ const ssize_t result = session.ProcessBytes(frames);
+ EXPECT_EQ(frames.size(), result);
+
+ EXPECT_EQ(session.GetRemoteWindowSize(),
+ kDefaultInitialStreamWindowSize + 1000);
+}
+
+} // namespace test
+} // namespace adapter
+} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_util.cc b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_util.cc
new file mode 100644
index 00000000000..3ed13dcf46e
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_util.cc
@@ -0,0 +1,17 @@
+#include "http2/adapter/oghttp2_util.h"
+
+namespace http2 {
+namespace adapter {
+
+spdy::SpdyHeaderBlock ToHeaderBlock(absl::Span<const Header> headers) {
+ spdy::SpdyHeaderBlock block;
+ for (const Header& header : headers) {
+ absl::string_view name = GetStringView(header.first).first;
+ absl::string_view value = GetStringView(header.second).first;
+ block[name] = value;
+ }
+ return block;
+}
+
+} // namespace adapter
+} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_util.h b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_util.h
new file mode 100644
index 00000000000..e222c96ccfd
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_util.h
@@ -0,0 +1,16 @@
+#ifndef QUICHE_HTTP2_ADAPTER_OGHTTP2_UTIL_H_
+#define QUICHE_HTTP2_ADAPTER_OGHTTP2_UTIL_H_
+
+#include "absl/types/span.h"
+#include "http2/adapter/http2_protocol.h"
+#include "spdy/core/spdy_header_block.h"
+
+namespace http2 {
+namespace adapter {
+
+spdy::SpdyHeaderBlock ToHeaderBlock(absl::Span<const Header> headers);
+
+} // namespace adapter
+} // namespace http2
+
+#endif // QUICHE_HTTP2_ADAPTER_OGHTTP2_UTIL_H_
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/recording_http2_visitor.cc b/chromium/net/third_party/quiche/src/http2/adapter/recording_http2_visitor.cc
new file mode 100644
index 00000000000..78ec423e25e
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/recording_http2_visitor.cc
@@ -0,0 +1,155 @@
+#include "http2/adapter/recording_http2_visitor.h"
+
+#include "absl/strings/str_format.h"
+#include "http2/adapter/http2_protocol.h"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+
+void RecordingHttp2Visitor::OnConnectionError() {
+ events_.push_back("OnConnectionError");
+}
+
+void RecordingHttp2Visitor::OnFrameHeader(Http2StreamId stream_id,
+ size_t length,
+ uint8_t type,
+ uint8_t flags) {
+ events_.push_back(absl::StrFormat("OnFrameHeader %d %d %d %d", stream_id,
+ length, type, flags));
+}
+
+void RecordingHttp2Visitor::OnSettingsStart() {
+ events_.push_back("OnSettingsStart");
+}
+
+void RecordingHttp2Visitor::OnSetting(Http2Setting setting) {
+ events_.push_back(absl::StrFormat(
+ "OnSetting %s %d", Http2SettingsIdToString(setting.id), setting.value));
+}
+
+void RecordingHttp2Visitor::OnSettingsEnd() {
+ events_.push_back("OnSettingsEnd");
+}
+
+void RecordingHttp2Visitor::OnSettingsAck() {
+ events_.push_back("OnSettingsAck");
+}
+
+void RecordingHttp2Visitor::OnBeginHeadersForStream(Http2StreamId stream_id) {
+ events_.push_back(absl::StrFormat("OnBeginHeadersForStream %d", stream_id));
+}
+
+void RecordingHttp2Visitor::OnHeaderForStream(Http2StreamId stream_id,
+ absl::string_view name,
+ absl::string_view value) {
+ events_.push_back(
+ absl::StrFormat("OnHeaderForStream %d %s %s", stream_id, name, value));
+}
+
+void RecordingHttp2Visitor::OnEndHeadersForStream(Http2StreamId stream_id) {
+ events_.push_back(absl::StrFormat("OnEndHeadersForStream %d", stream_id));
+}
+
+void RecordingHttp2Visitor::OnBeginDataForStream(Http2StreamId stream_id,
+ size_t payload_length) {
+ events_.push_back(
+ absl::StrFormat("OnBeginDataForStream %d %d", stream_id, payload_length));
+}
+
+void RecordingHttp2Visitor::OnDataForStream(Http2StreamId stream_id,
+ absl::string_view data) {
+ events_.push_back(absl::StrFormat("OnDataForStream %d %s", stream_id, data));
+}
+
+void RecordingHttp2Visitor::OnEndStream(Http2StreamId stream_id) {
+ events_.push_back(absl::StrFormat("OnEndStream %d", stream_id));
+}
+
+void RecordingHttp2Visitor::OnRstStream(Http2StreamId stream_id,
+ Http2ErrorCode error_code) {
+ events_.push_back(absl::StrFormat("OnRstStream %d %s", stream_id,
+ Http2ErrorCodeToString(error_code)));
+}
+
+void RecordingHttp2Visitor::OnCloseStream(Http2StreamId stream_id,
+ Http2ErrorCode error_code) {
+ events_.push_back(absl::StrFormat("OnCloseStream %d %s", stream_id,
+ Http2ErrorCodeToString(error_code)));
+}
+
+void RecordingHttp2Visitor::OnPriorityForStream(Http2StreamId stream_id,
+ Http2StreamId parent_stream_id,
+ int weight,
+ bool exclusive) {
+ events_.push_back(absl::StrFormat("OnPriorityForStream %d %d %d %d",
+ stream_id, parent_stream_id, weight,
+ exclusive));
+}
+
+void RecordingHttp2Visitor::OnPing(Http2PingId ping_id, bool is_ack) {
+ events_.push_back(absl::StrFormat("OnPing %d %d", ping_id, is_ack));
+}
+
+void RecordingHttp2Visitor::OnPushPromiseForStream(
+ Http2StreamId stream_id,
+ Http2StreamId promised_stream_id) {
+ events_.push_back(absl::StrFormat("OnPushPromiseForStream %d %d", stream_id,
+ promised_stream_id));
+}
+
+void RecordingHttp2Visitor::OnGoAway(Http2StreamId last_accepted_stream_id,
+ Http2ErrorCode error_code,
+ absl::string_view opaque_data) {
+ events_.push_back(
+ absl::StrFormat("OnGoAway %d %s %s", last_accepted_stream_id,
+ Http2ErrorCodeToString(error_code), opaque_data));
+}
+
+void RecordingHttp2Visitor::OnWindowUpdate(Http2StreamId stream_id,
+ int window_increment) {
+ events_.push_back(
+ absl::StrFormat("OnWindowUpdate %d %d", stream_id, window_increment));
+}
+
+void RecordingHttp2Visitor::OnReadyToSendDataForStream(Http2StreamId stream_id,
+ char* destination_buffer,
+ size_t length,
+ ssize_t* written,
+ bool* end_stream) {
+ // TODO(b/181586191): Revisit this. The visitor is expected to write to the
+ // |destination_buffer| and set the other pointer values appropriately.
+ events_.push_back(
+ absl::StrFormat("OnReadyToSendDataForStream %d %d", stream_id, length));
+}
+
+void RecordingHttp2Visitor::OnReadyToSendMetadataForStream(
+ Http2StreamId stream_id,
+ char* buffer,
+ size_t length,
+ ssize_t* written) {
+ // TODO(b/181586191): Revisit this. The visitor is expected to write to the
+ // |buffer| and set *written appropriately.
+ events_.push_back(absl::StrFormat("OnReadyToSendMetadataForStream %d %d",
+ stream_id, length));
+}
+
+void RecordingHttp2Visitor::OnBeginMetadataForStream(Http2StreamId stream_id,
+ size_t payload_length) {
+ events_.push_back(absl::StrFormat("OnBeginMetadataForStream %d %d", stream_id,
+ payload_length));
+}
+
+void RecordingHttp2Visitor::OnMetadataForStream(Http2StreamId stream_id,
+ absl::string_view metadata) {
+ events_.push_back(
+ absl::StrFormat("OnMetadataForStream %d %s", stream_id, metadata));
+}
+
+void RecordingHttp2Visitor::OnMetadataEndForStream(Http2StreamId stream_id) {
+ events_.push_back(absl::StrFormat("OnMetadataEndForStream %d", stream_id));
+}
+
+} // namespace test
+} // namespace adapter
+} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/recording_http2_visitor.h b/chromium/net/third_party/quiche/src/http2/adapter/recording_http2_visitor.h
new file mode 100644
index 00000000000..452b45185cb
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/recording_http2_visitor.h
@@ -0,0 +1,80 @@
+#ifndef QUICHE_HTTP2_ADAPTER_RECORDING_HTTP2_VISITOR_H_
+#define QUICHE_HTTP2_ADAPTER_RECORDING_HTTP2_VISITOR_H_
+
+#include <list>
+#include <string>
+
+#include "http2/adapter/http2_visitor_interface.h"
+#include "common/platform/api/quiche_test.h"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+
+// A visitor implementation that records the sequence of callbacks it receives.
+class RecordingHttp2Visitor : public Http2VisitorInterface {
+ public:
+ using Event = std::string;
+ using EventSequence = std::list<Event>;
+
+ // From Http2VisitorInterface
+ void OnConnectionError() override;
+ void OnFrameHeader(Http2StreamId stream_id,
+ size_t length,
+ uint8_t type,
+ uint8_t flags) override;
+ void OnSettingsStart() override;
+ void OnSetting(Http2Setting setting) override;
+ void OnSettingsEnd() override;
+ void OnSettingsAck() override;
+ void OnBeginHeadersForStream(Http2StreamId stream_id) override;
+ void OnHeaderForStream(Http2StreamId stream_id,
+ absl::string_view name,
+ absl::string_view value) override;
+ void OnEndHeadersForStream(Http2StreamId stream_id) override;
+ void OnBeginDataForStream(Http2StreamId stream_id,
+ size_t payload_length) override;
+ void OnDataForStream(Http2StreamId stream_id,
+ absl::string_view data) override;
+ void OnEndStream(Http2StreamId stream_id) override;
+ void OnRstStream(Http2StreamId stream_id, Http2ErrorCode error_code) override;
+ void OnCloseStream(Http2StreamId stream_id,
+ Http2ErrorCode error_code) override;
+ void OnPriorityForStream(Http2StreamId stream_id,
+ Http2StreamId parent_stream_id,
+ int weight,
+ bool exclusive) override;
+ void OnPing(Http2PingId ping_id, bool is_ack) override;
+ void OnPushPromiseForStream(Http2StreamId stream_id,
+ Http2StreamId promised_stream_id) override;
+ void OnGoAway(Http2StreamId last_accepted_stream_id,
+ Http2ErrorCode error_code,
+ absl::string_view opaque_data) override;
+ void OnWindowUpdate(Http2StreamId stream_id, int window_increment) override;
+ void OnReadyToSendDataForStream(Http2StreamId stream_id,
+ char* destination_buffer,
+ size_t length,
+ ssize_t* written,
+ bool* end_stream) override;
+ void OnReadyToSendMetadataForStream(Http2StreamId stream_id,
+ char* buffer,
+ size_t length,
+ ssize_t* written) override;
+ void OnBeginMetadataForStream(Http2StreamId stream_id,
+ size_t payload_length) override;
+ void OnMetadataForStream(Http2StreamId stream_id,
+ absl::string_view metadata) override;
+ void OnMetadataEndForStream(Http2StreamId stream_id) override;
+
+ const EventSequence& GetEventSequence() const { return events_; }
+ void Clear() { events_.clear(); }
+
+ private:
+ EventSequence events_;
+};
+
+} // namespace test
+} // namespace adapter
+} // namespace http2
+
+#endif // QUICHE_HTTP2_ADAPTER_RECORDING_HTTP2_VISITOR_H_
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/recording_http2_visitor_test.cc b/chromium/net/third_party/quiche/src/http2/adapter/recording_http2_visitor_test.cc
new file mode 100644
index 00000000000..8f278d75dcb
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/recording_http2_visitor_test.cc
@@ -0,0 +1,135 @@
+#include "http2/adapter/recording_http2_visitor.h"
+
+#include <list>
+
+#include "http2/adapter/http2_protocol.h"
+#include "http2/test_tools/http2_random.h"
+#include "common/platform/api/quiche_test.h"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+namespace {
+
+using ::testing::IsEmpty;
+
+TEST(RecordingHttp2VisitorTest, EmptySequence) {
+ RecordingHttp2Visitor chocolate_visitor;
+ RecordingHttp2Visitor vanilla_visitor;
+
+ EXPECT_THAT(chocolate_visitor.GetEventSequence(), IsEmpty());
+ EXPECT_THAT(vanilla_visitor.GetEventSequence(), IsEmpty());
+ EXPECT_EQ(chocolate_visitor.GetEventSequence(),
+ vanilla_visitor.GetEventSequence());
+
+ chocolate_visitor.OnSettingsStart();
+
+ EXPECT_THAT(chocolate_visitor.GetEventSequence(), testing::Not(IsEmpty()));
+ EXPECT_THAT(vanilla_visitor.GetEventSequence(), IsEmpty());
+ EXPECT_NE(chocolate_visitor.GetEventSequence(),
+ vanilla_visitor.GetEventSequence());
+
+ chocolate_visitor.Clear();
+
+ EXPECT_THAT(chocolate_visitor.GetEventSequence(), IsEmpty());
+ EXPECT_THAT(vanilla_visitor.GetEventSequence(), IsEmpty());
+ EXPECT_EQ(chocolate_visitor.GetEventSequence(),
+ vanilla_visitor.GetEventSequence());
+}
+
+TEST(RecordingHttp2VisitorTest, SameEventsProduceSameSequence) {
+ RecordingHttp2Visitor chocolate_visitor;
+ RecordingHttp2Visitor vanilla_visitor;
+
+ // Prepare some random values to deliver with the events.
+ http2::test::Http2Random random;
+ const Http2StreamId stream_id = random.Uniform(kMaxStreamId);
+ const Http2StreamId another_stream_id = random.Uniform(kMaxStreamId);
+ const size_t length = random.Rand16();
+ const uint8_t type = random.Rand8();
+ const uint8_t flags = random.Rand8();
+ const Http2ErrorCode error_code = static_cast<Http2ErrorCode>(
+ random.Uniform(static_cast<int>(Http2ErrorCode::MAX_ERROR_CODE)));
+ const Http2Setting setting = {.id = random.Rand16(),
+ .value = random.Rand32()};
+ const absl::string_view alphabet = "abcdefghijklmnopqrstuvwxyz0123456789-";
+ const std::string some_string =
+ random.RandStringWithAlphabet(random.Rand8(), alphabet);
+ const std::string another_string =
+ random.RandStringWithAlphabet(random.Rand8(), alphabet);
+ const uint16_t some_int = random.Rand16();
+ const bool some_bool = random.OneIn(2);
+
+ // Send the same arbitrary sequence of events to both visitors.
+ std::list<RecordingHttp2Visitor*> visitors = {&chocolate_visitor,
+ &vanilla_visitor};
+ for (RecordingHttp2Visitor* visitor : visitors) {
+ visitor->OnConnectionError();
+ visitor->OnFrameHeader(stream_id, length, type, flags);
+ visitor->OnSettingsStart();
+ visitor->OnSetting(setting);
+ visitor->OnSettingsEnd();
+ visitor->OnSettingsAck();
+ visitor->OnBeginHeadersForStream(stream_id);
+ visitor->OnHeaderForStream(stream_id, some_string, another_string);
+ visitor->OnEndHeadersForStream(stream_id);
+ visitor->OnBeginDataForStream(stream_id, length);
+ visitor->OnDataForStream(stream_id, some_string);
+ visitor->OnDataForStream(stream_id, another_string);
+ visitor->OnEndStream(stream_id);
+ visitor->OnRstStream(stream_id, error_code);
+ visitor->OnCloseStream(stream_id, error_code);
+ visitor->OnPriorityForStream(stream_id, another_stream_id, some_int,
+ some_bool);
+ visitor->OnPing(some_int, some_bool);
+ visitor->OnPushPromiseForStream(stream_id, another_stream_id);
+ visitor->OnGoAway(stream_id, error_code, some_string);
+ visitor->OnWindowUpdate(stream_id, some_int);
+ visitor->OnReadyToSendDataForStream(
+ stream_id, /*destination_buffer=*/nullptr, length, /*written=*/nullptr,
+ /*end_stream=*/nullptr);
+ visitor->OnReadyToSendMetadataForStream(stream_id, /*buffer=*/nullptr,
+ length, /*written=*/nullptr);
+ visitor->OnBeginMetadataForStream(stream_id, length);
+ visitor->OnMetadataForStream(stream_id, some_string);
+ visitor->OnMetadataForStream(stream_id, another_string);
+ visitor->OnMetadataEndForStream(stream_id);
+ }
+
+ EXPECT_EQ(chocolate_visitor.GetEventSequence(),
+ vanilla_visitor.GetEventSequence());
+}
+
+TEST(RecordingHttp2VisitorTest, DifferentEventsProduceDifferentSequence) {
+ RecordingHttp2Visitor chocolate_visitor;
+ RecordingHttp2Visitor vanilla_visitor;
+ EXPECT_EQ(chocolate_visitor.GetEventSequence(),
+ vanilla_visitor.GetEventSequence());
+
+ const Http2StreamId stream_id = 1;
+ const size_t length = 42;
+
+ // Different events with the same method arguments should produce different
+ // event sequences.
+ chocolate_visitor.OnBeginDataForStream(stream_id, length);
+ vanilla_visitor.OnBeginMetadataForStream(stream_id, length);
+ EXPECT_NE(chocolate_visitor.GetEventSequence(),
+ vanilla_visitor.GetEventSequence());
+
+ chocolate_visitor.Clear();
+ vanilla_visitor.Clear();
+ EXPECT_EQ(chocolate_visitor.GetEventSequence(),
+ vanilla_visitor.GetEventSequence());
+
+ // The same events with different method arguments should produce different
+ // event sequences.
+ chocolate_visitor.OnBeginHeadersForStream(stream_id);
+ vanilla_visitor.OnBeginHeadersForStream(stream_id + 2);
+ EXPECT_NE(chocolate_visitor.GetEventSequence(),
+ vanilla_visitor.GetEventSequence());
+}
+
+} // namespace
+} // namespace test
+} // namespace adapter
+} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/test_frame_sequence.cc b/chromium/net/third_party/quiche/src/http2/adapter/test_frame_sequence.cc
index 46d33b61798..7be368ea6a5 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/test_frame_sequence.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/test_frame_sequence.cc
@@ -1,12 +1,22 @@
#include "http2/adapter/test_frame_sequence.h"
#include "http2/adapter/http2_util.h"
+#include "http2/adapter/oghttp2_util.h"
#include "spdy/core/spdy_framer.h"
namespace http2 {
namespace adapter {
namespace test {
+std::vector<const Header> ToHeaders(
+ absl::Span<const std::pair<absl::string_view, absl::string_view>> headers) {
+ std::vector<const Header> out;
+ for (auto [name, value] : headers) {
+ out.push_back(std::make_pair(HeaderRep(name), HeaderRep(value)));
+ }
+ return out;
+}
+
TestFrameSequence& TestFrameSequence::ClientPreface() {
preface_ = spdy::kHttp2ConnectionHeaderPrefix;
frames_.push_back(absl::make_unique<spdy::SpdySettingsIR>());
@@ -75,6 +85,13 @@ TestFrameSequence& TestFrameSequence::GoAway(Http2StreamId last_good_stream_id,
return *this;
}
+TestFrameSequence& TestFrameSequence::Headers(
+ Http2StreamId stream_id,
+ absl::Span<const std::pair<absl::string_view, absl::string_view>> headers,
+ bool fin) {
+ return Headers(stream_id, ToHeaders(headers), fin);
+}
+
TestFrameSequence& TestFrameSequence::Headers(Http2StreamId stream_id,
spdy::Http2HeaderBlock block,
bool fin) {
@@ -88,11 +105,7 @@ TestFrameSequence& TestFrameSequence::Headers(Http2StreamId stream_id,
TestFrameSequence& TestFrameSequence::Headers(Http2StreamId stream_id,
absl::Span<const Header> headers,
bool fin) {
- spdy::SpdyHeaderBlock block;
- for (const Header& header : headers) {
- block[header.first] = header.second;
- }
- return Headers(stream_id, std::move(block), fin);
+ return Headers(stream_id, ToHeaderBlock(headers), fin);
}
TestFrameSequence& TestFrameSequence::WindowUpdate(Http2StreamId stream_id,
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/test_frame_sequence.h b/chromium/net/third_party/quiche/src/http2/adapter/test_frame_sequence.h
index dd110c1a729..cc5e8b5ff57 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/test_frame_sequence.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/test_frame_sequence.h
@@ -12,6 +12,9 @@ namespace http2 {
namespace adapter {
namespace test {
+std::vector<const Header> ToHeaders(
+ absl::Span<const std::pair<absl::string_view, absl::string_view>> headers);
+
class TestFrameSequence {
public:
TestFrameSequence() = default;
@@ -30,6 +33,10 @@ class TestFrameSequence {
TestFrameSequence& GoAway(Http2StreamId last_good_stream_id,
Http2ErrorCode error,
absl::string_view payload = "");
+ TestFrameSequence& Headers(
+ Http2StreamId stream_id,
+ absl::Span<const std::pair<absl::string_view, absl::string_view>> headers,
+ bool fin = false);
TestFrameSequence& Headers(Http2StreamId stream_id,
spdy::Http2HeaderBlock block,
bool fin = false);
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/test_utils.cc b/chromium/net/third_party/quiche/src/http2/adapter/test_utils.cc
index 9e1db9954f2..315a28f0717 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/test_utils.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/test_utils.cc
@@ -1,5 +1,7 @@
#include "http2/adapter/test_utils.h"
+#include "http2/adapter/nghttp2_util.h"
+#include "common/quiche_endian.h"
#include "spdy/core/spdy_frame_reader.h"
namespace http2 {
@@ -23,17 +25,15 @@ std::vector<std::pair<const char*, std::string>> LogFriendly(
return out;
}
-// Custom gMock matcher, used to determine if a particular type of frame
-// is in a string. This is useful in tests where we want to show that a
-// particular control frame type is serialized for sending to the peer.
+// Custom gMock matcher, used to implement EqualsFrames().
class SpdyControlFrameMatcher
- : public testing::MatcherInterface<const std::string> {
+ : public testing::MatcherInterface<absl::string_view> {
public:
explicit SpdyControlFrameMatcher(
std::vector<TypeAndOptionalLength> types_and_lengths)
: expected_types_and_lengths_(std::move(types_and_lengths)) {}
- bool MatchAndExplain(const std::string s,
+ bool MatchAndExplain(absl::string_view s,
testing::MatchResultListener* listener) const override {
spdy::SpdyFrameReader reader(s.data(), s.size());
@@ -43,6 +43,11 @@ class SpdyControlFrameMatcher
return false;
}
}
+ if (!reader.IsDoneReading()) {
+ size_t bytes_remaining = s.size() - reader.GetBytesConsumed();
+ *listener << "; " << bytes_remaining << " bytes left to read!";
+ return false;
+ }
return true;
}
@@ -103,15 +108,355 @@ class SpdyControlFrameMatcher
const std::vector<TypeAndOptionalLength> expected_types_and_lengths_;
};
+// Custom gMock matcher, used to implement HasFrameHeader().
+class FrameHeaderMatcher
+ : public testing::MatcherInterface<const nghttp2_frame_hd*> {
+ public:
+ FrameHeaderMatcher(int32_t streamid,
+ uint8_t type,
+ const testing::Matcher<int> flags)
+ : stream_id_(streamid), type_(type), flags_(flags) {}
+
+ bool MatchAndExplain(const nghttp2_frame_hd* frame,
+ testing::MatchResultListener* listener) const override {
+ bool matched = true;
+ if (stream_id_ != frame->stream_id) {
+ *listener << "; expected stream " << stream_id_ << ", saw "
+ << frame->stream_id;
+ matched = false;
+ }
+ if (type_ != frame->type) {
+ *listener << "; expected frame type " << type_ << ", saw "
+ << static_cast<int>(frame->type);
+ matched = false;
+ }
+ if (!flags_.MatchAndExplain(frame->flags, listener)) {
+ matched = false;
+ }
+ return matched;
+ }
+
+ void DescribeTo(std::ostream* os) const override {
+ *os << "contains a frame header with stream " << stream_id_ << ", type "
+ << type_ << ", ";
+ flags_.DescribeTo(os);
+ }
+
+ void DescribeNegationTo(std::ostream* os) const override {
+ *os << "does not contain a frame header with stream " << stream_id_
+ << ", type " << type_ << ", ";
+ flags_.DescribeNegationTo(os);
+ }
+
+ private:
+ const int32_t stream_id_;
+ const int type_;
+ const testing::Matcher<int> flags_;
+};
+
+class DataMatcher : public testing::MatcherInterface<const nghttp2_frame*> {
+ public:
+ DataMatcher(const testing::Matcher<uint32_t> stream_id,
+ const testing::Matcher<size_t> length,
+ const testing::Matcher<int> flags)
+ : stream_id_(stream_id), length_(length), flags_(flags) {}
+
+ bool MatchAndExplain(const nghttp2_frame* frame,
+ testing::MatchResultListener* listener) const override {
+ if (frame->hd.type != NGHTTP2_DATA) {
+ *listener << "; expected DATA frame, saw frame of type "
+ << static_cast<int>(frame->hd.type);
+ return false;
+ }
+ bool matched = true;
+ if (!stream_id_.MatchAndExplain(frame->hd.stream_id, listener)) {
+ matched = false;
+ }
+ if (!length_.MatchAndExplain(frame->hd.length, listener)) {
+ matched = false;
+ }
+ if (!flags_.MatchAndExplain(frame->hd.flags, listener)) {
+ matched = false;
+ }
+ return matched;
+ }
+
+ void DescribeTo(std::ostream* os) const override {
+ *os << "contains a DATA frame, ";
+ stream_id_.DescribeTo(os);
+ length_.DescribeTo(os);
+ flags_.DescribeTo(os);
+ }
+
+ void DescribeNegationTo(std::ostream* os) const override {
+ *os << "does not contain a DATA frame, ";
+ stream_id_.DescribeNegationTo(os);
+ length_.DescribeNegationTo(os);
+ flags_.DescribeNegationTo(os);
+ }
+
+ private:
+ const testing::Matcher<uint32_t> stream_id_;
+ const testing::Matcher<size_t> length_;
+ const testing::Matcher<int> flags_;
+};
+
+class HeadersMatcher : public testing::MatcherInterface<const nghttp2_frame*> {
+ public:
+ HeadersMatcher(const testing::Matcher<uint32_t> stream_id,
+ const testing::Matcher<int> flags,
+ const testing::Matcher<int> category)
+ : stream_id_(stream_id), flags_(flags), category_(category) {}
+
+ bool MatchAndExplain(const nghttp2_frame* frame,
+ testing::MatchResultListener* listener) const override {
+ if (frame->hd.type != NGHTTP2_HEADERS) {
+ *listener << "; expected HEADERS frame, saw frame of type "
+ << static_cast<int>(frame->hd.type);
+ return false;
+ }
+ bool matched = true;
+ if (!stream_id_.MatchAndExplain(frame->hd.stream_id, listener)) {
+ matched = false;
+ }
+ if (!flags_.MatchAndExplain(frame->hd.flags, listener)) {
+ matched = false;
+ }
+ if (!category_.MatchAndExplain(frame->headers.cat, listener)) {
+ matched = false;
+ }
+ return matched;
+ }
+
+ void DescribeTo(std::ostream* os) const override {
+ *os << "contains a HEADERS frame, ";
+ stream_id_.DescribeTo(os);
+ flags_.DescribeTo(os);
+ category_.DescribeTo(os);
+ }
+
+ void DescribeNegationTo(std::ostream* os) const override {
+ *os << "does not contain a HEADERS frame, ";
+ stream_id_.DescribeNegationTo(os);
+ flags_.DescribeNegationTo(os);
+ category_.DescribeNegationTo(os);
+ }
+
+ private:
+ const testing::Matcher<uint32_t> stream_id_;
+ const testing::Matcher<int> flags_;
+ const testing::Matcher<int> category_;
+};
+
+class RstStreamMatcher
+ : public testing::MatcherInterface<const nghttp2_frame*> {
+ public:
+ RstStreamMatcher(const testing::Matcher<uint32_t> stream_id,
+ const testing::Matcher<uint32_t> error_code)
+ : stream_id_(stream_id), error_code_(error_code) {}
+
+ bool MatchAndExplain(const nghttp2_frame* frame,
+ testing::MatchResultListener* listener) const override {
+ if (frame->hd.type != NGHTTP2_RST_STREAM) {
+ *listener << "; expected RST_STREAM frame, saw frame of type "
+ << static_cast<int>(frame->hd.type);
+ return false;
+ }
+ bool matched = true;
+ if (!stream_id_.MatchAndExplain(frame->hd.stream_id, listener)) {
+ matched = false;
+ }
+ if (!error_code_.MatchAndExplain(frame->rst_stream.error_code, listener)) {
+ matched = false;
+ }
+ return matched;
+ }
+
+ void DescribeTo(std::ostream* os) const override {
+ *os << "contains a RST_STREAM frame, ";
+ stream_id_.DescribeTo(os);
+ error_code_.DescribeTo(os);
+ }
+
+ void DescribeNegationTo(std::ostream* os) const override {
+ *os << "does not contain a RST_STREAM frame, ";
+ stream_id_.DescribeNegationTo(os);
+ error_code_.DescribeNegationTo(os);
+ }
+
+ private:
+ const testing::Matcher<uint32_t> stream_id_;
+ const testing::Matcher<uint32_t> error_code_;
+};
+
+class SettingsMatcher : public testing::MatcherInterface<const nghttp2_frame*> {
+ public:
+ SettingsMatcher(const testing::Matcher<std::vector<Http2Setting>> values)
+ : values_(values) {}
+
+ bool MatchAndExplain(const nghttp2_frame* frame,
+ testing::MatchResultListener* listener) const override {
+ if (frame->hd.type != NGHTTP2_SETTINGS) {
+ *listener << "; expected SETTINGS frame, saw frame of type "
+ << static_cast<int>(frame->hd.type);
+ return false;
+ }
+ std::vector<Http2Setting> settings;
+ settings.reserve(frame->settings.niv);
+ for (int i = 0; i < frame->settings.niv; ++i) {
+ const auto& p = frame->settings.iv[i];
+ settings.push_back({static_cast<uint16_t>(p.settings_id), p.value});
+ }
+ return values_.MatchAndExplain(settings, listener);
+ }
+
+ void DescribeTo(std::ostream* os) const override {
+ *os << "contains a SETTINGS frame, ";
+ values_.DescribeTo(os);
+ }
+
+ void DescribeNegationTo(std::ostream* os) const override {
+ *os << "does not contain a SETTINGS frame, ";
+ values_.DescribeNegationTo(os);
+ }
+
+ private:
+ const testing::Matcher<std::vector<Http2Setting>> values_;
+};
+
+class PingMatcher : public testing::MatcherInterface<const nghttp2_frame*> {
+ public:
+ PingMatcher(const testing::Matcher<uint64_t> id, bool is_ack)
+ : id_(id), is_ack_(is_ack) {}
+
+ bool MatchAndExplain(const nghttp2_frame* frame,
+ testing::MatchResultListener* listener) const override {
+ if (frame->hd.type != NGHTTP2_PING) {
+ *listener << "; expected PING frame, saw frame of type "
+ << static_cast<int>(frame->hd.type);
+ return false;
+ }
+ bool matched = true;
+ bool frame_ack = frame->hd.flags & NGHTTP2_FLAG_ACK;
+ if (is_ack_ != frame_ack) {
+ *listener << "; expected is_ack=" << is_ack_ << ", saw " << frame_ack;
+ matched = false;
+ }
+ uint64_t data;
+ std::memcpy(&data, frame->ping.opaque_data, sizeof(data));
+ data = quiche::QuicheEndian::HostToNet64(data);
+ if (!id_.MatchAndExplain(data, listener)) {
+ matched = false;
+ }
+ return matched;
+ }
+
+ void DescribeTo(std::ostream* os) const override {
+ *os << "contains a PING frame, ";
+ id_.DescribeTo(os);
+ }
+
+ void DescribeNegationTo(std::ostream* os) const override {
+ *os << "does not contain a PING frame, ";
+ id_.DescribeNegationTo(os);
+ }
+
+ private:
+ const testing::Matcher<uint64_t> id_;
+ const bool is_ack_;
+};
+
+class GoAwayMatcher : public testing::MatcherInterface<const nghttp2_frame*> {
+ public:
+ GoAwayMatcher(const testing::Matcher<uint32_t> last_stream_id,
+ const testing::Matcher<uint32_t> error_code,
+ const testing::Matcher<absl::string_view> opaque_data)
+ : last_stream_id_(last_stream_id),
+ error_code_(error_code),
+ opaque_data_(opaque_data) {}
+
+ bool MatchAndExplain(const nghttp2_frame* frame,
+ testing::MatchResultListener* listener) const override {
+ if (frame->hd.type != NGHTTP2_GOAWAY) {
+ *listener << "; expected GOAWAY frame, saw frame of type "
+ << static_cast<int>(frame->hd.type);
+ return false;
+ }
+ bool matched = true;
+ if (!last_stream_id_.MatchAndExplain(frame->goaway.last_stream_id,
+ listener)) {
+ matched = false;
+ }
+ if (!error_code_.MatchAndExplain(frame->goaway.error_code, listener)) {
+ matched = false;
+ }
+ auto opaque_data =
+ ToStringView(frame->goaway.opaque_data, frame->goaway.opaque_data_len);
+ if (!opaque_data_.MatchAndExplain(opaque_data, listener)) {
+ matched = false;
+ }
+ return matched;
+ }
+
+ void DescribeTo(std::ostream* os) const override {
+ *os << "contains a GOAWAY frame, ";
+ last_stream_id_.DescribeTo(os);
+ error_code_.DescribeTo(os);
+ opaque_data_.DescribeTo(os);
+ }
+
+ void DescribeNegationTo(std::ostream* os) const override {
+ *os << "does not contain a GOAWAY frame, ";
+ last_stream_id_.DescribeNegationTo(os);
+ error_code_.DescribeNegationTo(os);
+ opaque_data_.DescribeNegationTo(os);
+ }
+
+ private:
+ const testing::Matcher<uint32_t> last_stream_id_;
+ const testing::Matcher<uint32_t> error_code_;
+ const testing::Matcher<absl::string_view> opaque_data_;
+};
+
+class WindowUpdateMatcher
+ : public testing::MatcherInterface<const nghttp2_frame*> {
+ public:
+ WindowUpdateMatcher(const testing::Matcher<uint32_t> delta) : delta_(delta) {}
+
+ bool MatchAndExplain(const nghttp2_frame* frame,
+ testing::MatchResultListener* listener) const override {
+ if (frame->hd.type != NGHTTP2_WINDOW_UPDATE) {
+ *listener << "; expected WINDOW_UPDATE frame, saw frame of type "
+ << static_cast<int>(frame->hd.type);
+ return false;
+ }
+ return delta_.MatchAndExplain(frame->window_update.window_size_increment,
+ listener);
+ }
+
+ void DescribeTo(std::ostream* os) const override {
+ *os << "contains a WINDOW_UPDATE frame, ";
+ delta_.DescribeTo(os);
+ }
+
+ void DescribeNegationTo(std::ostream* os) const override {
+ *os << "does not contain a WINDOW_UPDATE frame, ";
+ delta_.DescribeNegationTo(os);
+ }
+
+ private:
+ const testing::Matcher<uint32_t> delta_;
+};
+
} // namespace
-testing::Matcher<const std::string> ContainsFrames(
+testing::Matcher<absl::string_view> EqualsFrames(
std::vector<std::pair<spdy::SpdyFrameType, absl::optional<size_t>>>
types_and_lengths) {
return MakeMatcher(new SpdyControlFrameMatcher(std::move(types_and_lengths)));
}
-testing::Matcher<const std::string> ContainsFrames(
+testing::Matcher<absl::string_view> EqualsFrames(
std::vector<spdy::SpdyFrameType> types) {
std::vector<std::pair<spdy::SpdyFrameType, absl::optional<size_t>>>
types_and_lengths;
@@ -122,6 +467,61 @@ testing::Matcher<const std::string> ContainsFrames(
return MakeMatcher(new SpdyControlFrameMatcher(std::move(types_and_lengths)));
}
+testing::Matcher<const nghttp2_frame_hd*> HasFrameHeader(
+ uint32_t streamid,
+ uint8_t type,
+ const testing::Matcher<int> flags) {
+ return MakeMatcher(new FrameHeaderMatcher(streamid, type, flags));
+}
+
+testing::Matcher<const nghttp2_frame*> IsData(
+ const testing::Matcher<uint32_t> stream_id,
+ const testing::Matcher<size_t> length,
+ const testing::Matcher<int> flags) {
+ return MakeMatcher(new DataMatcher(stream_id, length, flags));
+}
+
+testing::Matcher<const nghttp2_frame*> IsHeaders(
+ const testing::Matcher<uint32_t> stream_id,
+ const testing::Matcher<int> flags,
+ const testing::Matcher<int> category) {
+ return MakeMatcher(new HeadersMatcher(stream_id, flags, category));
+}
+
+testing::Matcher<const nghttp2_frame*> IsRstStream(
+ const testing::Matcher<uint32_t> stream_id,
+ const testing::Matcher<uint32_t> error_code) {
+ return MakeMatcher(new RstStreamMatcher(stream_id, error_code));
+}
+
+testing::Matcher<const nghttp2_frame*> IsSettings(
+ const testing::Matcher<std::vector<Http2Setting>> values) {
+ return MakeMatcher(new SettingsMatcher(values));
+}
+
+testing::Matcher<const nghttp2_frame*> IsPing(
+ const testing::Matcher<uint64_t> id) {
+ return MakeMatcher(new PingMatcher(id, false));
+}
+
+testing::Matcher<const nghttp2_frame*> IsPingAck(
+ const testing::Matcher<uint64_t> id) {
+ return MakeMatcher(new PingMatcher(id, true));
+}
+
+testing::Matcher<const nghttp2_frame*> IsGoAway(
+ const testing::Matcher<uint32_t> last_stream_id,
+ const testing::Matcher<uint32_t> error_code,
+ const testing::Matcher<absl::string_view> opaque_data) {
+ return MakeMatcher(
+ new GoAwayMatcher(last_stream_id, error_code, opaque_data));
+}
+
+testing::Matcher<const nghttp2_frame*> IsWindowUpdate(
+ const testing::Matcher<uint32_t> delta) {
+ return MakeMatcher(new WindowUpdateMatcher(delta));
+}
+
} // namespace test
} // namespace adapter
} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/test_utils.h b/chromium/net/third_party/quiche/src/http2/adapter/test_utils.h
index 6276bf1fe45..ef1ae29a650 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/test_utils.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/test_utils.h
@@ -4,6 +4,10 @@
#include <string>
#include <vector>
+#include "absl/strings/string_view.h"
+#include "http2/adapter/http2_protocol.h"
+#include "http2/adapter/mock_http2_visitor.h"
+#include "third_party/nghttp2/src/lib/includes/nghttp2/nghttp2.h"
#include "common/platform/api/quiche_test.h"
#include "spdy/core/spdy_protocol.h"
@@ -11,17 +15,68 @@ namespace http2 {
namespace adapter {
namespace test {
-// Matcher that checks whether a string contains HTTP/2 frames of the specified
-// ordered sequence of types and lengths.
-testing::Matcher<const std::string> ContainsFrames(
+class DataSavingVisitor : public testing::StrictMock<MockHttp2Visitor> {
+ public:
+ void Save(absl::string_view data) { absl::StrAppend(&data_, data); }
+
+ const std::string& data() { return data_; }
+ void Clear() { data_.clear(); }
+
+ private:
+ std::string data_;
+};
+
+// These matchers check whether a string consists entirely of HTTP/2 frames of
+// the specified ordered sequence. This is useful in tests where we want to show
+// that one or more particular frame types are serialized for sending to the
+// peer. The match will fail if there are input bytes not consumed by the
+// matcher.
+
+// Requires that frames match both types and lengths.
+testing::Matcher<absl::string_view> EqualsFrames(
std::vector<std::pair<spdy::SpdyFrameType, absl::optional<size_t>>>
types_and_lengths);
-// Matcher that checks whether a string contains HTTP/2 frames of the specified
-// ordered sequence of types.
-testing::Matcher<const std::string> ContainsFrames(
+// Requires that frames match the specified types.
+testing::Matcher<absl::string_view> EqualsFrames(
std::vector<spdy::SpdyFrameType> types);
+testing::Matcher<const nghttp2_frame_hd*> HasFrameHeader(
+ uint32_t streamid,
+ uint8_t type,
+ const testing::Matcher<int> flags);
+
+testing::Matcher<const nghttp2_frame*> IsData(
+ const testing::Matcher<uint32_t> stream_id,
+ const testing::Matcher<size_t> length,
+ const testing::Matcher<int> flags);
+
+testing::Matcher<const nghttp2_frame*> IsHeaders(
+ const testing::Matcher<uint32_t> stream_id,
+ const testing::Matcher<int> flags,
+ const testing::Matcher<int> category);
+
+testing::Matcher<const nghttp2_frame*> IsRstStream(
+ const testing::Matcher<uint32_t> stream_id,
+ const testing::Matcher<uint32_t> error_code);
+
+testing::Matcher<const nghttp2_frame*> IsSettings(
+ const testing::Matcher<std::vector<Http2Setting>> values);
+
+testing::Matcher<const nghttp2_frame*> IsPing(
+ const testing::Matcher<uint64_t> id);
+
+testing::Matcher<const nghttp2_frame*> IsPingAck(
+ const testing::Matcher<uint64_t> id);
+
+testing::Matcher<const nghttp2_frame*> IsGoAway(
+ const testing::Matcher<uint32_t> last_stream_id,
+ const testing::Matcher<uint32_t> error_code,
+ const testing::Matcher<absl::string_view> opaque_data);
+
+testing::Matcher<const nghttp2_frame*> IsWindowUpdate(
+ const testing::Matcher<uint32_t> delta);
+
} // namespace test
} // namespace adapter
} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/test_utils_test.cc b/chromium/net/third_party/quiche/src/http2/adapter/test_utils_test.cc
index e8f4ebda350..0de7b28ff6a 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/test_utils_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/test_utils_test.cc
@@ -10,38 +10,37 @@ namespace {
using spdy::SpdyFramer;
-TEST(ContainsFrames, Empty) {
- EXPECT_THAT("", ContainsFrames(std::vector<spdy::SpdyFrameType>{}));
+TEST(EqualsFrames, Empty) {
+ EXPECT_THAT("", EqualsFrames(std::vector<spdy::SpdyFrameType>{}));
}
-TEST(ContainsFrames, SingleFrameWithLength) {
+TEST(EqualsFrames, SingleFrameWithLength) {
SpdyFramer framer{SpdyFramer::ENABLE_COMPRESSION};
spdy::SpdyPingIR ping{511};
EXPECT_THAT(framer.SerializeFrame(ping),
- ContainsFrames({{spdy::SpdyFrameType::PING, 8}}));
+ EqualsFrames({{spdy::SpdyFrameType::PING, 8}}));
spdy::SpdyWindowUpdateIR window_update{1, 101};
EXPECT_THAT(framer.SerializeFrame(window_update),
- ContainsFrames({{spdy::SpdyFrameType::WINDOW_UPDATE, 4}}));
+ EqualsFrames({{spdy::SpdyFrameType::WINDOW_UPDATE, 4}}));
spdy::SpdyDataIR data{3, "Some example data, ha ha!"};
EXPECT_THAT(framer.SerializeFrame(data),
- ContainsFrames({{spdy::SpdyFrameType::DATA, 25}}));
+ EqualsFrames({{spdy::SpdyFrameType::DATA, 25}}));
}
-TEST(ContainsFrames, SingleFrameWithoutLength) {
+TEST(EqualsFrames, SingleFrameWithoutLength) {
SpdyFramer framer{SpdyFramer::ENABLE_COMPRESSION};
spdy::SpdyRstStreamIR rst_stream{7, spdy::ERROR_CODE_REFUSED_STREAM};
- EXPECT_THAT(
- framer.SerializeFrame(rst_stream),
- ContainsFrames({{spdy::SpdyFrameType::RST_STREAM, absl::nullopt}}));
+ EXPECT_THAT(framer.SerializeFrame(rst_stream),
+ EqualsFrames({{spdy::SpdyFrameType::RST_STREAM, absl::nullopt}}));
spdy::SpdyGoAwayIR goaway{13, spdy::ERROR_CODE_ENHANCE_YOUR_CALM,
"Consider taking some deep breaths."};
EXPECT_THAT(framer.SerializeFrame(goaway),
- ContainsFrames({{spdy::SpdyFrameType::GOAWAY, absl::nullopt}}));
+ EqualsFrames({{spdy::SpdyFrameType::GOAWAY, absl::nullopt}}));
spdy::Http2HeaderBlock block;
block[":method"] = "GET";
@@ -49,10 +48,10 @@ TEST(ContainsFrames, SingleFrameWithoutLength) {
block[":authority"] = "example.com";
spdy::SpdyHeadersIR headers{17, std::move(block)};
EXPECT_THAT(framer.SerializeFrame(headers),
- ContainsFrames({{spdy::SpdyFrameType::HEADERS, absl::nullopt}}));
+ EqualsFrames({{spdy::SpdyFrameType::HEADERS, absl::nullopt}}));
}
-TEST(ContainsFrames, MultipleFrames) {
+TEST(EqualsFrames, MultipleFrames) {
SpdyFramer framer{SpdyFramer::ENABLE_COMPRESSION};
spdy::SpdyPingIR ping{511};
@@ -74,20 +73,48 @@ TEST(ContainsFrames, MultipleFrames) {
absl::string_view(framer.SerializeFrame(rst_stream)),
absl::string_view(framer.SerializeFrame(goaway)),
absl::string_view(framer.SerializeFrame(headers)));
+ absl::string_view frame_sequence_view = frame_sequence;
+ EXPECT_THAT(frame_sequence,
+ EqualsFrames({{spdy::SpdyFrameType::PING, absl::nullopt},
+ {spdy::SpdyFrameType::WINDOW_UPDATE, absl::nullopt},
+ {spdy::SpdyFrameType::DATA, 25},
+ {spdy::SpdyFrameType::RST_STREAM, absl::nullopt},
+ {spdy::SpdyFrameType::GOAWAY, 42},
+ {spdy::SpdyFrameType::HEADERS, 19}}));
+ EXPECT_THAT(frame_sequence_view,
+ EqualsFrames({{spdy::SpdyFrameType::PING, absl::nullopt},
+ {spdy::SpdyFrameType::WINDOW_UPDATE, absl::nullopt},
+ {spdy::SpdyFrameType::DATA, 25},
+ {spdy::SpdyFrameType::RST_STREAM, absl::nullopt},
+ {spdy::SpdyFrameType::GOAWAY, 42},
+ {spdy::SpdyFrameType::HEADERS, 19}}));
EXPECT_THAT(
frame_sequence,
- ContainsFrames({{spdy::SpdyFrameType::PING, absl::nullopt},
- {spdy::SpdyFrameType::WINDOW_UPDATE, absl::nullopt},
- {spdy::SpdyFrameType::DATA, 25},
- {spdy::SpdyFrameType::RST_STREAM, absl::nullopt},
- {spdy::SpdyFrameType::GOAWAY, 42},
- {spdy::SpdyFrameType::HEADERS, 19}}));
+ EqualsFrames(
+ {spdy::SpdyFrameType::PING, spdy::SpdyFrameType::WINDOW_UPDATE,
+ spdy::SpdyFrameType::DATA, spdy::SpdyFrameType::RST_STREAM,
+ spdy::SpdyFrameType::GOAWAY, spdy::SpdyFrameType::HEADERS}));
EXPECT_THAT(
- frame_sequence,
- ContainsFrames(
+ frame_sequence_view,
+ EqualsFrames(
{spdy::SpdyFrameType::PING, spdy::SpdyFrameType::WINDOW_UPDATE,
spdy::SpdyFrameType::DATA, spdy::SpdyFrameType::RST_STREAM,
spdy::SpdyFrameType::GOAWAY, spdy::SpdyFrameType::HEADERS}));
+
+ // If the final frame type is removed the expectation fails, as there are
+ // bytes left to read.
+ EXPECT_THAT(
+ frame_sequence,
+ testing::Not(EqualsFrames(
+ {spdy::SpdyFrameType::PING, spdy::SpdyFrameType::WINDOW_UPDATE,
+ spdy::SpdyFrameType::DATA, spdy::SpdyFrameType::RST_STREAM,
+ spdy::SpdyFrameType::GOAWAY})));
+ EXPECT_THAT(
+ frame_sequence_view,
+ testing::Not(EqualsFrames(
+ {spdy::SpdyFrameType::PING, spdy::SpdyFrameType::WINDOW_UPDATE,
+ spdy::SpdyFrameType::DATA, spdy::SpdyFrameType::RST_STREAM,
+ spdy::SpdyFrameType::GOAWAY})));
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/window_manager.cc b/chromium/net/third_party/quiche/src/http2/adapter/window_manager.cc
index a1b92d5bf2c..de45dc3497b 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/window_manager.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/window_manager.cc
@@ -2,8 +2,8 @@
#include <utility>
+#include "common/platform/api/quiche_bug_tracker.h"
#include "common/platform/api/quiche_logging.h"
-#include "spdy/platform/api/spdy_bug_tracker.h"
namespace http2 {
namespace adapter {
@@ -20,7 +20,7 @@ void WindowManager::OnWindowSizeLimitChange(const size_t new_limit) {
if (new_limit > limit_) {
window_ += (new_limit - limit_);
} else {
- SPDY_BUG(H2 window decrease)
+ QUICHE_BUG(H2 window decrease)
<< "Window size limit decrease not currently supported.";
}
limit_ = new_limit;
@@ -56,8 +56,8 @@ void WindowManager::MarkDataFlushed(size_t bytes) {
QUICHE_VLOG(2) << "WindowManager@" << this << " buffered: " << buffered_
<< " bytes: " << bytes;
if (buffered_ < bytes) {
- SPDY_BUG(bug_2816_1) << "WindowManager@" << this << " buffered underflow "
- << "buffered_: " << buffered_ << " bytes: " << bytes;
+ QUICHE_BUG(bug_2816_1) << "WindowManager@" << this << " buffered underflow "
+ << "buffered_: " << buffered_ << " bytes: " << bytes;
buffered_ = 0;
} else {
buffered_ -= bytes;
@@ -73,7 +73,6 @@ void WindowManager::MaybeNotifyListener() {
}
// For the sake of efficiency, we want to send window updates if less than
// half of the max quota is available to the peer at any point in time.
- // http://google3/gfe/gfe2/stubby/autobahn_fd_wrapper.cc?l=1180-1183&rcl=307416556
const size_t kDesiredMinWindow = limit_ / 2;
const size_t kDesiredMinDelta = limit_ / 3;
const size_t delta = limit_ - (buffered_ + window_);
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/window_manager_test.cc b/chromium/net/third_party/quiche/src/http2/adapter/window_manager_test.cc
index 549fd1c3e1a..5e0645365ec 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/window_manager_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/window_manager_test.cc
@@ -5,7 +5,7 @@
#include "absl/functional/bind_front.h"
#include "http2/test_tools/http2_random.h"
#include "common/platform/api/quiche_test.h"
-#include "spdy/platform/api/spdy_test_helpers.h"
+#include "common/platform/api/quiche_test_helpers.h"
namespace http2 {
namespace adapter {
@@ -97,13 +97,13 @@ TEST_F(WindowManagerTest, AvoidWindowUnderflow) {
TEST_F(WindowManagerTest, AvoidBufferedUnderflow) {
EXPECT_EQ(peer_.buffered(), 0);
// Don't flush more than has been buffered!
- EXPECT_SPDY_BUG(wm_.MarkDataFlushed(1), "buffered underflow");
+ EXPECT_QUICHE_BUG(wm_.MarkDataFlushed(1), "buffered underflow");
EXPECT_EQ(peer_.buffered(), 0);
wm_.MarkDataBuffered(42);
EXPECT_EQ(peer_.buffered(), 42);
// Don't flush more than has been buffered!
- EXPECT_SPDY_BUG(wm_.MarkDataFlushed(43), "buffered underflow");
+ EXPECT_QUICHE_BUG(wm_.MarkDataFlushed(43), "buffered underflow");
EXPECT_EQ(peer_.buffered(), 0);
}
diff --git a/chromium/net/third_party/quiche/src/spdy/core/http2_priority_write_scheduler.h b/chromium/net/third_party/quiche/src/http2/core/http2_priority_write_scheduler.h
index 5820145aac4..b7046e7023a 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/http2_priority_write_scheduler.h
+++ b/chromium/net/third_party/quiche/src/http2/core/http2_priority_write_scheduler.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_SPDY_CORE_HTTP2_PRIORITY_WRITE_SCHEDULER_H_
-#define QUICHE_SPDY_CORE_HTTP2_PRIORITY_WRITE_SCHEDULER_H_
+#ifndef QUICHE_HTTP2_CORE_HTTP2_PRIORITY_WRITE_SCHEDULER_H_
+#define QUICHE_HTTP2_CORE_HTTP2_PRIORITY_WRITE_SCHEDULER_H_
#include <cstdint>
#include <deque>
@@ -17,16 +17,16 @@
#include <utility>
#include <vector>
+#include "absl/container/flat_hash_map.h"
#include "absl/strings/str_cat.h"
+#include "http2/core/write_scheduler.h"
+#include "common/platform/api/quiche_bug_tracker.h"
+#include "common/platform/api/quiche_logging.h"
#include "spdy/core/spdy_intrusive_list.h"
#include "spdy/core/spdy_protocol.h"
-#include "spdy/core/write_scheduler.h"
-#include "spdy/platform/api/spdy_bug_tracker.h"
-#include "spdy/platform/api/spdy_containers.h"
-#include "spdy/platform/api/spdy_logging.h"
#include "spdy/platform/api/spdy_string_utils.h"
-namespace spdy {
+namespace http2 {
namespace test {
template <typename StreamIdType>
@@ -84,13 +84,13 @@ class Http2PriorityWriteScheduler : public WriteScheduler<StreamIdType> {
struct StreamInfo;
using StreamInfoVector = absl::InlinedVector<StreamInfo*, 4>;
- struct StreamInfo : public SpdyIntrusiveLink<StreamInfo> {
+ struct StreamInfo : public spdy::SpdyIntrusiveLink<StreamInfo> {
// ID for this stream.
StreamIdType id;
// StreamInfo for parent stream.
StreamInfo* parent = nullptr;
// Weights can range between 1 and 256 (inclusive).
- int weight = kHttp2DefaultStreamWeight;
+ int weight = spdy::kHttp2DefaultStreamWeight;
// The total weight of this stream's direct descendants.
int total_child_weights = 0;
// Pointers to StreamInfos for children, if any.
@@ -129,7 +129,7 @@ class Http2PriorityWriteScheduler : public WriteScheduler<StreamIdType> {
// Returns the StreamPrecedenceType for this StreamInfo.
StreamPrecedenceType ToStreamPrecedence() const {
StreamIdType parent_id =
- parent == nullptr ? kHttp2RootStreamId : parent->id;
+ parent == nullptr ? spdy::kHttp2RootStreamId : parent->id;
bool exclusive = parent != nullptr && parent->children.size() == 1;
return StreamPrecedenceType(parent_id, weight, exclusive);
}
@@ -178,7 +178,8 @@ class Http2PriorityWriteScheduler : public WriteScheduler<StreamIdType> {
// Pointee owned by all_stream_infos_.
StreamInfo* root_stream_info_;
// Maps from stream IDs to StreamInfo objects.
- SpdySmallMap<StreamIdType, std::unique_ptr<StreamInfo>, 10> all_stream_infos_;
+ absl::flat_hash_map<StreamIdType, std::unique_ptr<StreamInfo>>
+ all_stream_infos_;
// Queue containing all ready streams, ordered with streams of higher
// priority before streams of lower priority, and, among streams of equal
// priority, streams with lower ordinal before those with higher
@@ -186,7 +187,7 @@ class Http2PriorityWriteScheduler : public WriteScheduler<StreamIdType> {
// picked as the next stream: some may have ancestor stream(s) that are ready
// and unblocked. In these situations the occluded child streams are left in
// the queue, to reduce churn.
- SpdyIntrusiveList<StreamInfo> scheduling_queue_;
+ spdy::SpdyIntrusiveList<StreamInfo> scheduling_queue_;
// Ordinal value to assign to next node inserted into scheduling_queue_ when
// |add_to_front == true|. Decremented after each assignment.
int64_t head_ordinal_ = -1;
@@ -199,12 +200,12 @@ template <typename StreamIdType>
Http2PriorityWriteScheduler<StreamIdType>::Http2PriorityWriteScheduler() {
auto root_stream_info = std::make_unique<StreamInfo>();
root_stream_info_ = root_stream_info.get();
- root_stream_info->id = kHttp2RootStreamId;
- root_stream_info->weight = kHttp2DefaultStreamWeight;
+ root_stream_info->id = spdy::kHttp2RootStreamId;
+ root_stream_info->weight = spdy::kHttp2DefaultStreamWeight;
root_stream_info->parent = nullptr;
root_stream_info->priority = 1.0;
root_stream_info->ready = false;
- all_stream_infos_[kHttp2RootStreamId] = std::move(root_stream_info);
+ all_stream_infos_[spdy::kHttp2RootStreamId] = std::move(root_stream_info);
}
template <typename StreamIdType>
@@ -217,23 +218,23 @@ template <typename StreamIdType>
void Http2PriorityWriteScheduler<StreamIdType>::RegisterStream(
StreamIdType stream_id,
const StreamPrecedenceType& precedence) {
- // TODO(mpw): uncomment the SPDY_BUG_IF below once all tests
+ // TODO(mpw): uncomment the QUICHE_BUG_IF below once all tests
// (e.g. SpdyClientDispatcher) modified to pass StreamPrecedence instances
// appropriate for protocol version under test.
//
- // SPDY_BUG_IF(spdy_bug_8_1, precedence.is_spdy3_priority())
+ // QUICHE_BUG_IF(spdy_bug_8_1, precedence.is_spdy3_priority())
// << "Expected HTTP/2 stream dependency";
if (StreamRegistered(stream_id)) {
- SPDY_BUG(spdy_bug_8_2) << "Stream " << stream_id << " already registered";
+ QUICHE_BUG(spdy_bug_8_2) << "Stream " << stream_id << " already registered";
return;
}
StreamInfo* parent = FindStream(precedence.parent_id());
if (parent == nullptr) {
// parent_id may legitimately not be registered yet--see b/15676312.
- SPDY_VLOG(1) << "Parent stream " << precedence.parent_id()
- << " not registered";
+ QUICHE_VLOG(1) << "Parent stream " << precedence.parent_id()
+ << " not registered";
parent = root_stream_info_;
}
@@ -271,14 +272,14 @@ void Http2PriorityWriteScheduler<StreamIdType>::RegisterStream(
template <typename StreamIdType>
void Http2PriorityWriteScheduler<StreamIdType>::UnregisterStream(
StreamIdType stream_id) {
- if (stream_id == kHttp2RootStreamId) {
- SPDY_BUG(spdy_bug_8_3) << "Cannot unregister root stream";
+ if (stream_id == spdy::kHttp2RootStreamId) {
+ QUICHE_BUG(spdy_bug_8_3) << "Cannot unregister root stream";
return;
}
// Remove the stream from table.
auto it = all_stream_infos_.find(stream_id);
if (it == all_stream_infos_.end()) {
- SPDY_BUG(spdy_bug_8_4) << "Stream " << stream_id << " not registered";
+ QUICHE_BUG(spdy_bug_8_4) << "Stream " << stream_id << " not registered";
return;
}
std::unique_ptr<StreamInfo> stream_info(std::move(it->second));
@@ -321,9 +322,9 @@ Http2PriorityWriteScheduler<StreamIdType>::GetStreamPrecedence(
if (stream_info == nullptr) {
// Unknown streams tolerated due to b/15676312. However, return lowest
// weight.
- SPDY_VLOG(1) << "Stream " << stream_id << " not registered";
- return StreamPrecedenceType(kHttp2RootStreamId, kHttp2MinStreamWeight,
- false);
+ QUICHE_VLOG(1) << "Stream " << stream_id << " not registered";
+ return StreamPrecedenceType(spdy::kHttp2RootStreamId,
+ spdy::kHttp2MinStreamWeight, false);
}
return stream_info->ToStreamPrecedence();
}
@@ -335,7 +336,7 @@ Http2PriorityWriteScheduler<StreamIdType>::GetStreamChildren(
std::vector<StreamIdType> child_vec;
const StreamInfo* stream_info = FindStream(stream_id);
if (stream_info == nullptr) {
- SPDY_BUG(spdy_bug_8_5) << "Stream " << stream_id << " not registered";
+ QUICHE_BUG(spdy_bug_8_5) << "Stream " << stream_id << " not registered";
} else {
child_vec.reserve(stream_info->children.size());
for (StreamInfo* child : stream_info->children) {
@@ -349,21 +350,21 @@ template <typename StreamIdType>
void Http2PriorityWriteScheduler<StreamIdType>::UpdateStreamPrecedence(
StreamIdType stream_id,
const StreamPrecedenceType& precedence) {
- // TODO(mpw): uncomment the SPDY_BUG_IF below once all tests
+ // TODO(mpw): uncomment the QUICHE_BUG_IF below once all tests
// (e.g. SpdyClientDispatcher) modified to pass StreamPrecedence instances
// appropriate for protocol version under test.
//
- // SPDY_BUG_IF(spdy_bug_8_6, precedence.is_spdy3_priority())
+ // QUICHE_BUG_IF(spdy_bug_8_6, precedence.is_spdy3_priority())
// << "Expected HTTP/2 stream dependency";
- if (stream_id == kHttp2RootStreamId) {
- SPDY_BUG(spdy_bug_8_7) << "Cannot set precedence of root stream";
+ if (stream_id == spdy::kHttp2RootStreamId) {
+ QUICHE_BUG(spdy_bug_8_7) << "Cannot set precedence of root stream";
return;
}
StreamInfo* stream_info = FindStream(stream_id);
if (stream_info == nullptr) {
// TODO(mpw): add to all_stream_infos_ on demand--see b/15676312.
- SPDY_VLOG(1) << "Stream " << stream_id << " not registered";
+ QUICHE_VLOG(1) << "Stream " << stream_id << " not registered";
return;
}
UpdateStreamParent(stream_info, precedence.parent_id(),
@@ -393,13 +394,13 @@ void Http2PriorityWriteScheduler<StreamIdType>::UpdateStreamParent(
StreamIdType parent_id,
bool exclusive) {
if (stream_info->id == parent_id) {
- SPDY_BUG(spdy_bug_8_8) << "Cannot set stream to be its own parent";
+ QUICHE_BUG(spdy_bug_8_8) << "Cannot set stream to be its own parent";
return;
}
StreamInfo* new_parent = FindStream(parent_id);
if (new_parent == nullptr) {
// parent_id may legitimately not be registered yet--see b/15676312.
- SPDY_VLOG(1) << "Parent stream " << parent_id << " not registered";
+ QUICHE_VLOG(1) << "Parent stream " << parent_id << " not registered";
return;
}
@@ -456,13 +457,13 @@ template <typename StreamIdType>
void Http2PriorityWriteScheduler<StreamIdType>::RecordStreamEventTime(
StreamIdType stream_id,
int64_t now_in_usec) {
- if (stream_id == kHttp2RootStreamId) {
- SPDY_BUG(spdy_bug_8_9) << "Cannot record event time for root stream";
+ if (stream_id == spdy::kHttp2RootStreamId) {
+ QUICHE_BUG(spdy_bug_8_9) << "Cannot record event time for root stream";
return;
}
StreamInfo* stream_info = FindStream(stream_id);
if (stream_info == nullptr) {
- SPDY_BUG(spdy_bug_8_10) << "Stream " << stream_id << " not registered";
+ QUICHE_BUG(spdy_bug_8_10) << "Stream " << stream_id << " not registered";
return;
}
stream_info->last_event_time_usec = now_in_usec;
@@ -476,13 +477,13 @@ void Http2PriorityWriteScheduler<StreamIdType>::RecordStreamEventTime(
template <typename StreamIdType>
int64_t Http2PriorityWriteScheduler<StreamIdType>::GetLatestEventWithPrecedence(
StreamIdType stream_id) const {
- if (stream_id == kHttp2RootStreamId) {
- SPDY_BUG(spdy_bug_8_11) << "Invalid argument: root stream";
+ if (stream_id == spdy::kHttp2RootStreamId) {
+ QUICHE_BUG(spdy_bug_8_11) << "Invalid argument: root stream";
return 0;
}
const StreamInfo* stream_info = FindStream(stream_id);
if (stream_info == nullptr) {
- SPDY_BUG(spdy_bug_8_12) << "Stream " << stream_id << " not registered";
+ QUICHE_BUG(spdy_bug_8_12) << "Stream " << stream_id << " not registered";
return 0;
}
int64_t last_event_time_usec = 0;
@@ -502,13 +503,13 @@ int64_t Http2PriorityWriteScheduler<StreamIdType>::GetLatestEventWithPrecedence(
template <typename StreamIdType>
bool Http2PriorityWriteScheduler<StreamIdType>::ShouldYield(
StreamIdType stream_id) const {
- if (stream_id == kHttp2RootStreamId) {
- SPDY_BUG(spdy_bug_8_13) << "Invalid argument: root stream";
+ if (stream_id == spdy::kHttp2RootStreamId) {
+ QUICHE_BUG(spdy_bug_8_13) << "Invalid argument: root stream";
return false;
}
const StreamInfo* stream_info = FindStream(stream_id);
if (stream_info == nullptr) {
- SPDY_BUG(spdy_bug_8_14) << "Stream " << stream_id << " not registered";
+ QUICHE_BUG(spdy_bug_8_14) << "Stream " << stream_id << " not registered";
return false;
}
if (HasReadyAncestor(*stream_info)) {
@@ -533,13 +534,13 @@ template <typename StreamIdType>
void Http2PriorityWriteScheduler<StreamIdType>::MarkStreamReady(
StreamIdType stream_id,
bool add_to_front) {
- if (stream_id == kHttp2RootStreamId) {
- SPDY_BUG(spdy_bug_8_15) << "Cannot mark root stream ready";
+ if (stream_id == spdy::kHttp2RootStreamId) {
+ QUICHE_BUG(spdy_bug_8_15) << "Cannot mark root stream ready";
return;
}
StreamInfo* stream_info = FindStream(stream_id);
if (stream_info == nullptr) {
- SPDY_BUG(spdy_bug_8_16) << "Stream " << stream_id << " not registered";
+ QUICHE_BUG(spdy_bug_8_16) << "Stream " << stream_id << " not registered";
return;
}
if (stream_info->ready) {
@@ -552,13 +553,13 @@ void Http2PriorityWriteScheduler<StreamIdType>::MarkStreamReady(
template <typename StreamIdType>
void Http2PriorityWriteScheduler<StreamIdType>::MarkStreamNotReady(
StreamIdType stream_id) {
- if (stream_id == kHttp2RootStreamId) {
- SPDY_BUG(spdy_bug_8_17) << "Cannot mark root stream unready";
+ if (stream_id == spdy::kHttp2RootStreamId) {
+ QUICHE_BUG(spdy_bug_8_17) << "Cannot mark root stream unready";
return;
}
StreamInfo* stream_info = FindStream(stream_id);
if (stream_info == nullptr) {
- SPDY_BUG(spdy_bug_8_18) << "Stream " << stream_id << " not registered";
+ QUICHE_BUG(spdy_bug_8_18) << "Stream " << stream_id << " not registered";
return;
}
if (!stream_info->ready) {
@@ -680,10 +681,11 @@ Http2PriorityWriteScheduler<StreamIdType>::PopNextReadyStreamAndPrecedence() {
return std::make_tuple(stream_info.id, stream_info.ToStreamPrecedence());
}
}
- SPDY_BUG(spdy_bug_8_19) << "No ready streams";
+ QUICHE_BUG(spdy_bug_8_19) << "No ready streams";
return std::make_tuple(
- kHttp2RootStreamId,
- StreamPrecedenceType(kHttp2RootStreamId, kHttp2MinStreamWeight, false));
+ spdy::kHttp2RootStreamId,
+ StreamPrecedenceType(spdy::kHttp2RootStreamId,
+ spdy::kHttp2MinStreamWeight, false));
}
template <typename StreamIdType>
@@ -694,13 +696,13 @@ size_t Http2PriorityWriteScheduler<StreamIdType>::NumReadyStreams() const {
template <typename StreamIdType>
bool Http2PriorityWriteScheduler<StreamIdType>::IsStreamReady(
StreamIdType stream_id) const {
- if (stream_id == kHttp2RootStreamId) {
- SPDY_BUG(spdy_bug_8_20) << "Try to check whether root stream is ready";
+ if (stream_id == spdy::kHttp2RootStreamId) {
+ QUICHE_BUG(spdy_bug_8_20) << "Try to check whether root stream is ready";
return false;
}
const StreamInfo* stream_info = FindStream(stream_id);
if (stream_info == nullptr) {
- SPDY_BUG(spdy_bug_8_21) << "Stream " << stream_id << " not registered";
+ QUICHE_BUG(spdy_bug_8_21) << "Stream " << stream_id << " not registered";
return false;
}
return stream_info->ready;
@@ -732,18 +734,18 @@ bool Http2PriorityWriteScheduler<StreamIdType>::ValidateInvariantsForTests()
// Verify each StreamInfo mapped under the proper stream ID.
if (stream_id != stream_info.id) {
- SPDY_DLOG(INFO) << "Stream ID " << stream_id
- << " maps to StreamInfo with ID " << stream_info.id;
+ QUICHE_DLOG(INFO) << "Stream ID " << stream_id
+ << " maps to StreamInfo with ID " << stream_info.id;
return false;
}
// All streams except the root should have a parent, and should appear in
// the children of that parent.
- if (stream_info.id != kHttp2RootStreamId &&
+ if (stream_info.id != spdy::kHttp2RootStreamId &&
!StreamHasChild(*stream_info.parent, &stream_info)) {
- SPDY_DLOG(INFO) << "Parent stream " << stream_info.parent->id
- << " is not registered, or does not list stream "
- << stream_info.id << " as its child.";
+ QUICHE_DLOG(INFO) << "Parent stream " << stream_info.parent->id
+ << " is not registered, or does not list stream "
+ << stream_info.id << " as its child.";
return false;
}
@@ -755,20 +757,19 @@ bool Http2PriorityWriteScheduler<StreamIdType>::ValidateInvariantsForTests()
// Each stream in the list should exist and should have this stream
// set as its parent.
if (!StreamRegistered(child->id) || child->parent != &stream_info) {
- SPDY_DLOG(INFO) << "Child stream " << child->id
- << " is not registered, "
- << "or does not list " << stream_info.id
- << " as its parent.";
+ QUICHE_DLOG(INFO)
+ << "Child stream " << child->id << " is not registered, "
+ << "or does not list " << stream_info.id << " as its parent.";
return false;
}
total_child_weights += child->weight;
}
// Verify that total_child_weights is correct.
if (total_child_weights != stream_info.total_child_weights) {
- SPDY_DLOG(INFO) << "Child weight totals do not agree. For stream "
- << stream_info.id << " total_child_weights has value "
- << stream_info.total_child_weights << ", expected "
- << total_child_weights;
+ QUICHE_DLOG(INFO) << "Child weight totals do not agree. For stream "
+ << stream_info.id << " total_child_weights has value "
+ << stream_info.total_child_weights << ", expected "
+ << total_child_weights;
return false;
}
}
@@ -777,7 +778,7 @@ bool Http2PriorityWriteScheduler<StreamIdType>::ValidateInvariantsForTests()
// Make sure NumRegisteredStreams() reflects the total number of streams the
// map contains.
if (total_streams != NumRegisteredStreams()) {
- SPDY_DLOG(INFO) << "Map contains incorrect number of streams.";
+ QUICHE_DLOG(INFO) << "Map contains incorrect number of streams.";
return false;
}
// Validate the validation function; we should have visited each stream twice
@@ -786,6 +787,6 @@ bool Http2PriorityWriteScheduler<StreamIdType>::ValidateInvariantsForTests()
return true;
}
-} // namespace spdy
+} // namespace http2
-#endif // QUICHE_SPDY_CORE_HTTP2_PRIORITY_WRITE_SCHEDULER_H_
+#endif // QUICHE_HTTP2_CORE_HTTP2_PRIORITY_WRITE_SCHEDULER_H_
diff --git a/chromium/net/third_party/quiche/src/spdy/core/http2_priority_write_scheduler_test.cc b/chromium/net/third_party/quiche/src/http2/core/http2_priority_write_scheduler_test.cc
index 7c9c2595811..7f086190eeb 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/http2_priority_write_scheduler_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/core/http2_priority_write_scheduler_test.cc
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "spdy/core/http2_priority_write_scheduler.h"
+#include "http2/core/http2_priority_write_scheduler.h"
#include <initializer_list>
#include "common/platform/api/quiche_test.h"
-#include "spdy/platform/api/spdy_test_helpers.h"
+#include "common/platform/api/quiche_test_helpers.h"
using ::testing::AssertionFailure;
using ::testing::AssertionResult;
@@ -16,10 +16,15 @@ using ::testing::ElementsAre;
using ::testing::IsEmpty;
using ::testing::UnorderedElementsAre;
-namespace spdy {
-
+namespace http2 {
namespace test {
+using ::spdy::kHttp2MaxStreamWeight;
+using ::spdy::kHttp2MinStreamWeight;
+using ::spdy::kHttp2RootStreamId;
+using ::spdy::kV3LowestPriority;
+using ::spdy::SpdyStreamPrecedence;
+
template <typename StreamIdType>
class Http2PriorityWriteSchedulerPeer {
public:
@@ -63,7 +68,7 @@ TEST_F(Http2PriorityWriteSchedulerTest, RegisterAndUnregisterStreams) {
scheduler_.RegisterStream(5, SpdyStreamPrecedence(0, 50, false));
// Should not be able to add a stream with an id that already exists.
- EXPECT_SPDY_BUG(
+ EXPECT_QUICHE_BUG(
scheduler_.RegisterStream(5, SpdyStreamPrecedence(1, 50, false)),
"Stream 5 already registered");
EXPECT_EQ(3u, scheduler_.NumRegisteredStreams());
@@ -82,7 +87,7 @@ TEST_F(Http2PriorityWriteSchedulerTest, RegisterAndUnregisterStreams) {
scheduler_.UnregisterStream(5);
// Cannot remove a stream that has already been removed.
- EXPECT_SPDY_BUG(scheduler_.UnregisterStream(5), "Stream 5 not registered");
+ EXPECT_QUICHE_BUG(scheduler_.UnregisterStream(5), "Stream 5 not registered");
EXPECT_EQ(3u, scheduler_.NumRegisteredStreams());
EXPECT_TRUE(scheduler_.StreamRegistered(1));
EXPECT_FALSE(scheduler_.StreamRegistered(5));
@@ -94,7 +99,7 @@ TEST_F(Http2PriorityWriteSchedulerTest, RegisterAndUnregisterStreams) {
EXPECT_TRUE(scheduler_.StreamRegistered(7));
EXPECT_EQ(0u, scheduler_.GetStreamPrecedence(7).parent_id());
// Now stream 7 already exists, so this should fail:
- EXPECT_SPDY_BUG(
+ EXPECT_QUICHE_BUG(
scheduler_.RegisterStream(7, SpdyStreamPrecedence(1, 70, false)),
"Stream 7 already registered");
// Try adding a second child to stream 13:
@@ -116,8 +121,8 @@ TEST_F(Http2PriorityWriteSchedulerTest, RegisterStreamWithSpdy3Priority) {
EXPECT_EQ(kHttp2RootStreamId, scheduler_.GetStreamPrecedence(1).parent_id());
EXPECT_THAT(scheduler_.GetStreamChildren(1), IsEmpty());
- EXPECT_SPDY_BUG(scheduler_.RegisterStream(1, SpdyStreamPrecedence(4)),
- "Stream 1 already registered");
+ EXPECT_QUICHE_BUG(scheduler_.RegisterStream(1, SpdyStreamPrecedence(4)),
+ "Stream 1 already registered");
EXPECT_EQ(3, scheduler_.GetStreamPrecedence(1).spdy3_priority());
}
@@ -156,20 +161,20 @@ TEST_F(Http2PriorityWriteSchedulerTest, GetStreamParent) {
}
TEST_F(Http2PriorityWriteSchedulerTest, GetStreamChildren) {
- EXPECT_SPDY_BUG(EXPECT_THAT(scheduler_.GetStreamChildren(7), IsEmpty()),
- "Stream 7 not registered");
+ EXPECT_QUICHE_BUG(EXPECT_THAT(scheduler_.GetStreamChildren(7), IsEmpty()),
+ "Stream 7 not registered");
scheduler_.RegisterStream(7, SpdyStreamPrecedence(0, 70, false));
EXPECT_THAT(scheduler_.GetStreamChildren(7), IsEmpty());
scheduler_.RegisterStream(9, SpdyStreamPrecedence(7, 90, false));
scheduler_.RegisterStream(15, SpdyStreamPrecedence(7, 150, false));
EXPECT_THAT(scheduler_.GetStreamChildren(7), UnorderedElementsAre(9, 15));
scheduler_.UnregisterStream(7);
- EXPECT_SPDY_BUG(EXPECT_THAT(scheduler_.GetStreamChildren(7), IsEmpty()),
- "Stream 7 not registered");
+ EXPECT_QUICHE_BUG(EXPECT_THAT(scheduler_.GetStreamChildren(7), IsEmpty()),
+ "Stream 7 not registered");
}
TEST_F(Http2PriorityWriteSchedulerTest, UpdateStreamWeight) {
- EXPECT_SPDY_BUG(
+ EXPECT_QUICHE_BUG(
scheduler_.UpdateStreamPrecedence(0, SpdyStreamPrecedence(0, 10, false)),
"Cannot set precedence of root stream");
@@ -184,11 +189,11 @@ TEST_F(Http2PriorityWriteSchedulerTest, UpdateStreamWeight) {
EXPECT_EQ(20, scheduler_.GetStreamPrecedence(3).weight());
ASSERT_TRUE(peer_.ValidateInvariants());
- EXPECT_SPDY_BUG(
+ EXPECT_QUICHE_BUG(
scheduler_.UpdateStreamPrecedence(3, SpdyStreamPrecedence(0, 500, false)),
"Invalid weight: 500");
EXPECT_EQ(kHttp2MaxStreamWeight, scheduler_.GetStreamPrecedence(3).weight());
- EXPECT_SPDY_BUG(
+ EXPECT_QUICHE_BUG(
scheduler_.UpdateStreamPrecedence(3, SpdyStreamPrecedence(0, 0, false)),
"Invalid weight: 0");
EXPECT_EQ(kHttp2MinStreamWeight, scheduler_.GetStreamPrecedence(3).weight());
@@ -569,10 +574,10 @@ TEST_F(Http2PriorityWriteSchedulerTest, UpdateStreamParentToParent) {
TEST_F(Http2PriorityWriteSchedulerTest, UpdateStreamParentToSelf) {
scheduler_.RegisterStream(1, SpdyStreamPrecedence(0, 100, false));
- EXPECT_SPDY_BUG(
+ EXPECT_QUICHE_BUG(
scheduler_.UpdateStreamPrecedence(1, SpdyStreamPrecedence(1, 100, false)),
"Cannot set stream to be its own parent");
- EXPECT_SPDY_BUG(
+ EXPECT_QUICHE_BUG(
scheduler_.UpdateStreamPrecedence(1, SpdyStreamPrecedence(1, 100, true)),
"Cannot set stream to be its own parent");
EXPECT_THAT(scheduler_.GetStreamChildren(0), ElementsAre(1));
@@ -661,7 +666,7 @@ TEST_F(Http2PriorityWriteSchedulerTest, HasReadyStreams) {
scheduler_.UnregisterStream(1);
EXPECT_FALSE(scheduler_.HasReadyStreams());
ASSERT_TRUE(peer_.ValidateInvariants());
- EXPECT_SPDY_BUG(scheduler_.IsStreamReady(1), "Stream 1 not registered");
+ EXPECT_QUICHE_BUG(scheduler_.IsStreamReady(1), "Stream 1 not registered");
}
TEST_F(Http2PriorityWriteSchedulerTest, CalculateRoundedWeights) {
@@ -699,10 +704,10 @@ TEST_F(Http2PriorityWriteSchedulerTest, CalculateRoundedWeights) {
}
TEST_F(Http2PriorityWriteSchedulerTest, GetLatestEventWithPrecedence) {
- EXPECT_SPDY_BUG(scheduler_.RecordStreamEventTime(3, 5),
- "Stream 3 not registered");
- EXPECT_SPDY_BUG(EXPECT_EQ(0, scheduler_.GetLatestEventWithPrecedence(4)),
- "Stream 4 not registered");
+ EXPECT_QUICHE_BUG(scheduler_.RecordStreamEventTime(3, 5),
+ "Stream 3 not registered");
+ EXPECT_QUICHE_BUG(EXPECT_EQ(0, scheduler_.GetLatestEventWithPrecedence(4)),
+ "Stream 4 not registered");
for (int i = 1; i < 5; ++i) {
int weight = SpdyStreamPrecedence(i).weight();
@@ -962,4 +967,4 @@ TEST_F(PopNextReadyStreamTest, ScatteredBlocked) {
}
} // namespace test
-} // namespace spdy
+} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/spdy/core/priority_write_scheduler.h b/chromium/net/third_party/quiche/src/http2/core/priority_write_scheduler.h
index fde9a286ed5..b59e294e899 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/priority_write_scheduler.h
+++ b/chromium/net/third_party/quiche/src/http2/core/priority_write_scheduler.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_SPDY_CORE_PRIORITY_WRITE_SCHEDULER_H_
-#define QUICHE_SPDY_CORE_PRIORITY_WRITE_SCHEDULER_H_
+#ifndef QUICHE_HTTP2_CORE_PRIORITY_WRITE_SCHEDULER_H_
+#define QUICHE_HTTP2_CORE_PRIORITY_WRITE_SCHEDULER_H_
#include <algorithm>
#include <cstddef>
@@ -16,12 +16,12 @@
#include <vector>
#include "absl/strings/str_cat.h"
+#include "http2/core/write_scheduler.h"
+#include "common/platform/api/quiche_bug_tracker.h"
+#include "common/platform/api/quiche_logging.h"
#include "spdy/core/spdy_protocol.h"
-#include "spdy/core/write_scheduler.h"
-#include "spdy/platform/api/spdy_bug_tracker.h"
-#include "spdy/platform/api/spdy_logging.h"
-namespace spdy {
+namespace http2 {
namespace test {
template <typename StreamIdType>
@@ -44,7 +44,7 @@ class PriorityWriteScheduler : public WriteScheduler<StreamIdType> {
using typename WriteScheduler<StreamIdType>::StreamPrecedenceType;
// Creates scheduler with no streams.
- PriorityWriteScheduler() : PriorityWriteScheduler(kHttp2RootStreamId) {}
+ PriorityWriteScheduler() : PriorityWriteScheduler(spdy::kHttp2RootStreamId) {}
explicit PriorityWriteScheduler(StreamIdType root_stream_id)
: root_stream_id_(root_stream_id) {}
@@ -56,26 +56,26 @@ class PriorityWriteScheduler : public WriteScheduler<StreamIdType> {
// parent_id not used here, but may as well validate it. However,
// parent_id may legitimately not be registered yet--see b/15676312.
StreamIdType parent_id = precedence.parent_id();
- SPDY_DVLOG_IF(1,
- parent_id != root_stream_id_ && !StreamRegistered(parent_id))
+ QUICHE_DVLOG_IF(
+ 1, parent_id != root_stream_id_ && !StreamRegistered(parent_id))
<< "Parent stream " << parent_id << " not registered";
if (stream_id == root_stream_id_) {
- SPDY_BUG(spdy_bug_19_1)
+ QUICHE_BUG(spdy_bug_19_1)
<< "Stream " << root_stream_id_ << " already registered";
return;
}
StreamInfo stream_info = {precedence.spdy3_priority(), stream_id, false};
bool inserted =
stream_infos_.insert(std::make_pair(stream_id, stream_info)).second;
- SPDY_BUG_IF(spdy_bug_19_2, !inserted)
+ QUICHE_BUG_IF(spdy_bug_19_2, !inserted)
<< "Stream " << stream_id << " already registered";
}
void UnregisterStream(StreamIdType stream_id) override {
auto it = stream_infos_.find(stream_id);
if (it == stream_infos_.end()) {
- SPDY_BUG(spdy_bug_19_3) << "Stream " << stream_id << " not registered";
+ QUICHE_BUG(spdy_bug_19_3) << "Stream " << stream_id << " not registered";
return;
}
StreamInfo& stream_info = it->second;
@@ -95,8 +95,8 @@ class PriorityWriteScheduler : public WriteScheduler<StreamIdType> {
StreamIdType stream_id) const override {
auto it = stream_infos_.find(stream_id);
if (it == stream_infos_.end()) {
- SPDY_DVLOG(1) << "Stream " << stream_id << " not registered";
- return StreamPrecedenceType(kV3LowestPriority);
+ QUICHE_DVLOG(1) << "Stream " << stream_id << " not registered";
+ return StreamPrecedenceType(spdy::kV3LowestPriority);
}
return StreamPrecedenceType(it->second.priority);
}
@@ -109,18 +109,18 @@ class PriorityWriteScheduler : public WriteScheduler<StreamIdType> {
// parent_id not used here, but may as well validate it. However,
// parent_id may legitimately not be registered yet--see b/15676312.
StreamIdType parent_id = precedence.parent_id();
- SPDY_DVLOG_IF(1,
- parent_id != root_stream_id_ && !StreamRegistered(parent_id))
+ QUICHE_DVLOG_IF(
+ 1, parent_id != root_stream_id_ && !StreamRegistered(parent_id))
<< "Parent stream " << parent_id << " not registered";
auto it = stream_infos_.find(stream_id);
if (it == stream_infos_.end()) {
// TODO(mpw): add to stream_infos_ on demand--see b/15676312.
- SPDY_DVLOG(1) << "Stream " << stream_id << " not registered";
+ QUICHE_DVLOG(1) << "Stream " << stream_id << " not registered";
return;
}
StreamInfo& stream_info = it->second;
- SpdyPriority new_priority = precedence.spdy3_priority();
+ spdy::SpdyPriority new_priority = precedence.spdy3_priority();
if (stream_info.priority == new_priority) {
return;
}
@@ -143,7 +143,7 @@ class PriorityWriteScheduler : public WriteScheduler<StreamIdType> {
int64_t now_in_usec) override {
auto it = stream_infos_.find(stream_id);
if (it == stream_infos_.end()) {
- SPDY_BUG(spdy_bug_19_4) << "Stream " << stream_id << " not registered";
+ QUICHE_BUG(spdy_bug_19_4) << "Stream " << stream_id << " not registered";
return;
}
PriorityInfo& priority_info = priority_infos_[it->second.priority];
@@ -154,12 +154,13 @@ class PriorityWriteScheduler : public WriteScheduler<StreamIdType> {
int64_t GetLatestEventWithPrecedence(StreamIdType stream_id) const override {
auto it = stream_infos_.find(stream_id);
if (it == stream_infos_.end()) {
- SPDY_BUG(spdy_bug_19_5) << "Stream " << stream_id << " not registered";
+ QUICHE_BUG(spdy_bug_19_5) << "Stream " << stream_id << " not registered";
return 0;
}
int64_t last_event_time_usec = 0;
const StreamInfo& stream_info = it->second;
- for (SpdyPriority p = kV3HighestPriority; p < stream_info.priority; ++p) {
+ for (spdy::SpdyPriority p = spdy::kV3HighestPriority;
+ p < stream_info.priority; ++p) {
last_event_time_usec = std::max(last_event_time_usec,
priority_infos_[p].last_event_time_usec);
}
@@ -173,7 +174,8 @@ class PriorityWriteScheduler : public WriteScheduler<StreamIdType> {
// Returns the next ready stream and its precedence.
std::tuple<StreamIdType, StreamPrecedenceType>
PopNextReadyStreamAndPrecedence() override {
- for (SpdyPriority p = kV3HighestPriority; p <= kV3LowestPriority; ++p) {
+ for (spdy::SpdyPriority p = spdy::kV3HighestPriority;
+ p <= spdy::kV3LowestPriority; ++p) {
ReadyList& ready_list = priority_infos_[p].ready_list;
if (!ready_list.empty()) {
StreamInfo* info = ready_list.front();
@@ -187,20 +189,21 @@ class PriorityWriteScheduler : public WriteScheduler<StreamIdType> {
StreamPrecedenceType(info->priority));
}
}
- SPDY_BUG(spdy_bug_19_6) << "No ready streams available";
- return std::make_tuple(0, StreamPrecedenceType(kV3LowestPriority));
+ QUICHE_BUG(spdy_bug_19_6) << "No ready streams available";
+ return std::make_tuple(0, StreamPrecedenceType(spdy::kV3LowestPriority));
}
bool ShouldYield(StreamIdType stream_id) const override {
auto it = stream_infos_.find(stream_id);
if (it == stream_infos_.end()) {
- SPDY_BUG(spdy_bug_19_7) << "Stream " << stream_id << " not registered";
+ QUICHE_BUG(spdy_bug_19_7) << "Stream " << stream_id << " not registered";
return false;
}
// If there's a higher priority stream, this stream should yield.
const StreamInfo& stream_info = it->second;
- for (SpdyPriority p = kV3HighestPriority; p < stream_info.priority; ++p) {
+ for (spdy::SpdyPriority p = spdy::kV3HighestPriority;
+ p < stream_info.priority; ++p) {
if (!priority_infos_[p].ready_list.empty()) {
return true;
}
@@ -221,7 +224,7 @@ class PriorityWriteScheduler : public WriteScheduler<StreamIdType> {
void MarkStreamReady(StreamIdType stream_id, bool add_to_front) override {
auto it = stream_infos_.find(stream_id);
if (it == stream_infos_.end()) {
- SPDY_BUG(spdy_bug_19_8) << "Stream " << stream_id << " not registered";
+ QUICHE_BUG(spdy_bug_19_8) << "Stream " << stream_id << " not registered";
return;
}
StreamInfo& stream_info = it->second;
@@ -241,7 +244,7 @@ class PriorityWriteScheduler : public WriteScheduler<StreamIdType> {
void MarkStreamNotReady(StreamIdType stream_id) override {
auto it = stream_infos_.find(stream_id);
if (it == stream_infos_.end()) {
- SPDY_BUG(spdy_bug_19_9) << "Stream " << stream_id << " not registered";
+ QUICHE_BUG(spdy_bug_19_9) << "Stream " << stream_id << " not registered";
return;
}
StreamInfo& stream_info = it->second;
@@ -272,7 +275,7 @@ class PriorityWriteScheduler : public WriteScheduler<StreamIdType> {
bool IsStreamReady(StreamIdType stream_id) const override {
auto it = stream_infos_.find(stream_id);
if (it == stream_infos_.end()) {
- SPDY_DLOG(INFO) << "Stream " << stream_id << " not registered";
+ QUICHE_DLOG(INFO) << "Stream " << stream_id << " not registered";
return false;
}
return it->second.ready;
@@ -284,7 +287,7 @@ class PriorityWriteScheduler : public WriteScheduler<StreamIdType> {
// State kept for all registered streams. All ready streams have ready = true
// and should be present in priority_infos_[priority].ready_list.
struct StreamInfo {
- SpdyPriority priority;
+ spdy::SpdyPriority priority;
StreamIdType stream_id;
bool ready;
};
@@ -318,12 +321,12 @@ class PriorityWriteScheduler : public WriteScheduler<StreamIdType> {
// Number of ready streams.
size_t num_ready_streams_ = 0;
// Per-priority state, including ready lists.
- PriorityInfo priority_infos_[kV3LowestPriority + 1];
+ PriorityInfo priority_infos_[spdy::kV3LowestPriority + 1];
// StreamInfos for all registered streams.
StreamInfoMap stream_infos_;
StreamIdType root_stream_id_;
};
-} // namespace spdy
+} // namespace http2
-#endif // QUICHE_SPDY_CORE_PRIORITY_WRITE_SCHEDULER_H_
+#endif // QUICHE_HTTP2_CORE_PRIORITY_WRITE_SCHEDULER_H_
diff --git a/chromium/net/third_party/quiche/src/spdy/core/priority_write_scheduler_test.cc b/chromium/net/third_party/quiche/src/http2/core/priority_write_scheduler_test.cc
index a76e0dc5801..e4e6997118d 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/priority_write_scheduler_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/core/priority_write_scheduler_test.cc
@@ -2,16 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "spdy/core/priority_write_scheduler.h"
+#include "http2/core/priority_write_scheduler.h"
#include "common/platform/api/quiche_test.h"
+#include "common/platform/api/quiche_test_helpers.h"
#include "spdy/core/spdy_protocol.h"
#include "spdy/core/spdy_test_utils.h"
-#include "spdy/platform/api/spdy_test_helpers.h"
-namespace spdy {
+namespace http2 {
namespace test {
+using ::spdy::kHttp2RootStreamId;
+using ::spdy::kV3LowestPriority;
+using ::spdy::SpdyPriority;
+using ::spdy::SpdyStreamId;
+using ::spdy::SpdyStreamPrecedence;
+
template <typename StreamIdType>
class PriorityWriteSchedulerPeer {
public:
@@ -46,15 +52,15 @@ TEST_F(PriorityWriteSchedulerTest, RegisterUnregisterStreams) {
EXPECT_EQ(1u, scheduler_.NumRegisteredStreams());
// Root stream counts as already registered.
- EXPECT_SPDY_BUG(
+ EXPECT_QUICHE_BUG(
scheduler_.RegisterStream(kHttp2RootStreamId, SpdyStreamPrecedence(1)),
"Stream 0 already registered");
// Try redundant registrations.
- EXPECT_SPDY_BUG(scheduler_.RegisterStream(1, SpdyStreamPrecedence(1)),
- "Stream 1 already registered");
- EXPECT_SPDY_BUG(scheduler_.RegisterStream(1, SpdyStreamPrecedence(2)),
- "Stream 1 already registered");
+ EXPECT_QUICHE_BUG(scheduler_.RegisterStream(1, SpdyStreamPrecedence(1)),
+ "Stream 1 already registered");
+ EXPECT_QUICHE_BUG(scheduler_.RegisterStream(1, SpdyStreamPrecedence(2)),
+ "Stream 1 already registered");
scheduler_.RegisterStream(2, SpdyStreamPrecedence(3));
EXPECT_EQ(2u, scheduler_.NumRegisteredStreams());
@@ -68,8 +74,8 @@ TEST_F(PriorityWriteSchedulerTest, RegisterUnregisterStreams) {
EXPECT_EQ(0u, scheduler_.NumRegisteredStreams());
// Try redundant unregistration.
- EXPECT_SPDY_BUG(scheduler_.UnregisterStream(1), "Stream 1 not registered");
- EXPECT_SPDY_BUG(scheduler_.UnregisterStream(2), "Stream 2 not registered");
+ EXPECT_QUICHE_BUG(scheduler_.UnregisterStream(1), "Stream 1 not registered");
+ EXPECT_QUICHE_BUG(scheduler_.UnregisterStream(2), "Stream 2 not registered");
}
TEST_F(PriorityWriteSchedulerTest, RegisterStreamWithHttp2StreamDependency) {
@@ -82,9 +88,10 @@ TEST_F(PriorityWriteSchedulerTest, RegisterStreamWithHttp2StreamDependency) {
EXPECT_EQ(3, scheduler_.GetStreamPrecedence(1).spdy3_priority());
EXPECT_FALSE(scheduler_.HasReadyStreams());
- EXPECT_SPDY_BUG(scheduler_.RegisterStream(
- 1, SpdyStreamPrecedence(kHttp2RootStreamId, 256, false)),
- "Stream 1 already registered");
+ EXPECT_QUICHE_BUG(
+ scheduler_.RegisterStream(
+ 1, SpdyStreamPrecedence(kHttp2RootStreamId, 256, false)),
+ "Stream 1 already registered");
EXPECT_TRUE(scheduler_.GetStreamPrecedence(1).is_spdy3_priority());
EXPECT_EQ(3, scheduler_.GetStreamPrecedence(1).spdy3_priority());
@@ -107,8 +114,8 @@ TEST_F(PriorityWriteSchedulerTest, GetStreamPrecedence) {
EXPECT_EQ(3, scheduler_.GetStreamPrecedence(1).spdy3_priority());
// Redundant registration shouldn't change stream priority.
- EXPECT_SPDY_BUG(scheduler_.RegisterStream(1, SpdyStreamPrecedence(4)),
- "Stream 1 already registered");
+ EXPECT_QUICHE_BUG(scheduler_.RegisterStream(1, SpdyStreamPrecedence(4)),
+ "Stream 1 already registered");
EXPECT_EQ(3, scheduler_.GetStreamPrecedence(1).spdy3_priority());
scheduler_.UpdateStreamPrecedence(1, SpdyStreamPrecedence(5));
@@ -204,11 +211,11 @@ TEST_F(PriorityWriteSchedulerTest,
TEST_F(PriorityWriteSchedulerTest, MarkStreamReadyBack) {
EXPECT_FALSE(scheduler_.HasReadyStreams());
- EXPECT_SPDY_BUG(scheduler_.MarkStreamReady(1, false),
- "Stream 1 not registered");
+ EXPECT_QUICHE_BUG(scheduler_.MarkStreamReady(1, false),
+ "Stream 1 not registered");
EXPECT_FALSE(scheduler_.HasReadyStreams());
- EXPECT_SPDY_BUG(EXPECT_EQ(0u, scheduler_.PopNextReadyStream()),
- "No ready streams available");
+ EXPECT_QUICHE_BUG(EXPECT_EQ(0u, scheduler_.PopNextReadyStream()),
+ "No ready streams available");
// Add a bunch of ready streams to tail of per-priority lists.
// Expected order: (P2) 4, (P3) 1, 2, 3, (P5) 5.
@@ -229,17 +236,17 @@ TEST_F(PriorityWriteSchedulerTest, MarkStreamReadyBack) {
EXPECT_EQ(2u, scheduler_.PopNextReadyStream());
EXPECT_EQ(3u, scheduler_.PopNextReadyStream());
EXPECT_EQ(5u, scheduler_.PopNextReadyStream());
- EXPECT_SPDY_BUG(EXPECT_EQ(0u, scheduler_.PopNextReadyStream()),
- "No ready streams available");
+ EXPECT_QUICHE_BUG(EXPECT_EQ(0u, scheduler_.PopNextReadyStream()),
+ "No ready streams available");
}
TEST_F(PriorityWriteSchedulerTest, MarkStreamReadyFront) {
EXPECT_FALSE(scheduler_.HasReadyStreams());
- EXPECT_SPDY_BUG(scheduler_.MarkStreamReady(1, true),
- "Stream 1 not registered");
+ EXPECT_QUICHE_BUG(scheduler_.MarkStreamReady(1, true),
+ "Stream 1 not registered");
EXPECT_FALSE(scheduler_.HasReadyStreams());
- EXPECT_SPDY_BUG(EXPECT_EQ(0u, scheduler_.PopNextReadyStream()),
- "No ready streams available");
+ EXPECT_QUICHE_BUG(EXPECT_EQ(0u, scheduler_.PopNextReadyStream()),
+ "No ready streams available");
// Add a bunch of ready streams to head of per-priority lists.
// Expected order: (P2) 4, (P3) 3, 2, 1, (P5) 5
@@ -260,8 +267,8 @@ TEST_F(PriorityWriteSchedulerTest, MarkStreamReadyFront) {
EXPECT_EQ(2u, scheduler_.PopNextReadyStream());
EXPECT_EQ(1u, scheduler_.PopNextReadyStream());
EXPECT_EQ(5u, scheduler_.PopNextReadyStream());
- EXPECT_SPDY_BUG(EXPECT_EQ(0u, scheduler_.PopNextReadyStream()),
- "No ready streams available");
+ EXPECT_QUICHE_BUG(EXPECT_EQ(0u, scheduler_.PopNextReadyStream()),
+ "No ready streams available");
}
TEST_F(PriorityWriteSchedulerTest, MarkStreamReadyBackAndFront) {
@@ -288,8 +295,8 @@ TEST_F(PriorityWriteSchedulerTest, MarkStreamReadyBackAndFront) {
EXPECT_EQ(3u, scheduler_.PopNextReadyStream());
EXPECT_EQ(1u, scheduler_.PopNextReadyStream());
EXPECT_EQ(5u, scheduler_.PopNextReadyStream());
- EXPECT_SPDY_BUG(EXPECT_EQ(0u, scheduler_.PopNextReadyStream()),
- "No ready streams available");
+ EXPECT_QUICHE_BUG(EXPECT_EQ(0u, scheduler_.PopNextReadyStream()),
+ "No ready streams available");
}
TEST_F(PriorityWriteSchedulerTest, MarkStreamNotReady) {
@@ -302,15 +309,16 @@ TEST_F(PriorityWriteSchedulerTest, MarkStreamNotReady) {
EXPECT_EQ(0u, scheduler_.NumReadyStreams());
// Empty pop should fail.
- EXPECT_SPDY_BUG(EXPECT_EQ(0u, scheduler_.PopNextReadyStream()),
- "No ready streams available");
+ EXPECT_QUICHE_BUG(EXPECT_EQ(0u, scheduler_.PopNextReadyStream()),
+ "No ready streams available");
// Tolerate redundant marking of a stream as not ready.
scheduler_.MarkStreamNotReady(1);
EXPECT_EQ(0u, scheduler_.NumReadyStreams());
// Should only be able to mark registered streams.
- EXPECT_SPDY_BUG(scheduler_.MarkStreamNotReady(3), "Stream 3 not registered");
+ EXPECT_QUICHE_BUG(scheduler_.MarkStreamNotReady(3),
+ "Stream 3 not registered");
}
TEST_F(PriorityWriteSchedulerTest, UnregisterRemovesStream) {
@@ -321,8 +329,8 @@ TEST_F(PriorityWriteSchedulerTest, UnregisterRemovesStream) {
// Unregistering a stream should remove it from set of ready streams.
scheduler_.UnregisterStream(3);
EXPECT_EQ(0u, scheduler_.NumReadyStreams());
- EXPECT_SPDY_BUG(EXPECT_EQ(0u, scheduler_.PopNextReadyStream()),
- "No ready streams available");
+ EXPECT_QUICHE_BUG(EXPECT_EQ(0u, scheduler_.PopNextReadyStream()),
+ "No ready streams available");
}
TEST_F(PriorityWriteSchedulerTest, ShouldYield) {
@@ -353,10 +361,10 @@ TEST_F(PriorityWriteSchedulerTest, ShouldYield) {
}
TEST_F(PriorityWriteSchedulerTest, GetLatestEventWithPrecedence) {
- EXPECT_SPDY_BUG(scheduler_.RecordStreamEventTime(3, 5),
- "Stream 3 not registered");
- EXPECT_SPDY_BUG(EXPECT_EQ(0, scheduler_.GetLatestEventWithPrecedence(4)),
- "Stream 4 not registered");
+ EXPECT_QUICHE_BUG(scheduler_.RecordStreamEventTime(3, 5),
+ "Stream 3 not registered");
+ EXPECT_QUICHE_BUG(EXPECT_EQ(0, scheduler_.GetLatestEventWithPrecedence(4)),
+ "Stream 4 not registered");
for (int i = 1; i < 5; ++i) {
scheduler_.RegisterStream(i, SpdyStreamPrecedence(i));
@@ -374,4 +382,4 @@ TEST_F(PriorityWriteSchedulerTest, GetLatestEventWithPrecedence) {
} // namespace
} // namespace test
-} // namespace spdy
+} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/spdy/core/write_scheduler.h b/chromium/net/third_party/quiche/src/http2/core/write_scheduler.h
index de9264d6a47..4973a2d83ec 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/write_scheduler.h
+++ b/chromium/net/third_party/quiche/src/http2/core/write_scheduler.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_SPDY_CORE_WRITE_SCHEDULER_H_
-#define QUICHE_SPDY_CORE_WRITE_SCHEDULER_H_
+#ifndef QUICHE_HTTP2_CORE_WRITE_SCHEDULER_H_
+#define QUICHE_HTTP2_CORE_WRITE_SCHEDULER_H_
#include <cstdint>
#include <string>
@@ -13,7 +13,7 @@
#include "common/platform/api/quiche_export.h"
#include "spdy/core/spdy_protocol.h"
-namespace spdy {
+namespace http2 {
// Abstract superclass for classes that decide which SPDY or HTTP/2 stream to
// write next. Concrete subclasses implement various scheduling policies:
@@ -42,7 +42,7 @@ namespace spdy {
template <typename StreamIdType>
class QUICHE_EXPORT_PRIVATE WriteScheduler {
public:
- typedef StreamPrecedence<StreamIdType> StreamPrecedenceType;
+ typedef spdy::StreamPrecedence<StreamIdType> StreamPrecedenceType;
virtual ~WriteScheduler() {}
@@ -157,6 +157,6 @@ class QUICHE_EXPORT_PRIVATE WriteScheduler {
virtual std::string DebugString() const = 0;
};
-} // namespace spdy
+} // namespace http2
-#endif // QUICHE_SPDY_CORE_WRITE_SCHEDULER_H_
+#endif // QUICHE_HTTP2_CORE_WRITE_SCHEDULER_H_
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc
index 6c6a9773c59..b7a8b39d051 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc
@@ -8,6 +8,7 @@
#include <initializer_list>
+#include "absl/strings/escaping.h"
#include "http2/platform/api/http2_logging.h"
#include "http2/platform/api/http2_string_utils.h"
#include "http2/platform/api/http2_test_helpers.h"
@@ -151,7 +152,7 @@ TEST_F(HpackDecoderStringBufferTest, PlainSplit) {
}
TEST_F(HpackDecoderStringBufferTest, HuffmanWhole) {
- std::string encoded = Http2HexDecode("f1e3c2e5f23a6ba0ab90f4ff");
+ std::string encoded = absl::HexStringToBytes("f1e3c2e5f23a6ba0ab90f4ff");
absl::string_view decoded("www.example.com");
EXPECT_EQ(state(), State::RESET);
@@ -176,7 +177,7 @@ TEST_F(HpackDecoderStringBufferTest, HuffmanWhole) {
}
TEST_F(HpackDecoderStringBufferTest, HuffmanSplit) {
- std::string encoded = Http2HexDecode("f1e3c2e5f23a6ba0ab90f4ff");
+ std::string encoded = absl::HexStringToBytes("f1e3c2e5f23a6ba0ab90f4ff");
std::string part1 = encoded.substr(0, 5);
std::string part2 = encoded.substr(5);
absl::string_view decoded("www.example.com");
@@ -215,7 +216,7 @@ TEST_F(HpackDecoderStringBufferTest, HuffmanSplit) {
TEST_F(HpackDecoderStringBufferTest, InvalidHuffmanOnData) {
// Explicitly encode the End-of-String symbol, a no-no.
- std::string encoded = Http2HexDecode("ffffffff");
+ std::string encoded = absl::HexStringToBytes("ffffffff");
buf_.OnStart(/*huffman_encoded*/ true, encoded.size());
EXPECT_EQ(state(), State::COLLECTING);
@@ -229,7 +230,7 @@ TEST_F(HpackDecoderStringBufferTest, InvalidHuffmanOnData) {
TEST_F(HpackDecoderStringBufferTest, InvalidHuffmanOnEnd) {
// Last byte of string doesn't end with prefix of End-of-String symbol.
- std::string encoded = Http2HexDecode("00");
+ std::string encoded = absl::HexStringToBytes("00");
buf_.OnStart(/*huffman_encoded*/ true, encoded.size());
EXPECT_EQ(state(), State::COLLECTING);
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables.h b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables.h
index f75916d67df..ef5b3d2d678 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables.h
+++ b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables.h
@@ -25,8 +25,8 @@
#include <vector>
#include "http2/http2_constants.h"
-#include "quic/core/quic_circular_deque.h"
#include "common/platform/api/quiche_export.h"
+#include "common/quiche_circular_deque.h"
namespace http2 {
namespace test {
@@ -107,7 +107,7 @@ class QUICHE_EXPORT_PRIVATE HpackDecoderDynamicTable {
// Removes the oldest dynamic table entry.
void RemoveLastEntry();
- quic::QuicCircularDeque<HpackStringPair> table_;
+ quiche::QuicheCircularDeque<HpackStringPair> table_;
// The last received DynamicTableSizeUpdate value, initialized to
// SETTINGS_HEADER_TABLE_SIZE.
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_decoder_test.cc
index fa88038af2f..e7a346e7719 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_decoder_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_decoder_test.cc
@@ -9,6 +9,7 @@
#include <iostream>
#include "absl/base/macros.h"
+#include "absl/strings/escaping.h"
#include "http2/decoder/decode_buffer.h"
#include "http2/decoder/decode_status.h"
#include "http2/platform/api/http2_string_utils.h"
@@ -188,13 +189,13 @@ class HpackHuffmanDecoderTest : public RandomDecoderTest {
TEST_F(HpackHuffmanDecoderTest, SpecRequestExamples) {
HpackHuffmanDecoder decoder;
std::string test_table[] = {
- Http2HexDecode("f1e3c2e5f23a6ba0ab90f4ff"),
+ absl::HexStringToBytes("f1e3c2e5f23a6ba0ab90f4ff"),
"www.example.com",
- Http2HexDecode("a8eb10649cbf"),
+ absl::HexStringToBytes("a8eb10649cbf"),
"no-cache",
- Http2HexDecode("25a849e95ba97d7f"),
+ absl::HexStringToBytes("25a849e95ba97d7f"),
"custom-key",
- Http2HexDecode("25a849e95bb8e8b4bf"),
+ absl::HexStringToBytes("25a849e95bb8e8b4bf"),
"custom-value",
};
for (size_t i = 0; i != ABSL_ARRAYSIZE(test_table); i += 2) {
@@ -212,17 +213,17 @@ TEST_F(HpackHuffmanDecoderTest, SpecResponseExamples) {
HpackHuffmanDecoder decoder;
// clang-format off
std::string test_table[] = {
- Http2HexDecode("6402"),
+ absl::HexStringToBytes("6402"),
"302",
- Http2HexDecode("aec3771a4b"),
+ absl::HexStringToBytes("aec3771a4b"),
"private",
- Http2HexDecode("d07abe941054d444a8200595040b8166"
+ absl::HexStringToBytes("d07abe941054d444a8200595040b8166"
"e082a62d1bff"),
"Mon, 21 Oct 2013 20:13:21 GMT",
- Http2HexDecode("9d29ad171863c78f0b97c8e9ae82ae43"
+ absl::HexStringToBytes("9d29ad171863c78f0b97c8e9ae82ae43"
"d3"),
"https://www.example.com",
- Http2HexDecode("94e7821dd7f2e6c7b335dfdfcd5b3960"
+ absl::HexStringToBytes("94e7821dd7f2e6c7b335dfdfcd5b3960"
"d5af27087f3672c1ab270fb5291f9587"
"316065c003ed4ee5b1063d5007"),
"foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1",
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_encoder_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_encoder_test.cc
index 666fe95d948..0d321876149 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_encoder_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_encoder_test.cc
@@ -5,6 +5,7 @@
#include "http2/hpack/huffman/hpack_huffman_encoder.h"
#include "absl/base/macros.h"
+#include "absl/strings/escaping.h"
#include "http2/platform/api/http2_string_utils.h"
#include "common/platform/api/quiche_test.h"
@@ -40,13 +41,13 @@ TEST_P(HuffmanEncoderTest, Empty) {
TEST_P(HuffmanEncoderTest, SpecRequestExamples) {
std::string test_table[] = {
- Http2HexDecode("f1e3c2e5f23a6ba0ab90f4ff"),
+ absl::HexStringToBytes("f1e3c2e5f23a6ba0ab90f4ff"),
"www.example.com",
- Http2HexDecode("a8eb10649cbf"),
+ absl::HexStringToBytes("a8eb10649cbf"),
"no-cache",
- Http2HexDecode("25a849e95ba97d7f"),
+ absl::HexStringToBytes("25a849e95ba97d7f"),
"custom-key",
- Http2HexDecode("25a849e95bb8e8b4bf"),
+ absl::HexStringToBytes("25a849e95bb8e8b4bf"),
"custom-value",
};
for (size_t i = 0; i != ABSL_ARRAYSIZE(test_table); i += 2) {
@@ -64,17 +65,17 @@ TEST_P(HuffmanEncoderTest, SpecRequestExamples) {
TEST_P(HuffmanEncoderTest, SpecResponseExamples) {
// clang-format off
std::string test_table[] = {
- Http2HexDecode("6402"),
+ absl::HexStringToBytes("6402"),
"302",
- Http2HexDecode("aec3771a4b"),
+ absl::HexStringToBytes("aec3771a4b"),
"private",
- Http2HexDecode("d07abe941054d444a8200595040b8166"
+ absl::HexStringToBytes("d07abe941054d444a8200595040b8166"
"e082a62d1bff"),
"Mon, 21 Oct 2013 20:13:21 GMT",
- Http2HexDecode("9d29ad171863c78f0b97c8e9ae82ae43"
+ absl::HexStringToBytes("9d29ad171863c78f0b97c8e9ae82ae43"
"d3"),
"https://www.example.com",
- Http2HexDecode("94e7821dd7f2e6c7b335dfdfcd5b3960"
+ absl::HexStringToBytes("94e7821dd7f2e6c7b335dfdfcd5b3960"
"d5af27087f3672c1ab270fb5291f9587"
"316065c003ed4ee5b1063d5007"),
"foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1",
@@ -120,11 +121,11 @@ TEST_P(HuffmanEncoderTest, AppendToOutput) {
size_t encoded_size = HuffmanSize("foo");
std::string buffer;
Encode("foo", encoded_size, &buffer);
- EXPECT_EQ(Http2HexDecode("94e7"), buffer);
+ EXPECT_EQ(absl::HexStringToBytes("94e7"), buffer);
encoded_size = HuffmanSize("bar");
Encode("bar", encoded_size, &buffer);
- EXPECT_EQ(Http2HexDecode("94e78c767f"), buffer);
+ EXPECT_EQ(absl::HexStringToBytes("94e78c767f"), buffer);
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder_test.cc
index d4eb3d78790..3821127bd08 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder_test.cc
@@ -4,6 +4,7 @@
#include "http2/hpack/tools/hpack_block_builder.h"
+#include "absl/strings/escaping.h"
#include "http2/platform/api/http2_string_utils.h"
#include "common/platform/api/quiche_test.h"
@@ -97,7 +98,7 @@ TEST(HpackBlockBuilderTest, ExamplesFromSpecC3) {
// 0x0010: 2e63 6f6d .com
const std::string expected =
- Http2HexDecode("828684410f7777772e6578616d706c652e636f6d");
+ absl::HexStringToBytes("828684410f7777772e6578616d706c652e636f6d");
EXPECT_EQ(expected, b.buffer());
}
}
@@ -128,7 +129,7 @@ TEST(HpackBlockBuilderTest, ExamplesFromSpecC4) {
// 0x0010: ff .
const std::string expected =
- Http2HexDecode("828684418cf1e3c2e5f23a6ba0ab90f4ff");
+ absl::HexStringToBytes("828684418cf1e3c2e5f23a6ba0ab90f4ff");
EXPECT_EQ(expected, b.buffer());
}
}
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_example.cc b/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_example.cc
index 00664b27f14..b2783e3b277 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_example.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_example.cc
@@ -6,6 +6,7 @@
#include <ctype.h>
+#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
#include "http2/platform/api/http2_bug_tracker.h"
#include "http2/platform/api/http2_logging.h"
@@ -22,7 +23,7 @@ void HpackExampleToStringOrDie(absl::string_view example, std::string* output) {
QUICHE_CHECK_GT(example.size(), 1u) << "Truncated hex byte?";
const char c1 = example[1];
QUICHE_CHECK(isxdigit(c1)) << "Found half a byte?";
- *output += Http2HexDecode(example.substr(0, 2));
+ *output += absl::HexStringToBytes(example.substr(0, 2));
example.remove_prefix(2);
continue;
}
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder_test.cc
index 3d73c5c4a86..a67cca6c729 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder_test.cc
@@ -9,6 +9,7 @@
#include <stddef.h>
#include "absl/base/macros.h"
+#include "absl/strings/escaping.h"
#include "absl/strings/string_view.h"
#include "http2/platform/api/http2_logging.h"
#include "http2/platform/api/http2_string_utils.h"
@@ -28,7 +29,7 @@ class HpackVarintDecoderTest : public RandomDecoderTest,
protected:
HpackVarintDecoderTest()
: high_bits_(::testing::get<0>(GetParam())),
- suffix_(Http2HexDecode(::testing::get<1>(GetParam()))),
+ suffix_(absl::HexStringToBytes(::testing::get<1>(GetParam()))),
prefix_length_(0) {}
void DecodeExpectSuccess(absl::string_view data,
@@ -261,7 +262,7 @@ struct {
TEST_P(HpackVarintDecoderTest, Success) {
for (size_t i = 0; i < ABSL_ARRAYSIZE(kSuccessTestData); ++i) {
- DecodeExpectSuccess(Http2HexDecode(kSuccessTestData[i].data),
+ DecodeExpectSuccess(absl::HexStringToBytes(kSuccessTestData[i].data),
kSuccessTestData[i].prefix_length,
kSuccessTestData[i].expected_value);
}
@@ -302,7 +303,7 @@ struct {
TEST_P(HpackVarintDecoderTest, Error) {
for (size_t i = 0; i < ABSL_ARRAYSIZE(kErrorTestData); ++i) {
- DecodeExpectError(Http2HexDecode(kErrorTestData[i].data),
+ DecodeExpectError(absl::HexStringToBytes(kErrorTestData[i].data),
kErrorTestData[i].prefix_length);
}
}
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_encoder_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_encoder_test.cc
index cd1666b8ce3..7f049e8eabf 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_encoder_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_encoder_test.cc
@@ -5,8 +5,8 @@
#include "http2/hpack/varint/hpack_varint_encoder.h"
#include "absl/base/macros.h"
+#include "absl/strings/escaping.h"
#include "http2/platform/api/http2_string_utils.h"
-
#include "common/platform/api/quiche_test.h"
namespace http2 {
@@ -105,7 +105,7 @@ TEST(HpackVarintEncoderTest, Long) {
// a single ResumeEncoding() call.
for (size_t i = 0; i < ABSL_ARRAYSIZE(kLongTestData); ++i) {
std::string expected_encoding =
- Http2HexDecode(kLongTestData[i].expected_encoding);
+ absl::HexStringToBytes(kLongTestData[i].expected_encoding);
std::string output;
HpackVarintEncoder::Encode(kLongTestData[i].high_bits,
@@ -145,16 +145,16 @@ TEST(HpackVarintEncoderTest, LastByteIsZero) {
// Test that encoder appends correctly to non-empty string.
TEST(HpackVarintEncoderTest, Append) {
std::string output("foo");
- EXPECT_EQ(Http2HexDecode("666f6f"), output);
+ EXPECT_EQ(absl::HexStringToBytes("666f6f"), output);
HpackVarintEncoder::Encode(0b10011000, 3, 103, &output);
- EXPECT_EQ(Http2HexDecode("666f6f9f60"), output);
+ EXPECT_EQ(absl::HexStringToBytes("666f6f9f60"), output);
HpackVarintEncoder::Encode(0b10100000, 5, 8, &output);
- EXPECT_EQ(Http2HexDecode("666f6f9f60a8"), output);
+ EXPECT_EQ(absl::HexStringToBytes("666f6f9f60a8"), output);
HpackVarintEncoder::Encode(0b10011000, 3, 202147110, &output);
- EXPECT_EQ(Http2HexDecode("666f6f9f60a89f9f8ab260"), output);
+ EXPECT_EQ(absl::HexStringToBytes("666f6f9f60a89f9f8ab260"), output);
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_round_trip_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_round_trip_test.cc
index a8ba99a8a31..d8152593547 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_round_trip_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_round_trip_test.cc
@@ -14,6 +14,7 @@
#include <vector>
#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "http2/hpack/tools/hpack_block_builder.h"
#include "http2/platform/api/http2_logging.h"
@@ -285,7 +286,7 @@ TEST_F(HpackVarintRoundTripTest, Encode) {
for (uint64_t value : values) {
EncodeNoRandom(value, prefix_length);
std::string dump = Http2HexDump(buffer_);
- HTTP2_LOG(INFO) << Http2StringPrintf("%10llu %0#18x ", value, value)
+ HTTP2_LOG(INFO) << absl::StrFormat("%10llu %0#18x ", value, value)
<< Http2HexDump(buffer_).substr(7);
}
}
diff --git a/chromium/net/third_party/quiche/src/http2/http2_constants.cc b/chromium/net/third_party/quiche/src/http2/http2_constants.cc
index 2faf2f94ebe..bebe8803652 100644
--- a/chromium/net/third_party/quiche/src/http2/http2_constants.cc
+++ b/chromium/net/third_party/quiche/src/http2/http2_constants.cc
@@ -5,6 +5,7 @@
#include "http2/http2_constants.h"
#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "http2/platform/api/http2_logging.h"
#include "http2/platform/api/http2_string_utils.h"
@@ -83,7 +84,7 @@ std::string Http2FrameFlagsToString(Http2FrameType type, uint8_t flags) {
}
}
if (flags != 0) {
- append_and_clear(Http2StringPrintf("0x%02x", flags), flags);
+ append_and_clear(absl::StrFormat("0x%02x", flags), flags);
}
QUICHE_DCHECK_EQ(0, flags);
return s;
diff --git a/chromium/net/third_party/quiche/src/http2/http2_structures.cc b/chromium/net/third_party/quiche/src/http2/http2_structures.cc
index dda0dd88302..a96edccdd71 100644
--- a/chromium/net/third_party/quiche/src/http2/http2_structures.cc
+++ b/chromium/net/third_party/quiche/src/http2/http2_structures.cc
@@ -7,6 +7,7 @@
#include <cstring> // For std::memcmp
#include <sstream>
+#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
#include "http2/platform/api/http2_string_utils.h"
@@ -98,7 +99,9 @@ bool operator==(const Http2PingFields& a, const Http2PingFields& b) {
std::ostream& operator<<(std::ostream& out, const Http2PingFields& v) {
return out << "opaque_bytes=0x"
- << Http2HexEncode(v.opaque_bytes, sizeof v.opaque_bytes);
+ << absl::BytesToHexString(absl::string_view(
+ reinterpret_cast<const char*>(v.opaque_bytes),
+ sizeof v.opaque_bytes));
}
// Http2GoAwayFields:
diff --git a/chromium/net/third_party/quiche/src/http2/platform/api/http2_string_utils.h b/chromium/net/third_party/quiche/src/http2/platform/api/http2_string_utils.h
index 087bd254a96..cf39515ad4c 100644
--- a/chromium/net/third_party/quiche/src/http2/platform/api/http2_string_utils.h
+++ b/chromium/net/third_party/quiche/src/http2/platform/api/http2_string_utils.h
@@ -14,19 +14,6 @@
namespace http2 {
-template <typename... Args>
-inline std::string Http2StringPrintf(const Args&... args) {
- return Http2StringPrintfImpl(std::forward<const Args&>(args)...);
-}
-
-inline std::string Http2HexEncode(const void* bytes, size_t size) {
- return Http2HexEncodeImpl(bytes, size);
-}
-
-inline std::string Http2HexDecode(absl::string_view data) {
- return Http2HexDecodeImpl(data);
-}
-
inline std::string Http2HexDump(absl::string_view data) {
return Http2HexDumpImpl(data);
}
diff --git a/chromium/net/third_party/quiche/src/http2/platform/api/http2_string_utils_test.cc b/chromium/net/third_party/quiche/src/http2/platform/api/http2_string_utils_test.cc
deleted file mode 100644
index 9ee7869edd3..00000000000
--- a/chromium/net/third_party/quiche/src/http2/platform/api/http2_string_utils_test.cc
+++ /dev/null
@@ -1,23 +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.
-
-#include "http2/platform/api/http2_string_utils.h"
-
-#include "common/platform/api/quiche_test.h"
-
-namespace http2 {
-namespace test {
-namespace {
-
-TEST(Http2StringUtilsTest, Http2StringPrintf) {
- EXPECT_EQ("", Http2StringPrintf("%s", ""));
- EXPECT_EQ("foobar", Http2StringPrintf("%sbar", "foo"));
- EXPECT_EQ("foobar", Http2StringPrintf("%s%s", "foo", "bar"));
- EXPECT_EQ("foo: 1, bar: 2.0",
- Http2StringPrintf("foo: %d, bar: %.1f", 1, 2.0));
-}
-
-} // namespace
-} // namespace test
-} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/test_tools/http2_random.cc b/chromium/net/third_party/quiche/src/http2/test_tools/http2_random.cc
index c9a071df9e0..8f9014efd17 100644
--- a/chromium/net/third_party/quiche/src/http2/test_tools/http2_random.cc
+++ b/chromium/net/third_party/quiche/src/http2/test_tools/http2_random.cc
@@ -1,5 +1,6 @@
#include "http2/test_tools/http2_random.h"
+#include "absl/strings/escaping.h"
#include "http2/platform/api/http2_logging.h"
#include "http2/platform/api/http2_string_utils.h"
#include "third_party/boringssl/src/include/openssl/chacha.h"
@@ -17,13 +18,14 @@ Http2Random::Http2Random() {
}
Http2Random::Http2Random(absl::string_view key) {
- std::string decoded_key = Http2HexDecode(key);
+ std::string decoded_key = absl::HexStringToBytes(key);
QUICHE_CHECK_EQ(sizeof(key_), decoded_key.size());
memcpy(key_, decoded_key.data(), sizeof(key_));
}
std::string Http2Random::Key() const {
- return Http2HexEncode(key_, sizeof(key_));
+ return absl::BytesToHexString(
+ absl::string_view(reinterpret_cast<const char*>(key_), sizeof(key_)));
}
void Http2Random::FillRandom(void* buffer, size_t buffer_size) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_base.cc b/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_base.cc
index 8b4a27f0866..173c8d30488 100644
--- a/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_base.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_base.cc
@@ -23,8 +23,20 @@ WriteResult QuicBatchWriterBase::WritePacket(
PerPacketOptions* options) {
const WriteResult result =
InternalWritePacket(buffer, buf_len, self_address, peer_address, options);
- if (result.status == WRITE_STATUS_BLOCKED) {
- write_blocked_ = true;
+
+ if (GetQuicReloadableFlag(quic_batch_writer_fix_write_blocked)) {
+ if (IsWriteBlockedStatus(result.status)) {
+ if (result.status == WRITE_STATUS_BLOCKED_DATA_BUFFERED) {
+ QUIC_CODE_COUNT(quic_batch_writer_fix_write_blocked_data_buffered);
+ } else {
+ QUIC_CODE_COUNT(quic_batch_writer_fix_write_blocked_data_not_buffered);
+ }
+ write_blocked_ = true;
+ }
+ } else {
+ if (result.status == WRITE_STATUS_BLOCKED) {
+ write_blocked_ = true;
+ }
}
return result;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_base.h b/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_base.h
index ff924d0481c..e7d1f129684 100644
--- a/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_base.h
+++ b/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_base.h
@@ -60,7 +60,7 @@ class QUIC_EXPORT_PRIVATE QuicBatchWriterBase : public QuicPacketWriter {
const QuicBatchWriterBuffer& batch_buffer() const { return *batch_buffer_; }
QuicBatchWriterBuffer& batch_buffer() { return *batch_buffer_; }
- const QuicCircularDeque<BufferedWrite>& buffered_writes() const {
+ const quiche::QuicheCircularDeque<BufferedWrite>& buffered_writes() const {
return batch_buffer_->buffered_writes();
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_buffer.h b/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_buffer.h
index 007c2834cc5..4faa3cba4e7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_buffer.h
+++ b/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_buffer.h
@@ -6,11 +6,11 @@
#define QUICHE_QUIC_PLATFORM_IMPL_BATCH_WRITER_QUIC_BATCH_WRITER_BUFFER_H_
#include "absl/base/optimization.h"
-#include "quic/core/quic_circular_deque.h"
#include "quic/core/quic_linux_socket_utils.h"
#include "quic/core/quic_packet_writer.h"
#include "quic/platform/api/quic_ip_address.h"
#include "quic/platform/api/quic_socket_address.h"
+#include "common/quiche_circular_deque.h"
namespace quic {
@@ -61,7 +61,7 @@ class QUIC_EXPORT_PRIVATE QuicBatchWriterBuffer {
};
PopResult PopBufferedWrite(int32_t num_buffered_writes);
- const QuicCircularDeque<BufferedWrite>& buffered_writes() const {
+ const quiche::QuicheCircularDeque<BufferedWrite>& buffered_writes() const {
return buffered_writes_;
}
@@ -87,7 +87,7 @@ class QUIC_EXPORT_PRIVATE QuicBatchWriterBuffer {
bool Invariants() const;
const char* buffer_end() const { return buffer_ + sizeof(buffer_); }
ABSL_CACHELINE_ALIGNED char buffer_[kBufferSize];
- QuicCircularDeque<BufferedWrite> buffered_writes_;
+ quiche::QuicheCircularDeque<BufferedWrite> buffered_writes_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_gso_batch_writer_test.cc b/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_gso_batch_writer_test.cc
index ec08164e529..8a1b93fc723 100644
--- a/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_gso_batch_writer_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_gso_batch_writer_test.cc
@@ -322,6 +322,11 @@ TEST_F(QuicGsoBatchWriterTest, WriteBlockDataBuffered) {
}));
ASSERT_EQ(WriteResult(WRITE_STATUS_BLOCKED_DATA_BUFFERED, EWOULDBLOCK),
WritePacket(&writer, 50));
+ if (GetQuicReloadableFlag(quic_batch_writer_fix_write_blocked)) {
+ EXPECT_TRUE(writer.IsWriteBlocked());
+ } else {
+ EXPECT_FALSE(writer.IsWriteBlocked());
+ }
ASSERT_EQ(250u, writer.batch_buffer().SizeInUse());
ASSERT_EQ(3u, writer.buffered_writes().size());
}
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 48fe9a82c05..29a43a605e0 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
@@ -17,7 +17,6 @@
#include "quic/core/quic_framer.h"
#include "quic/core/quic_types.h"
#include "quic/core/quic_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
namespace quic {
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 7a34097fd54..6738f49ab05 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,13 +9,13 @@
#include "quic/core/congestion_control/windowed_filter.h"
#include "quic/core/packet_number_indexed_queue.h"
#include "quic/core/quic_bandwidth.h"
-#include "quic/core/quic_circular_deque.h"
#include "quic/core/quic_packets.h"
#include "quic/core/quic_time.h"
#include "quic/core/quic_types.h"
#include "quic/core/quic_unacked_packet_map.h"
#include "quic/platform/api/quic_export.h"
#include "quic/platform/api/quic_flags.h"
+#include "common/quiche_circular_deque.h"
namespace quic {
@@ -540,7 +540,7 @@ class QUIC_EXPORT_PRIVATE BandwidthSampler : public BandwidthSamplerInterface {
PacketNumberIndexedQueue<ConnectionStateOnSentPacket> connection_state_map_;
RecentAckPoints recent_ack_points_;
- QuicCircularDeque<AckPoint> a0_candidates_;
+ quiche::QuicheCircularDeque<AckPoint> a0_candidates_;
// Maximum number of tracked packets.
const QuicPacketCount max_tracked_packets_;
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 d24e50efdbc..8d4a49350b5 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
@@ -116,9 +116,9 @@ void Bbr2NetworkModel::OnCongestionEventStart(
<< total_bytes_acked() - prior_bytes_acked << " bytes from "
<< acked_packets.size()
<< " packets have been acked, but sample_max_bandwidth is zero.";
+ congestion_event->sample_max_bandwidth = sample.sample_max_bandwidth;
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);
}
}
@@ -188,99 +188,112 @@ void Bbr2NetworkModel::OnCongestionEventStart(
void Bbr2NetworkModel::AdaptLowerBounds(
const Bbr2CongestionEvent& congestion_event) {
- if (Params().bw_lo_mode_ != Bbr2Params::DEFAULT) {
- if (congestion_event.bytes_lost == 0) {
+ if (Params().bw_lo_mode_ == Bbr2Params::DEFAULT) {
+ if (!congestion_event.end_of_round_trip ||
+ congestion_event.is_probing_for_bandwidth) {
return;
}
- // Ignore losses from packets sent when probing for more bandwidth in
- // STARTUP or PROBE_UP when they're lost in DRAIN or PROBE_DOWN.
- if (pacing_gain_ < 1) {
- return;
- }
- // Decrease bandwidth_lo whenever there is loss.
- // Set bandwidth_lo_ if it is not yet set.
- if (bandwidth_lo_.IsInfinite()) {
- bandwidth_lo_ = MaxBandwidth();
- }
- // Save bandwidth_lo_ if it hasn't already been saved.
- if (prior_bandwidth_lo_.IsZero()) {
- prior_bandwidth_lo_ = bandwidth_lo_;
- }
- switch (Params().bw_lo_mode_) {
- case Bbr2Params::MIN_RTT_REDUCTION:
- bandwidth_lo_ =
- bandwidth_lo_ - QuicBandwidth::FromBytesAndTimeDelta(
- congestion_event.bytes_lost, MinRtt());
- break;
- case Bbr2Params::INFLIGHT_REDUCTION: {
- // Use a max of BDP and inflight to avoid starving app-limited flows.
- const QuicByteCount effective_inflight =
- std::max(BDP(), congestion_event.prior_bytes_in_flight);
- // This could use bytes_lost_in_round if the bandwidth_lo_ was saved
- // when entering 'recovery', but this BBRv2 implementation doesn't have
- // recovery defined.
- bandwidth_lo_ = bandwidth_lo_ *
- ((effective_inflight - congestion_event.bytes_lost) /
- static_cast<double>(effective_inflight));
- break;
+
+ if (bytes_lost_in_round_ > 0) {
+ if (bandwidth_lo_.IsInfinite()) {
+ bandwidth_lo_ = MaxBandwidth();
}
- case Bbr2Params::CWND_REDUCTION:
- bandwidth_lo_ =
- bandwidth_lo_ *
- ((congestion_event.prior_cwnd - congestion_event.bytes_lost) /
- static_cast<double>(congestion_event.prior_cwnd));
- break;
- case Bbr2Params::DEFAULT:
- QUIC_BUG(quic_bug_10466_1) << "Unreachable case DEFAULT.";
- }
- if (pacing_gain_ > Params().startup_full_bw_threshold) {
- // In STARTUP, pacing_gain_ is applied to bandwidth_lo_ in
- // UpdatePacingRate, so this backs that multiplication out to allow the
- // pacing rate to decrease, but not below
- // bandwidth_latest_ * startup_full_bw_threshold.
- bandwidth_lo_ =
- std::max(bandwidth_lo_,
- bandwidth_latest_ *
- (Params().startup_full_bw_threshold / pacing_gain_));
- } else {
- // Ensure bandwidth_lo isn't lower than bandwidth_latest_.
- bandwidth_lo_ = std::max(bandwidth_lo_, bandwidth_latest_);
- }
- // If it's the end of the round, ensure bandwidth_lo doesn't decrease more
- // than beta.
- if (GetQuicReloadableFlag(quic_bbr2_fix_bw_lo_mode) &&
- congestion_event.end_of_round_trip) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_fix_bw_lo_mode, 2, 2);
bandwidth_lo_ =
- std::max(bandwidth_lo_, prior_bandwidth_lo_ * (1.0 - Params().beta));
- prior_bandwidth_lo_ = QuicBandwidth::Zero();
+ std::max(bandwidth_latest_, bandwidth_lo_ * (1.0 - Params().beta));
+ QUIC_DVLOG(3) << "bandwidth_lo_ updated to " << bandwidth_lo_
+ << ", bandwidth_latest_ is " << bandwidth_latest_;
+
+ if (Params().ignore_inflight_lo) {
+ return;
+ }
+ if (inflight_lo_ == inflight_lo_default()) {
+ inflight_lo_ = congestion_event.prior_cwnd;
+ }
+ inflight_lo_ = std::max<QuicByteCount>(
+ inflight_latest_, inflight_lo_ * (1.0 - Params().beta));
}
- // This early return ignores inflight_lo as well.
return;
}
- if (!congestion_event.end_of_round_trip ||
- congestion_event.is_probing_for_bandwidth) {
+
+ // Params().bw_lo_mode_ != Bbr2Params::DEFAULT
+ if (congestion_event.bytes_lost == 0) {
return;
}
-
- if (bytes_lost_in_round_ > 0) {
- if (bandwidth_lo_.IsInfinite()) {
- bandwidth_lo_ = MaxBandwidth();
+ // Ignore losses from packets sent when probing for more bandwidth in
+ // STARTUP or PROBE_UP when they're lost in DRAIN or PROBE_DOWN.
+ if (pacing_gain_ < 1) {
+ return;
+ }
+ // Decrease bandwidth_lo whenever there is loss.
+ // Set bandwidth_lo_ if it is not yet set.
+ if (bandwidth_lo_.IsInfinite()) {
+ bandwidth_lo_ = MaxBandwidth();
+ }
+ // Save bandwidth_lo_ if it hasn't already been saved.
+ if (prior_bandwidth_lo_.IsZero()) {
+ prior_bandwidth_lo_ = bandwidth_lo_;
+ }
+ switch (Params().bw_lo_mode_) {
+ case Bbr2Params::MIN_RTT_REDUCTION:
+ bandwidth_lo_ =
+ bandwidth_lo_ - QuicBandwidth::FromBytesAndTimeDelta(
+ congestion_event.bytes_lost, MinRtt());
+ break;
+ case Bbr2Params::INFLIGHT_REDUCTION: {
+ // Use a max of BDP and inflight to avoid starving app-limited flows.
+ const QuicByteCount effective_inflight =
+ std::max(BDP(), congestion_event.prior_bytes_in_flight);
+ // This could use bytes_lost_in_round if the bandwidth_lo_ was saved
+ // when entering 'recovery', but this BBRv2 implementation doesn't have
+ // recovery defined.
+ bandwidth_lo_ =
+ bandwidth_lo_ * ((effective_inflight - congestion_event.bytes_lost) /
+ static_cast<double>(effective_inflight));
+ break;
}
+ case Bbr2Params::CWND_REDUCTION:
+ bandwidth_lo_ =
+ bandwidth_lo_ *
+ ((congestion_event.prior_cwnd - congestion_event.bytes_lost) /
+ static_cast<double>(congestion_event.prior_cwnd));
+ break;
+ case Bbr2Params::DEFAULT:
+ QUIC_BUG(quic_bug_10466_1) << "Unreachable case DEFAULT.";
+ }
+ QuicBandwidth last_bandwidth = bandwidth_latest_;
+ // sample_max_bandwidth will be Zero() if the loss is triggered by a timer
+ // expiring. Ideally we'd use the most recent bandwidth sample,
+ // but bandwidth_latest is safer than Zero().
+ if (GetQuicReloadableFlag(quic_bbr2_fix_bw_lo_mode2) &&
+ !congestion_event.sample_max_bandwidth.IsZero()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_fix_bw_lo_mode2, 1, 2);
+ // bandwidth_latest_ is the max bandwidth for the round, but to allow
+ // fast, conservation style response to loss, use the last sample.
+ last_bandwidth = congestion_event.sample_max_bandwidth;
+ }
+ if (pacing_gain_ > Params().startup_full_bw_threshold) {
+ // In STARTUP, pacing_gain_ is applied to bandwidth_lo_ in
+ // UpdatePacingRate, so this backs that multiplication out to allow the
+ // pacing rate to decrease, but not below
+ // last_bandwidth * startup_full_bw_threshold.
+ // TODO(ianswett): Consider altering pacing_gain_ when in STARTUP instead.
+ bandwidth_lo_ = std::max(
+ bandwidth_lo_,
+ last_bandwidth * (Params().startup_full_bw_threshold / pacing_gain_));
+ } else {
+ // Ensure bandwidth_lo isn't lower than last_bandwidth.
+ bandwidth_lo_ = std::max(bandwidth_lo_, last_bandwidth);
+ }
+ // If it's the end of the round, ensure bandwidth_lo doesn't decrease more
+ // than beta.
+ if (GetQuicReloadableFlag(quic_bbr2_fix_bw_lo_mode) &&
+ congestion_event.end_of_round_trip) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_fix_bw_lo_mode, 2, 2);
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_;
-
- if (Params().ignore_inflight_lo) {
- return;
- }
- if (inflight_lo_ == inflight_lo_default()) {
- inflight_lo_ = congestion_event.prior_cwnd;
- }
- inflight_lo_ = std::max<QuicByteCount>(
- inflight_latest_, inflight_lo_ * (1.0 - Params().beta));
+ std::max(bandwidth_lo_, prior_bandwidth_lo_ * (1.0 - Params().beta));
+ prior_bandwidth_lo_ = QuicBandwidth::Zero();
}
+ // These modes ignore inflight_lo as well.
}
void Bbr2NetworkModel::OnCongestionEventFinish(
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 8f5d4185dfc..b7007f55705 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
@@ -92,7 +92,7 @@ struct QUIC_EXPORT_PRIVATE Bbr2Params {
// If true, always exit STARTUP on loss, even if bandwidth exceeds threshold.
// If false, exit STARTUP on loss only if bandwidth is below threshold.
- bool always_exit_startup_on_excess_loss = true;
+ bool always_exit_startup_on_excess_loss = false;
/*
* DRAIN parameters.
@@ -313,6 +313,8 @@ struct QUIC_EXPORT_PRIVATE Bbr2CongestionEvent {
QuicTime::Delta sample_min_rtt = QuicTime::Delta::Infinite();
// Maximum bandwidth of all bandwidth samples from acked_packets.
+ // This sample may be app-limited, and will be Zero() if there are no newly
+ // acknowledged inflight packets.
QuicBandwidth sample_max_bandwidth = QuicBandwidth::Zero();
// The send state of the largest packet in acked_packets, unless it is empty.
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 9045d7e034b..af0f00fee80 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
@@ -500,6 +500,15 @@ void Bbr2ProbeBwMode::EnterProbeDown(bool probed_too_high,
cycle_.rounds_in_phase = 0;
cycle_.phase_start_time = now;
++sender_->connection_stats_->bbr_num_cycles;
+ if (GetQuicReloadableFlag(quic_bbr2_fix_bw_lo_mode2) &&
+ Params().bw_lo_mode_ != Bbr2Params::QuicBandwidthLoMode::DEFAULT) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_fix_bw_lo_mode2, 2, 2);
+ // Clear bandwidth lo if it was set in PROBE_UP, because losses in PROBE_UP
+ // should not permanently change bandwidth_lo.
+ // It's possible for bandwidth_lo to be set during REFILL, but if that was
+ // a valid value, it'll quickly be rediscovered.
+ model_->clear_bandwidth_lo();
+ }
// Pick probe wait time.
cycle_.rounds_since_probe =
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 d0f61277283..b69a7952afa 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
@@ -132,7 +132,7 @@ void Bbr2Sender::ApplyConnectionOptions(
params_.ignore_inflight_lo = true;
}
if (ContainsQuicTag(connection_options, kB2NE)) {
- params_.always_exit_startup_on_excess_loss = false;
+ params_.always_exit_startup_on_excess_loss = true;
}
if (ContainsQuicTag(connection_options, kB2SL)) {
params_.startup_loss_exit_use_max_delivered_for_inflight_hi = false;
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 e26760e0bf9..99acf2c3e21 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
@@ -417,25 +417,6 @@ TEST_F(Bbr2DefaultTopologyTest, SimpleTransfer) {
EXPECT_APPROX_EQ(params.RTT(), rtt_stats()->smoothed_rtt(), 1.0f);
}
-TEST_F(Bbr2DefaultTopologyTest, SimpleTransferB2NE) {
- SetConnectionOption(kB2NE);
- DefaultTopologyParams params;
- CreateNetwork(params);
-
- // Transfer 12MB.
- DoSimpleTransfer(12 * 1024 * 1024, QuicTime::Delta::FromSeconds(35));
- EXPECT_TRUE(Bbr2ModeIsOneOf({Bbr2Mode::PROBE_BW, Bbr2Mode::PROBE_RTT}));
-
- EXPECT_APPROX_EQ(params.BottleneckBandwidth(),
- sender_->ExportDebugState().bandwidth_hi, 0.01f);
-
- EXPECT_LE(sender_loss_rate_in_packets(), 0.05);
- // The margin here is high, because the aggregation greatly increases
- // smoothed rtt.
- EXPECT_GE(params.RTT() * 4, rtt_stats()->smoothed_rtt());
- EXPECT_APPROX_EQ(params.RTT(), rtt_stats()->min_rtt(), 0.2f);
-}
-
TEST_F(Bbr2DefaultTopologyTest, SimpleTransferB2RC) {
SetConnectionOption(kB2RC);
DefaultTopologyParams params;
@@ -859,6 +840,42 @@ TEST_F(Bbr2DefaultTopologyTest, ExitStartupDueToLossB2SL) {
EXPECT_APPROX_EQ(sender_->ExportDebugState().inflight_hi, params.BDP(), 0.1f);
}
+// Verifies that in STARTUP, if we exceed loss threshold in a round, we exit
+// STARTUP at the end of the round even if there's enough bandwidth growth.
+TEST_F(Bbr2DefaultTopologyTest, ExitStartupDueToLossB2NE) {
+ // Set up flags such that any loss will be considered "too high".
+ SetQuicFlag(FLAGS_quic_bbr2_default_startup_full_loss_count, 0);
+ SetQuicFlag(FLAGS_quic_bbr2_default_loss_threshold, 0.0);
+
+ sender_ = SetupBbr2Sender(&sender_endpoint_, /*old_sender=*/nullptr);
+
+ SetConnectionOption(kB2NE);
+ DefaultTopologyParams params;
+ params.switch_queue_capacity_in_bdp = 0.5;
+ CreateNetwork(params);
+
+ // Run until the full bandwidth is reached and check how many rounds it was.
+ sender_endpoint_.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().bandwidth_hi) {
+ max_bw = sender_->ExportDebugState().bandwidth_hi;
+ max_bw_round = sender_->ExportDebugState().round_trip_count;
+ }
+ return sender_->ExportDebugState().startup.full_bandwidth_reached;
+ },
+ QuicTime::Delta::FromSeconds(5));
+ ASSERT_TRUE(simulator_result);
+ EXPECT_EQ(Bbr2Mode::DRAIN, sender_->ExportDebugState().mode);
+ EXPECT_EQ(sender_->ExportDebugState().round_trip_count, max_bw_round);
+ EXPECT_EQ(
+ 0u,
+ sender_->ExportDebugState().startup.round_trips_without_bandwidth_growth);
+ EXPECT_NE(0u, sender_connection_stats().packets_lost);
+}
+
TEST_F(Bbr2DefaultTopologyTest, SenderPoliced) {
DefaultTopologyParams params;
params.sender_policer_params = TrafficPolicerParams();
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 5a9a532e688..1bd89c6024f 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
@@ -112,8 +112,9 @@ void Bbr2StartupMode::CheckExcessiveLosses(
new_inflight_hi = model_->max_bytes_delivered_in_round();
}
}
- QUIC_DVLOG(3) << sender_ << " Exiting STARTUP due to loss. inflight_hi:"
- << new_inflight_hi;
+ QUIC_DVLOG(3) << sender_ << " Exiting STARTUP due to loss at round "
+ << model_->RoundTripCount()
+ << ". inflight_hi:" << new_inflight_hi;
// TODO(ianswett): Add a shared method to set inflight_hi in the model.
model_->set_inflight_hi(new_inflight_hi);
model_->set_full_bandwidth_reached();
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 c16668b2fdd..dccd7dfa48d 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
@@ -13,7 +13,6 @@
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/quic_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
#include "common/test_tools/quiche_test_utils.h"
namespace {
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 5c093ad4ee0..67e35ed8934 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
@@ -13,7 +13,6 @@
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/quic_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
#include "common/test_tools/quiche_test_utils.h"
namespace {
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 6877d9de48f..25abd716576 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
@@ -12,7 +12,6 @@
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/quic_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
#include "common/test_tools/quiche_test_utils.h"
namespace {
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 d51c5deb0ea..7e5fb25a937 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
@@ -12,7 +12,6 @@
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/quic_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
#include "common/test_tools/quiche_test_utils.h"
namespace {
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 bfafd2cb513..c63a589a3d8 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
@@ -13,7 +13,6 @@
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/quic_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
#include "common/test_tools/quiche_test_utils.h"
namespace {
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 8d4c1de8e16..a2f8066717c 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
@@ -13,7 +13,6 @@
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/quic_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
#include "common/test_tools/quiche_test_utils.h"
namespace {
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 b76ee7bf8d4..a024d131c2a 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
@@ -12,7 +12,6 @@
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/crypto_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
namespace quic {
namespace test {
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
index c21dd202b2d..4024a78e952 100644
--- 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
@@ -30,9 +30,9 @@
#include "quic/platform/api/quic_bug_tracker.h"
#include "quic/platform/api/quic_ip_address.h"
#include "quic/platform/api/quic_logging.h"
-#include "common/platform/api/quiche_text_utils.h"
#include "common/platform/api/quiche_time_utils.h"
#include "common/quiche_data_reader.h"
+#include "common/quiche_text_utils.h"
namespace quic {
namespace {
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 42d8899a781..93e48d257d0 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
@@ -12,7 +12,6 @@
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/quic_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
#include "common/test_tools/quiche_test_utils.h"
namespace {
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 8c403fede35..7fc32822f7e 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
@@ -8,12 +8,12 @@
#include <string>
#include "absl/base/macros.h"
+#include "absl/strings/escaping.h"
#include "absl/strings/string_view.h"
#include "quic/core/crypto/chacha20_poly1305_decrypter.h"
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/quic_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
#include "common/test_tools/quiche_test_utils.h"
namespace {
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 4b0f10bcd0d..b71bcf127f8 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
@@ -12,7 +12,6 @@
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/quic_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
#include "common/test_tools/quiche_test_utils.h"
namespace {
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 7bca425a708..61aaac73d17 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
@@ -14,7 +14,6 @@
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/quic_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
#include "common/test_tools/quiche_test_utils.h"
namespace {
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 3109924d59e..68e3d9cbe19 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
@@ -13,7 +13,6 @@
#include "absl/strings/escaping.h"
#include "quic/core/crypto/crypto_framer.h"
#include "quic/core/quic_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
using std::cerr;
using std::cout;
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 e08d90b1c08..af62865b653 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
@@ -28,7 +28,7 @@ using ServerConfigID = std::string;
// The following tags have been deprecated and should not be reused:
// "1CON", "BBQ4", "NCON", "RCID", "SREJ", "TBKP", "TB10", "SCLS", "SMHL",
-// "QNZR", "B2HI", "H2PR", "FIFO", "LIFO", "RRWS"
+// "QNZR", "B2HI", "H2PR", "FIFO", "LIFO", "RRWS", "QNSP"
// clang-format off
const QuicTag kCHLO = TAG('C', 'H', 'L', 'O'); // Client hello
@@ -127,9 +127,10 @@ 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 kB2NE = TAG('B', '2', 'N', 'E'); // For BBRv2, do not exit
- // STARTUP if there's enough
- // bandwidth growth
+const QuicTag kB2NE = TAG('B', '2', 'N', 'E'); // For BBRv2, always exit
+ // STARTUP on loss, even if
+ // bandwidth growth exceeds
+ // threshold.
const QuicTag kB2RP = TAG('B', '2', 'R', 'P'); // For BBRv2, run PROBE_RTT on
// the regular schedule
const QuicTag kB2CL = TAG('B', '2', 'C', 'L'); // For BBRv2, allow PROBE_BW
@@ -342,6 +343,7 @@ const QuicTag kMTUL = TAG('M', 'T', 'U', 'L'); // Low-target MTU discovery.
const QuicTag kNSLC = TAG('N', 'S', 'L', 'C'); // Always send connection close
// for idle timeout.
+const QuicTag kCHSP = TAG('C', 'H', 'S', 'P'); // Chaos protection.
// Proof types (i.e. certificate types)
// NOTE: although it would be silly to do so, specifying both kX509 and kX59R
@@ -401,9 +403,6 @@ const QuicTag kPDP5 = TAG('P', 'D', 'P', '5'); // Path degrading triggered
const QuicTag kQNZ2 = TAG('Q', 'N', 'Z', '2'); // Turn off QUIC crypto 0-RTT.
-const QuicTag kQNSP = TAG('Q', 'N', 'S', 'P'); // Turn off server push in
- // gQUIC.
-
const QuicTag kMAD = TAG('M', 'A', 'D', 0); // Max Ack Delay (IETF QUIC)
const QuicTag kIGNP = TAG('I', 'G', 'N', 'P'); // Do not use PING only packet
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 7414eda8692..7fadbbdcef7 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
@@ -33,7 +33,6 @@
#include "quic/test_tools/mock_random.h"
#include "quic/test_tools/quic_crypto_server_config_peer.h"
#include "quic/test_tools/quic_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
#include "common/quiche_endian.h"
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 2c8435035c9..67527d45826 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
@@ -762,4 +762,21 @@ std::string CryptoUtils::HashHandshakeMessage(
}
#undef RETURN_STRING_LITERAL // undef for jumbo builds
+
+// static
+bool CryptoUtils::GetSSLCapabilities(const SSL* ssl,
+ bssl::UniquePtr<uint8_t>* capabilities,
+ size_t* capabilities_len) {
+ uint8_t* buffer;
+ CBB cbb;
+
+ if (!CBB_init(&cbb, 128) || !SSL_serialize_capabilities(ssl, &cbb) ||
+ !CBB_finish(&cbb, &buffer, capabilities_len)) {
+ return false;
+ }
+
+ *capabilities = bssl::UniquePtr<uint8_t>(buffer);
+ return true;
+}
+
} // namespace quic
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 ec68c6580f4..7aa32e1445a 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
@@ -237,6 +237,11 @@ class QUIC_EXPORT_PRIVATE CryptoUtils {
// Returns a hash of the serialized |message|.
static std::string HashHandshakeMessage(const CryptoHandshakeMessage& message,
Perspective perspective);
+
+ // Wraps SSL_serialize_capabilities. Return nullptr if failed.
+ static bool GetSSLCapabilities(const SSL* ssl,
+ bssl::UniquePtr<uint8_t>* capabilities,
+ size_t* capabilities_len);
};
} // namespace quic
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 4586b9bbb4a..0f2df3a7f90 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
@@ -11,7 +11,6 @@
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/quic_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
#include "common/test_tools/quiche_test_utils.h"
namespace quic {
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 cee94f2e4af..31cbfd66114 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
@@ -229,12 +229,15 @@ class QUIC_EXPORT_PRIVATE ProofSourceHandleCallback {
// whether it is completed before ProofSourceHandle::SelectCertificate
// returned.
// |chain| the certificate chain in leaf-first order.
+ // |handshake_hints| (optional) handshake hints that can be used by
+ // SSL_set_handshake_hints.
//
// When called asynchronously(is_sync=false), this method will be responsible
// to continue the handshake from where it left off.
virtual void OnSelectCertificateDone(bool ok,
bool is_sync,
- const ProofSource::Chain* chain) = 0;
+ const ProofSource::Chain* chain,
+ absl::string_view handshake_hints) = 0;
// Called when a ProofSourceHandle::ComputeSignature operation completes.
virtual void OnComputeSignatureDone(
@@ -280,9 +283,11 @@ class QUIC_EXPORT_PRIVATE ProofSourceHandle {
virtual QuicAsyncStatus SelectCertificate(
const QuicSocketAddress& server_address,
const QuicSocketAddress& client_address,
+ absl::string_view ssl_capabilities,
const std::string& hostname,
absl::string_view client_hello,
const std::string& alpn,
+ absl::optional<std::string> alps,
const std::vector<uint8_t>& quic_transport_params,
const absl::optional<std::vector<uint8_t>>& early_data_context) = 0;
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 c886cbe989e..3f94e7cda60 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
@@ -34,7 +34,6 @@
#include "quic/platform/api/quic_hostname_utils.h"
#include "quic/platform/api/quic_logging.h"
#include "quic/platform/api/quic_map_util.h"
-#include "common/platform/api/quiche_text_utils.h"
namespace quic {
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 4f19533b008..f2a88095aac 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
@@ -51,7 +51,6 @@
#include "quic/platform/api/quic_reference_counted.h"
#include "quic/platform/api/quic_socket_address.h"
#include "quic/platform/api/quic_testvalue.h"
-#include "common/platform/api/quiche_text_utils.h"
namespace quic {
@@ -745,9 +744,7 @@ void QuicCryptoServerConfig::ProcessClientHelloAfterGetProof(
<< context->connection_id() << " which is invalid with version "
<< context->version();
- if (context->validate_chlo_result()->postpone_cert_validate_for_server &&
- context->info().reject_reasons.empty()) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_crypto_postpone_cert_validate_for_server);
+ if (context->info().reject_reasons.empty()) {
if (!context->signed_config() || !context->signed_config()->chain) {
// No chain.
context->validate_chlo_result()->info.reject_reasons.push_back(
@@ -1224,8 +1221,8 @@ void QuicCryptoServerConfig::SelectNewPrimaryConfig(
}
void QuicCryptoServerConfig::EvaluateClientHello(
- const QuicSocketAddress& server_address,
- const QuicSocketAddress& client_address,
+ const QuicSocketAddress& /*server_address*/,
+ const QuicSocketAddress& /*client_address*/,
QuicTransportVersion /*version*/,
const Configs& configs,
QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
@@ -1294,17 +1291,6 @@ void QuicCryptoServerConfig::EvaluateClientHello(
// No valid source address token.
}
- if (!client_hello_state->postpone_cert_validate_for_server) {
- QuicReferenceCountedPointer<ProofSource::Chain> chain =
- proof_source_->GetCertChain(server_address, client_address,
- std::string(info->sni));
- if (!chain) {
- info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
- } else if (!ValidateExpectedLeafCertificate(client_hello, chain->certs)) {
- info->reject_reasons.push_back(INVALID_EXPECTED_LEAF_CERTIFICATE);
- }
- }
-
if (info->client_nonce.size() != kNonceSize) {
info->reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE);
// Invalid client nonce.
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 464f2bbfc36..4f3ad0819e4 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
@@ -98,9 +98,6 @@ class QUIC_EXPORT_PRIVATE ValidateClientHelloResultCallback {
// Populated if the CHLO STK contained a CachedNetworkParameters proto.
CachedNetworkParameters cached_network_params;
- const bool postpone_cert_validate_for_server =
- GetQuicReloadableFlag(quic_crypto_postpone_cert_validate_for_server);
-
protected:
~Result() override;
};
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 9f70c355237..484e46eee6a 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
@@ -25,7 +25,6 @@
#include "quic/test_tools/mock_clock.h"
#include "quic/test_tools/quic_crypto_server_config_peer.h"
#include "quic/test_tools/quic_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
namespace quic {
namespace test {
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 73f850ed68a..e23d3f2a1e9 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
@@ -9,7 +9,6 @@
#include "absl/base/macros.h"
#include "absl/strings/escaping.h"
#include "quic/platform/api/quic_test.h"
-#include "common/platform/api/quiche_text_utils.h"
namespace quic {
namespace test {
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 8926909cd78..6e9901b995e 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
@@ -30,16 +30,12 @@ bssl::UniquePtr<SSL_CTX> TlsServerConnection::CreateSslCtx(
QUIC_CODE_COUNT(quic_session_tickets_enabled);
SSL_CTX_set_ticket_aead_method(ssl_ctx.get(),
&TlsServerConnection::kSessionTicketMethod);
- } else if (!GetQuicRestartFlag(quic_session_tickets_always_enabled)) {
- QUIC_CODE_COUNT(quic_session_tickets_disabled_by_flag);
- SSL_CTX_set_options(ssl_ctx.get(), SSL_OP_NO_TICKET);
} else {
QUIC_CODE_COUNT(quic_session_tickets_disabled);
}
- if (proof_source->GetTicketCrypter() ||
- GetQuicRestartFlag(quic_session_tickets_always_enabled)) {
- SSL_CTX_set_early_data_enabled(ssl_ctx.get(), 1);
- }
+
+ SSL_CTX_set_early_data_enabled(ssl_ctx.get(), 1);
+
SSL_CTX_set_select_certificate_cb(
ssl_ctx.get(), &TlsServerConnection::EarlySelectCertCallback);
SSL_CTX_set_options(ssl_ctx.get(), SSL_OP_CIPHER_SERVER_PREFERENCE);
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 8ad442fc694..8642fd93265 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,6 @@
#include "absl/strings/escaping.h"
#include "quic/platform/api/quic_logging.h"
-#include "common/platform/api/quiche_text_utils.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 857ca19291f..0f88bb83160 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,6 @@
#include "absl/strings/escaping.h"
#include "quic/platform/api/quic_bug_tracker.h"
-#include "common/platform/api/quiche_text_utils.h"
namespace quic {
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 ade4156b8ab..f802b131b30 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,6 @@
#include "absl/strings/escaping.h"
#include "quic/platform/api/quic_bug_tracker.h"
-#include "common/platform/api/quiche_text_utils.h"
namespace quic {
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 ae291b7826f..1e47d16a5f1 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
@@ -74,6 +74,9 @@ class QUIC_EXPORT_PRIVATE HandshakerDelegateInterface {
// Called at the end of an handshake operation callback.
virtual void OnHandshakeCallbackDone() = 0;
+
+ // Whether a packet flusher is currently attached.
+ virtual bool PacketFlusherAttached() const = 0;
};
} // namespace quic
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 aceebe1b33b..8efba8869bf 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
@@ -17,6 +17,7 @@
#include "quic/core/http/http_constants.h"
#include "quic/core/http/quic_spdy_client_stream.h"
#include "quic/core/http/web_transport_http3.h"
+#include "quic/core/quic_connection.h"
#include "quic/core/quic_data_writer.h"
#include "quic/core/quic_epoll_connection_helper.h"
#include "quic/core/quic_error_codes.h"
@@ -43,7 +44,6 @@
#include "quic/test_tools/packet_reordering_writer.h"
#include "quic/test_tools/qpack/qpack_encoder_peer.h"
#include "quic/test_tools/qpack/qpack_encoder_test_utils.h"
-#include "quic/test_tools/qpack/qpack_header_table_peer.h"
#include "quic/test_tools/qpack/qpack_test_utils.h"
#include "quic/test_tools/quic_client_peer.h"
#include "quic/test_tools/quic_config_peer.h"
@@ -80,6 +80,7 @@ using ::testing::_;
using ::testing::Assign;
using ::testing::Invoke;
using ::testing::NiceMock;
+using testing::NotNull;
namespace quic {
namespace test {
@@ -750,6 +751,18 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
}
}
+ void WaitForNewConnectionIds() {
+ // Wait until a new server CID is available for another migration.
+ const auto* client_connection = GetClientConnection();
+ while (!QuicConnectionPeer::HasUnusedPeerIssuedConnectionId(
+ client_connection) ||
+ (!client_connection->client_connection_id().IsEmpty() &&
+ !QuicConnectionPeer::HasSelfIssuedConnectionIdToConsume(
+ client_connection))) {
+ client_->client()->WaitForEvents();
+ }
+ }
+
ScopedEnvironmentForThreads environment_;
bool initialized_;
// If true, the Initialize() function will create |client_| and starts to
@@ -1552,17 +1565,11 @@ TEST_P(EndToEndTest, AddressToken) {
server_thread_->Pause();
QuicConnection* server_connection = GetServerConnection();
if (server_connection != nullptr) {
- if (GetQuicReloadableFlag(quic_enable_token_based_address_validation)) {
- // Verify address is validated via validating token received in INITIAL
- // packet.
- EXPECT_FALSE(server_connection->GetStats()
- .address_validated_via_decrypting_packet);
- EXPECT_TRUE(server_connection->GetStats().address_validated_via_token);
- } else {
- EXPECT_TRUE(server_connection->GetStats()
- .address_validated_via_decrypting_packet);
- EXPECT_FALSE(server_connection->GetStats().address_validated_via_token);
- }
+ // Verify address is validated via validating token received in INITIAL
+ // packet.
+ EXPECT_FALSE(
+ server_connection->GetStats().address_validated_via_decrypting_packet);
+ EXPECT_TRUE(server_connection->GetStats().address_validated_via_token);
} else {
ADD_FAILURE() << "Missing server connection";
}
@@ -2477,10 +2484,7 @@ TEST_P(
HalfRttResponseBlocksShloRetransmissionWithoutTokenBasedAddressValidation) {
// Turn off token based address validation to make the server get constrained
// by amplification factor during handshake.
- // TODO(fayang): Keep this test while deprecating
- // quic_enable_token_based_address_validation. For example, consider always
- // rejecting the received address token.
- SetQuicReloadableFlag(quic_enable_token_based_address_validation, false);
+ SetQuicFlag(FLAGS_quic_reject_retry_token_in_initial_packet, true);
ASSERT_TRUE(Initialize());
if (!version_.SupportsAntiAmplificationLimit()) {
return;
@@ -2502,17 +2506,8 @@ TEST_P(
// Large response (100KB) for 0-RTT request.
std::string large_body(102400, 'a');
AddToCache("/large_response", 200, large_body);
- if (GetQuicReloadableFlag(quic_preempt_stream_data_with_handshake_packet)) {
- SendSynchronousRequestAndCheckResponse(client_.get(), "/large_response",
- large_body);
- } else {
- // Server consistently gets constrained by amplification factor, hence PTO
- // never gets armed. The CHLO retransmission would trigger the
- // retransmission of SHLO, however, the ENCRYPTION_HANDSHAKE packet NEVER
- // gets retransmitted since half RTT data consumes the remaining space in
- // the coalescer.
- EXPECT_EQ("", client_->SendSynchronousRequest("/large_response"));
- }
+ SendSynchronousRequestAndCheckResponse(client_.get(), "/large_response",
+ large_body);
}
TEST_P(EndToEndTest, MaxStreamsUberTest) {
@@ -2620,6 +2615,253 @@ TEST_P(EndToEndTest, ConnectionMigrationClientIPChanged) {
server_thread_->Resume();
}
+TEST_P(EndToEndTest, IetfConnectionMigrationClientIPChangedMultipleTimes) {
+ ASSERT_TRUE(Initialize());
+ if (!GetClientConnection()->connection_migration_use_new_cid()) {
+ return;
+ }
+ SendSynchronousFooRequestAndCheckResponse();
+
+ // Store the client IP address which was used to send the first request.
+ QuicIpAddress host0 =
+ client_->client()->network_helper()->GetLatestClientAddress().host();
+ QuicConnection* client_connection = GetClientConnection();
+ ASSERT_TRUE(client_connection != nullptr);
+
+ // Migrate socket to a new IP address.
+ QuicIpAddress host1 = TestLoopback(2);
+ EXPECT_NE(host0, host1);
+ ASSERT_TRUE(
+ QuicConnectionPeer::HasUnusedPeerIssuedConnectionId(client_connection));
+ QuicConnectionId server_cid0 = client_connection->connection_id();
+ EXPECT_TRUE(QuicConnectionPeer::GetServerConnectionIdOnAlternativePath(
+ client_connection)
+ .IsEmpty());
+ EXPECT_TRUE(client_->client()->MigrateSocket(host1));
+ QuicConnectionId server_cid1 = client_connection->connection_id();
+ EXPECT_FALSE(server_cid1.IsEmpty());
+ EXPECT_NE(server_cid0, server_cid1);
+ EXPECT_TRUE(QuicConnectionPeer::GetServerConnectionIdOnAlternativePath(
+ client_connection)
+ .IsEmpty());
+
+ // Send a request using the new socket.
+ SendSynchronousBarRequestAndCheckResponse();
+ EXPECT_EQ(1u,
+ client_connection->GetStats().num_connectivity_probing_received);
+
+ // Send another request and wait for response making sure path response is
+ // received at server.
+ SendSynchronousBarRequestAndCheckResponse();
+
+ // Migrate socket to a new IP address.
+ WaitForNewConnectionIds();
+ EXPECT_EQ(1u, client_connection->GetStats().num_retire_connection_id_sent);
+ QuicIpAddress host2 = TestLoopback(3);
+ EXPECT_NE(host0, host2);
+ EXPECT_NE(host1, host2);
+ EXPECT_TRUE(QuicConnectionPeer::GetServerConnectionIdOnAlternativePath(
+ client_connection)
+ .IsEmpty());
+ EXPECT_TRUE(client_->client()->MigrateSocket(host2));
+ QuicConnectionId server_cid2 = client_connection->connection_id();
+ EXPECT_FALSE(server_cid2.IsEmpty());
+ EXPECT_NE(server_cid0, server_cid2);
+ EXPECT_NE(server_cid1, server_cid2);
+ EXPECT_TRUE(QuicConnectionPeer::GetServerConnectionIdOnAlternativePath(
+ client_connection)
+ .IsEmpty());
+
+ // Send another request using the new socket and wait for response making sure
+ // path response is received at server.
+ SendSynchronousBarRequestAndCheckResponse();
+ EXPECT_EQ(2u,
+ client_connection->GetStats().num_connectivity_probing_received);
+
+ // Migrate socket back to an old IP address.
+ WaitForNewConnectionIds();
+ EXPECT_EQ(2u, client_connection->GetStats().num_retire_connection_id_sent);
+ EXPECT_TRUE(QuicConnectionPeer::GetServerConnectionIdOnAlternativePath(
+ client_connection)
+ .IsEmpty());
+ EXPECT_TRUE(client_->client()->MigrateSocket(host1));
+ QuicConnectionId server_cid3 = client_connection->connection_id();
+ EXPECT_FALSE(server_cid3.IsEmpty());
+ EXPECT_NE(server_cid0, server_cid3);
+ EXPECT_NE(server_cid1, server_cid3);
+ EXPECT_NE(server_cid2, server_cid3);
+ EXPECT_TRUE(QuicConnectionPeer::GetServerConnectionIdOnAlternativePath(
+ client_connection)
+ .IsEmpty());
+ const auto* client_packet_creator =
+ QuicConnectionPeer::GetPacketCreator(client_connection);
+ EXPECT_TRUE(client_packet_creator->GetClientConnectionId().IsEmpty());
+ EXPECT_EQ(server_cid3, client_packet_creator->GetServerConnectionId());
+
+ // Send another request using the new socket and wait for response making sure
+ // path response is received at server.
+ SendSynchronousBarRequestAndCheckResponse();
+ // Even this is an old path, server has forgotten about it and thus needs to
+ // validate the path again.
+ EXPECT_EQ(3u,
+ client_connection->GetStats().num_connectivity_probing_received);
+
+ WaitForNewConnectionIds();
+ EXPECT_EQ(3u, client_connection->GetStats().num_retire_connection_id_sent);
+
+ server_thread_->Pause();
+ QuicConnection* server_connection = GetServerConnection();
+ // By the time the 2nd request is completed, the PATH_RESPONSE must have been
+ // received by the server.
+ EXPECT_FALSE(server_connection->HasPendingPathValidation());
+ EXPECT_EQ(3u, server_connection->GetStats().num_validated_peer_migration);
+ EXPECT_EQ(server_cid3, server_connection->connection_id());
+ const auto* server_packet_creator =
+ QuicConnectionPeer::GetPacketCreator(server_connection);
+ EXPECT_EQ(server_cid3, server_packet_creator->GetServerConnectionId());
+ EXPECT_TRUE(QuicConnectionPeer::GetServerConnectionIdOnAlternativePath(
+ server_connection)
+ .IsEmpty());
+ EXPECT_EQ(4u, server_connection->GetStats().num_new_connection_id_sent);
+ server_thread_->Resume();
+}
+
+TEST_P(EndToEndTest,
+ ConnectionMigrationWithNonZeroConnectionIDClientIPChangedMultipleTimes) {
+ if (!version_.SupportsClientConnectionIds()) {
+ ASSERT_TRUE(Initialize());
+ return;
+ }
+ override_client_connection_id_length_ = kQuicDefaultConnectionIdLength;
+ ASSERT_TRUE(Initialize());
+ if (!GetClientConnection()->connection_migration_use_new_cid()) {
+ return;
+ }
+ SendSynchronousFooRequestAndCheckResponse();
+
+ // Store the client IP address which was used to send the first request.
+ QuicIpAddress host0 =
+ client_->client()->network_helper()->GetLatestClientAddress().host();
+ QuicConnection* client_connection = GetClientConnection();
+ ASSERT_TRUE(client_connection != nullptr);
+
+ // Migrate socket to a new IP address.
+ QuicIpAddress host1 = TestLoopback(2);
+ EXPECT_NE(host0, host1);
+ ASSERT_TRUE(
+ QuicConnectionPeer::HasUnusedPeerIssuedConnectionId(client_connection));
+ QuicConnectionId server_cid0 = client_connection->connection_id();
+ QuicConnectionId client_cid0 = client_connection->client_connection_id();
+ EXPECT_TRUE(QuicConnectionPeer::GetServerConnectionIdOnAlternativePath(
+ client_connection)
+ .IsEmpty());
+ EXPECT_TRUE(QuicConnectionPeer::GetClientConnectionIdOnAlternativePath(
+ client_connection)
+ .IsEmpty());
+ EXPECT_TRUE(client_->client()->MigrateSocket(host1));
+ QuicConnectionId server_cid1 = client_connection->connection_id();
+ QuicConnectionId client_cid1 = client_connection->client_connection_id();
+ EXPECT_FALSE(server_cid1.IsEmpty());
+ EXPECT_FALSE(client_cid1.IsEmpty());
+ EXPECT_NE(server_cid0, server_cid1);
+ EXPECT_NE(client_cid0, client_cid1);
+ EXPECT_TRUE(QuicConnectionPeer::GetServerConnectionIdOnAlternativePath(
+ client_connection)
+ .IsEmpty());
+ EXPECT_TRUE(QuicConnectionPeer::GetClientConnectionIdOnAlternativePath(
+ client_connection)
+ .IsEmpty());
+
+ // Send another request to ensure that the server will have time to finish the
+ // reverse path validation and send address token.
+ SendSynchronousBarRequestAndCheckResponse();
+ EXPECT_EQ(1u,
+ client_connection->GetStats().num_connectivity_probing_received);
+
+ // Migrate socket to a new IP address.
+ WaitForNewConnectionIds();
+ EXPECT_EQ(1u, client_connection->GetStats().num_retire_connection_id_sent);
+ EXPECT_EQ(2u, client_connection->GetStats().num_new_connection_id_sent);
+ QuicIpAddress host2 = TestLoopback(3);
+ EXPECT_NE(host0, host2);
+ EXPECT_NE(host1, host2);
+ EXPECT_TRUE(client_->client()->MigrateSocket(host2));
+ QuicConnectionId server_cid2 = client_connection->connection_id();
+ QuicConnectionId client_cid2 = client_connection->client_connection_id();
+ EXPECT_FALSE(server_cid2.IsEmpty());
+ EXPECT_NE(server_cid0, server_cid2);
+ EXPECT_NE(server_cid1, server_cid2);
+ EXPECT_FALSE(client_cid2.IsEmpty());
+ EXPECT_NE(client_cid0, client_cid2);
+ EXPECT_NE(client_cid1, client_cid2);
+ EXPECT_TRUE(QuicConnectionPeer::GetServerConnectionIdOnAlternativePath(
+ client_connection)
+ .IsEmpty());
+ EXPECT_TRUE(QuicConnectionPeer::GetClientConnectionIdOnAlternativePath(
+ client_connection)
+ .IsEmpty());
+
+ // Send another request to ensure that the server will have time to finish the
+ // reverse path validation and send address token.
+ SendSynchronousBarRequestAndCheckResponse();
+ EXPECT_EQ(2u,
+ client_connection->GetStats().num_connectivity_probing_received);
+
+ // Migrate socket back to an old IP address.
+ WaitForNewConnectionIds();
+ EXPECT_EQ(2u, client_connection->GetStats().num_retire_connection_id_sent);
+ EXPECT_EQ(3u, client_connection->GetStats().num_new_connection_id_sent);
+ EXPECT_TRUE(client_->client()->MigrateSocket(host1));
+ QuicConnectionId server_cid3 = client_connection->connection_id();
+ QuicConnectionId client_cid3 = client_connection->client_connection_id();
+ EXPECT_FALSE(server_cid3.IsEmpty());
+ EXPECT_NE(server_cid0, server_cid3);
+ EXPECT_NE(server_cid1, server_cid3);
+ EXPECT_NE(server_cid2, server_cid3);
+ EXPECT_FALSE(client_cid3.IsEmpty());
+ EXPECT_NE(client_cid0, client_cid3);
+ EXPECT_NE(client_cid1, client_cid3);
+ EXPECT_NE(client_cid2, client_cid3);
+ const auto* client_packet_creator =
+ QuicConnectionPeer::GetPacketCreator(client_connection);
+ EXPECT_EQ(client_cid3, client_packet_creator->GetClientConnectionId());
+ EXPECT_EQ(server_cid3, client_packet_creator->GetServerConnectionId());
+ EXPECT_TRUE(QuicConnectionPeer::GetServerConnectionIdOnAlternativePath(
+ client_connection)
+ .IsEmpty());
+
+ // Send another request to ensure that the server will have time to finish the
+ // reverse path validation and send address token.
+ SendSynchronousBarRequestAndCheckResponse();
+ // Even this is an old path, server has forgotten about it and thus needs to
+ // validate the path again.
+ EXPECT_EQ(3u,
+ client_connection->GetStats().num_connectivity_probing_received);
+
+ WaitForNewConnectionIds();
+ EXPECT_EQ(3u, client_connection->GetStats().num_retire_connection_id_sent);
+ EXPECT_EQ(4u, client_connection->GetStats().num_new_connection_id_sent);
+
+ server_thread_->Pause();
+ // By the time the 2nd request is completed, the PATH_RESPONSE must have been
+ // received by the server.
+ QuicConnection* server_connection = GetServerConnection();
+ EXPECT_FALSE(server_connection->HasPendingPathValidation());
+ EXPECT_EQ(3u, server_connection->GetStats().num_validated_peer_migration);
+ EXPECT_EQ(server_cid3, server_connection->connection_id());
+ EXPECT_EQ(client_cid3, server_connection->client_connection_id());
+ EXPECT_TRUE(QuicConnectionPeer::GetServerConnectionIdOnAlternativePath(
+ server_connection)
+ .IsEmpty());
+ const auto* server_packet_creator =
+ QuicConnectionPeer::GetPacketCreator(server_connection);
+ EXPECT_EQ(client_cid3, server_packet_creator->GetClientConnectionId());
+ EXPECT_EQ(server_cid3, server_packet_creator->GetServerConnectionId());
+ EXPECT_EQ(3u, server_connection->GetStats().num_retire_connection_id_sent);
+ EXPECT_EQ(4u, server_connection->GetStats().num_new_connection_id_sent);
+ server_thread_->Resume();
+}
+
TEST_P(EndToEndTest, ConnectionMigrationNewTokenForNewIp) {
ASSERT_TRUE(Initialize());
if (!version_.HasIetfQuicFrames() ||
@@ -2644,7 +2886,7 @@ TEST_P(EndToEndTest, ConnectionMigrationNewTokenForNewIp) {
EXPECT_EQ(1u,
client_connection->GetStats().num_connectivity_probing_received);
- // Send another request to ensure that the server will time to finish the
+ // Send another request to ensure that the server will have time to finish the
// reverse path validation and send address token.
SendSynchronousBarRequestAndCheckResponse();
@@ -2661,17 +2903,11 @@ TEST_P(EndToEndTest, ConnectionMigrationNewTokenForNewIp) {
server_thread_->Pause();
QuicConnection* server_connection = GetServerConnection();
if (server_connection != nullptr) {
- if (GetQuicReloadableFlag(quic_enable_token_based_address_validation)) {
- // Verify address is validated via validating token received in INITIAL
- // packet.
- EXPECT_FALSE(server_connection->GetStats()
- .address_validated_via_decrypting_packet);
- EXPECT_TRUE(server_connection->GetStats().address_validated_via_token);
- } else {
- EXPECT_TRUE(server_connection->GetStats()
- .address_validated_via_decrypting_packet);
- EXPECT_FALSE(server_connection->GetStats().address_validated_via_token);
- }
+ // Verify address is validated via validating token received in INITIAL
+ // packet.
+ EXPECT_FALSE(
+ server_connection->GetStats().address_validated_via_decrypting_packet);
+ EXPECT_TRUE(server_connection->GetStats().address_validated_via_token);
} else {
ADD_FAILURE() << "Missing server connection";
}
@@ -2709,14 +2945,19 @@ class DuplicatePacketWithSpoofedSelfAddressWriter
TEST_P(EndToEndTest, ClientAddressSpoofedForSomePeriod) {
ASSERT_TRUE(Initialize());
- if (!version_.HasIetfQuicFrames() ||
- !client_->client()->session()->connection()->validate_client_address()) {
+ if (!GetClientConnection()->connection_migration_use_new_cid()) {
return;
}
auto writer = new DuplicatePacketWithSpoofedSelfAddressWriter();
client_.reset(CreateQuicClient(writer));
+
+ // Make sure client has unused peer connection ID before migration.
+ SendSynchronousFooRequestAndCheckResponse();
+ ASSERT_TRUE(QuicConnectionPeer::HasUnusedPeerIssuedConnectionId(
+ GetClientConnection()));
+
QuicIpAddress real_host = TestLoopback(1);
- client_->MigrateSocket(real_host);
+ ASSERT_TRUE(client_->MigrateSocket(real_host));
SendSynchronousFooRequestAndCheckResponse();
EXPECT_EQ(
0u, GetClientConnection()->GetStats().num_connectivity_probing_received);
@@ -2755,10 +2996,107 @@ TEST_P(EndToEndTest, ClientAddressSpoofedForSomePeriod) {
EXPECT_EQ(large_body, client_->response_body());
}
-TEST_P(EndToEndTest, AsynchronousConnectionMigrationClientIPChanged) {
+TEST_P(EndToEndTest,
+ AsynchronousConnectionMigrationClientIPChangedMultipleTimes) {
ASSERT_TRUE(Initialize());
- if (!version_.HasIetfQuicFrames() ||
- !client_->client()->session()->connection()->use_path_validator()) {
+ if (!GetClientConnection()->connection_migration_use_new_cid()) {
+ return;
+ }
+ client_.reset(CreateQuicClient(nullptr));
+
+ SendSynchronousFooRequestAndCheckResponse();
+
+ // Store the client IP address which was used to send the first request.
+ QuicIpAddress host0 =
+ client_->client()->network_helper()->GetLatestClientAddress().host();
+ QuicConnection* client_connection = GetClientConnection();
+ QuicConnectionId server_cid0 = client_connection->connection_id();
+ // Server should have one new connection ID upon handshake completion.
+ ASSERT_TRUE(
+ QuicConnectionPeer::HasUnusedPeerIssuedConnectionId(client_connection));
+
+ // Migrate socket to new IP address #1.
+ QuicIpAddress host1 = TestLoopback(2);
+ EXPECT_NE(host0, host1);
+ ASSERT_TRUE(client_->client()->ValidateAndMigrateSocket(host1));
+ while (client_->client()->HasPendingPathValidation()) {
+ client_->client()->WaitForEvents();
+ }
+ EXPECT_EQ(host1, client_->client()->session()->self_address().host());
+ EXPECT_EQ(1u,
+ client_connection->GetStats().num_connectivity_probing_received);
+ QuicConnectionId server_cid1 = client_connection->connection_id();
+ EXPECT_NE(server_cid0, server_cid1);
+ EXPECT_TRUE(QuicConnectionPeer::GetServerConnectionIdOnAlternativePath(
+ client_connection)
+ .IsEmpty());
+
+ // Send a request using the new socket.
+ SendSynchronousBarRequestAndCheckResponse();
+
+ // Migrate socket to new IP address #2.
+ WaitForNewConnectionIds();
+ QuicIpAddress host2 = TestLoopback(3);
+ EXPECT_NE(host0, host1);
+ ASSERT_TRUE(client_->client()->ValidateAndMigrateSocket(host2));
+
+ while (client_->client()->HasPendingPathValidation()) {
+ client_->client()->WaitForEvents();
+ }
+ EXPECT_EQ(host2, client_->client()->session()->self_address().host());
+ EXPECT_EQ(2u,
+ client_connection->GetStats().num_connectivity_probing_received);
+ QuicConnectionId server_cid2 = client_connection->connection_id();
+ EXPECT_NE(server_cid0, server_cid2);
+ EXPECT_NE(server_cid1, server_cid2);
+ EXPECT_TRUE(QuicConnectionPeer::GetServerConnectionIdOnAlternativePath(
+ client_connection)
+ .IsEmpty());
+
+ // Send a request using the new socket.
+ SendSynchronousBarRequestAndCheckResponse();
+
+ // Migrate socket back to IP address #1.
+ WaitForNewConnectionIds();
+ ASSERT_TRUE(client_->client()->ValidateAndMigrateSocket(host1));
+
+ while (client_->client()->HasPendingPathValidation()) {
+ client_->client()->WaitForEvents();
+ }
+ EXPECT_EQ(host1, client_->client()->session()->self_address().host());
+ EXPECT_EQ(3u,
+ client_connection->GetStats().num_connectivity_probing_received);
+ QuicConnectionId server_cid3 = client_connection->connection_id();
+ EXPECT_NE(server_cid0, server_cid3);
+ EXPECT_NE(server_cid1, server_cid3);
+ EXPECT_NE(server_cid2, server_cid3);
+ EXPECT_TRUE(QuicConnectionPeer::GetServerConnectionIdOnAlternativePath(
+ client_connection)
+ .IsEmpty());
+
+ // Send a request using the new socket.
+ SendSynchronousBarRequestAndCheckResponse();
+ server_thread_->Pause();
+ const QuicConnection* server_connection = GetServerConnection();
+ EXPECT_EQ(server_connection->connection_id(), server_cid3);
+ EXPECT_TRUE(QuicConnectionPeer::GetServerConnectionIdOnAlternativePath(
+ server_connection)
+ .IsEmpty());
+ server_thread_->Resume();
+
+ // There should be 1 new connection ID issued by the server.
+ WaitForNewConnectionIds();
+}
+
+TEST_P(EndToEndTest,
+ AsynchronousConnectionMigrationClientIPChangedWithNonEmptyClientCID) {
+ if (!version_.SupportsClientConnectionIds()) {
+ ASSERT_TRUE(Initialize());
+ return;
+ }
+ override_client_connection_id_length_ = kQuicDefaultConnectionIdLength;
+ ASSERT_TRUE(Initialize());
+ if (!GetClientConnection()->connection_migration_use_new_cid()) {
return;
}
client_.reset(CreateQuicClient(nullptr));
@@ -2768,6 +3106,9 @@ TEST_P(EndToEndTest, AsynchronousConnectionMigrationClientIPChanged) {
// Store the client IP address which was used to send the first request.
QuicIpAddress old_host =
client_->client()->network_helper()->GetLatestClientAddress().host();
+ auto* client_connection = GetClientConnection();
+ QuicConnectionId client_cid0 = client_connection->client_connection_id();
+ QuicConnectionId server_cid0 = client_connection->connection_id();
// Migrate socket to the new IP address.
QuicIpAddress new_host = TestLoopback(2);
@@ -2778,12 +3119,26 @@ TEST_P(EndToEndTest, AsynchronousConnectionMigrationClientIPChanged) {
client_->client()->WaitForEvents();
}
EXPECT_EQ(new_host, client_->client()->session()->self_address().host());
- QuicConnection* client_connection = GetClientConnection();
- ASSERT_TRUE(client_connection);
- EXPECT_EQ(client_connection->validate_client_address() ? 1u : 0,
+ EXPECT_EQ(1u,
client_connection->GetStats().num_connectivity_probing_received);
+ QuicConnectionId client_cid1 = client_connection->client_connection_id();
+ QuicConnectionId server_cid1 = client_connection->connection_id();
+ const auto* client_packet_creator =
+ QuicConnectionPeer::GetPacketCreator(client_connection);
+ EXPECT_EQ(client_cid1, client_packet_creator->GetClientConnectionId());
+ EXPECT_EQ(server_cid1, client_packet_creator->GetServerConnectionId());
// Send a request using the new socket.
SendSynchronousBarRequestAndCheckResponse();
+
+ server_thread_->Pause();
+ QuicConnection* server_connection = GetServerConnection();
+ EXPECT_EQ(client_cid1, server_connection->client_connection_id());
+ EXPECT_EQ(server_cid1, server_connection->connection_id());
+ const auto* server_packet_creator =
+ QuicConnectionPeer::GetPacketCreator(server_connection);
+ EXPECT_EQ(client_cid1, server_packet_creator->GetClientConnectionId());
+ EXPECT_EQ(server_cid1, server_packet_creator->GetServerConnectionId());
+ server_thread_->Resume();
}
TEST_P(EndToEndTest, ConnectionMigrationClientPortChanged) {
@@ -3257,13 +3612,13 @@ TEST_P(EndToEndTest, AckNotifierWithPacketLossAndBlockedSocket) {
ADD_FAILURE() << "Missing QPACK encoder";
return;
}
- QpackHeaderTable* header_table =
+ QpackEncoderHeaderTable* header_table =
QpackEncoderPeer::header_table(qpack_encoder);
if (header_table == nullptr) {
ADD_FAILURE() << "Missing header table";
return;
}
- if (QpackHeaderTablePeer::dynamic_table_capacity(header_table) > 0) {
+ if (header_table->dynamic_table_capacity() > 0) {
break;
}
}
@@ -3880,312 +4235,6 @@ TEST_P(EndToEndTest, Trailers) {
EXPECT_EQ(trailers, client_->response_trailers());
}
-class EndToEndTestServerPush : public EndToEndTest {
- protected:
- const size_t kNumMaxStreams = 10;
-
- EndToEndTestServerPush() : EndToEndTest() {
- 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
- // cache.
- // If |resource_size| == 0, response body of push resources use default string
- // concatenating with resource url. Otherwise, generate a string of
- // |resource_size| as body.
- void AddRequestAndResponseWithServerPush(std::string host,
- std::string path,
- std::string response_body,
- std::string* push_urls,
- const size_t num_resources,
- const size_t resource_size) {
- bool use_large_response = resource_size != 0;
- std::string large_resource;
- if (use_large_response) {
- // Generate a response common body larger than flow control window for
- // push response.
- large_resource = std::string(resource_size, 'a');
- }
- std::list<QuicBackendResponse::ServerPushInfo> push_resources;
- for (size_t i = 0; i < num_resources; ++i) {
- std::string url = push_urls[i];
- QuicUrl resource_url(url);
- std::string body =
- use_large_response
- ? large_resource
- : absl::StrCat("This is server push response body for ", url);
- SpdyHeaderBlock response_headers;
- response_headers[":status"] = "200";
- response_headers["content-length"] = absl::StrCat(body.size());
- push_resources.push_back(QuicBackendResponse::ServerPushInfo(
- resource_url, std::move(response_headers), kV3LowestPriority, body));
- }
-
- memory_cache_backend_.AddSimpleResponseWithServerPushResources(
- host, path, 200, response_body, push_resources);
- }
-};
-
-// Run all server push end to end tests with all supported versions.
-INSTANTIATE_TEST_SUITE_P(EndToEndTestsServerPush,
- EndToEndTestServerPush,
- ::testing::ValuesIn(GetTestParams()),
- ::testing::PrintToStringParamName());
-
-TEST_P(EndToEndTestServerPush, ServerPush) {
- ASSERT_TRUE(Initialize());
- EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
-
- // Set reordering to ensure that body arriving before PUSH_PROMISE is ok.
- SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
- SetReorderPercentage(30);
-
- // Add a response with headers, body, and push resources.
- const std::string kBody = "body content";
- size_t kNumResources = 4;
- std::string push_urls[] = {"https://example.com/font.woff",
- "https://example.com/script.js",
- "https://fonts.example.com/font.woff",
- "https://example.com/logo-hires.jpg"};
- AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody,
- push_urls, kNumResources, 0);
-
- client_->client()->set_response_listener(
- std::unique_ptr<QuicSpdyClientBase::ResponseListener>(
- new TestResponseListener));
-
- QUIC_DVLOG(1) << "send request for /push_example";
- EXPECT_EQ(kBody, client_->SendSynchronousRequest(
- "https://example.com/push_example"));
- QuicStreamSequencer* sequencer = nullptr;
- if (!version_.UsesHttp3()) {
- QuicSpdyClientSession* client_session = GetClientSession();
- ASSERT_TRUE(client_session);
- QuicHeadersStream* headers_stream =
- QuicSpdySessionPeer::GetHeadersStream(client_session);
- ASSERT_TRUE(headers_stream);
- sequencer = QuicStreamPeer::sequencer(headers_stream);
- ASSERT_TRUE(sequencer);
- // Headers stream's sequencer buffer shouldn't be released because server
- // push hasn't finished yet.
- EXPECT_TRUE(
- QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer));
- }
-
- for (const std::string& url : push_urls) {
- QUIC_DVLOG(1) << "send request for pushed stream on url " << url;
- std::string expected_body =
- absl::StrCat("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);
- }
- if (!version_.UsesHttp3()) {
- ASSERT_TRUE(sequencer);
- EXPECT_FALSE(
- QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer));
- }
-}
-
-TEST_P(EndToEndTestServerPush, ServerPushUnderLimit) {
- // 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.
- ASSERT_TRUE(Initialize());
-
- if (version_.UsesHttp3()) {
- return;
- }
-
- EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
- // Set reordering to ensure that body arriving before PUSH_PROMISE is ok.
- SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
- SetReorderPercentage(30);
-
- // Add a response with headers, body, and push resources.
- const std::string kBody = "body content";
- size_t const kNumResources = 4;
- std::string push_urls[] = {
- "https://example.com/font.woff",
- "https://example.com/script.js",
- "https://fonts.example.com/font.woff",
- "https://example.com/logo-hires.jpg",
- };
- AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody,
- push_urls, kNumResources, 0);
- client_->client()->set_response_listener(
- std::unique_ptr<QuicSpdyClientBase::ResponseListener>(
- new TestResponseListener));
-
- // Send the first request: this will trigger the server to send all the push
- // resources associated with this request, and these will be cached by the
- // client.
- EXPECT_EQ(kBody, client_->SendSynchronousRequest(
- "https://example.com/push_example"));
-
- 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.
- QUIC_DVLOG(1) << "send request for pushed stream on url " << url;
- std::string expected_body =
- absl::StrCat("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);
- }
- // Expect only original request has been sent and push responses have been
- // received as normal response.
- EXPECT_EQ(1u, client_->num_requests());
- EXPECT_EQ(1u + kNumResources, client_->num_responses());
-}
-
-TEST_P(EndToEndTestServerPush, ServerPushOverLimitNonBlocking) {
- if (version_.UsesHttp3()) {
- ASSERT_TRUE(Initialize());
- return;
- }
- // Tests that when streams are not blocked by flow control or congestion
- // control, pushing even more resources than max number of open outgoing
- // streams should still work because all response streams get closed
- // immediately after pushing resources.
- ASSERT_TRUE(Initialize());
- EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
-
- // Set reordering to ensure that body arriving before PUSH_PROMISE is ok.
- SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
- SetReorderPercentage(30);
-
- // Add a response with headers, body, and push resources.
- const std::string kBody = "body content";
-
- // One more resource than max number of outgoing stream of this session.
- const size_t kNumResources = 1 + kNumMaxStreams; // 11.
- std::string push_urls[11];
- for (size_t i = 0; i < kNumResources; ++i) {
- push_urls[i] = absl::StrCat("https://example.com/push_resources", i);
- }
- AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody,
- push_urls, kNumResources, 0);
- client_->client()->set_response_listener(
- std::unique_ptr<QuicSpdyClientBase::ResponseListener>(
- new TestResponseListener));
-
- // Send the first request: this will trigger the server to send all the push
- // resources associated with this request, and these will be cached by the
- // client.
- EXPECT_EQ(kBody, client_->SendSynchronousRequest(
- "https://example.com/push_example"));
-
- 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(absl::StrCat("This is server push response body for ", url),
- client_->SendSynchronousRequest(url));
- }
-
- // Only 1 request should have been sent.
- EXPECT_EQ(1u, client_->num_requests());
- // The responses to the original request and all the promised resources
- // should have been received.
- EXPECT_EQ(12u, client_->num_responses());
-}
-
-TEST_P(EndToEndTestServerPush, ServerPushOverLimitWithBlocking) {
- if (version_.UsesHttp3()) {
- ASSERT_TRUE(Initialize());
- return;
- }
-
- // 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
- // streams for them, and the rest will be queued up.
-
- // Reset flow control windows.
- size_t kFlowControlWnd = 20 * 1024; // 20KB.
- // Response body is larger than 1 flow controlblock window.
- size_t kBodySize = kFlowControlWnd * 2;
- set_client_initial_stream_flow_control_receive_window(kFlowControlWnd);
- // Make sure conntection level flow control window is large enough not to
- // block data being sent out though they will be blocked by stream level one.
- set_client_initial_session_flow_control_receive_window(
- kBodySize * kNumMaxStreams + 1024);
-
- ASSERT_TRUE(Initialize());
- EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
-
- // Set reordering to ensure that body arriving before PUSH_PROMISE is ok.
- SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
- SetReorderPercentage(30);
-
- // Add a response with headers, body, and push resources.
- const std::string kBody = "body content";
-
- const size_t kNumResources = kNumMaxStreams + 1;
- std::string push_urls[11];
- for (size_t i = 0; i < kNumResources; ++i) {
- push_urls[i] = absl::StrCat("http://example.com/push_resources", i);
- }
- AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody,
- push_urls, kNumResources, kBodySize);
-
- client_->client()->set_response_listener(
- std::unique_ptr<QuicSpdyClientBase::ResponseListener>(
- new TestResponseListener));
-
- client_->SendRequest("https://example.com/push_example");
-
- // Pause after the first response arrives.
- while (!client_->response_complete()) {
- // Because of priority, the first response arrived should be to original
- // request.
- client_->WaitForResponse();
- ASSERT_TRUE(client_->connected());
- }
-
- // Check server session to see if it has max number of outgoing streams opened
- // though more resources need to be pushed.
- if (!version_.HasIetfQuicFrames()) {
- server_thread_->Pause();
- QuicSession* server_session = GetServerSession();
- if (server_session != nullptr) {
- EXPECT_EQ(kNumMaxStreams,
- QuicSessionPeer::GetStreamIdManager(server_session)
- ->num_open_outgoing_streams());
- } else {
- ADD_FAILURE() << "Missing server session";
- }
- server_thread_->Resume();
- }
-
- EXPECT_EQ(1u, client_->num_requests());
- EXPECT_EQ(1u, client_->num_responses());
- EXPECT_EQ(kBody, client_->response_body());
-
- // "Send" request for a promised resources will not really send out it because
- // its response is being pushed(but blocked). And the following ack and
- // flow control behavior of SendSynchronousRequests()
- // will unblock the stream to finish receiving response.
- client_->SendSynchronousRequest(push_urls[0]);
- EXPECT_EQ(1u, client_->num_requests());
- EXPECT_EQ(2u, client_->num_responses());
-
- // Do same thing for the rest 10 resources.
- for (size_t i = 1; i < kNumResources; ++i) {
- client_->SendSynchronousRequest(push_urls[i]);
- }
-
- // Because of server push, client gets all pushed resources without actually
- // sending requests for them.
- EXPECT_EQ(1u, client_->num_requests());
- // Including response to original request, 12 responses in total were
- // received.
- EXPECT_EQ(12u, client_->num_responses());
-}
-
// TODO(fayang): this test seems to cause net_unittests timeouts :|
TEST_P(EndToEndTest, DISABLED_TestHugePostWithPacketLoss) {
// This test tests a huge post with introduced packet loss from client to
@@ -4440,11 +4489,7 @@ TEST_P(EndToEndTest,
client_.reset(CreateQuicClient(client_writer_));
EXPECT_EQ("", client_->SendSynchronousRequest("/foo"));
- if (GetQuicReloadableFlag(quic_fix_dispatcher_sent_error_code)) {
- EXPECT_THAT(client_->connection_error(), IsError(QUIC_PACKET_WRITE_ERROR));
- } else {
- EXPECT_THAT(client_->connection_error(), IsError(QUIC_HANDSHAKE_FAILED));
- }
+ EXPECT_THAT(client_->connection_error(), IsError(QUIC_HANDSHAKE_FAILED));
}
// Regression test for b/116200989.
@@ -5007,6 +5052,207 @@ TEST_P(EndToEndPacketReorderingTest, PathValidationFailure) {
server_thread_->Resume();
}
+TEST_P(EndToEndPacketReorderingTest, MigrateAgainAfterPathValidationFailure) {
+ ASSERT_TRUE(Initialize());
+ if (!GetClientConnection()->connection_migration_use_new_cid()) {
+ return;
+ }
+
+ client_.reset(CreateQuicClient(nullptr));
+ // Finish one request to make sure handshake established.
+ EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
+
+ // Wait for the connection to become idle, to make sure the packet gets
+ // delayed is the connectivity probing packet.
+ client_->WaitForDelayedAcks();
+
+ QuicSocketAddress addr1 = client_->client()->session()->self_address();
+ QuicConnection* client_connection = GetClientConnection();
+ QuicConnectionId server_cid1 = client_connection->connection_id();
+
+ // Migrate socket to the new IP address.
+ QuicIpAddress host2 = TestLoopback(2);
+ EXPECT_NE(addr1.host(), host2);
+
+ // Drop PATH_RESPONSE packets to timeout the path validation.
+ server_writer_->set_fake_packet_loss_percentage(100);
+ ASSERT_TRUE(
+ QuicConnectionPeer::HasUnusedPeerIssuedConnectionId(client_connection));
+
+ ASSERT_TRUE(client_->client()->ValidateAndMigrateSocket(host2));
+
+ QuicConnectionId server_cid2 =
+ QuicConnectionPeer::GetServerConnectionIdOnAlternativePath(
+ client_connection);
+ EXPECT_FALSE(server_cid2.IsEmpty());
+ EXPECT_NE(server_cid2, server_cid1);
+ // Wait until path validation fails at the client.
+ while (client_->client()->HasPendingPathValidation()) {
+ EXPECT_EQ(server_cid2,
+ QuicConnectionPeer::GetServerConnectionIdOnAlternativePath(
+ client_connection));
+ client_->client()->WaitForEvents();
+ }
+ EXPECT_EQ(addr1, client_->client()->session()->self_address());
+ EXPECT_EQ(server_cid1, GetClientConnection()->connection_id());
+
+ server_writer_->set_fake_packet_loss_percentage(0);
+ EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest("/bar"));
+
+ WaitForNewConnectionIds();
+ EXPECT_EQ(1u, client_connection->GetStats().num_retire_connection_id_sent);
+ EXPECT_EQ(0u, client_connection->GetStats().num_new_connection_id_sent);
+
+ server_thread_->Pause();
+ QuicConnection* server_connection = GetServerConnection();
+ // Server has received 3 path challenges.
+ EXPECT_EQ(3u,
+ server_connection->GetStats().num_connectivity_probing_received);
+ EXPECT_EQ(server_cid1, server_connection->connection_id());
+ EXPECT_EQ(0u, server_connection->GetStats().num_retire_connection_id_sent);
+ EXPECT_EQ(2u, server_connection->GetStats().num_new_connection_id_sent);
+ server_thread_->Resume();
+
+ // Migrate socket to a new IP address again.
+ QuicIpAddress host3 = TestLoopback(3);
+ EXPECT_NE(addr1.host(), host3);
+ EXPECT_NE(host2, host3);
+
+ WaitForNewConnectionIds();
+ EXPECT_EQ(1u, client_connection->GetStats().num_retire_connection_id_sent);
+ EXPECT_EQ(0u, client_connection->GetStats().num_new_connection_id_sent);
+
+ ASSERT_TRUE(client_->client()->ValidateAndMigrateSocket(host3));
+ QuicConnectionId server_cid3 =
+ QuicConnectionPeer::GetServerConnectionIdOnAlternativePath(
+ client_connection);
+ EXPECT_FALSE(server_cid3.IsEmpty());
+ EXPECT_NE(server_cid1, server_cid3);
+ EXPECT_NE(server_cid2, server_cid3);
+ while (client_->client()->HasPendingPathValidation()) {
+ client_->client()->WaitForEvents();
+ }
+ EXPECT_EQ(host3, client_->client()->session()->self_address().host());
+ EXPECT_EQ(server_cid3, GetClientConnection()->connection_id());
+ EXPECT_TRUE(QuicConnectionPeer::GetServerConnectionIdOnAlternativePath(
+ client_connection)
+ .IsEmpty());
+ EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest("/bar"));
+
+ // Server should send a new connection ID to client.
+ WaitForNewConnectionIds();
+ EXPECT_EQ(2u, client_connection->GetStats().num_retire_connection_id_sent);
+ EXPECT_EQ(0u, client_connection->GetStats().num_new_connection_id_sent);
+}
+
+TEST_P(EndToEndPacketReorderingTest,
+ MigrateAgainAfterPathValidationFailureWithNonZeroClientConnectionId) {
+ if (!version_.SupportsClientConnectionIds()) {
+ ASSERT_TRUE(Initialize());
+ return;
+ }
+ override_client_connection_id_length_ = kQuicDefaultConnectionIdLength;
+ ASSERT_TRUE(Initialize());
+ if (!GetClientConnection()->connection_migration_use_new_cid()) {
+ return;
+ }
+
+ client_.reset(CreateQuicClient(nullptr));
+ // Finish one request to make sure handshake established.
+ EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
+
+ // Wait for the connection to become idle, to make sure the packet gets
+ // delayed is the connectivity probing packet.
+ client_->WaitForDelayedAcks();
+
+ QuicSocketAddress addr1 = client_->client()->session()->self_address();
+ QuicConnection* client_connection = GetClientConnection();
+ QuicConnectionId server_cid1 = client_connection->connection_id();
+ QuicConnectionId client_cid1 = client_connection->client_connection_id();
+
+ // Migrate socket to the new IP address.
+ QuicIpAddress host2 = TestLoopback(2);
+ EXPECT_NE(addr1.host(), host2);
+
+ // Drop PATH_RESPONSE packets to timeout the path validation.
+ server_writer_->set_fake_packet_loss_percentage(100);
+ ASSERT_TRUE(
+ QuicConnectionPeer::HasUnusedPeerIssuedConnectionId(client_connection));
+ ASSERT_TRUE(client_->client()->ValidateAndMigrateSocket(host2));
+ QuicConnectionId server_cid2 =
+ QuicConnectionPeer::GetServerConnectionIdOnAlternativePath(
+ client_connection);
+ EXPECT_FALSE(server_cid2.IsEmpty());
+ EXPECT_NE(server_cid2, server_cid1);
+ QuicConnectionId client_cid2 =
+ QuicConnectionPeer::GetClientConnectionIdOnAlternativePath(
+ client_connection);
+ EXPECT_FALSE(client_cid2.IsEmpty());
+ EXPECT_NE(client_cid2, client_cid1);
+ while (client_->client()->HasPendingPathValidation()) {
+ EXPECT_EQ(server_cid2,
+ QuicConnectionPeer::GetServerConnectionIdOnAlternativePath(
+ client_connection));
+ client_->client()->WaitForEvents();
+ }
+ EXPECT_EQ(addr1, client_->client()->session()->self_address());
+ EXPECT_EQ(server_cid1, GetClientConnection()->connection_id());
+ EXPECT_TRUE(QuicConnectionPeer::GetServerConnectionIdOnAlternativePath(
+ client_connection)
+ .IsEmpty());
+ server_writer_->set_fake_packet_loss_percentage(0);
+ EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest("/bar"));
+ WaitForNewConnectionIds();
+ EXPECT_EQ(1u, client_connection->GetStats().num_retire_connection_id_sent);
+ EXPECT_EQ(2u, client_connection->GetStats().num_new_connection_id_sent);
+
+ server_thread_->Pause();
+ QuicConnection* server_connection = GetServerConnection();
+ if (server_connection != nullptr) {
+ EXPECT_EQ(3u,
+ server_connection->GetStats().num_connectivity_probing_received);
+ EXPECT_EQ(server_cid1, server_connection->connection_id());
+ } else {
+ ADD_FAILURE() << "Missing server connection";
+ }
+ EXPECT_EQ(1u, server_connection->GetStats().num_retire_connection_id_sent);
+ EXPECT_EQ(2u, server_connection->GetStats().num_new_connection_id_sent);
+ server_thread_->Resume();
+
+ // Migrate socket to a new IP address again.
+ QuicIpAddress host3 = TestLoopback(3);
+ EXPECT_NE(addr1.host(), host3);
+ EXPECT_NE(host2, host3);
+ ASSERT_TRUE(client_->client()->ValidateAndMigrateSocket(host3));
+
+ QuicConnectionId server_cid3 =
+ QuicConnectionPeer::GetServerConnectionIdOnAlternativePath(
+ client_connection);
+ EXPECT_FALSE(server_cid3.IsEmpty());
+ EXPECT_NE(server_cid1, server_cid3);
+ EXPECT_NE(server_cid2, server_cid3);
+ QuicConnectionId client_cid3 =
+ QuicConnectionPeer::GetClientConnectionIdOnAlternativePath(
+ client_connection);
+ EXPECT_NE(client_cid1, client_cid3);
+ EXPECT_NE(client_cid2, client_cid3);
+ while (client_->client()->HasPendingPathValidation()) {
+ client_->client()->WaitForEvents();
+ }
+ EXPECT_EQ(host3, client_->client()->session()->self_address().host());
+ EXPECT_EQ(server_cid3, GetClientConnection()->connection_id());
+ EXPECT_TRUE(QuicConnectionPeer::GetServerConnectionIdOnAlternativePath(
+ client_connection)
+ .IsEmpty());
+ EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest("/bar"));
+
+ // Server should send new server connection ID to client and retires old
+ // client connection ID.
+ WaitForNewConnectionIds();
+ EXPECT_EQ(2u, client_connection->GetStats().num_retire_connection_id_sent);
+ EXPECT_EQ(3u, client_connection->GetStats().num_new_connection_id_sent);
+}
+
TEST_P(EndToEndPacketReorderingTest, Buffer0RttRequest) {
ASSERT_TRUE(Initialize());
// Finish one request to make sure handshake established.
@@ -5384,6 +5630,74 @@ TEST_P(EndToEndTest, LegacyVersionEncapsulationWithLoss) {
0u);
}
+// Testing packet writer that makes a copy of the first sent packets before
+// sending them. Useful for tests that need access to sent packets.
+class CopyingPacketWriter : public PacketDroppingTestWriter {
+ public:
+ explicit CopyingPacketWriter(int num_packets_to_copy)
+ : num_packets_to_copy_(num_packets_to_copy) {}
+ WriteResult WritePacket(const char* buffer,
+ size_t buf_len,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
+ PerPacketOptions* options) override {
+ if (num_packets_to_copy_ > 0) {
+ num_packets_to_copy_--;
+ packets_.push_back(
+ QuicEncryptedPacket(buffer, buf_len, /*owns_buffer=*/false).Clone());
+ }
+ return PacketDroppingTestWriter::WritePacket(buffer, buf_len, self_address,
+ peer_address, options);
+ }
+
+ std::vector<std::unique_ptr<QuicEncryptedPacket>>& packets() {
+ return packets_;
+ }
+
+ private:
+ int num_packets_to_copy_;
+ std::vector<std::unique_ptr<QuicEncryptedPacket>> packets_;
+};
+
+TEST_P(EndToEndTest, ChaosProtection) {
+ if (!version_.UsesCryptoFrames()) {
+ ASSERT_TRUE(Initialize());
+ return;
+ }
+ // Replace the client's writer with one that'll save the first packet.
+ auto copying_writer = new CopyingPacketWriter(1);
+ delete client_writer_;
+ client_writer_ = copying_writer;
+ // Enable chaos protection and perform an HTTP request.
+ client_config_.SetClientConnectionOptions(QuicTagVector{kCHSP});
+ ASSERT_TRUE(Initialize());
+ SendSynchronousFooRequestAndCheckResponse();
+ // Parse the saved packet to make sure it's valid.
+ SimpleQuicFramer validation_framer({version_});
+ validation_framer.framer()->SetInitialObfuscators(
+ GetClientConnection()->connection_id());
+ ASSERT_GT(copying_writer->packets().size(), 0u);
+ EXPECT_TRUE(validation_framer.ProcessPacket(*copying_writer->packets()[0]));
+ // TODO(dschinazi) figure out a way to use a MockRandom in this test so we
+ // can inspect the contents of this packet.
+}
+
+TEST_P(EndToEndTest, ChaosProtectionWithMultiPacketChlo) {
+ if (!version_.UsesCryptoFrames()) {
+ ASSERT_TRUE(Initialize());
+ return;
+ }
+ // Enable chaos protection.
+ client_config_.SetClientConnectionOptions(QuicTagVector{kCHSP});
+ // Add a transport parameter to make the client hello span multiple packets.
+ constexpr auto kCustomParameter =
+ static_cast<TransportParameters::TransportParameterId>(0xff34);
+ client_config_.custom_transport_parameters_to_send()[kCustomParameter] =
+ std::string(2000, '?');
+ ASSERT_TRUE(Initialize());
+ SendSynchronousFooRequestAndCheckResponse();
+}
+
TEST_P(EndToEndTest, KeyUpdateInitiatedByClient) {
if (!version_.UsesTls()) {
// Key Update is only supported in TLS handshake.
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 3544cfddf9a..6d9290a12c1 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
@@ -36,8 +36,17 @@ HttpDecoder::HttpDecoder(Visitor* visitor, Options options)
current_push_id_length_(0),
remaining_push_id_length_(0),
error_(QUIC_NO_ERROR),
- error_detail_("") {
+ error_detail_(""),
+ ignore_old_priority_update_(
+ GetQuicReloadableFlag(quic_ignore_old_priority_update_frame)),
+ error_on_http3_push_(GetQuicReloadableFlag(quic_error_on_http3_push)) {
QUICHE_DCHECK(visitor_);
+ if (ignore_old_priority_update_) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_ignore_old_priority_update_frame);
+ }
+ if (error_on_http3_push_) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_error_on_http3_push);
+ }
}
HttpDecoder::~HttpDecoder() {}
@@ -172,6 +181,20 @@ bool HttpDecoder::ReadFrameType(QuicDataReader* reader) {
current_frame_type_));
return false;
}
+
+ if (error_on_http3_push_) {
+ if (current_frame_type_ ==
+ static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH)) {
+ RaiseError(QUIC_HTTP_FRAME_ERROR, "CANCEL_PUSH frame received.");
+ return false;
+ }
+ if (current_frame_type_ ==
+ static_cast<uint64_t>(HttpFrameType::PUSH_PROMISE)) {
+ RaiseError(QUIC_HTTP_FRAME_ERROR, "PUSH_PROMISE frame received.");
+ return false;
+ }
+ }
+
state_ = STATE_READING_FRAME_LENGTH;
return true;
}
@@ -238,11 +261,19 @@ bool HttpDecoder::ReadFrameLength(QuicDataReader* reader) {
visitor_->OnHeadersFrameStart(header_length, current_frame_length_);
break;
case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH):
+ if (error_on_http3_push_) {
+ QUICHE_NOTREACHED();
+ break;
+ }
break;
case static_cast<uint64_t>(HttpFrameType::SETTINGS):
continue_processing = visitor_->OnSettingsFrameStart(header_length);
break;
case static_cast<uint64_t>(HttpFrameType::PUSH_PROMISE):
+ if (error_on_http3_push_) {
+ QUICHE_NOTREACHED();
+ break;
+ }
// 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) {
@@ -257,7 +288,13 @@ bool HttpDecoder::ReadFrameLength(QuicDataReader* reader) {
case static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID):
break;
case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE):
- continue_processing = visitor_->OnPriorityUpdateFrameStart(header_length);
+ if (ignore_old_priority_update_) {
+ continue_processing = visitor_->OnUnknownFrameStart(
+ current_frame_type_, header_length, current_frame_length_);
+ } else {
+ continue_processing =
+ visitor_->OnPriorityUpdateFrameStart(header_length);
+ }
break;
case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE_REQUEST_STREAM):
continue_processing = visitor_->OnPriorityUpdateFrameStart(header_length);
@@ -307,7 +344,11 @@ bool HttpDecoder::ReadFramePayload(QuicDataReader* reader) {
break;
}
case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH): {
- continue_processing = BufferOrParsePayload(reader);
+ if (error_on_http3_push_) {
+ QUICHE_NOTREACHED();
+ } else {
+ continue_processing = BufferOrParsePayload(reader);
+ }
break;
}
case static_cast<uint64_t>(HttpFrameType::SETTINGS): {
@@ -315,6 +356,10 @@ bool HttpDecoder::ReadFramePayload(QuicDataReader* reader) {
break;
}
case static_cast<uint64_t>(HttpFrameType::PUSH_PROMISE): {
+ if (error_on_http3_push_) {
+ QUICHE_NOTREACHED();
+ break;
+ }
PushId push_id;
if (current_frame_length_ == remaining_frame_length_) {
// A new Push Promise frame just arrived.
@@ -388,7 +433,11 @@ bool HttpDecoder::ReadFramePayload(QuicDataReader* reader) {
break;
}
case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE): {
- continue_processing = BufferOrParsePayload(reader);
+ if (ignore_old_priority_update_) {
+ continue_processing = HandleUnknownFramePayload(reader);
+ } else {
+ continue_processing = BufferOrParsePayload(reader);
+ }
break;
}
case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE_REQUEST_STREAM): {
@@ -428,9 +477,13 @@ bool HttpDecoder::FinishParsing(QuicDataReader* reader) {
break;
}
case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH): {
- // If frame payload is not empty, FinishParsing() is skipped.
- QUICHE_DCHECK_EQ(0u, current_frame_length_);
- continue_processing = BufferOrParsePayload(reader);
+ if (error_on_http3_push_) {
+ QUICHE_NOTREACHED();
+ } else {
+ // If frame payload is not empty, FinishParsing() is skipped.
+ QUICHE_DCHECK_EQ(0u, current_frame_length_);
+ continue_processing = BufferOrParsePayload(reader);
+ }
break;
}
case static_cast<uint64_t>(HttpFrameType::SETTINGS): {
@@ -440,7 +493,11 @@ bool HttpDecoder::FinishParsing(QuicDataReader* reader) {
break;
}
case static_cast<uint64_t>(HttpFrameType::PUSH_PROMISE): {
- continue_processing = visitor_->OnPushPromiseFrameEnd();
+ if (error_on_http3_push_) {
+ QUICHE_NOTREACHED();
+ } else {
+ continue_processing = visitor_->OnPushPromiseFrameEnd();
+ }
break;
}
case static_cast<uint64_t>(HttpFrameType::GOAWAY): {
@@ -456,9 +513,13 @@ bool HttpDecoder::FinishParsing(QuicDataReader* reader) {
break;
}
case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE): {
- // If frame payload is not empty, FinishParsing() is skipped.
- QUICHE_DCHECK_EQ(0u, current_frame_length_);
- continue_processing = BufferOrParsePayload(reader);
+ if (ignore_old_priority_update_) {
+ continue_processing = visitor_->OnUnknownFrameEnd();
+ } else {
+ // If frame payload is not empty, FinishParsing() is skipped.
+ QUICHE_DCHECK_EQ(0u, current_frame_length_);
+ continue_processing = BufferOrParsePayload(reader);
+ }
break;
}
case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE_REQUEST_STREAM): {
@@ -559,6 +620,10 @@ bool HttpDecoder::ParseEntirePayload(QuicDataReader* reader) {
switch (current_frame_type_) {
case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH): {
+ if (error_on_http3_push_) {
+ QUICHE_NOTREACHED();
+ return false;
+ }
CancelPushFrame frame;
if (!reader->ReadVarInt62(&frame.push_id)) {
RaiseError(QUIC_HTTP_FRAME_ERROR,
@@ -606,11 +671,16 @@ bool HttpDecoder::ParseEntirePayload(QuicDataReader* reader) {
return visitor_->OnMaxPushIdFrame(frame);
}
case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE): {
- PriorityUpdateFrame frame;
- if (!ParsePriorityUpdateFrame(reader, &frame)) {
+ if (ignore_old_priority_update_) {
+ QUICHE_NOTREACHED();
return false;
+ } else {
+ PriorityUpdateFrame frame;
+ if (!ParsePriorityUpdateFrame(reader, &frame)) {
+ return false;
+ }
+ return visitor_->OnPriorityUpdateFrame(frame);
}
- return visitor_->OnPriorityUpdateFrame(frame);
}
case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE_REQUEST_STREAM): {
PriorityUpdateFrame frame;
@@ -767,6 +837,7 @@ bool HttpDecoder::ParseAcceptChFrame(QuicDataReader* reader,
QuicByteCount HttpDecoder::MaxFrameLength(uint64_t frame_type) {
switch (frame_type) {
case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH):
+ // TODO(b/171463363): Remove.
return sizeof(PushId);
case static_cast<uint64_t>(HttpFrameType::SETTINGS):
// This limit is arbitrary.
@@ -774,6 +845,7 @@ QuicByteCount HttpDecoder::MaxFrameLength(uint64_t frame_type) {
case static_cast<uint64_t>(HttpFrameType::GOAWAY):
return VARIABLE_LENGTH_INTEGER_LENGTH_8;
case static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID):
+ // TODO(b/171463363): Remove.
return sizeof(PushId);
case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE):
// This limit is arbitrary.
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 a351415e964..3a970fb63b1 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
@@ -45,6 +45,7 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
// processed. At that point it is safe to consume |header_length| bytes.
// Called when a CANCEL_PUSH frame has been successfully parsed.
+ // TODO(b/171463363): Remove.
virtual bool OnCancelPushFrame(const CancelPushFrame& frame) = 0;
// Called when a MAX_PUSH_ID frame has been successfully parsed.
@@ -83,6 +84,7 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
// Called when a HEADERS frame has been completely processed.
virtual bool OnHeadersFrameEnd() = 0;
+ // TODO(b/171463363): Remove all.
// 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.
@@ -230,7 +232,7 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
void BufferFrameType(QuicDataReader* reader);
// Buffers at most |remaining_push_id_length_| from |reader| to
- // |push_id_buffer_|.
+ // |push_id_buffer_|. TODO(b/171463363): Remove.
void BufferPushId(QuicDataReader* reader);
// Sets |error_| and |error_detail_| accordingly.
@@ -241,11 +243,13 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
// Parses the payload of a PRIORITY_UPDATE frame (draft-01, type 0x0f)
// from |reader| into |frame|.
+ // TODO(b/147306124): Remove.
bool ParsePriorityUpdateFrame(QuicDataReader* reader,
PriorityUpdateFrame* frame);
// Parses the payload of a PRIORITY_UPDATE frame (draft-02, type 0xf0700)
// from |reader| into |frame|.
+ // TODO(b/147306124): Rename to ParsePriorityUpdateFrame().
bool ParseNewPriorityUpdateFrame(QuicDataReader* reader,
PriorityUpdateFrame* frame);
@@ -276,8 +280,10 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
// Remaining length that's needed for the frame's type field.
QuicByteCount remaining_type_field_length_;
// Length of PUSH_PROMISE frame's push id.
+ // TODO(b/171463363): Remove.
QuicByteCount current_push_id_length_;
// Remaining length that's needed for PUSH_PROMISE frame's push id field.
+ // TODO(b/171463363): Remove.
QuicByteCount remaining_push_id_length_;
// Last error.
QuicErrorCode error_;
@@ -290,7 +296,16 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
// Remaining unparsed type field data.
std::array<char, sizeof(uint64_t)> type_buffer_;
// Remaining unparsed push id data.
+ // TODO(b/171463363): Remove.
std::array<char, sizeof(uint64_t)> push_id_buffer_;
+
+ // Latched value of
+ // gfe2_reloadable_flag_quic_ignore_old_priority_update_frame.
+ const bool ignore_old_priority_update_;
+
+ // Latched value of
+ // gfe2_reloadable_flag_quic_error_on_http3_push.
+ const bool error_on_http3_push_;
};
} // namespace quic
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 aac020a97a7..05d580e20e1 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
@@ -19,7 +19,6 @@
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/quic_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
using ::testing::_;
using ::testing::AnyNumber;
@@ -249,6 +248,14 @@ TEST_F(HttpDecoderTest, CancelPush) {
"01" // length
"01"); // Push Id
+ if (GetQuicReloadableFlag(quic_error_on_http3_push)) {
+ EXPECT_CALL(visitor_, OnError(&decoder_));
+ EXPECT_EQ(1u, ProcessInput(input));
+ EXPECT_THAT(decoder_.error(), IsError(QUIC_HTTP_FRAME_ERROR));
+ EXPECT_EQ("CANCEL_PUSH frame received.", decoder_.error_detail());
+ return;
+ }
+
// Visitor pauses processing.
EXPECT_CALL(visitor_, OnCancelPushFrame(CancelPushFrame({1})))
.WillOnce(Return(false));
@@ -277,6 +284,14 @@ TEST_F(HttpDecoderTest, PushPromiseFrame) {
"C000000000000101"), // push id 257
"Headers"); // headers
+ if (GetQuicReloadableFlag(quic_error_on_http3_push)) {
+ EXPECT_CALL(visitor_, OnError(&decoder_));
+ EXPECT_EQ(1u, ProcessInput(input));
+ EXPECT_THAT(decoder_.error(), IsError(QUIC_HTTP_FRAME_ERROR));
+ EXPECT_EQ("PUSH_PROMISE frame received.", decoder_.error_detail());
+ return;
+ }
+
// Visitor pauses processing.
EXPECT_CALL(visitor_, OnPushPromiseFrameStart(2)).WillOnce(Return(false));
EXPECT_CALL(visitor_, OnPushPromiseFramePushId(257, 8, 7))
@@ -338,6 +353,10 @@ TEST_F(HttpDecoderTest, PushPromiseFrame) {
}
TEST_F(HttpDecoderTest, CorruptPushPromiseFrame) {
+ if (GetQuicReloadableFlag(quic_error_on_http3_push)) {
+ return;
+ }
+
InSequence s;
std::string input = absl::HexStringToBytes(
@@ -733,6 +752,10 @@ TEST_F(HttpDecoderTest, EmptyHeadersFrame) {
}
TEST_F(HttpDecoderTest, PushPromiseFrameNoHeaders) {
+ if (GetQuicReloadableFlag(quic_error_on_http3_push)) {
+ return;
+ }
+
InSequence s;
std::string input = absl::HexStringToBytes(
"05" // type (PUSH_PROMISE)
@@ -768,6 +791,10 @@ TEST_F(HttpDecoderTest, PushPromiseFrameNoHeaders) {
}
TEST_F(HttpDecoderTest, MalformedFrameWithOverlyLargePayload) {
+ if (GetQuicReloadableFlag(quic_error_on_http3_push)) {
+ return;
+ }
+
std::string input = absl::HexStringToBytes(
"03" // type (CANCEL_PUSH)
"10" // length
@@ -841,97 +868,183 @@ TEST_F(HttpDecoderTest, HeadersPausedThenData) {
}
TEST_F(HttpDecoderTest, CorruptFrame) {
- InSequence s;
-
- struct {
- const char* const input;
- const char* const error_message;
- } kTestData[] = {{"\x03" // type (CANCEL_PUSH)
- "\x01" // length
- "\x40", // first byte of two-byte varint push id
- "Unable to read CANCEL_PUSH push_id."},
- {"\x03" // type (CANCEL_PUSH)
- "\x04" // length
- "\x05" // valid push id
- "foo", // superfluous data
- "Superfluous data in CANCEL_PUSH frame."},
- {"\x0D" // type (MAX_PUSH_ID)
- "\x01" // length
- "\x40", // first byte of two-byte varint 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."},
- {"\x07" // type (GOAWAY)
- "\x01" // length
- "\x40", // first byte of two-byte varint stream id
- "Unable to read GOAWAY ID."},
- {"\x07" // type (GOAWAY)
- "\x04" // length
- "\x05" // valid stream id
- "foo", // superfluous data
- "Superfluous data in GOAWAY frame."},
- {"\x40\x89" // type (ACCEPT_CH)
- "\x01" // length
- "\x40", // first byte of two-byte varint origin length
- "Unable to read ACCEPT_CH origin."},
- {"\x40\x89" // type (ACCEPT_CH)
- "\x01" // length
- "\x05", // valid origin length but no origin string
- "Unable to read ACCEPT_CH origin."},
- {"\x40\x89" // type (ACCEPT_CH)
- "\x04" // length
- "\x05" // valid origin length
- "foo", // payload ends before origin ends
- "Unable to read ACCEPT_CH origin."},
- {"\x40\x89" // type (ACCEPT_CH)
- "\x04" // length
- "\x03" // valid origin length
- "foo", // payload ends at end of origin: no value
- "Unable to read ACCEPT_CH value."},
- {"\x40\x89" // type (ACCEPT_CH)
- "\x05" // length
- "\x03" // valid origin length
- "foo" // payload ends at end of origin: no value
- "\x40", // first byte of two-byte varint value length
- "Unable to read ACCEPT_CH value."},
- {"\x40\x89" // type (ACCEPT_CH)
- "\x08" // length
- "\x03" // valid origin length
- "foo" // origin
- "\x05" // valid value length
- "bar", // payload ends before value ends
- "Unable to read ACCEPT_CH value."}};
-
- for (const auto& test_data : kTestData) {
- {
- HttpDecoder decoder(&visitor_);
- EXPECT_CALL(visitor_, OnAcceptChFrameStart(_)).Times(AnyNumber());
- EXPECT_CALL(visitor_, OnError(&decoder));
-
- absl::string_view input(test_data.input);
- decoder.ProcessInput(input.data(), input.size());
- EXPECT_THAT(decoder.error(), IsError(QUIC_HTTP_FRAME_ERROR));
- EXPECT_EQ(test_data.error_message, decoder.error_detail());
+ if (GetQuicReloadableFlag(quic_error_on_http3_push)) {
+ InSequence s;
+
+ struct {
+ const char* const input;
+ const char* const error_message;
+ } kTestData[] = {{"\x0D" // type (MAX_PUSH_ID)
+ "\x01" // length
+ "\x40", // first byte of two-byte varint 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."},
+ {"\x07" // type (GOAWAY)
+ "\x01" // length
+ "\x40", // first byte of two-byte varint stream id
+ "Unable to read GOAWAY ID."},
+ {"\x07" // type (GOAWAY)
+ "\x04" // length
+ "\x05" // valid stream id
+ "foo", // superfluous data
+ "Superfluous data in GOAWAY frame."},
+ {"\x40\x89" // type (ACCEPT_CH)
+ "\x01" // length
+ "\x40", // first byte of two-byte varint origin length
+ "Unable to read ACCEPT_CH origin."},
+ {"\x40\x89" // type (ACCEPT_CH)
+ "\x01" // length
+ "\x05", // valid origin length but no origin string
+ "Unable to read ACCEPT_CH origin."},
+ {"\x40\x89" // type (ACCEPT_CH)
+ "\x04" // length
+ "\x05" // valid origin length
+ "foo", // payload ends before origin ends
+ "Unable to read ACCEPT_CH origin."},
+ {"\x40\x89" // type (ACCEPT_CH)
+ "\x04" // length
+ "\x03" // valid origin length
+ "foo", // payload ends at end of origin: no value
+ "Unable to read ACCEPT_CH value."},
+ {"\x40\x89" // type (ACCEPT_CH)
+ "\x05" // length
+ "\x03" // valid origin length
+ "foo" // payload ends at end of origin: no value
+ "\x40", // first byte of two-byte varint value length
+ "Unable to read ACCEPT_CH value."},
+ {"\x40\x89" // type (ACCEPT_CH)
+ "\x08" // length
+ "\x03" // valid origin length
+ "foo" // origin
+ "\x05" // valid value length
+ "bar", // payload ends before value ends
+ "Unable to read ACCEPT_CH value."}};
+
+ for (const auto& test_data : kTestData) {
+ {
+ HttpDecoder decoder(&visitor_);
+ EXPECT_CALL(visitor_, OnAcceptChFrameStart(_)).Times(AnyNumber());
+ EXPECT_CALL(visitor_, OnError(&decoder));
+
+ absl::string_view input(test_data.input);
+ decoder.ProcessInput(input.data(), input.size());
+ EXPECT_THAT(decoder.error(), IsError(QUIC_HTTP_FRAME_ERROR));
+ EXPECT_EQ(test_data.error_message, decoder.error_detail());
+ }
+ {
+ HttpDecoder decoder(&visitor_);
+ EXPECT_CALL(visitor_, OnAcceptChFrameStart(_)).Times(AnyNumber());
+ EXPECT_CALL(visitor_, OnError(&decoder));
+
+ absl::string_view input(test_data.input);
+ for (auto c : input) {
+ decoder.ProcessInput(&c, 1);
+ }
+ EXPECT_THAT(decoder.error(), IsError(QUIC_HTTP_FRAME_ERROR));
+ EXPECT_EQ(test_data.error_message, decoder.error_detail());
+ }
}
- {
- HttpDecoder decoder(&visitor_);
- EXPECT_CALL(visitor_, OnAcceptChFrameStart(_)).Times(AnyNumber());
- EXPECT_CALL(visitor_, OnError(&decoder));
-
- absl::string_view input(test_data.input);
- for (auto c : input) {
- decoder.ProcessInput(&c, 1);
+ } else {
+ InSequence s;
+
+ struct {
+ const char* const input;
+ const char* const error_message;
+ } kTestData[] = {{"\x03" // type (CANCEL_PUSH)
+ "\x01" // length
+ "\x40", // first byte of two-byte varint push id
+ "Unable to read CANCEL_PUSH push_id."},
+ {"\x03" // type (CANCEL_PUSH)
+ "\x04" // length
+ "\x05" // valid push id
+ "foo", // superfluous data
+ "Superfluous data in CANCEL_PUSH frame."},
+ {"\x0D" // type (MAX_PUSH_ID)
+ "\x01" // length
+ "\x40", // first byte of two-byte varint 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."},
+ {"\x07" // type (GOAWAY)
+ "\x01" // length
+ "\x40", // first byte of two-byte varint stream id
+ "Unable to read GOAWAY ID."},
+ {"\x07" // type (GOAWAY)
+ "\x04" // length
+ "\x05" // valid stream id
+ "foo", // superfluous data
+ "Superfluous data in GOAWAY frame."},
+ {"\x40\x89" // type (ACCEPT_CH)
+ "\x01" // length
+ "\x40", // first byte of two-byte varint origin length
+ "Unable to read ACCEPT_CH origin."},
+ {"\x40\x89" // type (ACCEPT_CH)
+ "\x01" // length
+ "\x05", // valid origin length but no origin string
+ "Unable to read ACCEPT_CH origin."},
+ {"\x40\x89" // type (ACCEPT_CH)
+ "\x04" // length
+ "\x05" // valid origin length
+ "foo", // payload ends before origin ends
+ "Unable to read ACCEPT_CH origin."},
+ {"\x40\x89" // type (ACCEPT_CH)
+ "\x04" // length
+ "\x03" // valid origin length
+ "foo", // payload ends at end of origin: no value
+ "Unable to read ACCEPT_CH value."},
+ {"\x40\x89" // type (ACCEPT_CH)
+ "\x05" // length
+ "\x03" // valid origin length
+ "foo" // payload ends at end of origin: no value
+ "\x40", // first byte of two-byte varint value length
+ "Unable to read ACCEPT_CH value."},
+ {"\x40\x89" // type (ACCEPT_CH)
+ "\x08" // length
+ "\x03" // valid origin length
+ "foo" // origin
+ "\x05" // valid value length
+ "bar", // payload ends before value ends
+ "Unable to read ACCEPT_CH value."}};
+
+ for (const auto& test_data : kTestData) {
+ {
+ HttpDecoder decoder(&visitor_);
+ EXPECT_CALL(visitor_, OnAcceptChFrameStart(_)).Times(AnyNumber());
+ EXPECT_CALL(visitor_, OnError(&decoder));
+
+ absl::string_view input(test_data.input);
+ decoder.ProcessInput(input.data(), input.size());
+ EXPECT_THAT(decoder.error(), IsError(QUIC_HTTP_FRAME_ERROR));
+ EXPECT_EQ(test_data.error_message, decoder.error_detail());
+ }
+ {
+ HttpDecoder decoder(&visitor_);
+ EXPECT_CALL(visitor_, OnAcceptChFrameStart(_)).Times(AnyNumber());
+ EXPECT_CALL(visitor_, OnError(&decoder));
+
+ absl::string_view input(test_data.input);
+ for (auto c : input) {
+ decoder.ProcessInput(&c, 1);
+ }
+ EXPECT_THAT(decoder.error(), IsError(QUIC_HTTP_FRAME_ERROR));
+ EXPECT_EQ(test_data.error_message, decoder.error_detail());
}
- EXPECT_THAT(decoder.error(), IsError(QUIC_HTTP_FRAME_ERROR));
- EXPECT_EQ(test_data.error_message, decoder.error_detail());
}
}
}
TEST_F(HttpDecoderTest, EmptyCancelPushFrame) {
+ if (GetQuicReloadableFlag(quic_error_on_http3_push)) {
+ return;
+ }
+
std::string input = absl::HexStringToBytes(
"03" // type (CANCEL_PUSH)
"00"); // frame length
@@ -959,6 +1072,10 @@ TEST_F(HttpDecoderTest, EmptySettingsFrame) {
// Regression test for https://crbug.com/1001823.
TEST_F(HttpDecoderTest, EmptyPushPromiseFrame) {
+ if (GetQuicReloadableFlag(quic_error_on_http3_push)) {
+ return;
+ }
+
std::string input = absl::HexStringToBytes(
"05" // type (PUSH_PROMISE)
"00"); // frame length
@@ -1003,7 +1120,11 @@ TEST_F(HttpDecoderTest, LargeStreamIdInGoAway) {
EXPECT_EQ("", decoder_.error_detail());
}
-TEST_F(HttpDecoderTest, PriorityUpdateFrame) {
+TEST_F(HttpDecoderTest, OldPriorityUpdateFrame) {
+ if (GetQuicReloadableFlag(quic_ignore_old_priority_update_frame)) {
+ return;
+ }
+
InSequence s;
std::string input1 = absl::HexStringToBytes(
"0f" // type (PRIORITY_UPDATE)
@@ -1085,7 +1206,44 @@ TEST_F(HttpDecoderTest, PriorityUpdateFrame) {
EXPECT_EQ("", decoder_.error_detail());
}
-TEST_F(HttpDecoderTest, NewPriorityUpdateFrame) {
+TEST_F(HttpDecoderTest, ObsoletePriorityUpdateFrame) {
+ if (!GetQuicReloadableFlag(quic_ignore_old_priority_update_frame)) {
+ return;
+ }
+
+ const QuicByteCount header_length = 2;
+ const QuicByteCount payload_length = 3;
+ InSequence s;
+ std::string input = absl::HexStringToBytes(
+ "0f" // type (obsolete PRIORITY_UPDATE)
+ "03" // length
+ "666f6f"); // payload "foo"
+
+ // Process frame as a whole.
+ EXPECT_CALL(visitor_,
+ OnUnknownFrameStart(0x0f, header_length, payload_length));
+ EXPECT_CALL(visitor_, OnUnknownFramePayload(Eq("foo")));
+ EXPECT_CALL(visitor_, OnUnknownFrameEnd()).WillOnce(Return(false));
+
+ EXPECT_EQ(header_length + payload_length,
+ ProcessInputWithGarbageAppended(input));
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
+ EXPECT_EQ("", decoder_.error_detail());
+
+ // Process frame byte by byte.
+ EXPECT_CALL(visitor_,
+ OnUnknownFrameStart(0x0f, header_length, payload_length));
+ EXPECT_CALL(visitor_, OnUnknownFramePayload(Eq("f")));
+ EXPECT_CALL(visitor_, OnUnknownFramePayload(Eq("o")));
+ EXPECT_CALL(visitor_, OnUnknownFramePayload(Eq("o")));
+ EXPECT_CALL(visitor_, OnUnknownFrameEnd());
+
+ ProcessInputCharByChar(input);
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
+ EXPECT_EQ("", decoder_.error_detail());
+}
+
+TEST_F(HttpDecoderTest, PriorityUpdateFrame) {
InSequence s;
std::string input1 = absl::HexStringToBytes(
"800f0700" // type (PRIORITY_UPDATE)
@@ -1166,6 +1324,10 @@ TEST_F(HttpDecoderTest, NewPriorityUpdateFrame) {
}
TEST_F(HttpDecoderTest, CorruptPriorityUpdateFrame) {
+ if (GetQuicReloadableFlag(quic_ignore_old_priority_update_frame)) {
+ return;
+ }
+
std::string payload1 = absl::HexStringToBytes(
"80" // prioritized element type: PUSH_STREAM
"4005"); // prioritized element id
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 56e53487b24..b14ebe5a91b 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
@@ -29,6 +29,7 @@ enum class HttpFrameType {
GOAWAY = 0x7,
MAX_PUSH_ID = 0xD,
// https://tools.ietf.org/html/draft-ietf-httpbis-priority-01
+ // TODO(b/147306124): Remove.
PRIORITY_UPDATE = 0XF,
// https://tools.ietf.org/html/draft-davidben-http-client-hint-reliability-02
ACCEPT_CH = 0x89,
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 9ddf6de8a84..01c861d5905 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
@@ -11,9 +11,9 @@
#include <utility>
#include "absl/strings/string_view.h"
-#include "quic/core/quic_circular_deque.h"
#include "quic/platform/api/quic_bug_tracker.h"
#include "quic/platform/api/quic_export.h"
+#include "common/quiche_circular_deque.h"
#include "spdy/core/spdy_header_block.h"
#include "spdy/core/spdy_headers_handler_interface.h"
@@ -23,7 +23,8 @@ namespace quic {
class QUIC_EXPORT_PRIVATE QuicHeaderList
: public spdy::SpdyHeadersHandlerInterface {
public:
- using ListType = QuicCircularDeque<std::pair<std::string, std::string>>;
+ using ListType =
+ quiche::QuicheCircularDeque<std::pair<std::string, std::string>>;
using value_type = ListType::value_type;
using const_iterator = ListType::const_iterator;
@@ -59,7 +60,7 @@ class QUIC_EXPORT_PRIVATE QuicHeaderList
std::string DebugString() const;
private:
- QuicCircularDeque<std::pair<std::string, std::string>> header_list_;
+ quiche::QuicheCircularDeque<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.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream.h
index ae9e2afe0d1..153575be1de 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
@@ -91,7 +91,7 @@ class QUIC_EXPORT_PRIVATE QuicHeadersStream : public QuicStream {
QuicSpdySession* spdy_session_;
// Headers that have not been fully acked.
- QuicCircularDeque<CompressedHeaderInfo> unacked_headers_;
+ quiche::QuicheCircularDeque<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 55dafac3756..42fef63c978 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
@@ -563,6 +563,10 @@ TEST_P(QuicHeadersStreamTest, ProcessPriorityFrame) {
}
TEST_P(QuicHeadersStreamTest, ProcessPushPromiseDisabledSetting) {
+ if (perspective() != Perspective::IS_CLIENT) {
+ return;
+ }
+
session_.OnConfigNegotiated();
SpdySettingsIR data;
// Respect supported settings frames SETTINGS_ENABLE_PUSH.
@@ -570,15 +574,11 @@ TEST_P(QuicHeadersStreamTest, ProcessPushPromiseDisabledSetting) {
SpdySerializedFrame frame(framer_->SerializeFrame(data));
stream_frame_.data_buffer = frame.data();
stream_frame_.data_length = frame.size();
- if (perspective() == Perspective::IS_CLIENT) {
- EXPECT_CALL(
- *connection_,
- CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
- "Unsupported field of HTTP/2 SETTINGS frame: 2", _));
- }
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
+ "Unsupported field of HTTP/2 SETTINGS frame: 2", _));
headers_stream_->OnStreamFrame(stream_frame_);
- EXPECT_EQ(session_.server_push_enabled(),
- perspective() == Perspective::IS_CLIENT);
}
TEST_P(QuicHeadersStreamTest, ProcessLargeRawData) {
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 fbd7b2eb18e..39d8b42a5a2 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
@@ -15,7 +15,7 @@
#include "quic/core/quic_types.h"
#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"
-#include "common/platform/api/quiche_text_utils.h"
+#include "common/quiche_text_utils.h"
namespace quic {
@@ -70,7 +70,6 @@ bool QuicReceiveControlStream::OnCancelPushFrame(const CancelPushFrame& frame) {
spdy_session()->debug_visitor()->OnCancelPushFrameReceived(frame);
}
- // TODO(b/151841240): Handle CANCEL_PUSH frames instead of ignoring them.
return ValidateFrameType(HttpFrameType::CANCEL_PUSH);
}
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 c9133436e9f..03f21d8a70f 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
@@ -15,7 +15,6 @@
#include "quic/test_tools/quic_spdy_session_peer.h"
#include "quic/test_tools/quic_stream_peer.h"
#include "quic/test_tools/quic_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
namespace quic {
@@ -165,7 +164,7 @@ TEST_P(QuicReceiveControlStreamTest, ReceiveSettings) {
QuicStreamFrame frame(receive_control_stream_->id(), false, 1, data);
QpackEncoder* qpack_encoder = session_.qpack_encoder();
- QpackHeaderTable* header_table =
+ QpackEncoderHeaderTable* header_table =
QpackEncoderPeer::header_table(qpack_encoder);
EXPECT_EQ(std::numeric_limits<size_t>::max(),
session_.max_outbound_header_list_size());
@@ -311,7 +310,10 @@ TEST_P(QuicReceiveControlStreamTest, PushPromiseOnControlStreamShouldClose) {
push_promise_frame);
EXPECT_CALL(
*connection_,
- CloseConnection(QUIC_HTTP_FRAME_UNEXPECTED_ON_CONTROL_STREAM, _, _))
+ CloseConnection(GetQuicReloadableFlag(quic_error_on_http3_push)
+ ? QUIC_HTTP_FRAME_ERROR
+ : QUIC_HTTP_FRAME_UNEXPECTED_ON_CONTROL_STREAM,
+ _, _))
.WillOnce(
Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _, _));
@@ -382,13 +384,21 @@ TEST_P(QuicReceiveControlStreamTest, CancelPushFrameBeforeSettings) {
"01" // payload length
"01"); // push ID
- EXPECT_CALL(*connection_,
- CloseConnection(QUIC_HTTP_MISSING_SETTINGS_FRAME,
- "First frame received on control stream is type "
- "3, but it must be SETTINGS.",
- _))
- .WillOnce(
- Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
+ if (GetQuicReloadableFlag(quic_error_on_http3_push)) {
+ EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_FRAME_ERROR,
+ "CANCEL_PUSH frame received.", _))
+ .WillOnce(
+ Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
+ } else {
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_HTTP_MISSING_SETTINGS_FRAME,
+ "First frame received on control stream is type "
+ "3, but it must be SETTINGS.",
+ _))
+ .WillOnce(
+ Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
+ }
EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _, _));
EXPECT_CALL(session_, OnConnectionClosed(_, _));
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 d1be0df27ca..c5af1dc4a90 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
@@ -13,7 +13,6 @@
#include "quic/test_tools/quic_config_peer.h"
#include "quic/test_tools/quic_spdy_session_peer.h"
#include "quic/test_tools/quic_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
#include "common/test_tools/quiche_test_utils.h"
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 b955835e2b8..c78df58e18a 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
@@ -50,12 +50,6 @@ void QuicServerSessionBase::OnConfigNegotiated() {
return;
}
- // Disable server push if peer sends the corresponding connection option.
- if (!version().UsesHttp3() &&
- ContainsQuicTag(config()->ReceivedConnectionOptions(), kQNSP)) {
- OnSetting(spdy::SETTINGS_ENABLE_PUSH, 0);
- }
-
// Enable bandwidth resumption if peer sent correct connection options.
const bool last_bandwidth_resumption =
ContainsQuicTag(config()->ReceivedConnectionOptions(), kBWRE);
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 29750f2e3cf..ac7fc1e59c8 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
@@ -10,7 +10,6 @@
#include <utility>
#include "absl/memory/memory.h"
-#include "absl/strings/string_view.h"
#include "quic/core/crypto/null_encrypter.h"
#include "quic/core/crypto/quic_crypto_server_config.h"
#include "quic/core/crypto/quic_random.h"
@@ -51,6 +50,12 @@ namespace quic {
namespace test {
namespace {
+// Data to be sent on a request stream. In Google QUIC, this is interpreted as
+// DATA payload (there is no framing on request streams). In IETF QUIC, this is
+// interpreted as HEADERS frame (type 0x1) with payload length 122 ('z'). Since
+// no payload is included, QPACK decoder will not be invoked.
+const char* const kStreamData = "\1z";
+
class TestServerSession : public QuicServerSessionBase {
public:
TestServerSession(const QuicConfig& config,
@@ -148,7 +153,7 @@ class QuicServerSessionBaseTest : public QuicTestWithParam<ParsedQuicVersion> {
config_.SetInitialSessionFlowControlWindowToSend(
kInitialSessionFlowControlWindowForTest);
- ParsedQuicVersionVector supported_versions = SupportedVersions(GetParam());
+ ParsedQuicVersionVector supported_versions = SupportedVersions(version());
connection_ = new StrictMock<MockQuicConnection>(
&helper_, &alarm_factory_, Perspective::IS_SERVER, supported_versions);
connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
@@ -166,23 +171,24 @@ class QuicServerSessionBaseTest : public QuicTestWithParam<ParsedQuicVersion> {
QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(
session_->config(), kMinimumFlowControlSendWindow);
session_->OnConfigNegotiated();
- if (connection_->version().SupportsAntiAmplificationLimit()) {
+ if (version().SupportsAntiAmplificationLimit()) {
QuicConnectionPeer::SetAddressValidated(connection_);
}
}
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);
}
+ ParsedQuicVersion version() const { return GetParam(); }
+
QuicTransportVersion transport_version() const {
- return connection_->transport_version();
+ return version().transport_version;
}
// Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
@@ -242,10 +248,9 @@ INSTANTIATE_TEST_SUITE_P(Tests,
::testing::PrintToStringParamName());
TEST_P(QuicServerSessionBaseTest, CloseStreamDueToReset) {
- // Open a stream, then reset it.
- // Send two bytes of payload to open it.
+ // Send some data open a stream, then reset it.
QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
- absl::string_view("HT"));
+ kStreamData);
session_->OnStreamFrame(data1);
EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
@@ -298,9 +303,9 @@ TEST_P(QuicServerSessionBaseTest, NeverOpenStreamDueToReset) {
InjectStopSendingFrame(GetNthClientInitiatedBidirectionalId(0));
EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
- // Send two bytes of payload.
+
QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
- absl::string_view("HT"));
+ kStreamData);
session_->OnStreamFrame(data1);
// The stream should never be opened, now that the reset is received.
@@ -309,11 +314,11 @@ TEST_P(QuicServerSessionBaseTest, NeverOpenStreamDueToReset) {
}
TEST_P(QuicServerSessionBaseTest, AcceptClosedStream) {
- // Send (empty) compressed headers followed by two bytes of data.
+ // Send some data to open two streams.
QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
- absl::string_view("\1\0\0\0\0\0\0\0HT"));
+ kStreamData);
QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(1), false, 0,
- absl::string_view("\3\0\0\0\0\0\0\0HT"));
+ kStreamData);
session_->OnStreamFrame(frame1);
session_->OnStreamFrame(frame2);
EXPECT_EQ(2u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
@@ -341,9 +346,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,
- absl::string_view("TP"));
+ kStreamData);
QuicStreamFrame frame4(GetNthClientInitiatedBidirectionalId(1), false, 2,
- absl::string_view("TP"));
+ kStreamData);
session_->OnStreamFrame(frame3);
session_->OnStreamFrame(frame4);
// The stream should never be opened, now that the reset is received.
@@ -373,7 +378,7 @@ TEST_P(QuicServerSessionBaseTest, MaxOpenStreams) {
for (size_t i = 0; i < kMaxStreamsForTest; ++i) {
EXPECT_TRUE(QuicServerSessionBasePeer::GetOrCreateStream(session_.get(),
stream_id));
- stream_id += QuicUtils::StreamIdDelta(connection_->transport_version());
+ stream_id += QuicUtils::StreamIdDelta(transport_version());
}
if (!VersionHasIetfQuicFrames(transport_version())) {
@@ -382,11 +387,11 @@ TEST_P(QuicServerSessionBaseTest, MaxOpenStreams) {
for (size_t i = 0; i < kMaxStreamsMinimumIncrement; ++i) {
EXPECT_TRUE(QuicServerSessionBasePeer::GetOrCreateStream(session_.get(),
stream_id));
- stream_id += QuicUtils::StreamIdDelta(connection_->transport_version());
+ stream_id += QuicUtils::StreamIdDelta(transport_version());
}
}
// Now violate the server's internal stream limit.
- stream_id += QuicUtils::StreamIdDelta(connection_->transport_version());
+ stream_id += QuicUtils::StreamIdDelta(transport_version());
if (!VersionHasIetfQuicFrames(transport_version())) {
// For non-version 99, QUIC responds to an attempt to exceed the stream
@@ -418,8 +423,7 @@ TEST_P(QuicServerSessionBaseTest, MaxAvailableBidirectionalStreams) {
session_.get(), GetNthClientInitiatedBidirectionalId(0)));
// Establish available streams up to the server's limit.
- QuicStreamId next_id =
- QuicUtils::StreamIdDelta(connection_->transport_version());
+ QuicStreamId next_id = QuicUtils::StreamIdDelta(transport_version());
const int kLimitingStreamId =
GetNthClientInitiatedBidirectionalId(kAvailableStreamLimit + 1);
if (!VersionHasIetfQuicFrames(transport_version())) {
@@ -456,7 +460,7 @@ TEST_P(QuicServerSessionBaseTest, GetEvenIncomingError) {
TEST_P(QuicServerSessionBaseTest, GetStreamDisconnected) {
// EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
- if (GetParam() != AllSupportedVersions()[0]) {
+ if (version() != AllSupportedVersions()[0]) {
return;
}
@@ -527,14 +531,13 @@ TEST_P(QuicServerSessionBaseTest, BandwidthEstimates) {
if (!VersionUsesHttp3(transport_version())) {
session_->UnregisterStreamPriority(
- QuicUtils::GetHeadersStreamId(connection_->transport_version()),
+ QuicUtils::GetHeadersStreamId(transport_version()),
/*is_static=*/true);
}
QuicServerSessionBasePeer::SetCryptoStream(session_.get(), nullptr);
MockQuicCryptoServerStream* quic_crypto_stream = nullptr;
MockTlsServerHandshaker* tls_server_stream = nullptr;
- if (session_->connection()->version().handshake_protocol ==
- PROTOCOL_QUIC_CRYPTO) {
+ if (version().handshake_protocol == PROTOCOL_QUIC_CRYPTO) {
quic_crypto_stream = new MockQuicCryptoServerStream(
&crypto_config_, &compressed_certs_cache_, session_.get(),
&stream_helper_);
@@ -548,7 +551,7 @@ TEST_P(QuicServerSessionBaseTest, BandwidthEstimates) {
}
if (!VersionUsesHttp3(transport_version())) {
session_->RegisterStreamPriority(
- QuicUtils::GetHeadersStreamId(connection_->transport_version()),
+ QuicUtils::GetHeadersStreamId(transport_version()),
/*is_static=*/true,
spdy::SpdyStreamPrecedence(QuicStream::kDefaultPriority));
}
@@ -571,11 +574,11 @@ TEST_P(QuicServerSessionBaseTest, BandwidthEstimates) {
// Queue up some pending data.
if (!VersionUsesHttp3(transport_version())) {
session_->MarkConnectionLevelWriteBlocked(
- QuicUtils::GetHeadersStreamId(connection_->transport_version()));
+ QuicUtils::GetHeadersStreamId(transport_version()));
} else {
session_->MarkConnectionLevelWriteBlocked(
- QuicUtils::GetFirstUnidirectionalStreamId(
- connection_->transport_version(), Perspective::IS_SERVER));
+ QuicUtils::GetFirstUnidirectionalStreamId(transport_version(),
+ Perspective::IS_SERVER));
}
EXPECT_TRUE(session_->HasDataToWrite());
@@ -643,7 +646,7 @@ TEST_P(QuicServerSessionBaseTest, BandwidthEstimates) {
}
TEST_P(QuicServerSessionBaseTest, BandwidthResumptionExperiment) {
- if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
+ if (version().handshake_protocol == PROTOCOL_TLS1_3) {
// This test relies on resumption, which is not currently supported by the
// TLS handshake.
// TODO(nharper): Add support for resumption to the TLS handshake.
@@ -720,20 +723,6 @@ TEST_P(QuicServerSessionBaseTest, NoBandwidthResumptionByDefault) {
QuicServerSessionBasePeer::IsBandwidthResumptionEnabled(session_.get()));
}
-TEST_P(QuicServerSessionBaseTest, TurnOffServerPush) {
- if (session_->version().UsesHttp3()) {
- return;
- }
-
- EXPECT_TRUE(session_->server_push_enabled());
- QuicTagVector copt;
- copt.push_back(kQNSP);
- QuicConfigPeer::SetReceivedConnectionOptions(session_->config(), copt);
- connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
- session_->OnConfigNegotiated();
- EXPECT_FALSE(session_->server_push_enabled());
-}
-
// Tests which check the lifetime management of data members of
// QuicCryptoServerStream objects when async GetProof is in use.
class StreamMemberLifetimeTest : public QuicServerSessionBaseTest {
@@ -762,7 +751,7 @@ INSTANTIATE_TEST_SUITE_P(StreamMemberLifetimeTests,
// ProofSource::GetProof. Delay the completion of the operation until after the
// stream has been destroyed, and verify that there are no memory bugs.
TEST_P(StreamMemberLifetimeTest, Basic) {
- if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
+ if (version().handshake_protocol == PROTOCOL_TLS1_3) {
// This test depends on the QUIC crypto protocol, so it is disabled for the
// TLS handshake.
// TODO(nharper): Fix this test so it doesn't rely on QUIC crypto.
@@ -771,9 +760,9 @@ TEST_P(StreamMemberLifetimeTest, Basic) {
const QuicClock* clock = helper_.GetClock();
CryptoHandshakeMessage chlo = crypto_test_utils::GenerateDefaultInchoateCHLO(
- clock, GetParam().transport_version, &crypto_config_);
+ clock, transport_version(), &crypto_config_);
chlo.SetVector(kCOPT, QuicTagVector{kREJ});
- std::vector<ParsedQuicVersion> packet_version_list = {GetParam()};
+ std::vector<ParsedQuicVersion> packet_version_list = {version()};
std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
TestConnectionId(1), EmptyQuicConnectionId(), true, false, 1,
std::string(chlo.GetSerialized().AsStringPiece()), CONNECTION_ID_PRESENT,
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 7197c8ab7ed..af17b54ecff 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
@@ -278,10 +278,11 @@ TEST_P(QuicSpdyClientSessionTest, NoEncryptionAfterInitialEncryption) {
EXPECT_TRUE(session_->CreateOutgoingBidirectionalStream() == nullptr);
// Verify that no data may be send on existing streams.
char data[] = "hello world";
- EXPECT_QUIC_BUG(
+ QuicConsumedData consumed =
session_->WritevData(stream->id(), ABSL_ARRAYSIZE(data), 0, NO_FIN,
- NOT_RETRANSMISSION, ENCRYPTION_INITIAL),
- "Client: Try to send data of stream");
+ NOT_RETRANSMISSION, ENCRYPTION_INITIAL);
+ EXPECT_EQ(0u, consumed.bytes_consumed);
+ EXPECT_FALSE(consumed.fin_consumed);
}
TEST_P(QuicSpdyClientSessionTest, MaxNumStreamsWithNoFinOrRst) {
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 16948101c6c..276a7aff6b6 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
@@ -30,7 +30,6 @@
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
#include "quic/platform/api/quic_stack_trace.h"
-#include "common/platform/api/quiche_text_utils.h"
#include "spdy/core/http2_frame_decoder_adapter.h"
using http2::Http2DecoderAdapter;
@@ -497,7 +496,6 @@ QuicSpdySession::QuicSpdySession(
spdy_framer_visitor_(new SpdyFramerVisitor(this)),
debug_visitor_(nullptr),
destruction_indicator_(123456789),
- server_push_enabled_(true),
next_available_datagram_flow_id_(perspective() == Perspective::IS_SERVER
? kFirstDatagramFlowIdServer
: kFirstDatagramFlowIdClient) {
@@ -798,15 +796,12 @@ void QuicSpdySession::SendHttp3GoAway(QuicErrorCode error_code,
const std::string& reason) {
QUICHE_DCHECK_EQ(perspective(), Perspective::IS_SERVER);
QUICHE_DCHECK(VersionUsesHttp3(transport_version()));
- if (GetQuicReloadableFlag(quic_encrypted_goaway)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_encrypted_goaway, 2, 2);
- if (!IsEncryptionEstablished()) {
- QUIC_CODE_COUNT(quic_h3_goaway_before_encryption_established);
- connection()->CloseConnection(
- error_code, reason,
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- return;
- }
+ if (!IsEncryptionEstablished()) {
+ QUIC_CODE_COUNT(quic_h3_goaway_before_encryption_established);
+ connection()->CloseConnection(
+ error_code, reason,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return;
}
QuicStreamId stream_id;
@@ -858,10 +853,6 @@ void QuicSpdySession::WritePushPromise(QuicStreamId original_stream_id,
absl::string_view(frame.data(), frame.size()), false, nullptr);
}
-bool QuicSpdySession::server_push_enabled() const {
- return VersionUsesHttp3(transport_version()) ? false : server_push_enabled_;
-}
-
void QuicSpdySession::SendInitialData() {
if (!VersionUsesHttp3(transport_version())) {
return;
@@ -1239,8 +1230,7 @@ bool QuicSpdySession::OnSetting(uint64_t id, uint64_t value) {
return true;
}
QUIC_DVLOG(1) << ENDPOINT << "SETTINGS_ENABLE_PUSH received with value "
- << value;
- server_push_enabled_ = value;
+ << value << ", ignoring.";
break;
} else {
QUIC_DLOG(ERROR)
@@ -1458,14 +1448,7 @@ QuicStream* QuicSpdySession::ProcessPendingStream(PendingStream* pending) {
default:
break;
}
- if (GetQuicReloadableFlag(quic_unify_stop_sending)) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_unify_stop_sending);
- MaybeSendStopSendingFrame(pending->id(), QUIC_STREAM_STREAM_CREATION_ERROR);
- } else {
- // TODO(renjietang): deprecate SendStopSending() when the flag is
- // deprecated.
- SendStopSending(QUIC_STREAM_STREAM_CREATION_ERROR, pending->id());
- }
+ MaybeSendStopSendingFrame(pending->id(), QUIC_STREAM_STREAM_CREATION_ERROR);
pending->StopReading();
return nullptr;
}
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 b2004845306..214d1da13e2 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
@@ -26,13 +26,13 @@
#include "quic/core/qpack/qpack_encoder_stream_sender.h"
#include "quic/core/qpack/qpack_receive_stream.h"
#include "quic/core/qpack/qpack_send_stream.h"
-#include "quic/core/quic_circular_deque.h"
#include "quic/core/quic_session.h"
#include "quic/core/quic_time.h"
#include "quic/core/quic_types.h"
#include "quic/core/quic_versions.h"
#include "quic/platform/api/quic_containers.h"
#include "quic/platform/api/quic_export.h"
+#include "common/quiche_circular_deque.h"
#include "spdy/core/http2_frame_decoder_adapter.h"
namespace quic {
@@ -251,12 +251,6 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
const QuicHeadersStream* headers_stream() const { return headers_stream_; }
- // 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 or server this returns false.
- bool server_push_enabled() const;
-
// Called when the control stream receives HTTP/3 SETTINGS.
// Returns false in case of 0-RTT if received settings are incompatible with
// cached values, true otherwise.
@@ -684,10 +678,6 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
// an use-after-free.
int32_t destruction_indicator_;
- // Used in Google QUIC only. Set every time SETTINGS_ENABLE_PUSH is received.
- // Defaults to true.
- bool server_push_enabled_;
-
// The identifier in the most recently received GOAWAY frame. Unset if no
// GOAWAY frame has been received yet.
absl::optional<uint64_t> last_received_http3_goaway_id_;
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 d8bfa782aa7..29e1f6b7bcd 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
@@ -38,7 +38,6 @@
#include "quic/platform/api/quic_map_util.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/qpack/qpack_encoder_peer.h"
-#include "quic/test_tools/qpack/qpack_header_table_peer.h"
#include "quic/test_tools/qpack/qpack_test_utils.h"
#include "quic/test_tools/quic_config_peer.h"
#include "quic/test_tools/quic_connection_peer.h"
@@ -48,7 +47,6 @@
#include "quic/test_tools/quic_stream_peer.h"
#include "quic/test_tools/quic_stream_send_buffer_peer.h"
#include "quic/test_tools/quic_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
#include "common/quiche_endian.h"
#include "common/test_tools/quiche_test_utils.h"
#include "spdy/core/spdy_framer.h"
@@ -559,7 +557,6 @@ class QuicSpdySessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
}
void ReceiveWebTransportSession(WebTransportSessionId session_id) {
- SetQuicReloadableFlag(quic_accept_empty_stream_frame_with_no_fin, true);
QuicStreamFrame frame(session_id, /*fin=*/false, /*offset=*/0,
absl::string_view());
session_.OnStreamFrame(frame);
@@ -1178,7 +1175,6 @@ TEST_P(QuicSpdySessionTestServer, SendGoAway) {
}
TEST_P(QuicSpdySessionTestServer, SendGoAwayWithoutEncryption) {
- SetQuicReloadableFlag(quic_encrypted_goaway, true);
if (VersionHasIetfQuicFrames(transport_version())) {
// HTTP/3 GOAWAY has different semantic and thus has its own test.
return;
@@ -1220,7 +1216,6 @@ TEST_P(QuicSpdySessionTestServer, SendHttp3GoAway) {
}
TEST_P(QuicSpdySessionTestServer, SendHttp3GoAwayWithoutEncryption) {
- SetQuicReloadableFlag(quic_encrypted_goaway, true);
if (!VersionUsesHttp3(transport_version())) {
return;
}
@@ -1918,12 +1913,6 @@ TEST_P(QuicSpdySessionTestClient, BadStreamFramePendingStream) {
GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0);
// A bad stream frame with no data and no fin.
QuicStreamFrame data1(stream_id1, false, 0, 0);
- if (!GetQuicReloadableFlag(quic_accept_empty_stream_frame_with_no_fin)) {
- EXPECT_CALL(*connection_, CloseConnection(_, _, _))
- .WillOnce(
- Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
- EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _, _));
- }
session_.OnStreamFrame(data1);
}
@@ -2519,19 +2508,17 @@ TEST_P(QuicSpdySessionTestServer, ReceiveControlStream) {
QuicStreamFrame frame(stream_id, false, 1, absl::string_view(data));
QpackEncoder* qpack_encoder = session_.qpack_encoder();
- QpackHeaderTable* header_table =
+ QpackEncoderHeaderTable* header_table =
QpackEncoderPeer::header_table(qpack_encoder);
- EXPECT_NE(512u,
- QpackHeaderTablePeer::maximum_dynamic_table_capacity(header_table));
+ EXPECT_NE(512u, header_table->maximum_dynamic_table_capacity());
EXPECT_NE(5u, session_.max_outbound_header_list_size());
EXPECT_NE(42u, QpackEncoderPeer::maximum_blocked_streams(qpack_encoder));
EXPECT_CALL(debug_visitor, OnSettingsFrameReceived(settings));
session_.OnStreamFrame(frame);
- EXPECT_EQ(512u,
- QpackHeaderTablePeer::maximum_dynamic_table_capacity(header_table));
+ EXPECT_EQ(512u, header_table->maximum_dynamic_table_capacity());
EXPECT_EQ(5u, session_.max_outbound_header_list_size());
EXPECT_EQ(42u, QpackEncoderPeer::maximum_blocked_streams(qpack_encoder));
}
@@ -2618,10 +2605,10 @@ TEST_P(QuicSpdySessionTestServer, SessionDestroyedWhileHeaderDecodingBlocked) {
EXPECT_FALSE(stream->headers_decompressed());
// |session_| gets destoyed. That destroys QpackDecoder, a member of
- // QuicSpdySession (derived class), which destroys QpackHeaderTable.
+ // QuicSpdySession (derived class), which destroys QpackDecoderHeaderTable.
// Then |*stream|, owned by QuicSession (base class) get destroyed, which
- // destroys QpackProgessiveDecoder, a registered Observer of QpackHeaderTable.
- // This must not cause a crash.
+ // destroys QpackProgessiveDecoder, a registered Observer of
+ // QpackDecoderHeaderTable. This must not cause a crash.
}
TEST_P(QuicSpdySessionTestClient, ResetAfterInvalidIncomingStreamType) {
@@ -2897,10 +2884,7 @@ TEST_P(QuicSpdySessionTestClient, Http3GoAwayLargerIdThanBefore) {
session_.OnHttp3GoAway(stream_id2);
}
-// 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) {
+TEST_P(QuicSpdySessionTestClient, CloseConnectionOnCancelPush) {
if (!VersionUsesHttp3(transport_version())) {
return;
}
@@ -2937,16 +2921,19 @@ TEST_P(QuicSpdySessionTestClient, IgnoreCancelPush) {
"00"); // push ID
QuicStreamFrame data3(receive_control_stream_id, /* fin = */ false, offset,
cancel_push_frame);
- EXPECT_CALL(debug_visitor, OnCancelPushFrameReceived(_));
- session_.OnStreamFrame(data3);
-}
-
-TEST_P(QuicSpdySessionTestServer, ServerPushEnabledDefaultValue) {
- if (VersionUsesHttp3(transport_version())) {
- EXPECT_FALSE(session_.server_push_enabled());
+ if (GetQuicReloadableFlag(quic_error_on_http3_push)) {
+ EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_FRAME_ERROR,
+ "CANCEL_PUSH frame received.", _))
+ .WillOnce(
+ Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
+ EXPECT_CALL(*connection_,
+ SendConnectionClosePacket(QUIC_HTTP_FRAME_ERROR, _,
+ "CANCEL_PUSH frame received."));
} else {
- EXPECT_TRUE(session_.server_push_enabled());
+ // CANCEL_PUSH is ignored.
+ EXPECT_CALL(debug_visitor, OnCancelPushFrameReceived(_));
}
+ session_.OnStreamFrame(data3);
}
TEST_P(QuicSpdySessionTestServer, OnSetting) {
@@ -2964,7 +2951,7 @@ TEST_P(QuicSpdySessionTestServer, OnSetting) {
session_.OnSetting(SETTINGS_QPACK_BLOCKED_STREAMS, 12);
EXPECT_EQ(12u, QpackEncoderPeer::maximum_blocked_streams(qpack_encoder));
- QpackHeaderTable* header_table =
+ QpackEncoderHeaderTable* header_table =
QpackEncoderPeer::header_table(qpack_encoder);
EXPECT_EQ(0u, header_table->maximum_dynamic_table_capacity());
session_.OnSetting(SETTINGS_QPACK_MAX_TABLE_CAPACITY, 37);
@@ -2978,10 +2965,6 @@ TEST_P(QuicSpdySessionTestServer, OnSetting) {
session_.OnSetting(SETTINGS_MAX_FIELD_SECTION_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());
@@ -3108,10 +3091,7 @@ TEST_P(QuicSpdySessionTestServer, PeerClosesCriticalSendStream) {
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) {
+TEST_P(QuicSpdySessionTestServer, CloseConnectionOnCancelPush) {
if (!VersionUsesHttp3(transport_version())) {
return;
}
@@ -3148,7 +3128,18 @@ TEST_P(QuicSpdySessionTestServer, IgnoreCancelPush) {
"00"); // push ID
QuicStreamFrame data3(receive_control_stream_id, /* fin = */ false, offset,
cancel_push_frame);
- EXPECT_CALL(debug_visitor, OnCancelPushFrameReceived(_));
+ if (GetQuicReloadableFlag(quic_error_on_http3_push)) {
+ EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_FRAME_ERROR,
+ "CANCEL_PUSH frame received.", _))
+ .WillOnce(
+ Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
+ EXPECT_CALL(*connection_,
+ SendConnectionClosePacket(QUIC_HTTP_FRAME_ERROR, _,
+ "CANCEL_PUSH frame received."));
+ } else {
+ // CANCEL_PUSH is ignored.
+ EXPECT_CALL(debug_visitor, OnCancelPushFrameReceived(_));
+ }
session_.OnStreamFrame(data3);
}
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 4d4cc95f94d..6ec48ca5896 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
@@ -30,7 +30,7 @@
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
#include "quic/platform/api/quic_mem_slice_storage.h"
-#include "common/platform/api/quiche_text_utils.h"
+#include "common/quiche_text_utils.h"
#include "spdy/core/spdy_protocol.h"
using spdy::SpdyHeaderBlock;
@@ -434,7 +434,12 @@ QuicConsumedData QuicSpdyStream::WriteBodySlices(QuicMemSliceSpan slices,
QuicConnection::ScopedPacketFlusher flusher(spdy_session_->connection());
// Write frame header.
+#if !defined(__ANDROID__)
struct iovec header_iov = {static_cast<void*>(buffer.get()), header_length};
+#else
+ struct iovec header_iov = {static_cast<void*>(buffer.get()),
+ static_cast<__kernel_size_t>(header_length)};
+#endif
QuicMemSliceStorage storage(
&header_iov, 1,
spdy_session_->connection()->helper()->GetStreamSendBufferAllocator(),
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 7b2d9f19186..f34801a383c 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
@@ -7,11 +7,11 @@
#include "absl/base/attributes.h"
#include "absl/strings/string_view.h"
-#include "quic/core/quic_circular_deque.h"
#include "quic/core/quic_constants.h"
#include "quic/platform/api/quic_bug_tracker.h"
#include "quic/platform/api/quic_export.h"
#include "quic/platform/api/quic_iovec.h"
+#include "common/quiche_circular_deque.h"
namespace quic {
@@ -84,7 +84,7 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStreamBodyManager {
QuicByteCount trailing_non_body_byte_count;
};
// Queue of body fragments and trailing non-body byte counts.
- QuicCircularDeque<Fragment> fragments_;
+ quiche::QuicheCircularDeque<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_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_test.cc
index bb464bdb4d5..8b814b8400b 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
@@ -2772,6 +2772,9 @@ TEST_P(QuicSpdyStreamIncrementalConsumptionTest, UnknownFramesInterleaved) {
// TODO(b/171463363): Remove.
TEST_P(QuicSpdyStreamTest, PushPromiseOnDataStream) {
Initialize(kShouldProcessData);
+ if (GetQuicReloadableFlag(quic_error_on_http3_push)) {
+ return;
+ }
if (!UsesHttp3()) {
return;
}
@@ -2802,6 +2805,9 @@ TEST_P(QuicSpdyStreamTest, PushPromiseOnDataStream) {
TEST_P(QuicSpdyStreamTest,
OnStreamHeaderBlockArgumentDoesNotIncludePushedHeaderBlock) {
Initialize(kShouldProcessData);
+ if (GetQuicReloadableFlag(quic_error_on_http3_push)) {
+ return;
+ }
if (!UsesHttp3()) {
return;
}
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 d3a3c92d209..28b463afebe 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
@@ -17,7 +17,7 @@
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
#include "quic/platform/api/quic_map_util.h"
-#include "common/platform/api/quiche_text_utils.h"
+#include "common/quiche_text_utils.h"
#include "spdy/core/spdy_protocol.h"
using spdy::SpdyHeaderBlock;
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 c7207f383b3..7307665da3d 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
@@ -9,7 +9,6 @@
#include "absl/strings/string_view.h"
#include "quic/core/http/spdy_utils.h"
#include "quic/platform/api/quic_test.h"
-#include "common/platform/api/quiche_text_utils.h"
using spdy::SpdyHeaderBlock;
using testing::Pair;
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/web_transport_http3.h b/chromium/net/third_party/quiche/src/quic/core/http/web_transport_http3.h
index 0c91c2b32a4..667256ea515 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/web_transport_http3.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/web_transport_http3.h
@@ -75,8 +75,8 @@ class QUIC_EXPORT_PRIVATE WebTransportHttp3
bool ready_ = false;
std::unique_ptr<WebTransportVisitor> visitor_;
absl::flat_hash_set<QuicStreamId> streams_;
- QuicCircularDeque<QuicStreamId> incoming_bidirectional_streams_;
- QuicCircularDeque<QuicStreamId> incoming_unidirectional_streams_;
+ quiche::QuicheCircularDeque<QuicStreamId> incoming_bidirectional_streams_;
+ quiche::QuicheCircularDeque<QuicStreamId> incoming_unidirectional_streams_;
};
class QUIC_EXPORT_PRIVATE WebTransportHttp3UnidirectionalStream
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 b83916060e9..8e80c7de4b7 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 "quic/core/quic_circular_deque.h"
#include "quic/core/quic_constants.h"
#include "quic/core/quic_packet_number.h"
#include "quic/core/quic_types.h"
#include "quic/platform/api/quic_bug_tracker.h"
+#include "common/quiche_circular_deque.h"
namespace quic {
@@ -115,7 +115,7 @@ class QUIC_NO_EXPORT PacketNumberIndexedQueue {
return const_cast<EntryWrapper*>(const_this->GetEntryWrapper(offset));
}
- QuicCircularDeque<EntryWrapper> entries_;
+ quiche::QuicheCircularDeque<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.
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 70870a60314..4188350e463 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
@@ -75,8 +75,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 QuicCircularDeque because it has lower
- // memory footprint when holding few elements.
+ // same time. Use std::list instead of quiche::QuicheCircularDeque because it
+ // has lower memory footprint when holding few elements.
using HeaderBlocksForStream = std::list<IndexSet>;
using HeaderBlocks = absl::flat_hash_map<QuicStreamId, HeaderBlocksForStream>;
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 9ba7f1c511f..217f866dce1 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
@@ -12,7 +12,6 @@
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/qpack/qpack_decoder_test_utils.h"
#include "quic/test_tools/qpack/qpack_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
using ::testing::_;
using ::testing::ElementsAre;
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 32178bd9d7c..b947ce3cf0e 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
@@ -111,7 +111,7 @@ class QUIC_EXPORT_PRIVATE QpackDecoder
EncoderStreamErrorDelegate* const encoder_stream_error_delegate_;
QpackEncoderStreamReceiver encoder_stream_receiver_;
QpackDecoderStreamSender decoder_stream_sender_;
- QpackHeaderTable header_table_;
+ QpackDecoderHeaderTable header_table_;
std::set<QuicStreamId> blocked_streams_;
const uint64_t maximum_blocked_streams_;
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 272597ac191..0a76a17450f 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
@@ -7,7 +7,6 @@
#include "absl/strings/escaping.h"
#include "absl/strings/string_view.h"
#include "quic/platform/api/quic_test.h"
-#include "common/platform/api/quiche_text_utils.h"
using testing::Eq;
using testing::StrictMock;
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 275e76f3ca1..708e7a3d3f1 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
@@ -7,7 +7,6 @@
#include "absl/strings/escaping.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/qpack/qpack_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
using ::testing::Eq;
using ::testing::StrictMock;
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 3b57ca6f1c3..772b1d25480 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
@@ -13,7 +13,6 @@
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/qpack/qpack_decoder_test_utils.h"
#include "quic/test_tools/qpack/qpack_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
#include "spdy/core/spdy_header_block.h"
using ::testing::_;
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 5e61ee7490b..3ae944152c0 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
@@ -122,7 +122,7 @@ QpackEncoder::Representations QpackEncoder::FirstPassEncode(
header_table_.FindHeaderField(name, value, &is_static, &index);
switch (match_type) {
- case QpackHeaderTable::MatchType::kNameAndValue:
+ case QpackEncoderHeaderTable::MatchType::kNameAndValue:
if (is_static) {
// Refer to entry directly.
representations.push_back(
@@ -175,7 +175,7 @@ QpackEncoder::Representations QpackEncoder::FirstPassEncode(
break;
- case QpackHeaderTable::MatchType::kName:
+ case QpackEncoderHeaderTable::MatchType::kName:
if (is_static) {
if (blocking_allowed &&
QpackEntry::Size(name, value) <=
@@ -242,7 +242,7 @@ QpackEncoder::Representations QpackEncoder::FirstPassEncode(
break;
- case QpackHeaderTable::MatchType::kNoMatch:
+ case QpackEncoderHeaderTable::MatchType::kNoMatch:
// If allowed, insert entry and refer to it.
if (!blocking_allowed) {
blocked_stream_limit_exhausted = true;
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 9d024417c93..c3d77fea061 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
@@ -153,7 +153,7 @@ class QUIC_EXPORT_PRIVATE QpackEncoder
DecoderStreamErrorDelegate* const decoder_stream_error_delegate_;
QpackDecoderStreamReceiver decoder_stream_receiver_;
QpackEncoderStreamSender encoder_stream_sender_;
- QpackHeaderTable header_table_;
+ QpackEncoderHeaderTable header_table_;
uint64_t maximum_blocked_streams_;
QpackBlockingManager blocking_manager_;
int header_list_count_;
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 efe5eb90b98..2fa440b51b4 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
@@ -7,7 +7,6 @@
#include "absl/strings/escaping.h"
#include "absl/strings/string_view.h"
#include "quic/platform/api/quic_test.h"
-#include "common/platform/api/quiche_text_utils.h"
using testing::Eq;
using testing::StrictMock;
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 5078c8f0d05..98e3e23030f 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
@@ -7,7 +7,6 @@
#include "absl/strings/escaping.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/qpack/qpack_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
using ::testing::Eq;
using ::testing::StrictMock;
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 5045c8fb350..21397ed8571 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
@@ -14,9 +14,7 @@
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/qpack/qpack_encoder_peer.h"
#include "quic/test_tools/qpack/qpack_encoder_test_utils.h"
-#include "quic/test_tools/qpack/qpack_header_table_peer.h"
#include "quic/test_tools/qpack/qpack_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
using ::testing::_;
using ::testing::Eq;
@@ -186,7 +184,8 @@ TEST_F(QpackEncoderTest, TooLargeInsertCountIncrement) {
// Regression test for https://crbug.com/1014372.
TEST_F(QpackEncoderTest, InsertCountIncrementOverflow) {
- QpackHeaderTable* header_table = QpackEncoderPeer::header_table(&encoder_);
+ QpackEncoderHeaderTable* header_table =
+ QpackEncoderPeer::header_table(&encoder_);
// Set dynamic table capacity large enough to hold one entry.
header_table->SetMaximumDynamicTableCapacity(4096);
@@ -461,11 +460,11 @@ TEST_F(QpackEncoderTest, DynamicTableCapacityLessThanMaximum) {
encoder_.SetMaximumDynamicTableCapacity(1024);
encoder_.SetDynamicTableCapacity(30);
- QpackHeaderTable* header_table = QpackEncoderPeer::header_table(&encoder_);
+ QpackEncoderHeaderTable* header_table =
+ QpackEncoderPeer::header_table(&encoder_);
- EXPECT_EQ(1024u,
- QpackHeaderTablePeer::maximum_dynamic_table_capacity(header_table));
- EXPECT_EQ(30u, QpackHeaderTablePeer::dynamic_table_capacity(header_table));
+ EXPECT_EQ(1024u, header_table->maximum_dynamic_table_capacity());
+ EXPECT_EQ(30u, header_table->dynamic_table_capacity());
}
} // namespace
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 da3636db4e4..660727231d6 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
@@ -10,47 +10,47 @@
namespace quic {
-QpackHeaderTable::QpackHeaderTable()
- : static_entries_(ObtainQpackStaticTable().GetStaticEntries()),
- static_index_(ObtainQpackStaticTable().GetStaticIndex()),
- static_name_index_(ObtainQpackStaticTable().GetStaticNameIndex()),
- dynamic_table_size_(0),
- dynamic_table_capacity_(0),
- maximum_dynamic_table_capacity_(0),
- max_entries_(0),
- dropped_entry_count_(0),
- dynamic_table_entry_referenced_(false) {}
-
-QpackHeaderTable::~QpackHeaderTable() {
- for (auto& entry : observers_) {
- entry.second->Cancel();
- }
-}
+QpackEncoderHeaderTable::QpackEncoderHeaderTable()
+ : static_index_(ObtainQpackStaticTable().GetStaticIndex()),
+ static_name_index_(ObtainQpackStaticTable().GetStaticNameIndex()) {}
-const QpackEntry* QpackHeaderTable::LookupEntry(bool is_static,
- uint64_t index) const {
- if (is_static) {
- if (index >= static_entries_.size()) {
- return nullptr;
- }
+uint64_t QpackEncoderHeaderTable::InsertEntry(absl::string_view name,
+ absl::string_view value) {
+ const uint64_t index =
+ QpackHeaderTableBase<QpackEncoderDynamicTable>::InsertEntry(name, value);
- return &static_entries_[index];
- }
+ // Make name and value point to the new entry.
+ name = dynamic_entries().back().name();
+ value = dynamic_entries().back().value();
- if (index < dropped_entry_count_) {
- return nullptr;
+ auto index_result = dynamic_index_.insert(
+ std::make_pair(QpackLookupEntry{name, value}, index));
+ if (!index_result.second) {
+ // An entry with the same name and value already exists. It needs to be
+ // replaced, because |dynamic_index_| tracks the most recent entry for a
+ // given name and value.
+ QUICHE_DCHECK_GT(index, index_result.first->second);
+ dynamic_index_.erase(index_result.first);
+ auto result = dynamic_index_.insert(
+ std::make_pair(QpackLookupEntry{name, value}, index));
+ QUICHE_CHECK(result.second);
}
- index -= dropped_entry_count_;
-
- if (index >= dynamic_entries_.size()) {
- return nullptr;
+ auto name_result = dynamic_name_index_.insert({name, index});
+ if (!name_result.second) {
+ // An entry with the same name already exists. It needs to be replaced,
+ // because |dynamic_name_index_| tracks the most recent entry for a given
+ // name.
+ QUICHE_DCHECK_GT(index, name_result.first->second);
+ dynamic_name_index_.erase(name_result.first);
+ auto result = dynamic_name_index_.insert({name, index});
+ QUICHE_CHECK(result.second);
}
- return &dynamic_entries_[index];
+ return index;
}
-QpackHeaderTable::MatchType QpackHeaderTable::FindHeaderField(
+QpackEncoderHeaderTable::MatchType QpackEncoderHeaderTable::FindHeaderField(
absl::string_view name,
absl::string_view value,
bool* is_static,
@@ -92,56 +92,92 @@ QpackHeaderTable::MatchType QpackHeaderTable::FindHeaderField(
return MatchType::kNoMatch;
}
-bool QpackHeaderTable::EntryFitsDynamicTableCapacity(
- absl::string_view name,
- absl::string_view value) const {
- return QpackEntry::Size(name, value) <= dynamic_table_capacity_;
+uint64_t QpackEncoderHeaderTable::MaxInsertSizeWithoutEvictingGivenEntry(
+ uint64_t index) const {
+ QUICHE_DCHECK_LE(dropped_entry_count(), index);
+
+ if (index > inserted_entry_count()) {
+ // All entries are allowed to be evicted.
+ return dynamic_table_capacity();
+ }
+
+ // Initialize to current available capacity.
+ uint64_t max_insert_size = dynamic_table_capacity() - dynamic_table_size();
+
+ uint64_t entry_index = dropped_entry_count();
+ for (const auto& entry : dynamic_entries()) {
+ if (entry_index >= index) {
+ break;
+ }
+ ++entry_index;
+ max_insert_size += entry.Size();
+ }
+
+ return max_insert_size;
}
-uint64_t QpackHeaderTable::InsertEntry(absl::string_view name,
- absl::string_view value) {
- QUICHE_DCHECK(EntryFitsDynamicTableCapacity(name, value));
+uint64_t QpackEncoderHeaderTable::draining_index(
+ float draining_fraction) const {
+ QUICHE_DCHECK_LE(0.0, draining_fraction);
+ QUICHE_DCHECK_LE(draining_fraction, 1.0);
- const uint64_t index = dropped_entry_count_ + dynamic_entries_.size();
+ const uint64_t required_space = draining_fraction * dynamic_table_capacity();
+ uint64_t space_above_draining_index =
+ dynamic_table_capacity() - dynamic_table_size();
- // Copy name and value before modifying the container, because evicting
- // entries or even inserting a new one might invalidate |name| or |value| if
- // they point to an entry.
- QpackEntry new_entry((std::string(name)), (std::string(value)));
- const size_t entry_size = new_entry.Size();
+ if (dynamic_entries().empty() ||
+ space_above_draining_index >= required_space) {
+ return dropped_entry_count();
+ }
- EvictDownToCapacity(dynamic_table_capacity_ - entry_size);
+ auto it = dynamic_entries().begin();
+ uint64_t entry_index = dropped_entry_count();
+ while (space_above_draining_index < required_space) {
+ space_above_draining_index += it->Size();
+ ++it;
+ ++entry_index;
+ if (it == dynamic_entries().end()) {
+ return inserted_entry_count();
+ }
+ }
- dynamic_table_size_ += entry_size;
- dynamic_entries_.push_back(std::move(new_entry));
+ return entry_index;
+}
- // Make name and value point to the new entry.
- name = dynamic_entries_.back().name();
- value = dynamic_entries_.back().value();
+void QpackEncoderHeaderTable::RemoveEntryFromEnd() {
+ const QpackEntry* const entry = &dynamic_entries().front();
+ const uint64_t index = dropped_entry_count();
- auto index_result = dynamic_index_.insert(
- std::make_pair(QpackLookupEntry{name, value}, index));
- if (!index_result.second) {
- // An entry with the same name and value already exists. It needs to be
- // replaced, because |dynamic_index_| tracks the most recent entry for a
- // given name and value.
- QUICHE_DCHECK_GT(index, index_result.first->second);
- dynamic_index_.erase(index_result.first);
- auto result = dynamic_index_.insert(
- std::make_pair(QpackLookupEntry{name, value}, index));
- QUICHE_CHECK(result.second);
+ auto index_it = dynamic_index_.find({entry->name(), entry->value()});
+ // Remove |dynamic_index_| entry only if it points to the same
+ // QpackEntry in dynamic_entries().
+ if (index_it != dynamic_index_.end() && index_it->second == index) {
+ dynamic_index_.erase(index_it);
}
- auto name_result = dynamic_name_index_.insert({name, index});
- if (!name_result.second) {
- // An entry with the same name already exists. It needs to be replaced,
- // because |dynamic_name_index_| tracks the most recent entry for a given
- // name.
- QUICHE_DCHECK_GT(index, name_result.first->second);
- dynamic_name_index_.erase(name_result.first);
- auto result = dynamic_name_index_.insert({name, index});
- QUICHE_CHECK(result.second);
+ auto name_it = dynamic_name_index_.find(entry->name());
+ // Remove |dynamic_name_index_| entry only if it points to the same
+ // QpackEntry in dynamic_entries().
+ if (name_it != dynamic_name_index_.end() && name_it->second == index) {
+ dynamic_name_index_.erase(name_it);
+ }
+
+ QpackHeaderTableBase<QpackEncoderDynamicTable>::RemoveEntryFromEnd();
+}
+
+QpackDecoderHeaderTable::QpackDecoderHeaderTable()
+ : static_entries_(ObtainQpackStaticTable().GetStaticEntries()) {}
+
+QpackDecoderHeaderTable::~QpackDecoderHeaderTable() {
+ for (auto& entry : observers_) {
+ entry.second->Cancel();
}
+}
+
+uint64_t QpackDecoderHeaderTable::InsertEntry(absl::string_view name,
+ absl::string_view value) {
+ const uint64_t index =
+ QpackHeaderTableBase<QpackDecoderDynamicTable>::InsertEntry(name, value);
// Notify and deregister observers whose threshold is met, if any.
while (!observers_.empty()) {
@@ -157,62 +193,37 @@ uint64_t QpackHeaderTable::InsertEntry(absl::string_view name,
return index;
}
-uint64_t QpackHeaderTable::MaxInsertSizeWithoutEvictingGivenEntry(
- uint64_t index) const {
- QUICHE_DCHECK_LE(dropped_entry_count_, index);
+const QpackEntry* QpackDecoderHeaderTable::LookupEntry(bool is_static,
+ uint64_t index) const {
+ if (is_static) {
+ if (index >= static_entries_.size()) {
+ return nullptr;
+ }
- if (index > inserted_entry_count()) {
- // All entries are allowed to be evicted.
- return dynamic_table_capacity_;
+ return &static_entries_[index];
}
- // Initialize to current available capacity.
- uint64_t max_insert_size = dynamic_table_capacity_ - dynamic_table_size_;
-
- uint64_t entry_index = dropped_entry_count_;
- for (const auto& entry : dynamic_entries_) {
- if (entry_index >= index) {
- break;
- }
- ++entry_index;
- max_insert_size += entry.Size();
+ if (index < dropped_entry_count()) {
+ return nullptr;
}
- return max_insert_size;
-}
+ index -= dropped_entry_count();
-bool QpackHeaderTable::SetDynamicTableCapacity(uint64_t capacity) {
- if (capacity > maximum_dynamic_table_capacity_) {
- return false;
+ if (index >= dynamic_entries().size()) {
+ return nullptr;
}
- dynamic_table_capacity_ = capacity;
- EvictDownToCapacity(capacity);
-
- QUICHE_DCHECK_LE(dynamic_table_size_, dynamic_table_capacity_);
-
- return true;
-}
-
-bool QpackHeaderTable::SetMaximumDynamicTableCapacity(
- uint64_t maximum_dynamic_table_capacity) {
- if (maximum_dynamic_table_capacity_ == 0) {
- maximum_dynamic_table_capacity_ = maximum_dynamic_table_capacity;
- max_entries_ = maximum_dynamic_table_capacity / 32;
- return true;
- }
- // If the value is already set, it should not be changed.
- return maximum_dynamic_table_capacity == maximum_dynamic_table_capacity_;
+ return &dynamic_entries()[index];
}
-void QpackHeaderTable::RegisterObserver(uint64_t required_insert_count,
- Observer* observer) {
+void QpackDecoderHeaderTable::RegisterObserver(uint64_t required_insert_count,
+ Observer* observer) {
QUICHE_DCHECK_GT(required_insert_count, 0u);
observers_.insert({required_insert_count, observer});
}
-void QpackHeaderTable::UnregisterObserver(uint64_t required_insert_count,
- Observer* observer) {
+void QpackDecoderHeaderTable::UnregisterObserver(uint64_t required_insert_count,
+ Observer* observer) {
auto it = observers_.lower_bound(required_insert_count);
while (it != observers_.end() && it->first == required_insert_count) {
if (it->second == observer) {
@@ -226,62 +237,4 @@ void QpackHeaderTable::UnregisterObserver(uint64_t required_insert_count,
QUIC_NOTREACHED();
}
-uint64_t QpackHeaderTable::draining_index(float draining_fraction) const {
- QUICHE_DCHECK_LE(0.0, draining_fraction);
- QUICHE_DCHECK_LE(draining_fraction, 1.0);
-
- const uint64_t required_space = draining_fraction * dynamic_table_capacity_;
- uint64_t space_above_draining_index =
- dynamic_table_capacity_ - dynamic_table_size_;
-
- if (dynamic_entries_.empty() ||
- space_above_draining_index >= required_space) {
- return dropped_entry_count_;
- }
-
- auto it = dynamic_entries_.begin();
- uint64_t entry_index = dropped_entry_count_;
- while (space_above_draining_index < required_space) {
- space_above_draining_index += it->Size();
- ++it;
- ++entry_index;
- if (it == dynamic_entries_.end()) {
- return inserted_entry_count();
- }
- }
-
- return entry_index;
-}
-
-void QpackHeaderTable::EvictDownToCapacity(uint64_t capacity) {
- while (dynamic_table_size_ > capacity) {
- QUICHE_DCHECK(!dynamic_entries_.empty());
-
- QpackEntry* const entry = &dynamic_entries_.front();
-
- const uint64_t entry_size = entry->Size();
- QUICHE_DCHECK_GE(dynamic_table_size_, entry_size);
- dynamic_table_size_ -= entry_size;
-
- const uint64_t index = dropped_entry_count_;
-
- auto index_it = dynamic_index_.find({entry->name(), entry->value()});
- // Remove |dynamic_index_| entry only if it points to the same
- // QpackEntry in |dynamic_entries_|.
- if (index_it != dynamic_index_.end() && index_it->second == index) {
- dynamic_index_.erase(index_it);
- }
-
- auto name_it = dynamic_name_index_.find(entry->name());
- // Remove |dynamic_name_index_| entry only if it points to the same
- // QpackEntry in |dynamic_entries_|.
- if (name_it != dynamic_name_index_.end() && name_it->second == index) {
- dynamic_name_index_.erase(name_it);
- }
-
- dynamic_entries_.pop_front();
- ++dropped_entry_count_;
- }
-}
-
} // namespace quic
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 a5d6c5d74b8..7193d102294 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
@@ -6,75 +6,41 @@
#define QUICHE_QUIC_CORE_QPACK_QPACK_HEADER_TABLE_H_
#include <cstdint>
-#include <functional>
-#include <queue>
-#include <vector>
+#include <deque>
#include "absl/strings/string_view.h"
#include "quic/platform/api/quic_export.h"
+#include "common/quiche_circular_deque.h"
#include "spdy/core/hpack/hpack_entry.h"
#include "spdy/core/hpack/hpack_header_table.h"
namespace quic {
-namespace test {
-
-class QpackHeaderTablePeer;
-
-} // namespace test
-
using QpackEntry = spdy::HpackEntry;
using QpackLookupEntry = spdy::HpackLookupEntry;
constexpr size_t kQpackEntrySizeOverhead = spdy::kHpackEntrySizeOverhead;
-// This class manages the QPACK static and dynamic tables. For dynamic entries,
-// it only has a concept of absolute indices. The caller needs to perform the
-// necessary transformations to and from relative indices and post-base indices.
-class QUIC_EXPORT_PRIVATE QpackHeaderTable {
+// Encoder needs pointer stability for |dynamic_index_| and
+// |dynamic_name_index_|. However, it does not need random access.
+// TODO(b/182349990): Change to a more memory efficient container.
+using QpackEncoderDynamicTable = std::deque<QpackEntry>;
+
+// Decoder needs random access for LookupEntry().
+// However, it does not need pointer stability.
+using QpackDecoderDynamicTable = quiche::QuicheCircularDeque<QpackEntry>;
+
+// This is a base class for encoder and decoder classes that manage the QPACK
+// static and dynamic tables. For dynamic entries, it only has a concept of
+// absolute indices. The caller needs to perform the necessary transformations
+// to and from relative indices and post-base indices.
+template <typename DynamicEntryTable>
+class QUIC_EXPORT_PRIVATE QpackHeaderTableBase {
public:
- using StaticEntryTable = spdy::HpackHeaderTable::StaticEntryTable;
- using DynamicEntryTable = spdy::HpackHeaderTable::DynamicEntryTable;
- using NameValueToEntryMap = spdy::HpackHeaderTable::NameValueToEntryMap;
- using NameToEntryMap = spdy::HpackHeaderTable::NameToEntryMap;
+ QpackHeaderTableBase();
+ QpackHeaderTableBase(const QpackHeaderTableBase&) = delete;
+ QpackHeaderTableBase& operator=(const QpackHeaderTableBase&) = delete;
- // Result of header table lookup.
- enum class MatchType { kNameAndValue, kName, kNoMatch };
-
- // Observer interface for dynamic table insertion.
- class QUIC_EXPORT_PRIVATE Observer {
- public:
- virtual ~Observer() = default;
-
- // Called when inserted_entry_count() reaches the threshold the Observer was
- // registered with. After this call the Observer automatically gets
- // deregistered.
- virtual void OnInsertCountReachedThreshold() = 0;
-
- // Called when QpackHeaderTable is destroyed to let the Observer know that
- // it must not call UnregisterObserver().
- virtual void Cancel() = 0;
- };
-
- QpackHeaderTable();
- QpackHeaderTable(const QpackHeaderTable&) = delete;
- QpackHeaderTable& operator=(const QpackHeaderTable&) = delete;
-
- ~QpackHeaderTable();
-
- // Returns the entry at absolute index |index| from the static or dynamic
- // table according to |is_static|. |index| is zero based for both the static
- // and the dynamic table. The returned pointer is valid until the entry is
- // evicted, even if other entries are inserted into the dynamic table.
- // Returns nullptr if entry does not exist.
- const QpackEntry* LookupEntry(bool is_static, uint64_t index) const;
-
- // 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(absl::string_view name,
- absl::string_view value,
- bool* is_static,
- uint64_t* index) const;
+ virtual ~QpackHeaderTableBase() = default;
// Returns whether an entry with |name| and |value| has a size (including
// overhead) that is smaller than or equal to the capacity of the dynamic
@@ -89,13 +55,7 @@ class QUIC_EXPORT_PRIVATE QpackHeaderTable {
// the underlying container might move entries around when resizing for
// insertion.
// Returns the absolute index of the inserted dynamic table entry.
- uint64_t InsertEntry(absl::string_view name, absl::string_view 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
- // inserted_entry_count(), in which case the capacity of the table is
- // returned. |index| must not be smaller than dropped_entry_count().
- uint64_t MaxInsertSizeWithoutEvictingGivenEntry(uint64_t index) const;
+ virtual uint64_t InsertEntry(absl::string_view name, absl::string_view value);
// Change dynamic table capacity to |capacity|. Returns true on success.
// Returns false is |capacity| exceeds maximum dynamic table capacity.
@@ -112,24 +72,11 @@ class QUIC_EXPORT_PRIVATE QpackHeaderTable {
// returning false.
bool SetMaximumDynamicTableCapacity(uint64_t maximum_dynamic_table_capacity);
- // Get |maximum_dynamic_table_capacity_|.
+ uint64_t dynamic_table_size() const { return dynamic_table_size_; }
+ uint64_t dynamic_table_capacity() const { return dynamic_table_capacity_; }
uint64_t maximum_dynamic_table_capacity() const {
return maximum_dynamic_table_capacity_;
}
-
- // Register an observer to be notified when inserted_entry_count() reaches
- // |required_insert_count|. After the notification, |observer| automatically
- // gets unregistered. Each observer must only be registered at most once.
- void RegisterObserver(uint64_t required_insert_count, Observer* observer);
-
- // Unregister previously registered observer. Must be called with the same
- // |required_insert_count| value that |observer| was registered with. Must be
- // called before an observer still waiting for notification is destroyed,
- // unless QpackHeaderTable already called Observer::Cancel(), in which case
- // this method must not be called.
- void UnregisterObserver(uint64_t required_insert_count, Observer* observer);
-
- // Used on request streams to encode and decode Required Insert Count.
uint64_t max_entries() const { return max_entries_; }
// The number of entries inserted to the dynamic table (including ones that
@@ -141,14 +88,6 @@ class QUIC_EXPORT_PRIVATE QpackHeaderTable {
// The number of entries dropped from the dynamic table.
uint64_t dropped_entry_count() const { return dropped_entry_count_; }
- // Returns the draining index described at
- // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#avoiding-blocked-insertions.
- // Entries with an index larger than or equal to the draining index take up
- // approximately |1.0 - draining_fraction| of dynamic table capacity. The
- // remaining capacity is taken up by draining entries and unused space.
- // The returned index might not be the index of a valid entry.
- uint64_t draining_index(float draining_fraction) const;
-
void set_dynamic_table_entry_referenced() {
dynamic_table_entry_referenced_ = true;
}
@@ -156,20 +95,178 @@ class QUIC_EXPORT_PRIVATE QpackHeaderTable {
return dynamic_table_entry_referenced_;
}
- private:
- friend class test::QpackHeaderTablePeer;
+ protected:
+ // Removes a single entry from the end of the dynamic table, updates
+ // |dynamic_table_size_| and |dropped_entry_count_|.
+ virtual void RemoveEntryFromEnd();
+ const DynamicEntryTable& dynamic_entries() const { return dynamic_entries_; }
+
+ private:
// Evict entries from the dynamic table until table size is less than or equal
// to |capacity|.
void EvictDownToCapacity(uint64_t capacity);
- // Static Table
+ // Dynamic Table entries.
+ DynamicEntryTable dynamic_entries_;
- // |static_entries_|, |static_index_|, |static_name_index_| are owned by
- // QpackStaticTable singleton.
+ // Size of the dynamic table. This is the sum of the size of its entries.
+ uint64_t dynamic_table_size_;
- // Tracks QpackEntries by index.
- const StaticEntryTable& static_entries_;
+ // Dynamic Table Capacity is the maximum allowed value of
+ // |dynamic_table_size_|. Entries are evicted if necessary before inserting a
+ // new entry to ensure that dynamic table size never exceeds capacity.
+ // Initial value is |maximum_dynamic_table_capacity_|. Capacity can be
+ // changed by the encoder, as long as it does not exceed
+ // |maximum_dynamic_table_capacity_|.
+ uint64_t dynamic_table_capacity_;
+
+ // Maximum allowed value of |dynamic_table_capacity|. The initial value is
+ // zero. Can be changed by SetMaximumDynamicTableCapacity().
+ uint64_t maximum_dynamic_table_capacity_;
+
+ // MaxEntries, see Section 3.2.2. Calculated based on
+ // |maximum_dynamic_table_capacity_|. Used on request streams to encode and
+ // decode Required Insert Count.
+ uint64_t max_entries_;
+
+ // The number of entries dropped from the dynamic table.
+ uint64_t dropped_entry_count_;
+
+ // True if any dynamic table entries have been referenced from a header block.
+ // Set directly by the encoder or decoder. Used for stats.
+ bool dynamic_table_entry_referenced_;
+};
+
+template <typename DynamicEntryTable>
+QpackHeaderTableBase<DynamicEntryTable>::QpackHeaderTableBase()
+ : dynamic_table_size_(0),
+ dynamic_table_capacity_(0),
+ maximum_dynamic_table_capacity_(0),
+ max_entries_(0),
+ dropped_entry_count_(0),
+ dynamic_table_entry_referenced_(false) {}
+
+template <typename DynamicEntryTable>
+bool QpackHeaderTableBase<DynamicEntryTable>::EntryFitsDynamicTableCapacity(
+ absl::string_view name,
+ absl::string_view value) const {
+ return QpackEntry::Size(name, value) <= dynamic_table_capacity_;
+}
+
+template <typename DynamicEntryTable>
+uint64_t QpackHeaderTableBase<DynamicEntryTable>::InsertEntry(
+ absl::string_view name,
+ absl::string_view value) {
+ QUICHE_DCHECK(EntryFitsDynamicTableCapacity(name, value));
+
+ const uint64_t index = dropped_entry_count_ + dynamic_entries_.size();
+
+ // Copy name and value before modifying the container, because evicting
+ // entries or even inserting a new one might invalidate |name| or |value| if
+ // they point to an entry.
+ QpackEntry new_entry((std::string(name)), (std::string(value)));
+ const size_t entry_size = new_entry.Size();
+
+ EvictDownToCapacity(dynamic_table_capacity_ - entry_size);
+
+ dynamic_table_size_ += entry_size;
+ dynamic_entries_.push_back(std::move(new_entry));
+
+ return index;
+}
+
+template <typename DynamicEntryTable>
+bool QpackHeaderTableBase<DynamicEntryTable>::SetDynamicTableCapacity(
+ uint64_t capacity) {
+ if (capacity > maximum_dynamic_table_capacity_) {
+ return false;
+ }
+
+ dynamic_table_capacity_ = capacity;
+ EvictDownToCapacity(capacity);
+
+ QUICHE_DCHECK_LE(dynamic_table_size_, dynamic_table_capacity_);
+
+ return true;
+}
+
+template <typename DynamicEntryTable>
+bool QpackHeaderTableBase<DynamicEntryTable>::SetMaximumDynamicTableCapacity(
+ uint64_t maximum_dynamic_table_capacity) {
+ if (maximum_dynamic_table_capacity_ == 0) {
+ maximum_dynamic_table_capacity_ = maximum_dynamic_table_capacity;
+ max_entries_ = maximum_dynamic_table_capacity / 32;
+ return true;
+ }
+ // If the value is already set, it should not be changed.
+ return maximum_dynamic_table_capacity == maximum_dynamic_table_capacity_;
+}
+
+template <typename DynamicEntryTable>
+void QpackHeaderTableBase<DynamicEntryTable>::RemoveEntryFromEnd() {
+ const uint64_t entry_size = dynamic_entries_.front().Size();
+ QUICHE_DCHECK_GE(dynamic_table_size_, entry_size);
+ dynamic_table_size_ -= entry_size;
+
+ dynamic_entries_.pop_front();
+ ++dropped_entry_count_;
+}
+
+template <typename DynamicEntryTable>
+void QpackHeaderTableBase<DynamicEntryTable>::EvictDownToCapacity(
+ uint64_t capacity) {
+ while (dynamic_table_size_ > capacity) {
+ QUICHE_DCHECK(!dynamic_entries_.empty());
+ RemoveEntryFromEnd();
+ }
+}
+
+class QUIC_EXPORT_PRIVATE QpackEncoderHeaderTable
+ : public QpackHeaderTableBase<QpackEncoderDynamicTable> {
+ public:
+ // Result of header table lookup.
+ enum class MatchType { kNameAndValue, kName, kNoMatch };
+
+ QpackEncoderHeaderTable();
+ ~QpackEncoderHeaderTable() override = default;
+
+ uint64_t InsertEntry(absl::string_view name,
+ absl::string_view value) override;
+
+ // 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(absl::string_view name,
+ absl::string_view value,
+ bool* is_static,
+ uint64_t* index) const;
+
+ // Returns the size of the largest entry that could be inserted into the
+ // dynamic table without evicting entry |index|. |index| might be larger than
+ // inserted_entry_count(), in which case the capacity of the table is
+ // returned. |index| must not be smaller than dropped_entry_count().
+ uint64_t MaxInsertSizeWithoutEvictingGivenEntry(uint64_t index) const;
+
+ // Returns the draining index described at
+ // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#avoiding-blocked-insertions.
+ // Entries with an index larger than or equal to the draining index take up
+ // approximately |1.0 - draining_fraction| of dynamic table capacity. The
+ // remaining capacity is taken up by draining entries and unused space.
+ // The returned index might not be the index of a valid entry.
+ uint64_t draining_index(float draining_fraction) const;
+
+ protected:
+ void RemoveEntryFromEnd() override;
+
+ private:
+ using NameValueToEntryMap = spdy::HpackHeaderTable::NameValueToEntryMap;
+ using NameToEntryMap = spdy::HpackHeaderTable::NameToEntryMap;
+
+ // Static Table
+
+ // |static_index_| and |static_name_index_| are owned by QpackStaticTable
+ // singleton.
// Tracks the unique static entry for a given header name and value.
const NameValueToEntryMap& static_index_;
@@ -179,49 +276,69 @@ class QUIC_EXPORT_PRIVATE QpackHeaderTable {
// Dynamic Table
- // Queue of dynamic table entries, for lookup by index.
- // |dynamic_entries_| owns the entries in the dynamic table.
- DynamicEntryTable dynamic_entries_;
-
// An unordered set of QpackEntry pointers with a comparison operator that
// only cares about name and value. This allows fast lookup of the most
// recently inserted dynamic entry for a given header name and value pair.
- // Entries point to entries owned by |dynamic_entries_|.
+ // Entries point to entries owned by |QpackHeaderTableBase::dynamic_entries_|.
NameValueToEntryMap dynamic_index_;
// An unordered map of QpackEntry pointers keyed off header name. This allows
// fast lookup of the most recently inserted dynamic entry for a given header
- // name. Entries point to entries owned by |dynamic_entries_|.
+ // name. Entries point to entries owned by
+ // |QpackHeaderTableBase::dynamic_entries_|.
NameToEntryMap dynamic_name_index_;
+};
- // Size of the dynamic table. This is the sum of the size of its entries.
- uint64_t dynamic_table_size_;
+class QUIC_EXPORT_PRIVATE QpackDecoderHeaderTable
+ : public QpackHeaderTableBase<QpackDecoderDynamicTable> {
+ public:
+ // Observer interface for dynamic table insertion.
+ class QUIC_EXPORT_PRIVATE Observer {
+ public:
+ virtual ~Observer() = default;
- // Dynamic Table Capacity is the maximum allowed value of
- // |dynamic_table_size_|. Entries are evicted if necessary before inserting a
- // new entry to ensure that dynamic table size never exceeds capacity.
- // Initial value is |maximum_dynamic_table_capacity_|. Capacity can be
- // changed by the encoder, as long as it does not exceed
- // |maximum_dynamic_table_capacity_|.
- uint64_t dynamic_table_capacity_;
+ // Called when inserted_entry_count() reaches the threshold the Observer was
+ // registered with. After this call the Observer automatically gets
+ // deregistered.
+ virtual void OnInsertCountReachedThreshold() = 0;
- // Maximum allowed value of |dynamic_table_capacity|. The initial value is
- // zero. Can be changed by SetMaximumDynamicTableCapacity().
- uint64_t maximum_dynamic_table_capacity_;
+ // Called when QpackDecoderHeaderTable is destroyed to let the Observer know
+ // that it must not call UnregisterObserver().
+ virtual void Cancel() = 0;
+ };
- // MaxEntries, see Section 3.2.2. Calculated based on
- // |maximum_dynamic_table_capacity_|.
- uint64_t max_entries_;
+ QpackDecoderHeaderTable();
+ ~QpackDecoderHeaderTable() override;
- // The number of entries dropped from the dynamic table.
- uint64_t dropped_entry_count_;
+ uint64_t InsertEntry(absl::string_view name,
+ absl::string_view value) override;
+
+ // Returns the entry at absolute index |index| from the static or dynamic
+ // table according to |is_static|. |index| is zero based for both the static
+ // and the dynamic table. The returned pointer is valid until the entry is
+ // evicted, even if other entries are inserted into the dynamic table.
+ // Returns nullptr if entry does not exist.
+ const QpackEntry* LookupEntry(bool is_static, uint64_t index) const;
+
+ // Register an observer to be notified when inserted_entry_count() reaches
+ // |required_insert_count|. After the notification, |observer| automatically
+ // gets unregistered. Each observer must only be registered at most once.
+ void RegisterObserver(uint64_t required_insert_count, Observer* observer);
+
+ // Unregister previously registered observer. Must be called with the same
+ // |required_insert_count| value that |observer| was registered with. Must be
+ // called before an observer still waiting for notification is destroyed,
+ // unless QpackDecoderHeaderTable already called Observer::Cancel(), in which
+ // case this method must not be called.
+ void UnregisterObserver(uint64_t required_insert_count, Observer* observer);
+
+ private:
+ // Static Table entries. Owned by QpackStaticTable singleton.
+ using StaticEntryTable = spdy::HpackHeaderTable::StaticEntryTable;
+ const StaticEntryTable& static_entries_;
// Observers waiting to be notified, sorted by required insert count.
std::multimap<uint64_t, Observer*> observers_;
-
- // True if any dynamic table entries have been referenced from a header block.
- // Set directly by the encoder or decoder. Used for stats.
- bool dynamic_table_entry_referenced_;
};
} // namespace quic
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 0af250efd32..4a1e39c2325 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
@@ -21,64 +21,16 @@ namespace {
const uint64_t kMaximumDynamicTableCapacityForTesting = 1024 * 1024;
-class MockObserver : public QpackHeaderTable::Observer {
- public:
- ~MockObserver() override = default;
-
- MOCK_METHOD(void, OnInsertCountReachedThreshold, (), (override));
- MOCK_METHOD(void, Cancel, (), (override));
-};
-
+template <typename T>
class QpackHeaderTableTest : public QuicTest {
protected:
- QpackHeaderTableTest() {
- table_.SetMaximumDynamicTableCapacity(
- kMaximumDynamicTableCapacityForTesting);
- table_.SetDynamicTableCapacity(kMaximumDynamicTableCapacityForTesting);
- }
~QpackHeaderTableTest() override = default;
- void ExpectEntryAtIndex(bool is_static,
- uint64_t index,
- absl::string_view expected_name,
- absl::string_view expected_value) const {
- const auto* entry = table_.LookupEntry(is_static, index);
- ASSERT_TRUE(entry);
- EXPECT_EQ(expected_name, entry->name());
- EXPECT_EQ(expected_value, entry->value());
- }
-
- void ExpectNoEntryAtIndex(bool is_static, uint64_t index) const {
- EXPECT_FALSE(table_.LookupEntry(is_static, index));
- }
-
- void ExpectMatch(absl::string_view name,
- absl::string_view value,
- QpackHeaderTable::MatchType expected_match_type,
- bool expected_is_static,
- uint64_t expected_index) const {
- // Initialize outparams to a value different from the expected to ensure
- // that FindHeaderField() sets them.
- bool is_static = !expected_is_static;
- uint64_t index = expected_index + 1;
-
- QpackHeaderTable::MatchType matchtype =
- table_.FindHeaderField(name, value, &is_static, &index);
-
- EXPECT_EQ(expected_match_type, matchtype) << name << ": " << value;
- EXPECT_EQ(expected_is_static, is_static) << name << ": " << value;
- EXPECT_EQ(expected_index, index) << name << ": " << value;
- }
-
- void ExpectNoMatch(absl::string_view name, absl::string_view value) const {
- bool is_static = false;
- uint64_t index = 0;
-
- QpackHeaderTable::MatchType matchtype =
- table_.FindHeaderField(name, value, &is_static, &index);
-
- EXPECT_EQ(QpackHeaderTable::MatchType::kNoMatch, matchtype)
- << name << ": " << value;
+ void SetUp() override {
+ ASSERT_TRUE(table_.SetMaximumDynamicTableCapacity(
+ kMaximumDynamicTableCapacityForTesting));
+ ASSERT_TRUE(
+ table_.SetDynamicTableCapacity(kMaximumDynamicTableCapacityForTesting));
}
bool EntryFitsDynamicTableCapacity(absl::string_view name,
@@ -94,110 +46,129 @@ class QpackHeaderTableTest : public QuicTest {
return table_.SetDynamicTableCapacity(capacity);
}
- void RegisterObserver(uint64_t required_insert_count,
- QpackHeaderTable::Observer* observer) {
- table_.RegisterObserver(required_insert_count, observer);
- }
-
- void UnregisterObserver(uint64_t required_insert_count,
- QpackHeaderTable::Observer* observer) {
- table_.UnregisterObserver(required_insert_count, observer);
- }
-
uint64_t max_entries() const { return table_.max_entries(); }
uint64_t inserted_entry_count() const {
return table_.inserted_entry_count();
}
uint64_t dropped_entry_count() const { return table_.dropped_entry_count(); }
- private:
- QpackHeaderTable table_;
+ T table_;
};
-TEST_F(QpackHeaderTableTest, LookupStaticEntry) {
- ExpectEntryAtIndex(/* is_static = */ true, 0, ":authority", "");
+using MyTypes =
+ ::testing::Types<QpackEncoderHeaderTable, QpackDecoderHeaderTable>;
+TYPED_TEST_SUITE(QpackHeaderTableTest, MyTypes);
- ExpectEntryAtIndex(/* is_static = */ true, 1, ":path", "/");
-
- // 98 is the last entry.
- ExpectEntryAtIndex(/* is_static = */ true, 98, "x-frame-options",
- "sameorigin");
+// MaxEntries is determined by maximum dynamic table capacity,
+// which is set at construction time.
+TYPED_TEST(QpackHeaderTableTest, MaxEntries) {
+ TypeParam table1;
+ table1.SetMaximumDynamicTableCapacity(1024);
+ EXPECT_EQ(32u, table1.max_entries());
- ASSERT_EQ(99u, QpackStaticTableVector().size());
- ExpectNoEntryAtIndex(/* is_static = */ true, 99);
+ TypeParam table2;
+ table2.SetMaximumDynamicTableCapacity(500);
+ EXPECT_EQ(15u, table2.max_entries());
}
-TEST_F(QpackHeaderTableTest, InsertAndLookupDynamicEntry) {
- // Dynamic table is initially entry.
- ExpectNoEntryAtIndex(/* is_static = */ false, 0);
- ExpectNoEntryAtIndex(/* is_static = */ false, 1);
- ExpectNoEntryAtIndex(/* is_static = */ false, 2);
- ExpectNoEntryAtIndex(/* is_static = */ false, 3);
+TYPED_TEST(QpackHeaderTableTest, SetDynamicTableCapacity) {
+ // Dynamic table capacity does not affect MaxEntries.
+ EXPECT_TRUE(this->SetDynamicTableCapacity(1024));
+ EXPECT_EQ(32u * 1024, this->max_entries());
- // Insert one entry.
- InsertEntry("foo", "bar");
+ EXPECT_TRUE(this->SetDynamicTableCapacity(500));
+ EXPECT_EQ(32u * 1024, this->max_entries());
- ExpectEntryAtIndex(/* is_static = */ false, 0, "foo", "bar");
+ // Dynamic table capacity cannot exceed maximum dynamic table capacity.
+ EXPECT_FALSE(this->SetDynamicTableCapacity(
+ 2 * kMaximumDynamicTableCapacityForTesting));
+}
- ExpectNoEntryAtIndex(/* is_static = */ false, 1);
- ExpectNoEntryAtIndex(/* is_static = */ false, 2);
- ExpectNoEntryAtIndex(/* is_static = */ false, 3);
+TYPED_TEST(QpackHeaderTableTest, EntryFitsDynamicTableCapacity) {
+ EXPECT_TRUE(this->SetDynamicTableCapacity(39));
- // Insert a different entry.
- InsertEntry("baz", "bing");
+ EXPECT_TRUE(this->EntryFitsDynamicTableCapacity("foo", "bar"));
+ EXPECT_TRUE(this->EntryFitsDynamicTableCapacity("foo", "bar2"));
+ EXPECT_FALSE(this->EntryFitsDynamicTableCapacity("foo", "bar12"));
+}
- ExpectEntryAtIndex(/* is_static = */ false, 0, "foo", "bar");
+class QpackEncoderHeaderTableTest
+ : public QpackHeaderTableTest<QpackEncoderHeaderTable> {
+ protected:
+ ~QpackEncoderHeaderTableTest() override = default;
- ExpectEntryAtIndex(/* is_static = */ false, 1, "baz", "bing");
+ void ExpectMatch(absl::string_view name,
+ absl::string_view value,
+ QpackEncoderHeaderTable::MatchType expected_match_type,
+ bool expected_is_static,
+ uint64_t expected_index) const {
+ // Initialize outparams to a value different from the expected to ensure
+ // that FindHeaderField() sets them.
+ bool is_static = !expected_is_static;
+ uint64_t index = expected_index + 1;
- ExpectNoEntryAtIndex(/* is_static = */ false, 2);
- ExpectNoEntryAtIndex(/* is_static = */ false, 3);
+ QpackEncoderHeaderTable::MatchType matchtype =
+ table_.FindHeaderField(name, value, &is_static, &index);
- // Insert an entry identical to the most recently inserted one.
- InsertEntry("baz", "bing");
+ EXPECT_EQ(expected_match_type, matchtype) << name << ": " << value;
+ EXPECT_EQ(expected_is_static, is_static) << name << ": " << value;
+ EXPECT_EQ(expected_index, index) << name << ": " << value;
+ }
- ExpectEntryAtIndex(/* is_static = */ false, 0, "foo", "bar");
+ void ExpectNoMatch(absl::string_view name, absl::string_view value) const {
+ bool is_static = false;
+ uint64_t index = 0;
- ExpectEntryAtIndex(/* is_static = */ false, 1, "baz", "bing");
+ QpackEncoderHeaderTable::MatchType matchtype =
+ table_.FindHeaderField(name, value, &is_static, &index);
- ExpectEntryAtIndex(/* is_static = */ false, 2, "baz", "bing");
+ EXPECT_EQ(QpackEncoderHeaderTable::MatchType::kNoMatch, matchtype)
+ << name << ": " << value;
+ }
- ExpectNoEntryAtIndex(/* is_static = */ false, 3);
-}
+ uint64_t MaxInsertSizeWithoutEvictingGivenEntry(uint64_t index) const {
+ return table_.MaxInsertSizeWithoutEvictingGivenEntry(index);
+ }
-TEST_F(QpackHeaderTableTest, FindStaticHeaderField) {
+ uint64_t draining_index(float draining_fraction) const {
+ return table_.draining_index(draining_fraction);
+ }
+};
+
+TEST_F(QpackEncoderHeaderTableTest, FindStaticHeaderField) {
// A header name that has multiple entries with different values.
- ExpectMatch(":method", "GET", QpackHeaderTable::MatchType::kNameAndValue,
- true, 17u);
+ ExpectMatch(":method", "GET",
+ QpackEncoderHeaderTable::MatchType::kNameAndValue, true, 17u);
- ExpectMatch(":method", "POST", QpackHeaderTable::MatchType::kNameAndValue,
- true, 20u);
+ ExpectMatch(":method", "POST",
+ QpackEncoderHeaderTable::MatchType::kNameAndValue, true, 20u);
- ExpectMatch(":method", "TRACE", QpackHeaderTable::MatchType::kName, true,
- 15u);
+ ExpectMatch(":method", "TRACE", QpackEncoderHeaderTable::MatchType::kName,
+ true, 15u);
// A header name that has a single entry with non-empty value.
ExpectMatch("accept-encoding", "gzip, deflate, br",
- QpackHeaderTable::MatchType::kNameAndValue, true, 31u);
+ QpackEncoderHeaderTable::MatchType::kNameAndValue, true, 31u);
- ExpectMatch("accept-encoding", "compress", QpackHeaderTable::MatchType::kName,
- true, 31u);
+ ExpectMatch("accept-encoding", "compress",
+ QpackEncoderHeaderTable::MatchType::kName, true, 31u);
- ExpectMatch("accept-encoding", "", QpackHeaderTable::MatchType::kName, true,
- 31u);
+ ExpectMatch("accept-encoding", "", QpackEncoderHeaderTable::MatchType::kName,
+ true, 31u);
// A header name that has a single entry with empty value.
- ExpectMatch("location", "", QpackHeaderTable::MatchType::kNameAndValue, true,
- 12u);
+ ExpectMatch("location", "", QpackEncoderHeaderTable::MatchType::kNameAndValue,
+ true, 12u);
- ExpectMatch("location", "foo", QpackHeaderTable::MatchType::kName, true, 12u);
+ ExpectMatch("location", "foo", QpackEncoderHeaderTable::MatchType::kName,
+ true, 12u);
// No matching header name.
ExpectNoMatch("foo", "");
ExpectNoMatch("foo", "bar");
}
-TEST_F(QpackHeaderTableTest, FindDynamicHeaderField) {
+TEST_F(QpackEncoderHeaderTableTest, FindDynamicHeaderField) {
// Dynamic table is initially entry.
ExpectNoMatch("foo", "bar");
ExpectNoMatch("foo", "baz");
@@ -206,75 +177,49 @@ TEST_F(QpackHeaderTableTest, FindDynamicHeaderField) {
InsertEntry("foo", "bar");
// Match name and value.
- ExpectMatch("foo", "bar", QpackHeaderTable::MatchType::kNameAndValue, false,
- 0u);
+ ExpectMatch("foo", "bar", QpackEncoderHeaderTable::MatchType::kNameAndValue,
+ false, 0u);
// Match name only.
- ExpectMatch("foo", "baz", QpackHeaderTable::MatchType::kName, false, 0u);
+ ExpectMatch("foo", "baz", QpackEncoderHeaderTable::MatchType::kName, false,
+ 0u);
// Insert an identical entry. FindHeaderField() should return the index of
// the most recently inserted matching entry.
InsertEntry("foo", "bar");
// Match name and value.
- ExpectMatch("foo", "bar", QpackHeaderTable::MatchType::kNameAndValue, false,
- 1u);
+ ExpectMatch("foo", "bar", QpackEncoderHeaderTable::MatchType::kNameAndValue,
+ false, 1u);
// Match name only.
- ExpectMatch("foo", "baz", QpackHeaderTable::MatchType::kName, false, 1u);
+ ExpectMatch("foo", "baz", QpackEncoderHeaderTable::MatchType::kName, false,
+ 1u);
}
-TEST_F(QpackHeaderTableTest, FindHeaderFieldPrefersStaticTable) {
+TEST_F(QpackEncoderHeaderTableTest, FindHeaderFieldPrefersStaticTable) {
// Insert an entry to the dynamic table that exists in the static table.
InsertEntry(":method", "GET");
- // Insertion works.
- ExpectEntryAtIndex(/* is_static = */ false, 0, ":method", "GET");
-
// FindHeaderField() prefers static table if both have name-and-value match.
- ExpectMatch(":method", "GET", QpackHeaderTable::MatchType::kNameAndValue,
- true, 17u);
+ ExpectMatch(":method", "GET",
+ QpackEncoderHeaderTable::MatchType::kNameAndValue, true, 17u);
// FindHeaderField() prefers static table if both have name match but no value
// match, and prefers the first entry with matching name.
- ExpectMatch(":method", "TRACE", QpackHeaderTable::MatchType::kName, true,
- 15u);
+ ExpectMatch(":method", "TRACE", QpackEncoderHeaderTable::MatchType::kName,
+ true, 15u);
// Add new entry to the dynamic table.
InsertEntry(":method", "TRACE");
// FindHeaderField prefers name-and-value match in dynamic table over name
// only match in static table.
- ExpectMatch(":method", "TRACE", QpackHeaderTable::MatchType::kNameAndValue,
- false, 1u);
+ ExpectMatch(":method", "TRACE",
+ QpackEncoderHeaderTable::MatchType::kNameAndValue, false, 1u);
}
-// MaxEntries is determined by maximum dynamic table capacity,
-// which is set at construction time.
-TEST_F(QpackHeaderTableTest, MaxEntries) {
- QpackHeaderTable table1;
- table1.SetMaximumDynamicTableCapacity(1024);
- EXPECT_EQ(32u, table1.max_entries());
-
- QpackHeaderTable table2;
- table2.SetMaximumDynamicTableCapacity(500);
- EXPECT_EQ(15u, table2.max_entries());
-}
-
-TEST_F(QpackHeaderTableTest, SetDynamicTableCapacity) {
- // Dynamic table capacity does not affect MaxEntries.
- EXPECT_TRUE(SetDynamicTableCapacity(1024));
- EXPECT_EQ(32u * 1024, max_entries());
-
- EXPECT_TRUE(SetDynamicTableCapacity(500));
- EXPECT_EQ(32u * 1024, max_entries());
-
- // Dynamic table capacity cannot exceed maximum dynamic table capacity.
- EXPECT_FALSE(
- SetDynamicTableCapacity(2 * kMaximumDynamicTableCapacityForTesting));
-}
-
-TEST_F(QpackHeaderTableTest, EvictByInsertion) {
+TEST_F(QpackEncoderHeaderTableTest, EvictByInsertion) {
EXPECT_TRUE(SetDynamicTableCapacity(40));
// Entry size is 3 + 3 + 32 = 38.
@@ -282,7 +227,7 @@ TEST_F(QpackHeaderTableTest, EvictByInsertion) {
EXPECT_EQ(1u, inserted_entry_count());
EXPECT_EQ(0u, dropped_entry_count());
- ExpectMatch("foo", "bar", QpackHeaderTable::MatchType::kNameAndValue,
+ ExpectMatch("foo", "bar", QpackEncoderHeaderTable::MatchType::kNameAndValue,
/* expected_is_static = */ false, 0u);
// Inserting second entry evicts the first one.
@@ -291,20 +236,20 @@ TEST_F(QpackHeaderTableTest, EvictByInsertion) {
EXPECT_EQ(1u, dropped_entry_count());
ExpectNoMatch("foo", "bar");
- ExpectMatch("baz", "qux", QpackHeaderTable::MatchType::kNameAndValue,
+ ExpectMatch("baz", "qux", QpackEncoderHeaderTable::MatchType::kNameAndValue,
/* expected_is_static = */ false, 1u);
}
-TEST_F(QpackHeaderTableTest, EvictByUpdateTableSize) {
+TEST_F(QpackEncoderHeaderTableTest, EvictByUpdateTableSize) {
// Entry size is 3 + 3 + 32 = 38.
InsertEntry("foo", "bar");
InsertEntry("baz", "qux");
EXPECT_EQ(2u, inserted_entry_count());
EXPECT_EQ(0u, dropped_entry_count());
- ExpectMatch("foo", "bar", QpackHeaderTable::MatchType::kNameAndValue,
+ ExpectMatch("foo", "bar", QpackEncoderHeaderTable::MatchType::kNameAndValue,
/* expected_is_static = */ false, 0u);
- ExpectMatch("baz", "qux", QpackHeaderTable::MatchType::kNameAndValue,
+ ExpectMatch("baz", "qux", QpackEncoderHeaderTable::MatchType::kNameAndValue,
/* expected_is_static = */ false, 1u);
EXPECT_TRUE(SetDynamicTableCapacity(40));
@@ -312,7 +257,7 @@ TEST_F(QpackHeaderTableTest, EvictByUpdateTableSize) {
EXPECT_EQ(1u, dropped_entry_count());
ExpectNoMatch("foo", "bar");
- ExpectMatch("baz", "qux", QpackHeaderTable::MatchType::kNameAndValue,
+ ExpectMatch("baz", "qux", QpackEncoderHeaderTable::MatchType::kNameAndValue,
/* expected_is_static = */ false, 1u);
EXPECT_TRUE(SetDynamicTableCapacity(20));
@@ -323,7 +268,7 @@ TEST_F(QpackHeaderTableTest, EvictByUpdateTableSize) {
ExpectNoMatch("baz", "qux");
}
-TEST_F(QpackHeaderTableTest, EvictOldestOfIdentical) {
+TEST_F(QpackEncoderHeaderTableTest, EvictOldestOfIdentical) {
EXPECT_TRUE(SetDynamicTableCapacity(80));
// Entry size is 3 + 3 + 32 = 38.
@@ -334,7 +279,7 @@ TEST_F(QpackHeaderTableTest, EvictOldestOfIdentical) {
EXPECT_EQ(0u, dropped_entry_count());
// Find most recently inserted entry.
- ExpectMatch("foo", "bar", QpackHeaderTable::MatchType::kNameAndValue,
+ ExpectMatch("foo", "bar", QpackEncoderHeaderTable::MatchType::kNameAndValue,
/* expected_is_static = */ false, 1u);
// Inserting third entry evicts the first one, not the second.
@@ -342,13 +287,13 @@ TEST_F(QpackHeaderTableTest, EvictOldestOfIdentical) {
EXPECT_EQ(3u, inserted_entry_count());
EXPECT_EQ(1u, dropped_entry_count());
- ExpectMatch("foo", "bar", QpackHeaderTable::MatchType::kNameAndValue,
+ ExpectMatch("foo", "bar", QpackEncoderHeaderTable::MatchType::kNameAndValue,
/* expected_is_static = */ false, 1u);
- ExpectMatch("baz", "qux", QpackHeaderTable::MatchType::kNameAndValue,
+ ExpectMatch("baz", "qux", QpackEncoderHeaderTable::MatchType::kNameAndValue,
/* expected_is_static = */ false, 2u);
}
-TEST_F(QpackHeaderTableTest, EvictOldestOfSameName) {
+TEST_F(QpackEncoderHeaderTableTest, EvictOldestOfSameName) {
EXPECT_TRUE(SetDynamicTableCapacity(80));
// Entry size is 3 + 3 + 32 = 38.
@@ -359,7 +304,7 @@ TEST_F(QpackHeaderTableTest, EvictOldestOfSameName) {
EXPECT_EQ(0u, dropped_entry_count());
// Find most recently inserted entry with matching name.
- ExpectMatch("foo", "foo", QpackHeaderTable::MatchType::kName,
+ ExpectMatch("foo", "foo", QpackEncoderHeaderTable::MatchType::kName,
/* expected_is_static = */ false, 1u);
// Inserting third entry evicts the first one, not the second.
@@ -367,63 +312,276 @@ TEST_F(QpackHeaderTableTest, EvictOldestOfSameName) {
EXPECT_EQ(3u, inserted_entry_count());
EXPECT_EQ(1u, dropped_entry_count());
- ExpectMatch("foo", "foo", QpackHeaderTable::MatchType::kName,
+ ExpectMatch("foo", "foo", QpackEncoderHeaderTable::MatchType::kName,
/* expected_is_static = */ false, 1u);
- ExpectMatch("baz", "qux", QpackHeaderTable::MatchType::kNameAndValue,
+ ExpectMatch("baz", "qux", QpackEncoderHeaderTable::MatchType::kNameAndValue,
/* expected_is_static = */ false, 2u);
}
// Returns the size of the largest entry that could be inserted into the
// dynamic table without evicting entry |index|.
-TEST_F(QpackHeaderTableTest, MaxInsertSizeWithoutEvictingGivenEntry) {
+TEST_F(QpackEncoderHeaderTableTest, MaxInsertSizeWithoutEvictingGivenEntry) {
const uint64_t dynamic_table_capacity = 100;
- QpackHeaderTable table;
- table.SetMaximumDynamicTableCapacity(dynamic_table_capacity);
- EXPECT_TRUE(table.SetDynamicTableCapacity(dynamic_table_capacity));
+ EXPECT_TRUE(SetDynamicTableCapacity(dynamic_table_capacity));
// Empty table can take an entry up to its capacity.
- EXPECT_EQ(dynamic_table_capacity,
- table.MaxInsertSizeWithoutEvictingGivenEntry(0));
+ EXPECT_EQ(dynamic_table_capacity, MaxInsertSizeWithoutEvictingGivenEntry(0));
const uint64_t entry_size1 = QpackEntry::Size("foo", "bar");
- table.InsertEntry("foo", "bar");
+ InsertEntry("foo", "bar");
EXPECT_EQ(dynamic_table_capacity - entry_size1,
- table.MaxInsertSizeWithoutEvictingGivenEntry(0));
+ MaxInsertSizeWithoutEvictingGivenEntry(0));
// Table can take an entry up to its capacity if all entries are allowed to be
// evicted.
- EXPECT_EQ(dynamic_table_capacity,
- table.MaxInsertSizeWithoutEvictingGivenEntry(1));
+ EXPECT_EQ(dynamic_table_capacity, MaxInsertSizeWithoutEvictingGivenEntry(1));
const uint64_t entry_size2 = QpackEntry::Size("baz", "foobar");
- table.InsertEntry("baz", "foobar");
+ InsertEntry("baz", "foobar");
// Table can take an entry up to its capacity if all entries are allowed to be
// evicted.
- EXPECT_EQ(dynamic_table_capacity,
- table.MaxInsertSizeWithoutEvictingGivenEntry(2));
+ EXPECT_EQ(dynamic_table_capacity, MaxInsertSizeWithoutEvictingGivenEntry(2));
// Second entry must stay.
EXPECT_EQ(dynamic_table_capacity - entry_size2,
- table.MaxInsertSizeWithoutEvictingGivenEntry(1));
+ MaxInsertSizeWithoutEvictingGivenEntry(1));
// First and second entry must stay.
EXPECT_EQ(dynamic_table_capacity - entry_size2 - entry_size1,
- table.MaxInsertSizeWithoutEvictingGivenEntry(0));
+ MaxInsertSizeWithoutEvictingGivenEntry(0));
// Third entry evicts first one.
const uint64_t entry_size3 = QpackEntry::Size("last", "entry");
- table.InsertEntry("last", "entry");
- EXPECT_EQ(1u, table.dropped_entry_count());
+ InsertEntry("last", "entry");
+ EXPECT_EQ(1u, dropped_entry_count());
// Table can take an entry up to its capacity if all entries are allowed to be
// evicted.
- EXPECT_EQ(dynamic_table_capacity,
- table.MaxInsertSizeWithoutEvictingGivenEntry(3));
+ EXPECT_EQ(dynamic_table_capacity, MaxInsertSizeWithoutEvictingGivenEntry(3));
// Third entry must stay.
EXPECT_EQ(dynamic_table_capacity - entry_size3,
- table.MaxInsertSizeWithoutEvictingGivenEntry(2));
+ MaxInsertSizeWithoutEvictingGivenEntry(2));
// Second and third entry must stay.
EXPECT_EQ(dynamic_table_capacity - entry_size3 - entry_size2,
- table.MaxInsertSizeWithoutEvictingGivenEntry(1));
+ MaxInsertSizeWithoutEvictingGivenEntry(1));
+}
+
+TEST_F(QpackEncoderHeaderTableTest, DrainingIndex) {
+ EXPECT_TRUE(SetDynamicTableCapacity(4 * QpackEntry::Size("foo", "bar")));
+
+ // Empty table: no draining entry.
+ EXPECT_EQ(0u, draining_index(0.0));
+ EXPECT_EQ(0u, draining_index(1.0));
+
+ // Table with one entry.
+ InsertEntry("foo", "bar");
+ // Any entry can be referenced if none of the table is draining.
+ EXPECT_EQ(0u, draining_index(0.0));
+ // No entry can be referenced if all of the table is draining.
+ EXPECT_EQ(1u, draining_index(1.0));
+
+ // Table with two entries is at half capacity.
+ InsertEntry("foo", "bar");
+ // Any entry can be referenced if at most half of the table is draining,
+ // because current entries only take up half of total capacity.
+ EXPECT_EQ(0u, draining_index(0.0));
+ EXPECT_EQ(0u, draining_index(0.5));
+ // No entry can be referenced if all of the table is draining.
+ EXPECT_EQ(2u, draining_index(1.0));
+
+ // Table with four entries is full.
+ InsertEntry("foo", "bar");
+ InsertEntry("foo", "bar");
+ // Any entry can be referenced if none of the table is draining.
+ EXPECT_EQ(0u, draining_index(0.0));
+ // In a full table with identically sized entries, |draining_fraction| of all
+ // entries are draining.
+ EXPECT_EQ(2u, draining_index(0.5));
+ // No entry can be referenced if all of the table is draining.
+ EXPECT_EQ(4u, draining_index(1.0));
}
-TEST_F(QpackHeaderTableTest, RegisterObserver) {
+class MockObserver : public QpackDecoderHeaderTable::Observer {
+ public:
+ ~MockObserver() override = default;
+
+ MOCK_METHOD(void, OnInsertCountReachedThreshold, (), (override));
+ MOCK_METHOD(void, Cancel, (), (override));
+};
+
+class QpackDecoderHeaderTableTest
+ : public QpackHeaderTableTest<QpackDecoderHeaderTable> {
+ protected:
+ ~QpackDecoderHeaderTableTest() override = default;
+
+ void ExpectEntryAtIndex(bool is_static,
+ uint64_t index,
+ absl::string_view expected_name,
+ absl::string_view expected_value) const {
+ const auto* entry = table_.LookupEntry(is_static, index);
+ ASSERT_TRUE(entry);
+ EXPECT_EQ(expected_name, entry->name());
+ EXPECT_EQ(expected_value, entry->value());
+ }
+
+ void ExpectNoEntryAtIndex(bool is_static, uint64_t index) const {
+ EXPECT_FALSE(table_.LookupEntry(is_static, index));
+ }
+
+ void RegisterObserver(uint64_t required_insert_count,
+ QpackDecoderHeaderTable::Observer* observer) {
+ table_.RegisterObserver(required_insert_count, observer);
+ }
+
+ void UnregisterObserver(uint64_t required_insert_count,
+ QpackDecoderHeaderTable::Observer* observer) {
+ table_.UnregisterObserver(required_insert_count, observer);
+ }
+};
+
+TEST_F(QpackDecoderHeaderTableTest, LookupStaticEntry) {
+ ExpectEntryAtIndex(/* is_static = */ true, 0, ":authority", "");
+
+ ExpectEntryAtIndex(/* is_static = */ true, 1, ":path", "/");
+
+ // 98 is the last entry.
+ ExpectEntryAtIndex(/* is_static = */ true, 98, "x-frame-options",
+ "sameorigin");
+
+ ASSERT_EQ(99u, QpackStaticTableVector().size());
+ ExpectNoEntryAtIndex(/* is_static = */ true, 99);
+}
+
+TEST_F(QpackDecoderHeaderTableTest, InsertAndLookupDynamicEntry) {
+ // Dynamic table is initially entry.
+ ExpectNoEntryAtIndex(/* is_static = */ false, 0);
+ ExpectNoEntryAtIndex(/* is_static = */ false, 1);
+ ExpectNoEntryAtIndex(/* is_static = */ false, 2);
+ ExpectNoEntryAtIndex(/* is_static = */ false, 3);
+
+ // Insert one entry.
+ InsertEntry("foo", "bar");
+
+ ExpectEntryAtIndex(/* is_static = */ false, 0, "foo", "bar");
+
+ ExpectNoEntryAtIndex(/* is_static = */ false, 1);
+ ExpectNoEntryAtIndex(/* is_static = */ false, 2);
+ ExpectNoEntryAtIndex(/* is_static = */ false, 3);
+
+ // Insert a different entry.
+ InsertEntry("baz", "bing");
+
+ ExpectEntryAtIndex(/* is_static = */ false, 0, "foo", "bar");
+
+ ExpectEntryAtIndex(/* is_static = */ false, 1, "baz", "bing");
+
+ ExpectNoEntryAtIndex(/* is_static = */ false, 2);
+ ExpectNoEntryAtIndex(/* is_static = */ false, 3);
+
+ // Insert an entry identical to the most recently inserted one.
+ InsertEntry("baz", "bing");
+
+ ExpectEntryAtIndex(/* is_static = */ false, 0, "foo", "bar");
+
+ ExpectEntryAtIndex(/* is_static = */ false, 1, "baz", "bing");
+
+ ExpectEntryAtIndex(/* is_static = */ false, 2, "baz", "bing");
+
+ ExpectNoEntryAtIndex(/* is_static = */ false, 3);
+}
+
+TEST_F(QpackDecoderHeaderTableTest, EvictByInsertion) {
+ EXPECT_TRUE(SetDynamicTableCapacity(40));
+
+ // Entry size is 3 + 3 + 32 = 38.
+ InsertEntry("foo", "bar");
+ EXPECT_EQ(1u, inserted_entry_count());
+ EXPECT_EQ(0u, dropped_entry_count());
+
+ ExpectEntryAtIndex(/* is_static = */ false, 0u, "foo", "bar");
+
+ // Inserting second entry evicts the first one.
+ InsertEntry("baz", "qux");
+ EXPECT_EQ(2u, inserted_entry_count());
+ EXPECT_EQ(1u, dropped_entry_count());
+
+ ExpectNoEntryAtIndex(/* is_static = */ false, 0u);
+ ExpectEntryAtIndex(/* is_static = */ false, 1u, "baz", "qux");
+}
+
+TEST_F(QpackDecoderHeaderTableTest, EvictByUpdateTableSize) {
+ ExpectNoEntryAtIndex(/* is_static = */ false, 0u);
+ ExpectNoEntryAtIndex(/* is_static = */ false, 1u);
+
+ // Entry size is 3 + 3 + 32 = 38.
+ InsertEntry("foo", "bar");
+ InsertEntry("baz", "qux");
+ EXPECT_EQ(2u, inserted_entry_count());
+ EXPECT_EQ(0u, dropped_entry_count());
+
+ ExpectEntryAtIndex(/* is_static = */ false, 0u, "foo", "bar");
+ ExpectEntryAtIndex(/* is_static = */ false, 1u, "baz", "qux");
+
+ EXPECT_TRUE(SetDynamicTableCapacity(40));
+ EXPECT_EQ(2u, inserted_entry_count());
+ EXPECT_EQ(1u, dropped_entry_count());
+
+ ExpectNoEntryAtIndex(/* is_static = */ false, 0u);
+ ExpectEntryAtIndex(/* is_static = */ false, 1u, "baz", "qux");
+
+ EXPECT_TRUE(SetDynamicTableCapacity(20));
+ EXPECT_EQ(2u, inserted_entry_count());
+ EXPECT_EQ(2u, dropped_entry_count());
+
+ ExpectNoEntryAtIndex(/* is_static = */ false, 0u);
+ ExpectNoEntryAtIndex(/* is_static = */ false, 1u);
+}
+
+TEST_F(QpackDecoderHeaderTableTest, EvictOldestOfIdentical) {
+ EXPECT_TRUE(SetDynamicTableCapacity(80));
+
+ // Entry size is 3 + 3 + 32 = 38.
+ // Insert same entry twice.
+ InsertEntry("foo", "bar");
+ InsertEntry("foo", "bar");
+ EXPECT_EQ(2u, inserted_entry_count());
+ EXPECT_EQ(0u, dropped_entry_count());
+
+ ExpectEntryAtIndex(/* is_static = */ false, 0u, "foo", "bar");
+ ExpectEntryAtIndex(/* is_static = */ false, 1u, "foo", "bar");
+ ExpectNoEntryAtIndex(/* is_static = */ false, 2u);
+
+ // Inserting third entry evicts the first one, not the second.
+ InsertEntry("baz", "qux");
+ EXPECT_EQ(3u, inserted_entry_count());
+ EXPECT_EQ(1u, dropped_entry_count());
+
+ ExpectNoEntryAtIndex(/* is_static = */ false, 0u);
+ ExpectEntryAtIndex(/* is_static = */ false, 1u, "foo", "bar");
+ ExpectEntryAtIndex(/* is_static = */ false, 2u, "baz", "qux");
+}
+
+TEST_F(QpackDecoderHeaderTableTest, EvictOldestOfSameName) {
+ EXPECT_TRUE(SetDynamicTableCapacity(80));
+
+ // Entry size is 3 + 3 + 32 = 38.
+ // Insert two entries with same name but different values.
+ InsertEntry("foo", "bar");
+ InsertEntry("foo", "baz");
+ EXPECT_EQ(2u, inserted_entry_count());
+ EXPECT_EQ(0u, dropped_entry_count());
+
+ ExpectEntryAtIndex(/* is_static = */ false, 0u, "foo", "bar");
+ ExpectEntryAtIndex(/* is_static = */ false, 1u, "foo", "baz");
+ ExpectNoEntryAtIndex(/* is_static = */ false, 2u);
+
+ // Inserting third entry evicts the first one, not the second.
+ InsertEntry("baz", "qux");
+ EXPECT_EQ(3u, inserted_entry_count());
+ EXPECT_EQ(1u, dropped_entry_count());
+
+ ExpectNoEntryAtIndex(/* is_static = */ false, 0u);
+ ExpectEntryAtIndex(/* is_static = */ false, 1u, "foo", "baz");
+ ExpectEntryAtIndex(/* is_static = */ false, 2u, "baz", "qux");
+}
+
+TEST_F(QpackDecoderHeaderTableTest, RegisterObserver) {
StrictMock<MockObserver> observer1;
RegisterObserver(1, &observer1);
EXPECT_CALL(observer1, OnInsertCountReachedThreshold);
@@ -462,7 +620,7 @@ TEST_F(QpackHeaderTableTest, RegisterObserver) {
Mock::VerifyAndClearExpectations(&observer5);
}
-TEST_F(QpackHeaderTableTest, UnregisterObserver) {
+TEST_F(QpackDecoderHeaderTableTest, UnregisterObserver) {
StrictMock<MockObserver> observer1;
StrictMock<MockObserver> observer2;
StrictMock<MockObserver> observer3;
@@ -483,61 +641,15 @@ TEST_F(QpackHeaderTableTest, UnregisterObserver) {
EXPECT_EQ(3u, inserted_entry_count());
}
-TEST_F(QpackHeaderTableTest, DrainingIndex) {
- QpackHeaderTable table;
- table.SetMaximumDynamicTableCapacity(kMaximumDynamicTableCapacityForTesting);
- EXPECT_TRUE(
- table.SetDynamicTableCapacity(4 * QpackEntry::Size("foo", "bar")));
-
- // Empty table: no draining entry.
- EXPECT_EQ(0u, table.draining_index(0.0));
- EXPECT_EQ(0u, table.draining_index(1.0));
-
- // Table with one entry.
- table.InsertEntry("foo", "bar");
- // Any entry can be referenced if none of the table is draining.
- EXPECT_EQ(0u, table.draining_index(0.0));
- // No entry can be referenced if all of the table is draining.
- EXPECT_EQ(1u, table.draining_index(1.0));
-
- // Table with two entries is at half capacity.
- table.InsertEntry("foo", "bar");
- // Any entry can be referenced if at most half of the table is draining,
- // because current entries only take up half of total capacity.
- EXPECT_EQ(0u, table.draining_index(0.0));
- EXPECT_EQ(0u, table.draining_index(0.5));
- // No entry can be referenced if all of the table is draining.
- EXPECT_EQ(2u, table.draining_index(1.0));
-
- // Table with four entries is full.
- table.InsertEntry("foo", "bar");
- table.InsertEntry("foo", "bar");
- // Any entry can be referenced if none of the table is draining.
- EXPECT_EQ(0u, table.draining_index(0.0));
- // In a full table with identically sized entries, |draining_fraction| of all
- // entries are draining.
- EXPECT_EQ(2u, table.draining_index(0.5));
- // No entry can be referenced if all of the table is draining.
- EXPECT_EQ(4u, table.draining_index(1.0));
-}
-
-TEST_F(QpackHeaderTableTest, Cancel) {
+TEST_F(QpackDecoderHeaderTableTest, Cancel) {
StrictMock<MockObserver> observer;
- auto table = std::make_unique<QpackHeaderTable>();
+ auto table = std::make_unique<QpackDecoderHeaderTable>();
table->RegisterObserver(1, &observer);
EXPECT_CALL(observer, Cancel);
table.reset();
}
-TEST_F(QpackHeaderTableTest, EntryFitsDynamicTableCapacity) {
- EXPECT_TRUE(SetDynamicTableCapacity(39));
-
- EXPECT_TRUE(EntryFitsDynamicTableCapacity("foo", "bar"));
- EXPECT_TRUE(EntryFitsDynamicTableCapacity("foo", "bar2"));
- EXPECT_FALSE(EntryFitsDynamicTableCapacity("foo", "bar12"));
-}
-
} // namespace
} // namespace test
} // namespace quic
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 3f68d749f36..b10c1b42d86 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
@@ -12,7 +12,6 @@
#include "quic/platform/api/quic_logging.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/qpack/qpack_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
using ::testing::_;
using ::testing::Eq;
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 36b89bd01ec..c84634b1321 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
@@ -8,7 +8,6 @@
#include "absl/strings/string_view.h"
#include "quic/platform/api/quic_logging.h"
#include "quic/platform/api/quic_test.h"
-#include "common/platform/api/quiche_text_utils.h"
namespace quic {
namespace test {
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 ac07fedff61..3e7d0ad5127 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
@@ -20,7 +20,7 @@ QpackProgressiveDecoder::QpackProgressiveDecoder(
QuicStreamId stream_id,
BlockedStreamLimitEnforcer* enforcer,
DecodingCompletedVisitor* visitor,
- QpackHeaderTable* header_table,
+ QpackDecoderHeaderTable* header_table,
HeadersHandlerInterface* handler)
: stream_id_(stream_id),
prefix_decoder_(
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 e806ea0fd66..ced6bf0c2dd 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
@@ -18,12 +18,12 @@
namespace quic {
-class QpackHeaderTable;
+class QpackDecoderHeaderTable;
// Class to decode a single header block.
class QUIC_EXPORT_PRIVATE QpackProgressiveDecoder
: public QpackInstructionDecoder::Delegate,
- public QpackHeaderTable::Observer {
+ public QpackDecoderHeaderTable::Observer {
public:
// Interface for receiving decoded header block from the decoder.
class QUIC_EXPORT_PRIVATE HeadersHandlerInterface {
@@ -82,7 +82,7 @@ class QUIC_EXPORT_PRIVATE QpackProgressiveDecoder
QpackProgressiveDecoder(QuicStreamId stream_id,
BlockedStreamLimitEnforcer* enforcer,
DecodingCompletedVisitor* visitor,
- QpackHeaderTable* header_table,
+ QpackDecoderHeaderTable* header_table,
HeadersHandlerInterface* handler);
QpackProgressiveDecoder(const QpackProgressiveDecoder&) = delete;
QpackProgressiveDecoder& operator=(const QpackProgressiveDecoder&) = delete;
@@ -103,7 +103,7 @@ class QUIC_EXPORT_PRIVATE QpackProgressiveDecoder
void OnInstructionDecodingError(QpackInstructionDecoder::ErrorCode error_code,
absl::string_view error_message) override;
- // QpackHeaderTable::Observer implementation.
+ // QpackDecoderHeaderTable::Observer implementation.
void OnInsertCountReachedThreshold() override;
void Cancel() override;
@@ -134,7 +134,7 @@ class QUIC_EXPORT_PRIVATE QpackProgressiveDecoder
BlockedStreamLimitEnforcer* const enforcer_;
DecodingCompletedVisitor* const visitor_;
- QpackHeaderTable* const header_table_;
+ QpackDecoderHeaderTable* const header_table_;
HeadersHandlerInterface* const handler_;
// Required Insert Count and Base are decoded from the Header Data Prefix.
@@ -163,7 +163,7 @@ class QUIC_EXPORT_PRIVATE QpackProgressiveDecoder
// True if a decoding error has been detected.
bool error_detected_;
- // True if QpackHeaderTable has been destroyed
+ // True if QpackDecoderHeaderTable has been destroyed
// while decoding is still blocked.
bool cancelled_;
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_chaos_protector.cc b/chromium/net/third_party/quiche/src/quic/core/quic_chaos_protector.cc
new file mode 100644
index 00000000000..4eb353b183d
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_chaos_protector.cc
@@ -0,0 +1,229 @@
+// Copyright (c) 2021 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 "quic/core/quic_chaos_protector.h"
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+#include <memory>
+
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "quic/core/crypto/quic_random.h"
+#include "quic/core/frames/quic_crypto_frame.h"
+#include "quic/core/frames/quic_frame.h"
+#include "quic/core/frames/quic_padding_frame.h"
+#include "quic/core/frames/quic_ping_frame.h"
+#include "quic/core/quic_data_reader.h"
+#include "quic/core/quic_data_writer.h"
+#include "quic/core/quic_framer.h"
+#include "quic/core/quic_packets.h"
+#include "quic/core/quic_stream_frame_data_producer.h"
+#include "quic/platform/api/quic_bug_tracker.h"
+#include "common/platform/api/quiche_logging.h"
+
+namespace quic {
+
+QuicChaosProtector::QuicChaosProtector(const QuicCryptoFrame& crypto_frame,
+ int num_padding_bytes,
+ size_t packet_size,
+ QuicFramer* framer,
+ QuicRandom* random)
+ : packet_size_(packet_size),
+ crypto_data_length_(crypto_frame.data_length),
+ crypto_buffer_offset_(crypto_frame.offset),
+ level_(crypto_frame.level),
+ remaining_padding_bytes_(num_padding_bytes),
+ framer_(framer),
+ random_(random) {
+ QUICHE_DCHECK_NE(framer_, nullptr);
+ QUICHE_DCHECK_NE(framer_->data_producer(), nullptr);
+ QUICHE_DCHECK_NE(random_, nullptr);
+}
+
+QuicChaosProtector::~QuicChaosProtector() {
+ DeleteFrames(&frames_);
+}
+
+absl::optional<size_t> QuicChaosProtector::BuildDataPacket(
+ const QuicPacketHeader& header,
+ char* buffer) {
+ if (!CopyCryptoDataToLocalBuffer()) {
+ return absl::nullopt;
+ }
+ SplitCryptoFrame();
+ AddPingFrames();
+ SpreadPadding();
+ ReorderFrames();
+ return BuildPacket(header, buffer);
+}
+
+WriteStreamDataResult QuicChaosProtector::WriteStreamData(
+ QuicStreamId id,
+ QuicStreamOffset offset,
+ QuicByteCount data_length,
+ QuicDataWriter* /*writer*/) {
+ QUIC_BUG(chaos stream) << "This should never be called; id " << id
+ << " offset " << offset << " data_length "
+ << data_length;
+ return STREAM_MISSING;
+}
+
+bool QuicChaosProtector::WriteCryptoData(EncryptionLevel level,
+ QuicStreamOffset offset,
+ QuicByteCount data_length,
+ QuicDataWriter* writer) {
+ if (level != level_) {
+ QUIC_BUG(chaos bad level) << "Unexpected " << level << " != " << level_;
+ return false;
+ }
+ // This is `offset + data_length > buffer_offset_ + buffer_length_`
+ // but with integer overflow protection.
+ if (offset < crypto_buffer_offset_ || data_length > crypto_data_length_ ||
+ offset - crypto_buffer_offset_ > crypto_data_length_ - data_length) {
+ QUIC_BUG(chaos bad lengths)
+ << "Unexpected buffer_offset_ " << crypto_buffer_offset_ << " offset "
+ << offset << " buffer_length_ " << crypto_data_length_
+ << " data_length " << data_length;
+ return false;
+ }
+ writer->WriteBytes(&crypto_data_buffer_[offset - crypto_buffer_offset_],
+ data_length);
+ return true;
+}
+
+bool QuicChaosProtector::CopyCryptoDataToLocalBuffer() {
+ crypto_frame_buffer_ = std::make_unique<char[]>(packet_size_);
+ frames_.push_back(QuicFrame(
+ new QuicCryptoFrame(level_, crypto_buffer_offset_, crypto_data_length_)));
+ // We use |framer_| to serialize the CRYPTO frame in order to extract its
+ // data from the crypto data producer. This ensures that we reuse the
+ // usual serialization code path, but has the downside that we then need to
+ // parse the offset and length in order to skip over those fields.
+ QuicDataWriter writer(packet_size_, crypto_frame_buffer_.get());
+ if (!framer_->AppendCryptoFrame(*frames_.front().crypto_frame, &writer)) {
+ QUIC_BUG(chaos write crypto data);
+ return false;
+ }
+ QuicDataReader reader(crypto_frame_buffer_.get(), writer.length());
+ uint64_t parsed_offset, parsed_length;
+ if (!reader.ReadVarInt62(&parsed_offset) ||
+ !reader.ReadVarInt62(&parsed_length)) {
+ QUIC_BUG(chaos parse crypto frame);
+ return false;
+ }
+
+ absl::string_view crypto_data = reader.ReadRemainingPayload();
+ crypto_data_buffer_ = crypto_data.data();
+
+ QUICHE_DCHECK_EQ(parsed_offset, crypto_buffer_offset_);
+ QUICHE_DCHECK_EQ(parsed_length, crypto_data_length_);
+ QUICHE_DCHECK_EQ(parsed_length, crypto_data.length());
+
+ return true;
+}
+
+void QuicChaosProtector::SplitCryptoFrame() {
+ const int max_overhead_of_adding_a_crypto_frame =
+ static_cast<int>(QuicFramer::GetMinCryptoFrameSize(
+ crypto_buffer_offset_ + crypto_data_length_, crypto_data_length_));
+ // Pick a random number of CRYPTO frames to add.
+ constexpr uint64_t kMaxAddedCryptoFrames = 10;
+ const uint64_t num_added_crypto_frames =
+ random_->InsecureRandUint64() % (kMaxAddedCryptoFrames + 1);
+ for (uint64_t i = 0; i < num_added_crypto_frames; i++) {
+ if (remaining_padding_bytes_ < max_overhead_of_adding_a_crypto_frame) {
+ break;
+ }
+ // Pick a random frame and split it by shrinking the picked frame and
+ // moving the second half of its data to a new frame that is then appended
+ // to |frames|.
+ size_t frame_to_split_index =
+ random_->InsecureRandUint64() % frames_.size();
+ QuicCryptoFrame* frame_to_split =
+ frames_[frame_to_split_index].crypto_frame;
+ if (frame_to_split->data_length <= 1) {
+ continue;
+ }
+ const int frame_to_split_old_overhead =
+ static_cast<int>(QuicFramer::GetMinCryptoFrameSize(
+ frame_to_split->offset, frame_to_split->data_length));
+ const QuicPacketLength frame_to_split_new_data_length =
+ 1 + (random_->InsecureRandUint64() % (frame_to_split->data_length - 1));
+ const QuicPacketLength new_frame_data_length =
+ frame_to_split->data_length - frame_to_split_new_data_length;
+ const QuicStreamOffset new_frame_offset =
+ frame_to_split->offset + frame_to_split_new_data_length;
+ frame_to_split->data_length -= new_frame_data_length;
+ frames_.push_back(QuicFrame(
+ new QuicCryptoFrame(level_, new_frame_offset, new_frame_data_length)));
+ const int frame_to_split_new_overhead =
+ static_cast<int>(QuicFramer::GetMinCryptoFrameSize(
+ frame_to_split->offset, frame_to_split->data_length));
+ const int new_frame_overhead =
+ static_cast<int>(QuicFramer::GetMinCryptoFrameSize(
+ new_frame_offset, new_frame_data_length));
+ QUICHE_DCHECK_LE(frame_to_split_new_overhead, frame_to_split_old_overhead);
+ // Readjust padding based on increased overhead.
+ remaining_padding_bytes_ -= new_frame_overhead;
+ remaining_padding_bytes_ -= frame_to_split_new_overhead;
+ remaining_padding_bytes_ += frame_to_split_old_overhead;
+ }
+}
+
+void QuicChaosProtector::AddPingFrames() {
+ constexpr uint64_t kMaxAddedPingFrames = 10;
+ const uint64_t num_ping_frames =
+ random_->InsecureRandUint64() %
+ std::min<uint64_t>(kMaxAddedPingFrames, remaining_padding_bytes_);
+ for (uint64_t i = 0; i < num_ping_frames; i++) {
+ frames_.push_back(QuicFrame(QuicPingFrame()));
+ }
+ remaining_padding_bytes_ -= static_cast<int>(num_ping_frames);
+}
+
+void QuicChaosProtector::ReorderFrames() {
+ // Walk the array backwards and swap each frame with a random earlier one.
+ for (size_t i = frames_.size() - 1; i > 0; i--) {
+ std::swap(frames_[i], frames_[random_->InsecureRandUint64() % (i + 1)]);
+ }
+}
+
+void QuicChaosProtector::SpreadPadding() {
+ for (auto it = frames_.begin(); it != frames_.end(); ++it) {
+ const int padding_bytes_in_this_frame =
+ random_->InsecureRandUint64() % (remaining_padding_bytes_ + 1);
+ if (padding_bytes_in_this_frame <= 0) {
+ continue;
+ }
+ it = frames_.insert(
+ it, QuicFrame(QuicPaddingFrame(padding_bytes_in_this_frame)));
+ ++it; // Skip over the padding frame we just added.
+ remaining_padding_bytes_ -= padding_bytes_in_this_frame;
+ }
+ if (remaining_padding_bytes_ > 0) {
+ frames_.push_back(QuicFrame(QuicPaddingFrame(remaining_padding_bytes_)));
+ }
+}
+
+absl::optional<size_t> QuicChaosProtector::BuildPacket(
+ const QuicPacketHeader& header,
+ char* buffer) {
+ QuicStreamFrameDataProducer* original_data_producer =
+ framer_->data_producer();
+ framer_->set_data_producer(this);
+
+ size_t length =
+ framer_->BuildDataPacket(header, frames_, buffer, packet_size_, level_);
+
+ framer_->set_data_producer(original_data_producer);
+ if (length == 0) {
+ return absl::nullopt;
+ }
+ return length;
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_chaos_protector.h b/chromium/net/third_party/quiche/src/quic/core/quic_chaos_protector.h
new file mode 100644
index 00000000000..6bcd42087e7
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_chaos_protector.h
@@ -0,0 +1,99 @@
+// Copyright (c) 2021 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_CHAOS_PROTECTOR_H_
+#define QUICHE_QUIC_CORE_QUIC_CHAOS_PROTECTOR_H_
+
+#include <cstddef>
+#include <memory>
+
+#include "absl/types/optional.h"
+#include "quic/core/crypto/quic_random.h"
+#include "quic/core/frames/quic_crypto_frame.h"
+#include "quic/core/frames/quic_frame.h"
+#include "quic/core/quic_data_writer.h"
+#include "quic/core/quic_framer.h"
+#include "quic/core/quic_packets.h"
+#include "quic/core/quic_stream_frame_data_producer.h"
+#include "quic/core/quic_types.h"
+
+namespace quic {
+
+namespace test {
+class QuicChaosProtectorTest;
+}
+
+// QuicChaosProtector will take a crypto frame and an amount of padding and
+// build a data packet that will parse to something equivalent.
+class QUIC_EXPORT_PRIVATE QuicChaosProtector
+ : public QuicStreamFrameDataProducer {
+ public:
+ // |framer| and |random| must be valid for the lifetime of QuicChaosProtector.
+ explicit QuicChaosProtector(const QuicCryptoFrame& crypto_frame,
+ int num_padding_bytes,
+ size_t packet_size,
+ QuicFramer* framer,
+ QuicRandom* random);
+
+ ~QuicChaosProtector() override;
+
+ QuicChaosProtector(const QuicChaosProtector&) = delete;
+ QuicChaosProtector(QuicChaosProtector&&) = delete;
+ QuicChaosProtector& operator=(const QuicChaosProtector&) = delete;
+ QuicChaosProtector& operator=(QuicChaosProtector&&) = delete;
+
+ // Attempts to build a data packet with chaos protection. If an error occurs,
+ // then absl::nullopt is returned. Otherwise returns the serialized length.
+ absl::optional<size_t> BuildDataPacket(const QuicPacketHeader& header,
+ char* buffer);
+
+ // From QuicStreamFrameDataProducer.
+ WriteStreamDataResult WriteStreamData(QuicStreamId id,
+ QuicStreamOffset offset,
+ QuicByteCount data_length,
+ QuicDataWriter* /*writer*/) override;
+ bool WriteCryptoData(EncryptionLevel level,
+ QuicStreamOffset offset,
+ QuicByteCount data_length,
+ QuicDataWriter* writer) override;
+
+ private:
+ friend class test::QuicChaosProtectorTest;
+
+ // Allocate the crypto data buffer, create the CRYPTO frame and write the
+ // crypto data to our buffer.
+ bool CopyCryptoDataToLocalBuffer();
+
+ // Split the CRYPTO frame in |frames_| into one or more CRYPTO frames that
+ // collectively represent the same data. Adjusts padding to compensate.
+ void SplitCryptoFrame();
+
+ // Add a random number of PING frames to |frames_| and adjust padding.
+ void AddPingFrames();
+
+ // Randomly reorder |frames_|.
+ void ReorderFrames();
+
+ // Add PADDING frames randomly between all other frames.
+ void SpreadPadding();
+
+ // Serialize |frames_| using |framer_|.
+ absl::optional<size_t> BuildPacket(const QuicPacketHeader& header,
+ char* buffer);
+
+ size_t packet_size_;
+ std::unique_ptr<char[]> crypto_frame_buffer_;
+ const char* crypto_data_buffer_ = nullptr;
+ QuicByteCount crypto_data_length_;
+ QuicStreamOffset crypto_buffer_offset_;
+ EncryptionLevel level_;
+ int remaining_padding_bytes_;
+ QuicFrames frames_; // Inner frames owned, will be deleted by destructor.
+ QuicFramer* framer_; // Unowned.
+ QuicRandom* random_; // Unowned.
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_QUIC_CHAOS_PROTECTOR_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_chaos_protector_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_chaos_protector_test.cc
new file mode 100644
index 00000000000..1ec985beea1
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_chaos_protector_test.cc
@@ -0,0 +1,207 @@
+// Copyright (c) 2021 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 "quic/core/quic_chaos_protector.h"
+
+#include <cstddef>
+#include <memory>
+
+#include "absl/strings/string_view.h"
+#include "quic/core/frames/quic_crypto_frame.h"
+#include "quic/core/quic_connection_id.h"
+#include "quic/core/quic_framer.h"
+#include "quic/core/quic_packet_number.h"
+#include "quic/core/quic_packets.h"
+#include "quic/core/quic_stream_frame_data_producer.h"
+#include "quic/core/quic_time.h"
+#include "quic/core/quic_types.h"
+#include "quic/core/quic_versions.h"
+#include "quic/platform/api/quic_test.h"
+#include "quic/test_tools/mock_random.h"
+#include "quic/test_tools/quic_test_utils.h"
+#include "quic/test_tools/simple_quic_framer.h"
+
+namespace quic {
+namespace test {
+
+class QuicChaosProtectorTest : public QuicTestWithParam<ParsedQuicVersion>,
+ public QuicStreamFrameDataProducer {
+ public:
+ QuicChaosProtectorTest()
+ : version_(GetParam()),
+ framer_({version_},
+ QuicTime::Zero(),
+ Perspective::IS_CLIENT,
+ kQuicDefaultConnectionIdLength),
+ validation_framer_({version_}),
+ random_(/*base=*/3),
+ level_(ENCRYPTION_INITIAL),
+ crypto_offset_(0),
+ crypto_data_length_(100),
+ crypto_frame_(level_, crypto_offset_, crypto_data_length_),
+ num_padding_bytes_(50),
+ packet_size_(1000),
+ packet_buffer_(std::make_unique<char[]>(packet_size_)),
+ chaos_protector_(crypto_frame_,
+ num_padding_bytes_,
+ packet_size_,
+ SetupHeaderAndFramers(),
+ &random_) {}
+
+ // From QuicStreamFrameDataProducer.
+ WriteStreamDataResult WriteStreamData(QuicStreamId /*id*/,
+ QuicStreamOffset /*offset*/,
+ QuicByteCount /*data_length*/,
+ QuicDataWriter* /*writer*/) override {
+ ADD_FAILURE() << "This should never be called";
+ return STREAM_MISSING;
+ }
+
+ // From QuicStreamFrameDataProducer.
+ bool WriteCryptoData(EncryptionLevel level,
+ QuicStreamOffset offset,
+ QuicByteCount data_length,
+ QuicDataWriter* writer) override {
+ EXPECT_EQ(level, level);
+ EXPECT_EQ(offset, crypto_offset_);
+ EXPECT_EQ(data_length, crypto_data_length_);
+ for (QuicByteCount i = 0; i < data_length; i++) {
+ EXPECT_TRUE(writer->WriteUInt8(static_cast<uint8_t>(i & 0xFF)));
+ }
+ return true;
+ }
+
+ protected:
+ QuicFramer* SetupHeaderAndFramers() {
+ // Setup header.
+ header_.destination_connection_id = TestConnectionId();
+ header_.destination_connection_id_included = CONNECTION_ID_PRESENT;
+ header_.source_connection_id = EmptyQuicConnectionId();
+ header_.source_connection_id_included = CONNECTION_ID_PRESENT;
+ header_.reset_flag = false;
+ header_.version_flag = true;
+ header_.has_possible_stateless_reset_token = false;
+ header_.packet_number_length = PACKET_4BYTE_PACKET_NUMBER;
+ header_.version = version_;
+ header_.packet_number = QuicPacketNumber(1);
+ header_.form = IETF_QUIC_LONG_HEADER_PACKET;
+ header_.long_packet_type = INITIAL;
+ header_.retry_token_length_length = VARIABLE_LENGTH_INTEGER_LENGTH_1;
+ header_.length_length = kQuicDefaultLongHeaderLengthLength;
+ // Setup validation framer.
+ validation_framer_.framer()->SetInitialObfuscators(
+ header_.destination_connection_id);
+ // Setup framer.
+ framer_.SetInitialObfuscators(header_.destination_connection_id);
+ framer_.set_data_producer(this);
+ return &framer_;
+ }
+
+ void BuildEncryptAndParse() {
+ absl::optional<size_t> length =
+ chaos_protector_.BuildDataPacket(header_, packet_buffer_.get());
+ ASSERT_TRUE(length.has_value());
+ ASSERT_GT(length.value(), 0u);
+ size_t encrypted_length = framer_.EncryptInPlace(
+ level_, header_.packet_number,
+ GetStartOfEncryptedData(framer_.transport_version(), header_),
+ length.value(), packet_size_, packet_buffer_.get());
+ ASSERT_GT(encrypted_length, 0u);
+ ASSERT_TRUE(validation_framer_.ProcessPacket(QuicEncryptedPacket(
+ absl::string_view(packet_buffer_.get(), encrypted_length))));
+ }
+
+ void ResetOffset(QuicStreamOffset offset) {
+ crypto_offset_ = offset;
+ crypto_frame_.offset = offset;
+ chaos_protector_.crypto_buffer_offset_ = offset;
+ }
+
+ ParsedQuicVersion version_;
+ QuicPacketHeader header_;
+ QuicFramer framer_;
+ SimpleQuicFramer validation_framer_;
+ MockRandom random_;
+ EncryptionLevel level_;
+ QuicStreamOffset crypto_offset_;
+ QuicByteCount crypto_data_length_;
+ QuicCryptoFrame crypto_frame_;
+ int num_padding_bytes_;
+ size_t packet_size_;
+ std::unique_ptr<char[]> packet_buffer_;
+ QuicChaosProtector chaos_protector_;
+};
+
+namespace {
+
+ParsedQuicVersionVector TestVersions() {
+ ParsedQuicVersionVector versions;
+ for (const ParsedQuicVersion& version : AllSupportedVersions()) {
+ if (version.UsesCryptoFrames()) {
+ versions.push_back(version);
+ }
+ }
+ return versions;
+}
+
+INSTANTIATE_TEST_SUITE_P(QuicChaosProtectorTests,
+ QuicChaosProtectorTest,
+ ::testing::ValuesIn(TestVersions()),
+ ::testing::PrintToStringParamName());
+
+TEST_P(QuicChaosProtectorTest, Main) {
+ BuildEncryptAndParse();
+ ASSERT_EQ(validation_framer_.crypto_frames().size(), 4u);
+ EXPECT_EQ(validation_framer_.crypto_frames()[0]->offset, 0u);
+ EXPECT_EQ(validation_framer_.crypto_frames()[0]->data_length, 1u);
+ ASSERT_EQ(validation_framer_.ping_frames().size(), 3u);
+ ASSERT_EQ(validation_framer_.padding_frames().size(), 7u);
+ EXPECT_EQ(validation_framer_.padding_frames()[0].num_padding_bytes, 3);
+}
+
+TEST_P(QuicChaosProtectorTest, DifferentRandom) {
+ random_.ResetBase(4);
+ BuildEncryptAndParse();
+ ASSERT_EQ(validation_framer_.crypto_frames().size(), 4u);
+ ASSERT_EQ(validation_framer_.ping_frames().size(), 4u);
+ ASSERT_EQ(validation_framer_.padding_frames().size(), 8u);
+}
+
+TEST_P(QuicChaosProtectorTest, RandomnessZero) {
+ random_.ResetBase(0);
+ BuildEncryptAndParse();
+ ASSERT_EQ(validation_framer_.crypto_frames().size(), 1u);
+ EXPECT_EQ(validation_framer_.crypto_frames()[0]->offset, crypto_offset_);
+ EXPECT_EQ(validation_framer_.crypto_frames()[0]->data_length,
+ crypto_data_length_);
+ ASSERT_EQ(validation_framer_.ping_frames().size(), 0u);
+ ASSERT_EQ(validation_framer_.padding_frames().size(), 1u);
+}
+
+TEST_P(QuicChaosProtectorTest, Offset) {
+ ResetOffset(123);
+ BuildEncryptAndParse();
+ ASSERT_EQ(validation_framer_.crypto_frames().size(), 4u);
+ EXPECT_EQ(validation_framer_.crypto_frames()[0]->offset, crypto_offset_);
+ EXPECT_EQ(validation_framer_.crypto_frames()[0]->data_length, 1u);
+ ASSERT_EQ(validation_framer_.ping_frames().size(), 3u);
+ ASSERT_EQ(validation_framer_.padding_frames().size(), 7u);
+ EXPECT_EQ(validation_framer_.padding_frames()[0].num_padding_bytes, 3);
+}
+
+TEST_P(QuicChaosProtectorTest, OffsetAndRandomnessZero) {
+ ResetOffset(123);
+ random_.ResetBase(0);
+ BuildEncryptAndParse();
+ ASSERT_EQ(validation_framer_.crypto_frames().size(), 1u);
+ EXPECT_EQ(validation_framer_.crypto_frames()[0]->offset, crypto_offset_);
+ EXPECT_EQ(validation_framer_.crypto_frames()[0]->data_length,
+ crypto_data_length_);
+ ASSERT_EQ(validation_framer_.ping_frames().size(), 0u);
+ ASSERT_EQ(validation_framer_.padding_frames().size(), 1u);
+}
+
+} // namespace
+} // namespace test
+} // namespace quic
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 9bd21403263..09806f5a8a8 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
@@ -48,7 +48,7 @@
#include "quic/platform/api/quic_map_util.h"
#include "quic/platform/api/quic_server_stats.h"
#include "quic/platform/api/quic_socket_address.h"
-#include "common/platform/api/quiche_text_utils.h"
+#include "common/quiche_text_utils.h"
namespace quic {
@@ -225,8 +225,8 @@ class ScopedCoalescedPacketClearer {
};
// Whether this incoming packet is allowed to replace our connection ID.
-bool PacketCanReplaceConnectionId(const QuicPacketHeader& header,
- Perspective perspective) {
+bool PacketCanReplaceServerConnectionId(const QuicPacketHeader& header,
+ Perspective perspective) {
return perspective == Perspective::IS_CLIENT &&
header.form == IETF_QUIC_LONG_HEADER_PACKET &&
header.version.IsKnown() &&
@@ -282,7 +282,12 @@ QuicConnection::QuicConnection(
client_connection_id_(EmptyQuicConnectionId()),
client_connection_id_is_set_(false),
direct_peer_address_(initial_peer_address),
- default_path_(initial_self_address, QuicSocketAddress()),
+ default_path_(initial_self_address,
+ QuicSocketAddress(),
+ /*client_connection_id=*/EmptyQuicConnectionId(),
+ server_connection_id,
+ /*stateless_reset_token_received=*/false,
+ /*stateless_reset_token=*/{}),
active_effective_peer_migration_type_(NO_CHANGE),
support_key_update_for_connection_(false),
last_packet_decrypted_(false),
@@ -329,7 +334,7 @@ QuicConnection::QuicConnection(
&arena_)),
visitor_(nullptr),
debug_visitor_(nullptr),
- packet_creator_(server_connection_id_, &framer_, random_generator_, this),
+ packet_creator_(server_connection_id, &framer_, random_generator_, this),
time_of_last_received_packet_(clock_->ApproximateNow()),
sent_packet_manager_(perspective,
clock_,
@@ -370,11 +375,7 @@ QuicConnection::QuicConnection(
encrypted_control_frames_ &&
GetQuicReloadableFlag(quic_use_encryption_level_context)),
path_validator_(alarm_factory_, &arena_, this, random_generator_),
- alternative_path_(QuicSocketAddress(), QuicSocketAddress()),
most_recent_frame_type_(NUM_FRAME_TYPES) {
- QUIC_BUG_IF(quic_bug_12714_1,
- !start_peer_migration_earlier_ && send_path_response_);
-
QUICHE_DCHECK(perspective_ == Perspective::IS_CLIENT ||
default_path_.self_address.IsInitialized());
@@ -384,12 +385,10 @@ QuicConnection::QuicConnection(
support_multiple_connection_ids_ =
version().HasIetfQuicFrames() &&
- framer_.do_not_synthesize_source_cid_for_short_header() &&
- GetQuicRestartFlag(quic_use_reference_counted_sesssion_map) &&
GetQuicRestartFlag(quic_time_wait_list_support_multiple_cid_v2) &&
GetQuicRestartFlag(
quic_dispatcher_support_multiple_cid_per_connection_v2) &&
- GetQuicReloadableFlag(quic_connection_support_multiple_cids_v2);
+ GetQuicReloadableFlag(quic_connection_support_multiple_cids_v4);
QUIC_DLOG(INFO) << ENDPOINT << "Created connection with server connection ID "
<< server_connection_id
@@ -418,7 +417,7 @@ QuicConnection::QuicConnection(
MaybeEnableMultiplePacketNumberSpacesSupport();
QUICHE_DCHECK(perspective_ == Perspective::IS_CLIENT ||
supported_versions.size() == 1);
- InstallInitialCrypters(server_connection_id_);
+ InstallInitialCrypters(ServerConnectionId());
// On the server side, version negotiation has been done by the dispatcher,
// and the server connection is created with the right version.
@@ -449,6 +448,7 @@ void QuicConnection::InstallInitialCrypters(QuicConnectionId connection_id) {
}
QuicConnection::~QuicConnection() {
+ QUICHE_DCHECK_GE(stats_.max_egress_mtu, long_term_mtu_);
if (owns_writer_) {
delete writer_;
}
@@ -482,9 +482,9 @@ bool QuicConnection::ValidateConfigConnectionIds(const QuicConfig& config) {
// Validate initial_source_connection_id.
QuicConnectionId expected_initial_source_connection_id;
if (perspective_ == Perspective::IS_CLIENT) {
- expected_initial_source_connection_id = server_connection_id_;
+ expected_initial_source_connection_id = ServerConnectionId();
} else {
- expected_initial_source_connection_id = client_connection_id_;
+ expected_initial_source_connection_id = ClientConnectionId();
}
if (!config.HasReceivedInitialSourceConnectionId() ||
config.ReceivedInitialSourceConnectionId() !=
@@ -585,6 +585,9 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) {
} else {
SetNetworkTimeouts(config.max_time_before_crypto_handshake(),
config.max_idle_time_before_crypto_handshake());
+ if (config.HasClientRequestedIndependentOption(kCHSP, perspective_)) {
+ packet_creator_.set_chaos_protection_enabled(true);
+ }
}
if (support_multiple_connection_ids_ &&
@@ -679,8 +682,14 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) {
no_stop_waiting_frames_ = true;
}
if (config.HasReceivedStatelessResetToken()) {
- stateless_reset_token_received_ = true;
- received_stateless_reset_token_ = config.ReceivedStatelessResetToken();
+ if (use_connection_id_on_default_path_) {
+ default_path_.stateless_reset_token_received = true;
+ default_path_.stateless_reset_token =
+ config.ReceivedStatelessResetToken();
+ } else {
+ stateless_reset_token_received_ = true;
+ received_stateless_reset_token_ = config.ReceivedStatelessResetToken();
+ }
}
if (config.HasReceivedAckDelayExponent()) {
framer_.set_peer_ack_delay_exponent(config.ReceivedAckDelayExponent());
@@ -704,6 +713,17 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) {
QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path3, 6, 6);
validate_client_addresses_ = true;
}
+ // Having connection_migration_use_new_cid_ depends on the same set of flags
+ // and connection option on both client and server sides has the advantage of:
+ // 1) Less chance of skew in using new connection ID or not between client
+ // and server in unit tests with random flag combinations.
+ // 2) Client side's rollout can be protected by the same connection option.
+ connection_migration_use_new_cid_ =
+ support_multiple_connection_ids_ && validate_client_addresses_ &&
+ use_connection_id_on_default_path_ &&
+ group_path_response_and_challenge_sending_closer_ &&
+ GetQuicReloadableFlag(quic_drop_unsent_path_response) &&
+ GetQuicReloadableFlag(quic_connection_migration_use_new_cid_v2);
if (config.HasReceivedMaxPacketSize()) {
peer_max_packet_size_ = config.ReceivedMaxPacketSize();
MaybeUpdatePacketCreatorMaxPacketLengthAndPadding();
@@ -865,7 +885,7 @@ void QuicConnection::OnPublicResetPacket(const QuicPublicResetPacket& packet) {
// Check that any public reset packet with a different connection ID that was
// routed to this QuicConnection has been redirected before control reaches
// here. (Check for a bug regression.)
- QUICHE_DCHECK_EQ(server_connection_id_, packet.connection_id);
+ QUICHE_DCHECK_EQ(ServerConnectionId(), packet.connection_id);
QUICHE_DCHECK_EQ(perspective_, Perspective::IS_CLIENT);
QUICHE_DCHECK(!version().HasIetfInvariantHeader());
if (debug_visitor_ != nullptr) {
@@ -903,7 +923,7 @@ void QuicConnection::OnVersionNegotiationPacket(
// Check that any public reset packet with a different connection ID that was
// routed to this QuicConnection has been redirected before control reaches
// here. (Check for a bug regression.)
- QUICHE_DCHECK_EQ(server_connection_id_, packet.connection_id);
+ QUICHE_DCHECK_EQ(ServerConnectionId(), packet.connection_id);
if (perspective_ == Perspective::IS_SERVER) {
const std::string error_details =
"Server received version negotiation packet.";
@@ -954,17 +974,17 @@ void QuicConnection::OnRetryPacket(QuicConnectionId original_connection_id,
absl::string_view retry_without_tag) {
QUICHE_DCHECK_EQ(Perspective::IS_CLIENT, perspective_);
if (version().UsesTls()) {
- if (!CryptoUtils::ValidateRetryIntegrityTag(
- version(), server_connection_id_, retry_without_tag,
- retry_integrity_tag)) {
+ if (!CryptoUtils::ValidateRetryIntegrityTag(version(), ServerConnectionId(),
+ retry_without_tag,
+ retry_integrity_tag)) {
QUIC_DLOG(ERROR) << "Ignoring RETRY with invalid integrity tag";
return;
}
} else {
- if (original_connection_id != server_connection_id_) {
+ if (original_connection_id != ServerConnectionId()) {
QUIC_DLOG(ERROR) << "Ignoring RETRY with original connection ID "
<< original_connection_id << " not matching expected "
- << server_connection_id_ << " token "
+ << ServerConnectionId() << " token "
<< absl::BytesToHexString(retry_token);
return;
}
@@ -972,10 +992,10 @@ void QuicConnection::OnRetryPacket(QuicConnectionId original_connection_id,
framer_.set_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
+ << ServerConnectionId() << " with " << new_connection_id
<< ", received token " << absl::BytesToHexString(retry_token);
if (!original_destination_connection_id_.has_value()) {
- original_destination_connection_id_ = server_connection_id_;
+ original_destination_connection_id_ = ServerConnectionId();
}
QUICHE_DCHECK(!retry_source_connection_id_.has_value())
<< retry_source_connection_id_.value();
@@ -984,12 +1004,18 @@ void QuicConnection::OnRetryPacket(QuicConnectionId original_connection_id,
packet_creator_.SetRetryToken(retry_token);
// Reinstall initial crypters because the connection ID changed.
- InstallInitialCrypters(server_connection_id_);
+ InstallInitialCrypters(ServerConnectionId());
sent_packet_manager_.MarkInitialPacketsForRetransmission();
}
-bool QuicConnection::HasIncomingConnectionId(QuicConnectionId connection_id) {
+bool QuicConnection::HasIncomingConnectionId(
+ QuicConnectionId connection_id) const {
+ if (quic_deprecate_incoming_connection_ids_) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_deprecate_incoming_connection_ids);
+ // TODO(haoyuewang) Inline this after the flag is deprecated.
+ return connection_id == original_destination_connection_id_;
+ }
for (QuicConnectionId const& incoming_connection_id :
incoming_connection_ids_) {
if (incoming_connection_id == connection_id) {
@@ -1004,54 +1030,89 @@ void QuicConnection::SetOriginalDestinationConnectionId(
QUIC_DLOG(INFO) << "Setting original_destination_connection_id to "
<< original_destination_connection_id
<< " on connection with server_connection_id "
- << server_connection_id_;
- QUICHE_DCHECK_NE(original_destination_connection_id, server_connection_id_);
- if (!HasIncomingConnectionId(original_destination_connection_id)) {
- incoming_connection_ids_.push_back(original_destination_connection_id);
+ << ServerConnectionId();
+ QUICHE_DCHECK_NE(original_destination_connection_id, ServerConnectionId());
+ if (!quic_deprecate_incoming_connection_ids_) {
+ if (!HasIncomingConnectionId(original_destination_connection_id)) {
+ incoming_connection_ids_.push_back(original_destination_connection_id);
+ }
}
InstallInitialCrypters(original_destination_connection_id);
QUICHE_DCHECK(!original_destination_connection_id_.has_value())
<< original_destination_connection_id_.value();
original_destination_connection_id_ = original_destination_connection_id;
+ original_destination_connection_id_replacement_ = ServerConnectionId();
}
QuicConnectionId QuicConnection::GetOriginalDestinationConnectionId() {
if (original_destination_connection_id_.has_value()) {
return original_destination_connection_id_.value();
}
- return server_connection_id_;
+ return ServerConnectionId();
+}
+
+bool QuicConnection::ValidateServerConnectionId(
+ const QuicPacketHeader& header) const {
+ if (perspective_ == Perspective::IS_CLIENT &&
+ header.form == IETF_QUIC_SHORT_HEADER_PACKET) {
+ return true;
+ }
+
+ QuicConnectionId server_connection_id =
+ GetServerConnectionIdAsRecipient(header, perspective_);
+
+ if (server_connection_id == ServerConnectionId() ||
+ HasIncomingConnectionId(server_connection_id)) {
+ return true;
+ }
+
+ if (PacketCanReplaceServerConnectionId(header, perspective_)) {
+ QUIC_DLOG(INFO) << ENDPOINT << "Accepting packet with new connection ID "
+ << server_connection_id << " instead of "
+ << ServerConnectionId();
+ return true;
+ }
+
+ if (connection_migration_use_new_cid_ &&
+ perspective_ == Perspective::IS_SERVER &&
+ self_issued_cid_manager_ != nullptr &&
+ self_issued_cid_manager_->IsConnectionIdInUse(server_connection_id)) {
+ return true;
+ }
+
+ return false;
}
bool QuicConnection::OnUnauthenticatedPublicHeader(
const QuicPacketHeader& header) {
+ last_packet_destination_connection_id_ = header.destination_connection_id;
+ // If last packet destination connection ID is the original server
+ // connection ID chosen by client, replaces it with the connection ID chosen
+ // by server.
+ if (use_connection_id_on_default_path_ &&
+ perspective_ == Perspective::IS_SERVER &&
+ original_destination_connection_id_.has_value() &&
+ last_packet_destination_connection_id_ ==
+ *original_destination_connection_id_) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_connection_id_on_default_path_v2, 3,
+ 3);
+ last_packet_destination_connection_id_ =
+ original_destination_connection_id_replacement_;
+ }
+
// As soon as we receive an initial we start ignoring subsequent retries.
if (header.version_flag && header.long_packet_type == INITIAL) {
framer_.set_drop_incoming_retry_packets(true);
}
- bool skip_server_connection_id_validation =
- framer_.do_not_synthesize_source_cid_for_short_header() &&
- perspective_ == Perspective::IS_CLIENT &&
- header.form == IETF_QUIC_SHORT_HEADER_PACKET;
-
- QuicConnectionId server_connection_id =
- GetServerConnectionIdAsRecipient(header, perspective_);
-
- if (!skip_server_connection_id_validation &&
- server_connection_id != server_connection_id_ &&
- !HasIncomingConnectionId(server_connection_id)) {
- if (PacketCanReplaceConnectionId(header, perspective_)) {
- QUIC_DLOG(INFO) << ENDPOINT << "Accepting packet with new connection ID "
- << server_connection_id << " instead of "
- << server_connection_id_;
- return true;
- }
-
+ if (!ValidateServerConnectionId(header)) {
++stats_.packets_dropped;
+ QuicConnectionId server_connection_id =
+ GetServerConnectionIdAsRecipient(header, perspective_);
QUIC_DLOG(INFO) << ENDPOINT
<< "Ignoring packet from unexpected server connection ID "
<< server_connection_id << " instead of "
- << server_connection_id_;
+ << ServerConnectionId();
if (debug_visitor_ != nullptr) {
debug_visitor_->OnIncorrectConnectionId(server_connection_id);
}
@@ -1066,18 +1127,15 @@ bool QuicConnection::OnUnauthenticatedPublicHeader(
return true;
}
- if (framer_.do_not_synthesize_source_cid_for_short_header() &&
- perspective_ == Perspective::IS_SERVER &&
+ if (perspective_ == Perspective::IS_SERVER &&
header.form == IETF_QUIC_SHORT_HEADER_PACKET) {
- QUIC_RELOADABLE_FLAG_COUNT_N(
- quic_do_not_synthesize_source_cid_for_short_header, 3, 3);
return true;
}
QuicConnectionId client_connection_id =
GetClientConnectionIdAsRecipient(header, perspective_);
- if (client_connection_id == client_connection_id_) {
+ if (client_connection_id == ClientConnectionId()) {
return true;
}
@@ -1089,11 +1147,18 @@ bool QuicConnection::OnUnauthenticatedPublicHeader(
return true;
}
+ if (connection_migration_use_new_cid_ &&
+ perspective_ == Perspective::IS_CLIENT &&
+ self_issued_cid_manager_ != nullptr &&
+ self_issued_cid_manager_->IsConnectionIdInUse(client_connection_id)) {
+ return true;
+ }
+
++stats_.packets_dropped;
QUIC_DLOG(INFO) << ENDPOINT
<< "Ignoring packet from unexpected client connection ID "
<< client_connection_id << " instead of "
- << client_connection_id_;
+ << ClientConnectionId();
return false;
}
@@ -1102,17 +1167,8 @@ bool QuicConnection::OnUnauthenticatedHeader(const QuicPacketHeader& header) {
debug_visitor_->OnUnauthenticatedHeader(header);
}
- // Check that any public reset packet with a different connection ID that was
- // routed to this QuicConnection has been redirected before control reaches
- // here.
- QUICHE_DCHECK((framer_.do_not_synthesize_source_cid_for_short_header() &&
- perspective_ == Perspective::IS_CLIENT &&
- header.form == IETF_QUIC_SHORT_HEADER_PACKET) ||
- GetServerConnectionIdAsRecipient(header, perspective_) ==
- server_connection_id_ ||
- HasIncomingConnectionId(
- GetServerConnectionIdAsRecipient(header, perspective_)) ||
- PacketCanReplaceConnectionId(header, perspective_));
+ // Sanity check on the server connection ID in header.
+ QUICHE_DCHECK(ValidateServerConnectionId(header));
if (packet_creator_.HasPendingFrames()) {
// Incoming packets may change a queued ACK frame.
@@ -1264,6 +1320,43 @@ bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) {
default_path_.peer_address,
GetEffectivePeerAddressFromCurrentPacket());
+ if (connection_migration_use_new_cid_) {
+ auto effective_peer_address = GetEffectivePeerAddressFromCurrentPacket();
+ // Since server does not send new connection ID to client before handshake
+ // completion and source connection ID is omitted in short header packet,
+ // the server_connection_id on PathState on the server side does not
+ // affect the packets server writes after handshake completion. On the
+ // other hand, it is still desirable to have the "correct" server
+ // connection ID set on path.
+ // 1) If client uses 1 unique server connection ID per path and the packet
+ // is received from an existing path, then
+ // last_packet_destination_connection_id_ will always be the same as the
+ // server connection ID on path. Server side will maintain the 1-to-1
+ // mapping from server connection ID to path.
+ // 2) If client uses multiple server connection IDs on the same path,
+ // compared to the server_connection_id on path,
+ // last_packet_destination_connection_id_ has the advantage that it is
+ // still present in the session map since the packet can be routed here
+ // regardless of packet reordering.
+ if (IsDefaultPath(last_packet_destination_address_,
+ effective_peer_address)) {
+ default_path_.server_connection_id =
+ last_packet_destination_connection_id_;
+ } else if (IsAlternativePath(last_packet_destination_address_,
+ effective_peer_address)) {
+ alternative_path_.server_connection_id =
+ last_packet_destination_connection_id_;
+ }
+ }
+
+ if (use_connection_id_on_default_path_ &&
+ last_packet_destination_connection_id_ != ServerConnectionId() &&
+ (!original_destination_connection_id_.has_value() ||
+ last_packet_destination_connection_id_ !=
+ *original_destination_connection_id_)) {
+ QUIC_CODE_COUNT(quic_connection_id_change);
+ }
+
QUIC_DLOG_IF(INFO, current_effective_peer_migration_type_ != NO_CHANGE)
<< ENDPOINT << "Effective peer's ip:port changed from "
<< default_path_.peer_address.ToString() << " to "
@@ -1284,17 +1377,13 @@ bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) {
uber_received_packet_manager_.RecordPacketReceived(
last_decrypted_packet_level_, last_header_,
idle_network_detector_.time_of_last_received_packet());
- if (GetQuicReloadableFlag(quic_enable_token_based_address_validation)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_token_based_address_validation, 2,
- 2);
- if (EnforceAntiAmplificationLimit() && !IsHandshakeConfirmed() &&
- !header.retry_token.empty() &&
- visitor_->ValidateToken(header.retry_token)) {
- QUIC_DLOG(INFO) << ENDPOINT << "Address validated via token.";
- QUIC_CODE_COUNT(quic_address_validated_via_token);
- default_path_.validated = true;
- stats_.address_validated_via_token = true;
- }
+ if (EnforceAntiAmplificationLimit() && !IsHandshakeConfirmed() &&
+ !header.retry_token.empty() &&
+ visitor_->ValidateToken(header.retry_token)) {
+ QUIC_DLOG(INFO) << ENDPOINT << "Address validated via token.";
+ QUIC_CODE_COUNT(quic_address_validated_via_token);
+ default_path_.validated = true;
+ stats_.address_validated_via_token = true;
}
QUICHE_DCHECK(connected_);
return true;
@@ -1684,8 +1773,12 @@ bool QuicConnection::OnPathChallengeFrame(const QuicPathChallengeFrame& frame) {
// PATH_RESPONSE. This context needs to be out of scope before returning.
// TODO(danzh) inline OnPathChallengeFrameInternal() once
// support_reverse_path_validation_ is deprecated.
- QuicPacketCreator::ScopedPeerAddressContext context(
- &packet_creator_, last_packet_source_address_);
+ auto context =
+ group_path_response_and_challenge_sending_closer_
+ ? nullptr
+ : std::make_unique<QuicPacketCreator::ScopedPeerAddressContext>(
+ &packet_creator_, last_packet_source_address_,
+ /*update_connection_id=*/false);
if (!OnPathChallengeFrameInternal(frame)) {
return false;
}
@@ -1695,6 +1788,7 @@ bool QuicConnection::OnPathChallengeFrame(const QuicPathChallengeFrame& frame) {
bool QuicConnection::OnPathChallengeFrameInternal(
const QuicPathChallengeFrame& frame) {
+ should_proactively_validate_peer_address_on_path_challenge_ = false;
// UpdatePacketContent() may start reverse path validation.
if (!UpdatePacketContent(PATH_CHALLENGE_FRAME)) {
return false;
@@ -1703,6 +1797,35 @@ bool QuicConnection::OnPathChallengeFrameInternal(
debug_visitor_->OnPathChallengeFrame(frame);
}
+ std::unique_ptr<QuicPacketCreator::ScopedPeerAddressContext> context;
+ const QuicSocketAddress current_effective_peer_address =
+ GetEffectivePeerAddressFromCurrentPacket();
+ if (group_path_response_and_challenge_sending_closer_) {
+ QuicConnectionId client_cid, server_cid;
+ FindOnPathConnectionIds(last_packet_destination_address_,
+ current_effective_peer_address, &client_cid,
+ &server_cid);
+ context = std::make_unique<QuicPacketCreator::ScopedPeerAddressContext>(
+ &packet_creator_, last_packet_source_address_, client_cid, server_cid,
+ connection_migration_use_new_cid_);
+ }
+ if (should_proactively_validate_peer_address_on_path_challenge_) {
+ QUIC_RELOADABLE_FLAG_COUNT(
+ quic_group_path_response_and_challenge_sending_closer);
+ // Conditions to proactively validate peer address:
+ // The perspective is server
+ // The PATH_CHALLENGE is received on an unvalidated alternative path.
+ // The connection isn't validating migrated peer address, which is of
+ // higher prority.
+ QUIC_DVLOG(1) << "Proactively validate the effective peer address "
+ << current_effective_peer_address;
+ QUIC_CODE_COUNT_N(quic_kick_off_client_address_validation, 2, 6);
+ ValidatePath(std::make_unique<ReversePathValidationContext>(
+ default_path_.self_address, last_packet_source_address_,
+ current_effective_peer_address, this),
+ std::make_unique<ReversePathValidationResultDelegate>(
+ this, peer_address()));
+ }
if (!send_path_response_) {
// Save the path challenge's payload, for later use in generating the
// response.
@@ -1717,10 +1840,19 @@ bool QuicConnection::OnPathChallengeFrameInternal(
// Queue or send PATH_RESPONSE. Send PATH_RESPONSE to the source address of
// the current incoming packet, even if it's not the default path or the
// alternative path.
- if (!SendPathResponse(frame.data_buffer, last_packet_source_address_)) {
- // Queue the payloads to re-try later.
- pending_path_challenge_payloads_.push_back(
- {frame.data_buffer, last_packet_source_address_});
+ const bool success =
+ SendPathResponse(frame.data_buffer, last_packet_source_address_,
+ current_effective_peer_address);
+ if (GetQuicReloadableFlag(quic_drop_unsent_path_response)) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_drop_unsent_path_response);
+ }
+ if (!success) {
+ QUIC_CODE_COUNT(quic_failed_to_send_path_response);
+ if (!GetQuicReloadableFlag(quic_drop_unsent_path_response)) {
+ // Queue the payloads to re-try later.
+ pending_path_challenge_payloads_.push_back(
+ {frame.data_buffer, last_packet_source_address_});
+ }
}
// TODO(b/150095588): change the stats to
// num_valid_path_challenge_received.
@@ -1885,6 +2017,39 @@ bool QuicConnection::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) {
return connected_;
}
+void QuicConnection::OnClientConnectionIdAvailable() {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 3, 5);
+ QUICHE_DCHECK(perspective_ == Perspective::IS_SERVER);
+ if (!peer_issued_cid_manager_->HasUnusedConnectionId()) {
+ return;
+ }
+ if (default_path_.client_connection_id.IsEmpty()) {
+ const QuicConnectionIdData* unused_cid_data =
+ peer_issued_cid_manager_->ConsumeOneUnusedConnectionId();
+ QUIC_DVLOG(1) << ENDPOINT << "Patch connection ID "
+ << unused_cid_data->connection_id << " to default path";
+ default_path_.client_connection_id = unused_cid_data->connection_id;
+ default_path_.stateless_reset_token_received = true;
+ default_path_.stateless_reset_token =
+ unused_cid_data->stateless_reset_token;
+ QUICHE_DCHECK(!packet_creator_.HasPendingFrames());
+ QUICHE_DCHECK(packet_creator_.GetDestinationConnectionId().IsEmpty());
+ packet_creator_.SetClientConnectionId(default_path_.client_connection_id);
+ return;
+ }
+ if (alternative_path_.peer_address.IsInitialized() &&
+ alternative_path_.client_connection_id.IsEmpty()) {
+ const QuicConnectionIdData* unused_cid_data =
+ peer_issued_cid_manager_->ConsumeOneUnusedConnectionId();
+ QUIC_DVLOG(1) << ENDPOINT << "Patch connection ID "
+ << unused_cid_data->connection_id << " to alternative path";
+ alternative_path_.client_connection_id = unused_cid_data->connection_id;
+ alternative_path_.stateless_reset_token_received = true;
+ alternative_path_.stateless_reset_token =
+ unused_cid_data->stateless_reset_token;
+ }
+}
+
bool QuicConnection::OnNewConnectionIdFrameInner(
const QuicNewConnectionIdFrame& frame) {
QUICHE_DCHECK(support_multiple_connection_ids_);
@@ -1903,7 +2068,11 @@ bool QuicConnection::OnNewConnectionIdFrameInner(
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return false;
}
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_support_multiple_cids_v2, 1, 2);
+ if (use_connection_id_on_default_path_ &&
+ perspective_ == Perspective::IS_SERVER) {
+ OnClientConnectionIdAvailable();
+ }
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_support_multiple_cids_v4, 1, 2);
return true;
}
@@ -1939,6 +2108,11 @@ bool QuicConnection::OnRetireConnectionIdFrame(
if (debug_visitor_ != nullptr) {
debug_visitor_->OnRetireConnectionIdFrame(frame);
}
+ if (use_connection_id_on_default_path_ &&
+ !connection_migration_use_new_cid_) {
+ // Do not respond to RetireConnectionId frame.
+ return true;
+ }
if (!support_multiple_connection_ids_) {
return true;
}
@@ -1957,7 +2131,7 @@ bool QuicConnection::OnRetireConnectionIdFrame(
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return false;
}
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_support_multiple_cids_v2, 2, 2);
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_support_multiple_cids_v4, 2, 2);
return true;
}
@@ -1972,17 +2146,14 @@ bool QuicConnection::OnNewTokenFrame(const QuicNewTokenFrame& frame) {
if (debug_visitor_ != nullptr) {
debug_visitor_->OnNewTokenFrame(frame);
}
- if (GetQuicReloadableFlag(quic_enable_token_based_address_validation)) {
- if (perspective_ == Perspective::IS_SERVER) {
- CloseConnection(QUIC_INVALID_NEW_TOKEN,
- "Server received new token frame.",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- return false;
- }
- // NEW_TOKEN frame should insitgate ACKs.
- MaybeUpdateAckTimeout();
- visitor_->OnNewTokenReceived(frame.token);
+ if (perspective_ == Perspective::IS_SERVER) {
+ CloseConnection(QUIC_INVALID_NEW_TOKEN, "Server received new token frame.",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
}
+ // NEW_TOKEN frame should insitgate ACKs.
+ MaybeUpdateAckTimeout();
+ visitor_->OnNewTokenReceived(frame.token);
return true;
}
@@ -2181,21 +2352,14 @@ void QuicConnection::MaybeRespondToConnectivityProbingOrMigration() {
return;
}
}
- // Server starts to migrate connection upon receiving of non-probing packet
- // from a new peer address.
- if (!start_peer_migration_earlier_ &&
- 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_);
- }
- }
}
bool QuicConnection::IsValidStatelessResetToken(
const StatelessResetToken& token) const {
+ if (use_connection_id_on_default_path_) {
+ return default_path_.stateless_reset_token_received &&
+ token == default_path_.stateless_reset_token;
+ }
return stateless_reset_token_received_ &&
token == received_stateless_reset_token_;
}
@@ -2280,23 +2444,13 @@ void QuicConnection::ClearLastFrames() {
}
void QuicConnection::CloseIfTooManyOutstandingSentPackets() {
- bool should_close;
- if (GetQuicReloadableFlag(
- quic_close_connection_with_too_many_outstanding_packets)) {
- QUIC_RELOADABLE_FLAG_COUNT(
- quic_close_connection_with_too_many_outstanding_packets);
- should_close =
- sent_packet_manager_.GetLargestSentPacket().IsInitialized() &&
- sent_packet_manager_.GetLargestSentPacket() >
- sent_packet_manager_.GetLeastUnacked() + max_tracked_packets_;
- } else {
- should_close =
- sent_packet_manager_.GetLargestObserved().IsInitialized() &&
- sent_packet_manager_.GetLargestObserved() >
- sent_packet_manager_.GetLeastUnacked() + max_tracked_packets_;
- }
// This occurs if we don't discard old packets we've seen fast enough. It's
// possible largest observed is less than leaset unacked.
+ const bool should_close =
+ sent_packet_manager_.GetLargestSentPacket().IsInitialized() &&
+ sent_packet_manager_.GetLargestSentPacket() >
+ sent_packet_manager_.GetLeastUnacked() + max_tracked_packets_;
+
if (should_close) {
CloseConnection(
QUIC_TOO_MANY_OUTSTANDING_SENT_PACKETS,
@@ -2414,18 +2568,23 @@ QuicConsumedData QuicConnection::SendStreamData(QuicStreamId id,
QuicUtils::IsCryptoStreamId(transport_version(), id)) {
MaybeActivateLegacyVersionEncapsulation();
}
- if (GetQuicReloadableFlag(quic_preempt_stream_data_with_handshake_packet) &&
- perspective_ == Perspective::IS_SERVER &&
+ if (perspective_ == Perspective::IS_SERVER &&
version().CanSendCoalescedPackets() && !IsHandshakeConfirmed()) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_preempt_stream_data_with_handshake_packet,
- 1, 2);
+ if (GetQuicReloadableFlag(quic_donot_pto_half_rtt_data)) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_donot_pto_half_rtt_data);
+ if (in_on_retransmission_time_out_ &&
+ coalesced_packet_.NumberOfPackets() == 0u) {
+ // PTO fires while handshake is not confirmed. Do not preempt handshake
+ // data with stream data.
+ QUIC_CODE_COUNT(quic_try_to_send_half_rtt_data_when_pto_fires);
+ return QuicConsumedData(0, false);
+ }
+ }
if (coalesced_packet_.ContainsPacketOfEncryptionLevel(ENCRYPTION_INITIAL) &&
coalesced_packet_.NumberOfPackets() == 1u) {
// Handshake is not confirmed yet, if there is only an initial packet in
// the coalescer, try to bundle an ENCRYPTION_HANDSHAKE packet before
// sending stream data.
- QUIC_RELOADABLE_FLAG_COUNT_N(
- quic_preempt_stream_data_with_handshake_packet, 2, 2);
sent_packet_manager_.RetransmitDataOfSpaceIfAny(HANDSHAKE_DATA);
}
}
@@ -2510,8 +2669,8 @@ const QuicConnectionStats& QuicConnection::GetStats() {
stats_.estimated_bandwidth = sent_packet_manager_.BandwidthEstimate();
sent_packet_manager_.GetSendAlgorithm()->PopulateConnectionStats(&stats_);
- stats_.max_packet_size = packet_creator_.max_packet_length();
- stats_.max_received_packet_size = largest_received_packet_size_;
+ stats_.egress_mtu = long_term_mtu_;
+ stats_.ingress_mtu = largest_received_packet_size_;
return stats_;
}
@@ -2745,6 +2904,7 @@ void QuicConnection::ProcessUdpPacket(const QuicSocketAddress& self_address,
MaybeSendInResponseToPacket();
}
SetPingAlarm();
+ RetirePeerIssuedConnectionIdsNoLongerOnPath();
current_packet_data_ = nullptr;
is_current_packet_connectivity_probing_ = false;
}
@@ -2789,8 +2949,12 @@ void QuicConnection::OnCanWrite() {
QUIC_RELOADABLE_FLAG_COUNT_N(quic_send_path_response2, 4, 5);
const PendingPathChallenge& pending_path_challenge =
pending_path_challenge_payloads_.front();
+ // Note connection_migration_use_cid_ will depends on
+ // quic_drop_unsent_path_response flag eventually, and hence the empty
+ // effective_peer_address here will not be used.
if (!SendPathResponse(pending_path_challenge.received_path_challenge,
- pending_path_challenge.peer_address)) {
+ pending_path_challenge.peer_address,
+ /*effective_peer_address=*/QuicSocketAddress())) {
break;
}
pending_path_challenge_payloads_.pop_front();
@@ -2826,6 +2990,17 @@ void QuicConnection::WriteIfNotBlocked() {
}
}
+void QuicConnection::SetServerConnectionId(
+ const QuicConnectionId& server_connection_id) {
+ if (use_connection_id_on_default_path_) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_connection_id_on_default_path_v2, 2,
+ 3);
+ default_path_.server_connection_id = server_connection_id;
+ } else {
+ server_connection_id_ = server_connection_id;
+ }
+}
+
void QuicConnection::ReplaceInitialServerConnectionId(
const QuicConnectionId& new_server_connection_id) {
QUICHE_DCHECK(perspective_ == Perspective::IS_CLIENT);
@@ -2836,10 +3011,10 @@ void QuicConnection::ReplaceInitialServerConnectionId(
if (peer_issued_cid_manager_ != nullptr) {
QUIC_BUG_IF(quic_bug_12714_22,
!peer_issued_cid_manager_->IsConnectionIdActive(
- server_connection_id_))
+ ServerConnectionId()))
<< "Connection ID replaced header is no longer active. old id: "
- << server_connection_id_ << " new_id: " << new_server_connection_id;
- peer_issued_cid_manager_->ReplaceConnectionId(server_connection_id_,
+ << ServerConnectionId() << " new_id: " << new_server_connection_id;
+ peer_issued_cid_manager_->ReplaceConnectionId(ServerConnectionId(),
new_server_connection_id);
} else {
peer_issued_cid_manager_ =
@@ -2849,8 +3024,74 @@ void QuicConnection::ReplaceInitialServerConnectionId(
}
}
}
- server_connection_id_ = new_server_connection_id;
- packet_creator_.SetServerConnectionId(server_connection_id_);
+ SetServerConnectionId(new_server_connection_id);
+ packet_creator_.SetServerConnectionId(ServerConnectionId());
+}
+
+void QuicConnection::FindMatchingOrNewClientConnectionIdOrToken(
+ const PathState& default_path,
+ const PathState& alternative_path,
+ const QuicConnectionId& server_connection_id,
+ QuicConnectionId* client_connection_id,
+ bool* stateless_reset_token_received,
+ StatelessResetToken* stateless_reset_token) {
+ if (!use_connection_id_on_default_path_) {
+ return;
+ }
+ QUICHE_DCHECK(perspective_ == Perspective::IS_SERVER);
+ if (peer_issued_cid_manager_ == nullptr ||
+ server_connection_id == default_path.server_connection_id) {
+ *client_connection_id = default_path.client_connection_id;
+ *stateless_reset_token_received =
+ default_path.stateless_reset_token_received;
+ *stateless_reset_token = default_path.stateless_reset_token;
+ return;
+ }
+ if (server_connection_id == alternative_path_.server_connection_id) {
+ *client_connection_id = alternative_path.client_connection_id;
+ *stateless_reset_token_received =
+ alternative_path.stateless_reset_token_received;
+ *stateless_reset_token = alternative_path.stateless_reset_token;
+ return;
+ }
+ if (!connection_migration_use_new_cid_) {
+ QUIC_BUG(quic_bug_46004) << "Cannot find matching connection ID.";
+ return;
+ }
+ auto* connection_id_data =
+ peer_issued_cid_manager_->ConsumeOneUnusedConnectionId();
+ if (connection_id_data == nullptr) {
+ return;
+ }
+ *client_connection_id = connection_id_data->connection_id;
+ *stateless_reset_token = connection_id_data->stateless_reset_token;
+ *stateless_reset_token_received = true;
+}
+
+bool QuicConnection::FindOnPathConnectionIds(
+ const QuicSocketAddress& self_address,
+ const QuicSocketAddress& peer_address,
+ QuicConnectionId* client_connection_id,
+ QuicConnectionId* server_connection_id) const {
+ if (IsDefaultPath(self_address, peer_address)) {
+ *client_connection_id = default_path_.client_connection_id,
+ *server_connection_id = default_path_.server_connection_id;
+ return true;
+ }
+ if (IsAlternativePath(self_address, peer_address)) {
+ *client_connection_id = alternative_path_.client_connection_id,
+ *server_connection_id = alternative_path_.server_connection_id;
+ return true;
+ }
+ return false;
+}
+
+void QuicConnection::SetDefaultPathState(PathState new_path_state) {
+ default_path_ = std::move(new_path_state);
+ if (connection_migration_use_new_cid_) {
+ packet_creator_.SetClientConnectionId(default_path_.client_connection_id);
+ packet_creator_.SetServerConnectionId(default_path_.server_connection_id);
+ }
}
bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) {
@@ -2885,21 +3126,21 @@ bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) {
default_path_.self_address = last_packet_destination_address_;
}
- if (PacketCanReplaceConnectionId(header, perspective_) &&
- server_connection_id_ != header.source_connection_id) {
+ if (PacketCanReplaceServerConnectionId(header, perspective_) &&
+ ServerConnectionId() != header.source_connection_id) {
QUICHE_DCHECK_EQ(header.long_packet_type, INITIAL);
if (server_connection_id_replaced_by_initial_) {
QUIC_DLOG(ERROR) << ENDPOINT << "Refusing to replace connection ID "
- << server_connection_id_ << " with "
+ << ServerConnectionId() << " with "
<< header.source_connection_id;
return false;
}
server_connection_id_replaced_by_initial_ = true;
QUIC_DLOG(INFO) << ENDPOINT << "Replacing connection ID "
- << server_connection_id_ << " with "
+ << ServerConnectionId() << " with "
<< header.source_connection_id;
if (!original_destination_connection_id_.has_value()) {
- original_destination_connection_id_ = server_connection_id_;
+ original_destination_connection_id_ = ServerConnectionId();
}
ReplaceInitialServerConnectionId(header.source_connection_id);
}
@@ -3039,6 +3280,15 @@ bool QuicConnection::ShouldGeneratePacket(
QuicVersionUsesCryptoFrames(transport_version()))
<< ENDPOINT
<< "Handshake in STREAM frames should not check ShouldGeneratePacket";
+ if (support_multiple_connection_ids_ && peer_issued_cid_manager_ != nullptr &&
+ packet_creator_.GetDestinationConnectionId().IsEmpty()) {
+ QUIC_CODE_COUNT(quic_generate_packet_blocked_by_no_connection_id);
+ QUIC_BUG_IF(quic_bug_90265_1, perspective_ == Perspective::IS_CLIENT);
+ QUIC_DLOG(INFO) << ENDPOINT
+ << "There is no destination connection ID available to "
+ "generate packet.";
+ return false;
+ }
if (!count_bytes_on_alternative_path_separately_) {
return CanWrite(retransmittable);
}
@@ -3319,7 +3569,7 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
legacy_version_encapsulation_sni_,
absl::string_view(packet->encrypted_buffer,
packet->encrypted_length),
- server_connection_id_, framer_.creation_time(),
+ ServerConnectionId(), framer_.creation_time(),
GetLimitedMaxPacketSize(long_term_mtu_),
const_cast<char*>(packet->encrypted_buffer));
if (encapsulated_length != 0) {
@@ -3514,6 +3764,7 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
SetRetransmissionAlarm();
}
SetPingAlarm();
+ RetirePeerIssuedConnectionIdsNoLongerOnPath();
// The packet number length must be updated after OnPacketSent, because it
// may change the packet number length in packet.
@@ -3827,13 +4078,13 @@ void QuicConnection::OnPathMtuIncreased(QuicPacketLength packet_size) {
std::unique_ptr<QuicSelfIssuedConnectionIdManager>
QuicConnection::MakeSelfIssuedConnectionIdManager() {
QUICHE_DCHECK((perspective_ == Perspective::IS_CLIENT &&
- !client_connection_id_.IsEmpty()) ||
+ !ClientConnectionId().IsEmpty()) ||
(perspective_ == Perspective::IS_SERVER &&
- !server_connection_id_.IsEmpty()));
+ !ServerConnectionId().IsEmpty()));
return std::make_unique<QuicSelfIssuedConnectionIdManager>(
kMinNumOfActiveConnectionIds,
- perspective_ == Perspective::IS_CLIENT ? client_connection_id_
- : server_connection_id_,
+ perspective_ == Perspective::IS_CLIENT ? ClientConnectionId()
+ : ServerConnectionId(),
clock_, alarm_factory_, this);
}
@@ -3847,6 +4098,11 @@ void QuicConnection::MaybeSendConnectionIdToClient() {
void QuicConnection::OnHandshakeComplete() {
sent_packet_manager_.SetHandshakeConfirmed();
+ if (connection_migration_use_new_cid_ &&
+ perspective_ == Perspective::IS_SERVER &&
+ self_issued_cid_manager_ != nullptr) {
+ self_issued_cid_manager_->MaybeSendNewConnectionIds();
+ }
if (send_ack_frequency_on_handshake_completion_ &&
sent_packet_manager_.CanSendAckFrequency()) {
QUIC_RELOADABLE_FLAG_COUNT_N(quic_can_send_ack_frequency, 2, 3);
@@ -3926,6 +4182,7 @@ void QuicConnection::SendAck() {
}
void QuicConnection::OnRetransmissionTimeout() {
+ ScopedRetransmissionTimeoutIndicator indicator(this);
#ifndef NDEBUG
if (sent_packet_manager_.unacked_packets().empty()) {
QUICHE_DCHECK(sent_packet_manager_.handshake_mode_disabled());
@@ -4309,8 +4566,9 @@ void QuicConnection::SendConnectionClosePacket(
QuicIetfTransportErrorCodes ietf_error,
const std::string& details) {
// Always use the current path to send CONNECTION_CLOSE.
- QuicPacketCreator::ScopedPeerAddressContext context(&packet_creator_,
- peer_address());
+ QuicPacketCreator::ScopedPeerAddressContext context(
+ &packet_creator_, peer_address(), default_path_.client_connection_id,
+ default_path_.server_connection_id, connection_migration_use_new_cid_);
if (!SupportsMultiplePacketNumberSpaces()) {
QUIC_DLOG(INFO) << ENDPOINT << "Sending connection close packet.";
if (!use_encryption_level_context_) {
@@ -4472,6 +4730,7 @@ QuicByteCount QuicConnection::max_packet_length() const {
void QuicConnection::SetMaxPacketLength(QuicByteCount length) {
long_term_mtu_ = length;
+ stats_.max_egress_mtu = std::max(stats_.max_egress_mtu, long_term_mtu_);
MaybeUpdatePacketCreatorMaxPacketLengthAndPadding();
}
@@ -4838,7 +5097,7 @@ bool QuicConnection::SendGenericPathProbePacket(
QUIC_DLOG(INFO) << ENDPOINT
<< "Sending path probe packet for connection_id = "
- << server_connection_id_;
+ << ServerConnectionId();
std::unique_ptr<SerializedPacket> probing_packet;
if (!version().HasIetfQuicFrames()) {
@@ -4883,7 +5142,7 @@ bool QuicConnection::WritePacketUsingWriter(
const QuicTime packet_send_time = clock_->Now();
QUIC_DVLOG(2) << ENDPOINT
<< "Sending path probe packet for server connection ID "
- << server_connection_id_ << std::endl
+ << ServerConnectionId() << std::endl
<< quiche::QuicheTextUtils::HexDump(absl::string_view(
packet->encrypted_buffer, packet->encrypted_length));
WriteResult result = writer->WritePacket(
@@ -5083,10 +5342,19 @@ void QuicConnection::StartEffectivePeerMigration(AddressChangeType type) {
// Update the default path.
if (IsAlternativePath(last_packet_destination_address_,
current_effective_peer_address)) {
- default_path_ = std::move(alternative_path_);
+ SetDefaultPathState(std::move(alternative_path_));
} else {
- default_path_ = PathState(last_packet_destination_address_,
- current_effective_peer_address);
+ QuicConnectionId client_connection_id;
+ bool stateless_reset_token_received = false;
+ StatelessResetToken stateless_reset_token;
+ FindMatchingOrNewClientConnectionIdOrToken(
+ previous_default_path, alternative_path_,
+ last_packet_destination_connection_id_, &client_connection_id,
+ &stateless_reset_token_received, &stateless_reset_token);
+ SetDefaultPathState(PathState(
+ last_packet_destination_address_, current_effective_peer_address,
+ client_connection_id, last_packet_destination_connection_id_,
+ stateless_reset_token_received, stateless_reset_token));
// The path is considered validated if its peer IP address matches any
// validated path's peer IP address.
default_path_.validated =
@@ -5293,8 +5561,17 @@ bool QuicConnection::UpdatePacketContent(QuicFrameType type) {
<< current_effective_peer_address << ", self address "
<< last_packet_destination_address_;
if (!validate_client_addresses_) {
- alternative_path_ = PathState(last_packet_destination_address_,
- current_effective_peer_address);
+ QuicConnectionId client_cid;
+ bool stateless_reset_token_received = false;
+ StatelessResetToken stateless_reset_token;
+ FindMatchingOrNewClientConnectionIdOrToken(
+ default_path_, alternative_path_,
+ last_packet_destination_connection_id_, &client_cid,
+ &stateless_reset_token_received, &stateless_reset_token);
+ alternative_path_ = PathState(
+ last_packet_destination_address_, current_effective_peer_address,
+ client_cid, last_packet_destination_connection_id_,
+ stateless_reset_token_received, stateless_reset_token);
} else if (!default_path_.validated) {
QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path3, 4, 6);
// Skip reverse path validation because either handshake hasn't
@@ -5311,24 +5588,38 @@ bool QuicConnection::UpdatePacketContent(QuicFrameType type) {
<< "No validated peer address to send after handshake comfirmed.";
} else if (!IsReceivedPeerAddressValidated()) {
QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path3, 5, 6);
+ QuicConnectionId client_connection_id;
+ bool stateless_reset_token_received;
+ StatelessResetToken stateless_reset_token;
+ FindMatchingOrNewClientConnectionIdOrToken(
+ default_path_, alternative_path_,
+ last_packet_destination_connection_id_, &client_connection_id,
+ &stateless_reset_token_received, &stateless_reset_token);
// Only override alternative path state upon receiving a PATH_CHALLENGE
// from an unvalidated peer address, and the connection isn't validating
// a recent peer migration.
- alternative_path_ = PathState(last_packet_destination_address_,
- current_effective_peer_address);
- // Conditions to proactively validate peer address:
- // The perspective is server
- // The PATH_CHALLENGE is received on an unvalidated alternative path.
- // The connection isn't validating migrated peer address, which is of
- // higher prority.
- QUIC_DVLOG(1) << "Proactively validate the effective peer address "
- << current_effective_peer_address;
- ValidatePath(
- std::make_unique<ReversePathValidationContext>(
- default_path_.self_address, current_effective_peer_address,
- current_effective_peer_address, this),
- std::make_unique<ReversePathValidationResultDelegate>(
- this, peer_address()));
+ alternative_path_ = PathState(
+ last_packet_destination_address_, current_effective_peer_address,
+ client_connection_id, last_packet_destination_connection_id_,
+ stateless_reset_token_received, stateless_reset_token);
+ if (group_path_response_and_challenge_sending_closer_) {
+ should_proactively_validate_peer_address_on_path_challenge_ = true;
+ } else {
+ // Conditions to proactively validate peer address:
+ // The perspective is server
+ // The PATH_CHALLENGE is received on an unvalidated alternative path.
+ // The connection isn't validating migrated peer address, which is of
+ // higher prority.
+ QUIC_DVLOG(1) << "Proactively validate the effective peer address "
+ << current_effective_peer_address;
+ QUIC_CODE_COUNT_N(quic_kick_off_client_address_validation, 1, 6);
+ ValidatePath(
+ std::make_unique<ReversePathValidationContext>(
+ default_path_.self_address, last_packet_source_address_,
+ current_effective_peer_address, this),
+ std::make_unique<ReversePathValidationResultDelegate>(
+ this, peer_address()));
+ }
}
}
MaybeUpdateBytesReceivedFromAlternativeAddress(last_size_);
@@ -5398,10 +5689,6 @@ bool QuicConnection::UpdatePacketContent(QuicFrameType type) {
void QuicConnection::MaybeStartIetfPeerMigration() {
QUICHE_DCHECK(version().HasIetfQuicFrames());
- if (!start_peer_migration_earlier_) {
- return;
- }
- QUIC_CODE_COUNT(quic_start_peer_migration_earlier);
if (current_effective_peer_migration_type_ != NO_CHANGE &&
!IsHandshakeConfirmed()) {
QUIC_LOG_EVERY_N_SEC(INFO, 60)
@@ -5970,14 +6257,21 @@ void QuicConnection::set_client_connection_id(
<< client_connection_id << " with unsupported version " << version();
return;
}
- client_connection_id_ = client_connection_id;
+ if (use_connection_id_on_default_path_) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_connection_id_on_default_path_v2, 1,
+ 3);
+ default_path_.client_connection_id = client_connection_id;
+ } else {
+ client_connection_id_ = client_connection_id;
+ }
+
client_connection_id_is_set_ = true;
- if (support_multiple_connection_ids_ && !client_connection_id_.IsEmpty()) {
+ if (support_multiple_connection_ids_ && !client_connection_id.IsEmpty()) {
if (perspective_ == Perspective::IS_SERVER) {
QUICHE_DCHECK(peer_issued_cid_manager_ == nullptr);
peer_issued_cid_manager_ =
std::make_unique<QuicPeerIssuedConnectionIdManager>(
- kMinNumOfActiveConnectionIds, client_connection_id_, clock_,
+ kMinNumOfActiveConnectionIds, client_connection_id, clock_,
alarm_factory_, this);
} else {
// Note in Chromium client, set_client_connection_id is not called and
@@ -5986,11 +6280,11 @@ void QuicConnection::set_client_connection_id(
}
}
QUIC_DLOG(INFO) << ENDPOINT << "setting client connection ID to "
- << client_connection_id_
+ << ClientConnectionId()
<< " for connection with server connection ID "
- << server_connection_id_;
- packet_creator_.SetClientConnectionId(client_connection_id_);
- framer_.SetExpectedClientConnectionIdLength(client_connection_id_.length());
+ << ServerConnectionId();
+ packet_creator_.SetClientConnectionId(ClientConnectionId());
+ framer_.SetExpectedClientConnectionIdLength(ClientConnectionId().length());
}
void QuicConnection::OnPathDegradingDetected() {
@@ -6069,12 +6363,21 @@ void QuicConnection::OnIdleNetworkDetected() {
void QuicConnection::OnPeerIssuedConnectionIdRetired() {
QUICHE_DCHECK(peer_issued_cid_manager_ != nullptr);
QuicConnectionId* default_path_cid = perspective_ == Perspective::IS_CLIENT
- ? &server_connection_id_
- : &client_connection_id_;
+ ? &ServerConnectionId()
+ : &ClientConnectionId();
+ QuicConnectionId* alternative_path_cid =
+ perspective_ == Perspective::IS_CLIENT
+ ? &alternative_path_.server_connection_id
+ : &alternative_path_.client_connection_id;
+ bool default_path_and_alternative_path_use_the_same_peer_connection_id =
+ *default_path_cid == *alternative_path_cid;
if (!default_path_cid->IsEmpty() &&
!peer_issued_cid_manager_->IsConnectionIdActive(*default_path_cid)) {
*default_path_cid = QuicConnectionId();
}
+ // TODO(haoyuewang) Handle the change for default_path_ & alternatvie_path_
+ // via the same helper function after use_connection_id_on_default_path_ is
+ // default true.
if (default_path_cid->IsEmpty()) {
// Try setting a new connection ID now such that subsequent
// RetireConnectionId frames can be sent on the default path.
@@ -6082,9 +6385,15 @@ void QuicConnection::OnPeerIssuedConnectionIdRetired() {
peer_issued_cid_manager_->ConsumeOneUnusedConnectionId();
if (unused_connection_id_data != nullptr) {
*default_path_cid = unused_connection_id_data->connection_id;
- received_stateless_reset_token_ =
- unused_connection_id_data->stateless_reset_token;
- stateless_reset_token_received_ = true;
+ if (use_connection_id_on_default_path_) {
+ default_path_.stateless_reset_token =
+ unused_connection_id_data->stateless_reset_token;
+ default_path_.stateless_reset_token_received = true;
+ } else {
+ received_stateless_reset_token_ =
+ unused_connection_id_data->stateless_reset_token;
+ stateless_reset_token_received_ = true;
+ }
if (perspective_ == Perspective::IS_CLIENT) {
packet_creator_.SetServerConnectionId(
unused_connection_id_data->connection_id);
@@ -6094,32 +6403,56 @@ void QuicConnection::OnPeerIssuedConnectionIdRetired() {
}
}
}
+ if (use_connection_id_on_default_path_) {
+ if (default_path_and_alternative_path_use_the_same_peer_connection_id) {
+ *alternative_path_cid = *default_path_cid;
+ alternative_path_.stateless_reset_token_received =
+ default_path_.stateless_reset_token_received;
+ alternative_path_.stateless_reset_token =
+ default_path_.stateless_reset_token;
+ } else if (!alternative_path_cid->IsEmpty() &&
+ !peer_issued_cid_manager_->IsConnectionIdActive(
+ *alternative_path_cid)) {
+ *alternative_path_cid = EmptyQuicConnectionId();
+ const QuicConnectionIdData* unused_connection_id_data =
+ peer_issued_cid_manager_->ConsumeOneUnusedConnectionId();
+ if (unused_connection_id_data != nullptr) {
+ *alternative_path_cid = unused_connection_id_data->connection_id;
+ alternative_path_.stateless_reset_token =
+ unused_connection_id_data->stateless_reset_token;
+ alternative_path_.stateless_reset_token_received = true;
+ }
+ }
+ }
std::vector<uint64_t> retired_cid_sequence_numbers =
peer_issued_cid_manager_->ConsumeToBeRetiredConnectionIdSequenceNumbers();
QUICHE_DCHECK(!retired_cid_sequence_numbers.empty());
for (const auto& sequence_number : retired_cid_sequence_numbers) {
+ ++stats_.num_retire_connection_id_sent;
visitor_->SendRetireConnectionId(sequence_number);
}
}
bool QuicConnection::SendNewConnectionId(
const QuicNewConnectionIdFrame& frame) {
- QUICHE_DCHECK(perspective_ == Perspective::IS_SERVER);
visitor_->SendNewConnectionId(frame);
+ ++stats_.num_new_connection_id_sent;
return connected_;
}
void QuicConnection::OnNewConnectionIdIssued(
const QuicConnectionId& connection_id) {
- QUICHE_DCHECK(perspective_ == Perspective::IS_SERVER);
- visitor_->OnServerConnectionIdIssued(connection_id);
+ if (perspective_ == Perspective::IS_SERVER) {
+ visitor_->OnServerConnectionIdIssued(connection_id);
+ }
}
void QuicConnection::OnSelfIssuedConnectionIdRetired(
const QuicConnectionId& connection_id) {
- QUICHE_DCHECK(perspective_ == Perspective::IS_SERVER);
- visitor_->OnServerConnectionIdRetired(connection_id);
+ if (perspective_ == Perspective::IS_SERVER) {
+ visitor_->OnServerConnectionIdRetired(connection_id);
+ }
}
void QuicConnection::MaybeUpdateAckTimeout() {
@@ -6197,15 +6530,41 @@ bool QuicConnection::SendPathChallenge(
const QuicPathFrameBuffer& data_buffer,
const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
- const QuicSocketAddress& /*effective_peer_address*/,
+ const QuicSocketAddress& effective_peer_address,
QuicPacketWriter* writer) {
+ if (connection_migration_use_new_cid_) {
+ {
+ QuicConnectionId client_cid, server_cid;
+ FindOnPathConnectionIds(self_address, effective_peer_address, &client_cid,
+ &server_cid);
+ QuicPacketCreator::ScopedPeerAddressContext context(
+ &packet_creator_, peer_address, client_cid, server_cid,
+ connection_migration_use_new_cid_);
+ if (writer == writer_) {
+ ScopedPacketFlusher flusher(this);
+ // It's on current path, add the PATH_CHALLENGE the same way as other
+ // frames. This may cause connection to be closed.
+ packet_creator_.AddPathChallengeFrame(data_buffer);
+ } else {
+ std::unique_ptr<SerializedPacket> probing_packet =
+ packet_creator_.SerializePathChallengeConnectivityProbingPacket(
+ data_buffer);
+ QUICHE_DCHECK_EQ(IsRetransmittable(*probing_packet),
+ NO_RETRANSMITTABLE_DATA);
+ QUICHE_DCHECK_EQ(self_address, alternative_path_.self_address);
+ WritePacketUsingWriter(std::move(probing_packet), writer, self_address,
+ peer_address, /*measure_rtt=*/false);
+ }
+ }
+ return connected_;
+ }
if (writer == writer_) {
ScopedPacketFlusher flusher(this);
{
// It's on current path, add the PATH_CHALLENGE the same way as other
// frames.
- QuicPacketCreator::ScopedPeerAddressContext context(&packet_creator_,
- peer_address);
+ QuicPacketCreator::ScopedPeerAddressContext context(
+ &packet_creator_, peer_address, /*update_connection_id=*/false);
// This may cause connection to be closed.
packet_creator_.AddPathChallengeFrame(data_buffer);
}
@@ -6236,26 +6595,75 @@ void QuicConnection::ValidatePath(
std::unique_ptr<QuicPathValidationContext> context,
std::unique_ptr<QuicPathValidator::ResultDelegate> result_delegate) {
QUICHE_DCHECK(use_path_validator_);
- if (perspective_ == Perspective::IS_CLIENT &&
+ if (!connection_migration_use_new_cid_ &&
+ perspective_ == Perspective::IS_CLIENT &&
!IsDefaultPath(context->self_address(), context->peer_address())) {
- alternative_path_ =
- PathState(context->self_address(), context->peer_address());
+ alternative_path_ = PathState(
+ context->self_address(), context->peer_address(),
+ default_path_.client_connection_id, default_path_.server_connection_id,
+ default_path_.stateless_reset_token_received,
+ default_path_.stateless_reset_token);
}
if (path_validator_.HasPendingPathValidation()) {
// Cancel and fail any earlier validation.
path_validator_.CancelPathValidation();
}
+ if (connection_migration_use_new_cid_ &&
+ perspective_ == Perspective::IS_CLIENT &&
+ !IsDefaultPath(context->self_address(), context->peer_address())) {
+ if (self_issued_cid_manager_ != nullptr) {
+ self_issued_cid_manager_->MaybeSendNewConnectionIds();
+ if (!connected_) {
+ return;
+ }
+ }
+ if ((self_issued_cid_manager_ != nullptr &&
+ !self_issued_cid_manager_->HasConnectionIdToConsume()) ||
+ (peer_issued_cid_manager_ != nullptr &&
+ !peer_issued_cid_manager_->HasUnusedConnectionId())) {
+ QUIC_DVLOG(1) << "Client cannot start new path validation as there is no "
+ "requried connection ID is available.";
+ result_delegate->OnPathValidationFailure(std::move(context));
+ return;
+ }
+ QuicConnectionId client_connection_id, server_connection_id;
+ StatelessResetToken stateless_reset_token;
+ bool stateless_reset_token_received = false;
+ if (self_issued_cid_manager_ != nullptr) {
+ client_connection_id =
+ *self_issued_cid_manager_->ConsumeOneConnectionId();
+ }
+ if (peer_issued_cid_manager_ != nullptr) {
+ const auto* connection_id_data =
+ peer_issued_cid_manager_->ConsumeOneUnusedConnectionId();
+ server_connection_id = connection_id_data->connection_id;
+ stateless_reset_token_received = true;
+ stateless_reset_token = connection_id_data->stateless_reset_token;
+ }
+ alternative_path_ =
+ PathState(context->self_address(), context->peer_address(),
+ client_connection_id, server_connection_id,
+ stateless_reset_token_received, stateless_reset_token);
+ }
path_validator_.StartPathValidation(std::move(context),
std::move(result_delegate));
}
-bool QuicConnection::SendPathResponse(const QuicPathFrameBuffer& data_buffer,
- QuicSocketAddress peer_address_to_send) {
+bool QuicConnection::SendPathResponse(
+ const QuicPathFrameBuffer& data_buffer,
+ const QuicSocketAddress& peer_address_to_send,
+ const QuicSocketAddress& effective_peer_address) {
+ QuicConnectionId client_cid, server_cid;
+ if (connection_migration_use_new_cid_) {
+ FindOnPathConnectionIds(last_packet_destination_address_,
+ effective_peer_address, &client_cid, &server_cid);
+ }
// Send PATH_RESPONSE using the provided peer address. If the creator has been
// using a different peer address, it will flush before and after serializing
// the current PATH_RESPONSE.
- QuicPacketCreator::ScopedPeerAddressContext context(&packet_creator_,
- peer_address_to_send);
+ QuicPacketCreator::ScopedPeerAddressContext context(
+ &packet_creator_, peer_address_to_send, client_cid, server_cid,
+ connection_migration_use_new_cid_);
QUIC_DVLOG(1) << ENDPOINT << "Send PATH_RESPONSE to " << peer_address_to_send;
if (default_path_.self_address == last_packet_destination_address_) {
// The PATH_CHALLENGE is received on the default socket. Respond on the same
@@ -6315,12 +6723,84 @@ void QuicConnection::CancelPathValidation() {
path_validator_.CancelPathValidation();
}
-void QuicConnection::MigratePath(const QuicSocketAddress& self_address,
+bool QuicConnection::UpdateConnectionIdsOnClientMigration(
+ const QuicSocketAddress& self_address,
+ const QuicSocketAddress& peer_address) {
+ QUICHE_DCHECK(perspective_ == Perspective::IS_CLIENT);
+ if (IsAlternativePath(self_address, peer_address)) {
+ // Client migration is after path validation.
+ default_path_.client_connection_id = alternative_path_.client_connection_id;
+ default_path_.server_connection_id = alternative_path_.server_connection_id;
+ default_path_.stateless_reset_token =
+ alternative_path_.stateless_reset_token;
+ default_path_.stateless_reset_token_received =
+ alternative_path_.stateless_reset_token_received;
+ return true;
+ }
+ // Client migration is without path validation.
+ if (self_issued_cid_manager_ != nullptr) {
+ self_issued_cid_manager_->MaybeSendNewConnectionIds();
+ if (!connected_) {
+ return false;
+ }
+ }
+ if ((self_issued_cid_manager_ != nullptr &&
+ !self_issued_cid_manager_->HasConnectionIdToConsume()) ||
+ (peer_issued_cid_manager_ != nullptr &&
+ !peer_issued_cid_manager_->HasUnusedConnectionId())) {
+ return false;
+ }
+ if (self_issued_cid_manager_ != nullptr) {
+ default_path_.client_connection_id =
+ *self_issued_cid_manager_->ConsumeOneConnectionId();
+ }
+ if (peer_issued_cid_manager_ != nullptr) {
+ const auto* connection_id_data =
+ peer_issued_cid_manager_->ConsumeOneUnusedConnectionId();
+ default_path_.server_connection_id = connection_id_data->connection_id;
+ default_path_.stateless_reset_token_received = true;
+ default_path_.stateless_reset_token =
+ connection_id_data->stateless_reset_token;
+ }
+ return true;
+}
+
+void QuicConnection::RetirePeerIssuedConnectionIdsNoLongerOnPath() {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 4, 5);
+ if (!connection_migration_use_new_cid_ ||
+ peer_issued_cid_manager_ == nullptr) {
+ return;
+ }
+ if (perspective_ == Perspective::IS_CLIENT) {
+ peer_issued_cid_manager_->MaybeRetireUnusedConnectionIds(
+ {default_path_.server_connection_id,
+ alternative_path_.server_connection_id});
+ } else {
+ peer_issued_cid_manager_->MaybeRetireUnusedConnectionIds(
+ {default_path_.client_connection_id,
+ alternative_path_.client_connection_id});
+ }
+}
+
+bool QuicConnection::MigratePath(const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
QuicPacketWriter* writer,
bool owns_writer) {
if (!connected_) {
- return;
+ return false;
+ }
+ QUICHE_DCHECK(!version().UsesHttp3() || IsHandshakeConfirmed());
+
+ if (connection_migration_use_new_cid_) {
+ if (!UpdateConnectionIdsOnClientMigration(self_address, peer_address)) {
+ return false;
+ }
+ if (packet_creator_.GetServerConnectionId().length() !=
+ default_path_.server_connection_id.length()) {
+ packet_creator_.FlushCurrentPacket();
+ }
+ packet_creator_.SetClientConnectionId(default_path_.client_connection_id);
+ packet_creator_.SetServerConnectionId(default_path_.server_connection_id);
}
const auto self_address_change_type = QuicUtils::DetermineAddressChangeType(
@@ -6337,13 +6817,21 @@ void QuicConnection::MigratePath(const QuicSocketAddress& self_address,
UpdatePeerAddress(peer_address);
SetQuicPacketWriter(writer, owns_writer);
OnSuccessfulMigration(is_port_change);
+ return true;
+}
+
+void QuicConnection::OnPathValidationFailureAtClient() {
+ if (connection_migration_use_new_cid_) {
+ QUICHE_DCHECK(perspective_ == Perspective::IS_CLIENT);
+ alternative_path_.Clear();
+ }
}
std::vector<QuicConnectionId> QuicConnection::GetActiveServerConnectionIds()
const {
if (!support_multiple_connection_ids_ ||
self_issued_cid_manager_ == nullptr) {
- return {server_connection_id_};
+ return {ServerConnectionId()};
}
return self_issued_cid_manager_->GetUnretiredConnectionIds();
}
@@ -6354,14 +6842,14 @@ void QuicConnection::CreateConnectionIdManager() {
}
if (perspective_ == Perspective::IS_CLIENT) {
- if (!server_connection_id_.IsEmpty()) {
+ if (!ServerConnectionId().IsEmpty()) {
peer_issued_cid_manager_ =
std::make_unique<QuicPeerIssuedConnectionIdManager>(
- kMinNumOfActiveConnectionIds, server_connection_id_, clock_,
+ kMinNumOfActiveConnectionIds, ServerConnectionId(), clock_,
alarm_factory_, this);
}
} else {
- if (!server_connection_id_.IsEmpty()) {
+ if (!ServerConnectionId().IsEmpty()) {
self_issued_cid_manager_ = MakeSelfIssuedConnectionIdManager();
}
}
@@ -6450,6 +6938,9 @@ bool QuicConnection::IsAlternativePath(
void QuicConnection::PathState::Clear() {
self_address = QuicSocketAddress();
peer_address = QuicSocketAddress();
+ client_connection_id = {};
+ server_connection_id = {};
+ stateless_reset_token_received = false;
validated = false;
bytes_received_before_address_validation = 0;
bytes_sent_before_address_validation = 0;
@@ -6466,6 +6957,10 @@ QuicConnection::PathState& QuicConnection::PathState::operator=(
if (this != &other) {
self_address = other.self_address;
peer_address = other.peer_address;
+ client_connection_id = other.client_connection_id;
+ server_connection_id = other.server_connection_id;
+ stateless_reset_token_received = other.stateless_reset_token_received;
+ stateless_reset_token = other.stateless_reset_token;
validated = other.validated;
bytes_received_before_address_validation =
other.bytes_received_before_address_validation;
@@ -6508,10 +7003,12 @@ void QuicConnection::ReversePathValidationResultDelegate::
QUIC_DLOG(INFO) << "Successfully validated new path " << *context;
if (connection_->IsDefaultPath(context->self_address(),
context->peer_address())) {
+ QUIC_CODE_COUNT_N(quic_kick_off_client_address_validation, 3, 6);
connection_->OnEffectivePeerMigrationValidated();
} else {
QUICHE_DCHECK(connection_->IsAlternativePath(
context->self_address(), context->effective_peer_address()));
+ QUIC_CODE_COUNT_N(quic_kick_off_client_address_validation, 4, 6);
QUIC_DVLOG(1) << "Mark alternative peer address "
<< context->effective_peer_address() << " validated.";
connection_->alternative_path_.validated = true;
@@ -6528,13 +7025,29 @@ void QuicConnection::ReversePathValidationResultDelegate::
if (connection_->IsDefaultPath(context->self_address(),
context->peer_address())) {
// Only act upon validation failure on the default path.
+ QUIC_CODE_COUNT_N(quic_kick_off_client_address_validation, 5, 6);
connection_->RestoreToLastValidatedPath(original_direct_peer_address_);
} else if (connection_->IsAlternativePath(
context->self_address(), context->effective_peer_address())) {
+ QUIC_CODE_COUNT_N(quic_kick_off_client_address_validation, 6, 6);
connection_->alternative_path_.Clear();
}
}
+QuicConnection::ScopedRetransmissionTimeoutIndicator::
+ ScopedRetransmissionTimeoutIndicator(QuicConnection* connection)
+ : connection_(connection) {
+ QUICHE_DCHECK(!connection_->in_on_retransmission_time_out_)
+ << "ScopedRetransmissionTimeoutIndicator is not supposed to be nested";
+ connection_->in_on_retransmission_time_out_ = true;
+}
+
+QuicConnection::ScopedRetransmissionTimeoutIndicator::
+ ~ScopedRetransmissionTimeoutIndicator() {
+ QUICHE_DCHECK(connection_->in_on_retransmission_time_out_);
+ connection_->in_on_retransmission_time_out_ = false;
+}
+
void QuicConnection::RestoreToLastValidatedPath(
QuicSocketAddress original_direct_peer_address) {
QUIC_DLOG(INFO) << "Switch back to use the old peer address "
@@ -6562,7 +7075,7 @@ void QuicConnection::RestoreToLastValidatedPath(
}
UpdatePeerAddress(original_direct_peer_address);
- default_path_ = std::move(alternative_path_);
+ SetDefaultPathState(std::move(alternative_path_));
active_effective_peer_migration_type_ = NO_CHANGE;
++stats_.num_invalid_peer_migration;
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 e2ba17bd9d8..b9567250637 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
@@ -36,7 +36,6 @@
#include "quic/core/quic_alarm.h"
#include "quic/core/quic_alarm_factory.h"
#include "quic/core/quic_blocked_writer_interface.h"
-#include "quic/core/quic_circular_deque.h"
#include "quic/core/quic_connection_id.h"
#include "quic/core/quic_connection_id_manager.h"
#include "quic/core/quic_connection_stats.h"
@@ -58,6 +57,7 @@
#include "quic/platform/api/quic_export.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_socket_address.h"
+#include "common/quiche_circular_deque.h"
namespace quic {
@@ -777,9 +777,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection
const QuicSocketAddress& effective_peer_address() const {
return default_path_.peer_address;
}
- QuicConnectionId connection_id() const { return server_connection_id_; }
- QuicConnectionId client_connection_id() const {
- return client_connection_id_;
+ const QuicConnectionId& connection_id() const { return ServerConnectionId(); }
+ const QuicConnectionId& client_connection_id() const {
+ return ClientConnectionId();
}
void set_client_connection_id(QuicConnectionId client_connection_id);
const QuicClock* clock() const { return clock_; }
@@ -1211,11 +1211,17 @@ class QUIC_EXPORT_PRIVATE QuicConnection
void CancelPathValidation();
- void MigratePath(const QuicSocketAddress& self_address,
+ // Returns true if the migration succeeds, otherwise returns false (e.g., no
+ // available CIDs, connection disconnected, etc).
+ bool MigratePath(const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
QuicPacketWriter* writer,
bool owns_writer);
+ // Called to clear the alternative_path_ when path validation failed on the
+ // client side.
+ void OnPathValidationFailureAtClient();
+
void SetSourceAddressTokenToSend(absl::string_view token);
void SendPing() {
@@ -1228,6 +1234,22 @@ class QUIC_EXPORT_PRIVATE QuicConnection
bool validate_client_address() const { return validate_client_addresses_; }
+ bool support_multiple_connection_ids() const {
+ return support_multiple_connection_ids_;
+ }
+
+ bool use_connection_id_on_default_path() const {
+ return use_connection_id_on_default_path_;
+ }
+
+ bool connection_migration_use_new_cid() const {
+ return connection_migration_use_new_cid_;
+ }
+
+ bool count_bytes_on_alternative_path_separately() const {
+ return count_bytes_on_alternative_path_separately_;
+ }
+
// Instantiates connection ID manager.
void CreateConnectionIdManager();
@@ -1331,10 +1353,20 @@ class QUIC_EXPORT_PRIVATE QuicConnection
};
struct QUIC_EXPORT_PRIVATE PathState {
+ PathState() = default;
+
PathState(const QuicSocketAddress& alternative_self_address,
- const QuicSocketAddress& alternative_peer_address)
+ const QuicSocketAddress& alternative_peer_address,
+ const QuicConnectionId& client_connection_id,
+ const QuicConnectionId& server_connection_id,
+ bool stateless_reset_token_received,
+ StatelessResetToken stateless_reset_token)
: self_address(alternative_self_address),
- peer_address(alternative_peer_address) {}
+ peer_address(alternative_peer_address),
+ client_connection_id(client_connection_id),
+ server_connection_id(server_connection_id),
+ stateless_reset_token(stateless_reset_token),
+ stateless_reset_token_received(stateless_reset_token_received) {}
PathState(PathState&& other);
@@ -1346,6 +1378,10 @@ class QUIC_EXPORT_PRIVATE QuicConnection
QuicSocketAddress self_address;
// The actual peer address behind the proxy if there is any.
QuicSocketAddress peer_address;
+ QuicConnectionId client_connection_id;
+ QuicConnectionId server_connection_id;
+ StatelessResetToken stateless_reset_token;
+ bool stateless_reset_token_received = false;
// True if the peer address has been validated. Address is considered
// validated when 1) an address token of the peer address is received and
// validated, or 2) a HANDSHAKE packet has been successfully processed on
@@ -1419,6 +1455,41 @@ class QUIC_EXPORT_PRIVATE QuicConnection
QuicSocketAddress original_direct_peer_address_;
};
+ // A class which sets and clears in_on_retransmission_time_out_ when entering
+ // and exiting OnRetransmissionTimeout, respectively.
+ class QUIC_EXPORT_PRIVATE ScopedRetransmissionTimeoutIndicator {
+ public:
+ // |connection| must outlive this indicator.
+ explicit ScopedRetransmissionTimeoutIndicator(QuicConnection* connection);
+
+ ~ScopedRetransmissionTimeoutIndicator();
+
+ private:
+ QuicConnection* connection_; // Not owned.
+ };
+
+ QuicConnectionId& ClientConnectionId() {
+ return use_connection_id_on_default_path_
+ ? default_path_.client_connection_id
+ : client_connection_id_;
+ }
+ const QuicConnectionId& ClientConnectionId() const {
+ return use_connection_id_on_default_path_
+ ? default_path_.client_connection_id
+ : client_connection_id_;
+ }
+ QuicConnectionId& ServerConnectionId() {
+ return use_connection_id_on_default_path_
+ ? default_path_.server_connection_id
+ : server_connection_id_;
+ }
+ const QuicConnectionId& ServerConnectionId() const {
+ return use_connection_id_on_default_path_
+ ? default_path_.server_connection_id
+ : server_connection_id_;
+ }
+ void SetServerConnectionId(const QuicConnectionId& server_connection_id);
+
// Notifies the visitor of the close and marks the connection as disconnected.
// Does not send a connection close frame to the peer. It should only be
// called by CloseConnection or OnConnectionCloseFrame, OnPublicResetPacket,
@@ -1438,6 +1509,42 @@ class QUIC_EXPORT_PRIVATE QuicConnection
void ReplaceInitialServerConnectionId(
const QuicConnectionId& new_server_connection_id);
+ // Given the server_connection_id find if there is already a corresponding
+ // client connection ID used on default/alternative path. If not, find if
+ // there is an unused connection ID.
+ void FindMatchingOrNewClientConnectionIdOrToken(
+ const PathState& default_path,
+ const PathState& alternative_path,
+ const QuicConnectionId& server_connection_id,
+ QuicConnectionId* client_connection_id,
+ bool* stateless_reset_token_received,
+ StatelessResetToken* stateless_reset_token);
+
+ // Returns true and sets connection IDs if (self_address, peer_address)
+ // corresponds to either the default path or alternative path. Returns false
+ // otherwise.
+ bool FindOnPathConnectionIds(const QuicSocketAddress& self_address,
+ const QuicSocketAddress& peer_address,
+ QuicConnectionId* client_connection_id,
+ QuicConnectionId* server_connection_id) const;
+
+ // Set default_path_ to the new_path_state and update the connection IDs in
+ // packet creator accordingly.
+ void SetDefaultPathState(PathState new_path_state);
+
+ // Returns true if header contains valid server connection ID.
+ bool ValidateServerConnectionId(const QuicPacketHeader& header) const;
+
+ // Update the connection IDs when client migrates with/without validation.
+ // Returns false if required connection ID is not available.
+ bool UpdateConnectionIdsOnClientMigration(
+ const QuicSocketAddress& self_address,
+ const QuicSocketAddress& peer_address);
+
+ // Retire active peer issued connection IDs after they are no longer used on
+ // any path.
+ void RetirePeerIssuedConnectionIdsNoLongerOnPath();
+
// Writes the given packet to socket, encrypted with packet's
// encryption_level. Returns true on successful write, and false if the writer
// was blocked and the write needs to be tried again. Notifies the
@@ -1598,7 +1705,7 @@ class QUIC_EXPORT_PRIVATE QuicConnection
QuicPacketNumber GetLargestAckedPacket() const;
// Whether incoming_connection_ids_ contains connection_id.
- bool HasIncomingConnectionId(QuicConnectionId connection_id);
+ bool HasIncomingConnectionId(QuicConnectionId connection_id) const;
// Whether connection is limited by amplification factor.
bool LimitedByAmplificationFactor() const;
@@ -1671,7 +1778,8 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// Send PATH_RESPONSE to the given peer address.
bool SendPathResponse(const QuicPathFrameBuffer& data_buffer,
- QuicSocketAddress peer_address_to_send);
+ const QuicSocketAddress& peer_address_to_send,
+ const QuicSocketAddress& effective_peer_address);
// Update both connection's and packet creator's peer address.
void UpdatePeerAddress(QuicSocketAddress peer_address);
@@ -1734,6 +1842,10 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// preferred_address transport parameter.
bool OnNewConnectionIdFrameInner(const QuicNewConnectionIdFrame& frame);
+ // Called to patch missing client connection ID on default/alternative paths
+ // when a new client connection ID is received.
+ void OnClientConnectionIdAvailable();
+
QuicFramer framer_;
// Contents received in the current packet, especially used to identify
@@ -1829,7 +1941,7 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// Collection of coalesced packets which were received while processing
// the current packet.
- QuicCircularDeque<std::unique_ptr<QuicEncryptedPacket>>
+ quiche::QuicheCircularDeque<std::unique_ptr<QuicEncryptedPacket>>
received_coalesced_packets_;
// Maximum number of undecryptable packets the connection will store.
@@ -1937,6 +2049,12 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// Source address of the last received packet.
QuicSocketAddress last_packet_source_address_;
+ // Destination connection ID of the last received packet. If this ID is the
+ // original server connection ID chosen by client and server replaces it with
+ // a different ID, last_packet_destination_connection_id_ is set to the
+ // replacement connection ID on the server side.
+ QuicConnectionId last_packet_destination_connection_id_;
+
// Set to false if the connection should not send truncated connection IDs to
// the peer, even if the peer supports it.
bool can_truncate_connection_ids_;
@@ -2036,12 +2154,15 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// saved and responded to.
// TODO(danzh) deprecate this field when deprecating
// --quic_send_path_response.
- QuicCircularDeque<QuicPathFrameBuffer> received_path_challenge_payloads_;
+ quiche::QuicheCircularDeque<QuicPathFrameBuffer>
+ received_path_challenge_payloads_;
// Buffer outstanding PATH_CHALLENGEs if socket write is blocked, future
// OnCanWrite will attempt to respond with PATH_RESPONSEs using the retained
// payload and peer addresses.
- QuicCircularDeque<PendingPathChallenge> pending_path_challenge_payloads_;
+ // TODO(fayang): remove this when deprecating quic_drop_unsent_path_response.
+ quiche::QuicheCircularDeque<PendingPathChallenge>
+ pending_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
@@ -2054,6 +2175,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// |original_destination_connection_id_| for validation.
absl::optional<QuicConnectionId> original_destination_connection_id_;
+ // The connection ID that replaces original_destination_connection_id_.
+ QuicConnectionId original_destination_connection_id_replacement_;
+
// After we receive a RETRY packet, |retry_source_connection_id_| contains
// the source connection ID from that packet.
absl::optional<QuicConnectionId> retry_source_connection_id_;
@@ -2094,13 +2218,8 @@ class QUIC_EXPORT_PRIVATE QuicConnection
size_t anti_amplification_factor_ =
GetQuicFlag(FLAGS_quic_anti_amplification_factor);
- bool start_peer_migration_earlier_ =
- GetQuicReloadableFlag(quic_start_peer_migration_earlier);
-
- // latch --gfe2_reloadable_flag_quic_send_path_response and
- // --gfe2_reloadable_flag_quic_start_peer_migration_earlier.
- bool send_path_response_ = start_peer_migration_earlier_ &&
- GetQuicReloadableFlag(quic_send_path_response2);
+ // latch --gfe2_reloadable_flag_quic_send_path_response.
+ bool send_path_response_ = GetQuicReloadableFlag(quic_send_path_response2);
bool use_path_validator_ =
send_path_response_ &&
@@ -2130,6 +2249,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// True after the first 1-RTT packet has successfully decrypted.
bool have_decrypted_first_one_rtt_packet_ = false;
+ // True if we are currently processing OnRetransmissionTimeout.
+ bool in_on_retransmission_time_out_ = false;
+
const bool encrypted_control_frames_;
const bool use_encryption_level_context_;
@@ -2163,6 +2285,23 @@ class QUIC_EXPORT_PRIVATE QuicConnection
const bool donot_write_mid_packet_processing_ =
GetQuicReloadableFlag(quic_donot_write_mid_packet_processing);
+
+ bool use_connection_id_on_default_path_ =
+ GetQuicReloadableFlag(quic_use_connection_id_on_default_path_v2);
+
+ // Indicates whether we should proactively validate peer address on a
+ // PATH_CHALLENGE received.
+ bool should_proactively_validate_peer_address_on_path_challenge_ = false;
+
+ // Enable this via reloadable flag once this feature is complete.
+ bool connection_migration_use_new_cid_ = false;
+
+ const bool group_path_response_and_challenge_sending_closer_ =
+ GetQuicReloadableFlag(
+ quic_group_path_response_and_challenge_sending_closer);
+
+ const bool quic_deprecate_incoming_connection_ids_ =
+ GetQuicReloadableFlag(quic_deprecate_incoming_connection_ids);
};
} // 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 303db8f2069..a8cb4c0f377 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
@@ -18,7 +18,6 @@
#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
-#include "common/platform/api/quiche_text_utils.h"
#include "common/quiche_endian.h"
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection_id_manager.cc b/chromium/net/third_party/quiche/src/quic/core/quic_connection_id_manager.cc
index a8e8c542f5f..f7089b7ebfd 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_connection_id_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_connection_id_manager.cc
@@ -199,6 +199,22 @@ void QuicPeerIssuedConnectionIdManager::PrepareToRetireActiveConnectionId(
}
}
+void QuicPeerIssuedConnectionIdManager::MaybeRetireUnusedConnectionIds(
+ const std::vector<QuicConnectionId>& active_connection_ids_on_path) {
+ std::vector<QuicConnectionId> cids_to_retire;
+ for (const auto& cid_data : active_connection_id_data_) {
+ if (std::find(active_connection_ids_on_path.begin(),
+ active_connection_ids_on_path.end(),
+ cid_data.connection_id) ==
+ active_connection_ids_on_path.end()) {
+ cids_to_retire.push_back(cid_data.connection_id);
+ }
+ }
+ for (const auto& cid : cids_to_retire) {
+ PrepareToRetireActiveConnectionId(cid);
+ }
+}
+
bool QuicPeerIssuedConnectionIdManager::IsConnectionIdActive(
const QuicConnectionId& cid) const {
return FindConnectionIdData(active_connection_id_data_, cid) !=
@@ -263,7 +279,8 @@ QuicSelfIssuedConnectionIdManager::QuicSelfIssuedConnectionIdManager(
retire_connection_id_alarm_(alarm_factory->CreateAlarm(
new RetireSelfIssuedConnectionIdAlarmDelegate(this))),
last_connection_id_(initial_connection_id),
- next_connection_id_sequence_number_(1u) {
+ next_connection_id_sequence_number_(1u),
+ last_connection_id_consumed_by_self_sequence_number_(0u) {
active_connection_ids_.emplace_back(initial_connection_id, 0u);
}
@@ -386,4 +403,45 @@ void QuicSelfIssuedConnectionIdManager::MaybeSendNewConnectionIds() {
}
}
+bool QuicSelfIssuedConnectionIdManager::HasConnectionIdToConsume() const {
+ for (const auto& active_cid_data : active_connection_ids_) {
+ if (active_cid_data.second >
+ last_connection_id_consumed_by_self_sequence_number_) {
+ return true;
+ }
+ }
+ return false;
+}
+
+absl::optional<QuicConnectionId>
+QuicSelfIssuedConnectionIdManager::ConsumeOneConnectionId() {
+ for (const auto& active_cid_data : active_connection_ids_) {
+ if (active_cid_data.second >
+ last_connection_id_consumed_by_self_sequence_number_) {
+ // Since connection IDs in active_connection_ids_ has monotonically
+ // increasing sequence numbers, the returned connection ID has the
+ // smallest sequence number among all unconsumed active connection IDs.
+ last_connection_id_consumed_by_self_sequence_number_ =
+ active_cid_data.second;
+ return active_cid_data.first;
+ }
+ }
+ return absl::nullopt;
+}
+
+bool QuicSelfIssuedConnectionIdManager::IsConnectionIdInUse(
+ const QuicConnectionId& cid) const {
+ for (const auto& active_cid_data : active_connection_ids_) {
+ if (active_cid_data.first == cid) {
+ return true;
+ }
+ }
+ for (const auto& to_be_retired_cid_data : to_be_retired_connection_ids_) {
+ if (to_be_retired_cid_data.first == cid) {
+ return true;
+ }
+ }
+ return false;
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection_id_manager.h b/chromium/net/third_party/quiche/src/quic/core/quic_connection_id_manager.h
index b933a69f158..5e7fc8ccf72 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_connection_id_manager.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_connection_id_manager.h
@@ -13,6 +13,7 @@
#include <cstddef>
#include <memory>
+#include "absl/types/optional.h"
#include "quic/core/frames/quic_new_connection_id_frame.h"
#include "quic/core/frames/quic_retire_connection_id_frame.h"
#include "quic/core/quic_alarm.h"
@@ -68,13 +69,19 @@ class QUIC_EXPORT_PRIVATE QuicPeerIssuedConnectionIdManager {
QuicErrorCode OnNewConnectionIdFrame(const QuicNewConnectionIdFrame& frame,
std::string* error_detail);
+ bool HasUnusedConnectionId() const {
+ return !unused_connection_id_data_.empty();
+ }
+
// Returns the data associated with an unused connection Id. After the call,
// the Id is marked as used. Returns nullptr if there is no unused connection
// Id.
const QuicConnectionIdData* ConsumeOneUnusedConnectionId();
- // Add the connection Id to the pending retirement connection Id list.
- void PrepareToRetireActiveConnectionId(const QuicConnectionId& cid);
+ // Add each active connection Id that is no longer on path to the pending
+ // retirement connection Id list.
+ void MaybeRetireUnusedConnectionIds(
+ const std::vector<QuicConnectionId>& active_connection_ids_on_path);
bool IsConnectionIdActive(const QuicConnectionId& cid) const;
@@ -90,6 +97,10 @@ class QUIC_EXPORT_PRIVATE QuicPeerIssuedConnectionIdManager {
private:
friend class test::QuicConnectionIdManagerPeer;
+ // Add the connection Id to the pending retirement connection Id list and
+ // schedule an alarm if needed.
+ void PrepareToRetireActiveConnectionId(const QuicConnectionId& cid);
+
bool IsConnectionIdNew(const QuicNewConnectionIdFrame& frame);
void PrepareToRetireConnectionIdPriorTo(
@@ -135,6 +146,17 @@ class QUIC_EXPORT_PRIVATE QuicSelfIssuedConnectionIdManager {
// Sends new connection IDs if more can be sent.
void MaybeSendNewConnectionIds();
+ // The two functions are called on the client side to associate a client
+ // connection ID with a new probing/migration path when client uses
+ // non-empty connection ID.
+ bool HasConnectionIdToConsume() const;
+ absl::optional<QuicConnectionId> ConsumeOneConnectionId();
+
+ // Returns true if the given connection ID is issued by the
+ // QuicSelfIssuedConnectionIdManager and not retired locally yet. Called to
+ // tell if a received packet has a valid connection ID.
+ bool IsConnectionIdInUse(const QuicConnectionId& cid) const;
+
virtual QuicConnectionId GenerateNewConnectionId(
const QuicConnectionId& old_connection_id) const;
@@ -162,6 +184,8 @@ class QUIC_EXPORT_PRIVATE QuicSelfIssuedConnectionIdManager {
// State of the last issued connection Id.
QuicConnectionId last_connection_id_;
uint64_t next_connection_id_sequence_number_;
+ // The sequence number of last connection ID consumed.
+ uint64_t last_connection_id_consumed_by_self_sequence_number_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection_id_manager_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_connection_id_manager_test.cc
index 9c7daf0db5e..7baeb2b247e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_connection_id_manager_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_connection_id_manager_test.cc
@@ -126,8 +126,8 @@ TEST_F(QuicPeerIssuedConnectionIdManagerTest,
frame.stateless_reset_token);
// Connection migration succeed. Prepares to retire CID #0.
- peer_issued_cid_manager_.PrepareToRetireActiveConnectionId(
- TestConnectionId(0));
+ peer_issued_cid_manager_.MaybeRetireUnusedConnectionIds(
+ {TestConnectionId(1)});
cid_manager_visitor_.SetCurrentPeerConnectionId(TestConnectionId(1));
ASSERT_TRUE(retire_peer_issued_cid_alarm_->IsSet());
alarm_factory_.FireAlarm(retire_peer_issued_cid_alarm_);
@@ -150,8 +150,8 @@ TEST_F(QuicPeerIssuedConnectionIdManagerTest,
// Start to use CID #2 for alternative path.
peer_issued_cid_manager_.ConsumeOneUnusedConnectionId();
// Connection migration succeed. Prepares to retire CID #1.
- peer_issued_cid_manager_.PrepareToRetireActiveConnectionId(
- TestConnectionId(1));
+ peer_issued_cid_manager_.MaybeRetireUnusedConnectionIds(
+ {TestConnectionId(2)});
cid_manager_visitor_.SetCurrentPeerConnectionId(TestConnectionId(2));
ASSERT_TRUE(retire_peer_issued_cid_alarm_->IsSet());
alarm_factory_.FireAlarm(retire_peer_issued_cid_alarm_);
@@ -174,8 +174,8 @@ TEST_F(QuicPeerIssuedConnectionIdManagerTest,
// Start to use CID #3 for alternative path.
peer_issued_cid_manager_.ConsumeOneUnusedConnectionId();
// Connection migration succeed. Prepares to retire CID #2.
- peer_issued_cid_manager_.PrepareToRetireActiveConnectionId(
- TestConnectionId(2));
+ peer_issued_cid_manager_.MaybeRetireUnusedConnectionIds(
+ {TestConnectionId(3)});
cid_manager_visitor_.SetCurrentPeerConnectionId(TestConnectionId(3));
ASSERT_TRUE(retire_peer_issued_cid_alarm_->IsSet());
alarm_factory_.FireAlarm(retire_peer_issued_cid_alarm_);
@@ -214,8 +214,8 @@ TEST_F(QuicPeerIssuedConnectionIdManagerTest,
// Start to use CID #1 for alternative path.
peer_issued_cid_manager_.ConsumeOneUnusedConnectionId();
// Connection migration fails. Prepares to retire CID #1.
- peer_issued_cid_manager_.PrepareToRetireActiveConnectionId(
- TestConnectionId(1));
+ peer_issued_cid_manager_.MaybeRetireUnusedConnectionIds(
+ {initial_connection_id_});
// Actually retires CID #1.
ASSERT_TRUE(retire_peer_issued_cid_alarm_->IsSet());
alarm_factory_.FireAlarm(retire_peer_issued_cid_alarm_);
@@ -238,8 +238,8 @@ TEST_F(QuicPeerIssuedConnectionIdManagerTest,
// Start to use CID #2 for alternative path.
peer_issued_cid_manager_.ConsumeOneUnusedConnectionId();
// Connection migration fails again. Prepares to retire CID #2.
- peer_issued_cid_manager_.PrepareToRetireActiveConnectionId(
- TestConnectionId(2));
+ peer_issued_cid_manager_.MaybeRetireUnusedConnectionIds(
+ {initial_connection_id_});
// Actually retires CID #2.
ASSERT_TRUE(retire_peer_issued_cid_alarm_->IsSet());
alarm_factory_.FireAlarm(retire_peer_issued_cid_alarm_);
@@ -262,8 +262,8 @@ TEST_F(QuicPeerIssuedConnectionIdManagerTest,
// Start to use CID #3 for alternative path.
peer_issued_cid_manager_.ConsumeOneUnusedConnectionId();
// Connection migration succeed. Prepares to retire CID #0.
- peer_issued_cid_manager_.PrepareToRetireActiveConnectionId(
- TestConnectionId(0));
+ peer_issued_cid_manager_.MaybeRetireUnusedConnectionIds(
+ {TestConnectionId(3)});
// After CID #3 is default (i.e., when there is no pending frame to write
// associated with CID #0), #0 can actually be retired.
cid_manager_visitor_.SetCurrentPeerConnectionId(TestConnectionId(3));
@@ -374,8 +374,8 @@ TEST_F(QuicPeerIssuedConnectionIdManagerTest,
// Outcome: (active: #0 #1 unused: None)
peer_issued_cid_manager_.ConsumeOneUnusedConnectionId();
// Prepare to retire CID #1 as path validation fails.
- peer_issued_cid_manager_.PrepareToRetireActiveConnectionId(
- TestConnectionId(1));
+ peer_issued_cid_manager_.MaybeRetireUnusedConnectionIds(
+ {initial_connection_id_});
// Actually retires CID #1.
ASSERT_TRUE(retire_peer_issued_cid_alarm_->IsSet());
alarm_factory_.FireAlarm(retire_peer_issued_cid_alarm_);
@@ -845,20 +845,36 @@ TEST_F(QuicSelfIssuedConnectionIdManagerTest,
QuicConnectionId cid1 = cid_manager_.GenerateNewConnectionId(cid0);
QuicConnectionId cid2 = cid_manager_.GenerateNewConnectionId(cid1);
QuicConnectionId cid3 = cid_manager_.GenerateNewConnectionId(cid2);
+ QuicConnectionId cid;
EXPECT_CALL(cid_manager_visitor_, OnNewConnectionIdIssued(_)).Times(3);
EXPECT_CALL(cid_manager_visitor_, SendNewConnectionId(_))
.Times(3)
.WillRepeatedly(Return(true));
QuicTime::Delta connection_id_expire_timeout = 3 * pto_delay_;
QuicRetireConnectionIdFrame retire_cid_frame;
+ EXPECT_TRUE(cid_manager_.IsConnectionIdInUse(cid0));
+ EXPECT_FALSE(cid_manager_.HasConnectionIdToConsume());
+ EXPECT_FALSE(cid_manager_.ConsumeOneConnectionId().has_value());
// CID #1 is sent to peer.
cid_manager_.MaybeSendNewConnectionIds();
+ EXPECT_TRUE(cid_manager_.IsConnectionIdInUse(cid1));
+ EXPECT_TRUE(cid_manager_.HasConnectionIdToConsume());
+ cid = *cid_manager_.ConsumeOneConnectionId();
+ EXPECT_EQ(cid1, cid);
+ EXPECT_FALSE(cid_manager_.HasConnectionIdToConsume());
// CID #0's retirement is scheduled and CID #2 is sent to peer.
retire_cid_frame.sequence_number = 0u;
cid_manager_.OnRetireConnectionIdFrame(retire_cid_frame, pto_delay_,
&error_details_);
+ EXPECT_TRUE(cid_manager_.IsConnectionIdInUse(cid0));
+ EXPECT_TRUE(cid_manager_.IsConnectionIdInUse(cid1));
+ EXPECT_TRUE(cid_manager_.IsConnectionIdInUse(cid2));
+ EXPECT_TRUE(cid_manager_.HasConnectionIdToConsume());
+ cid = *cid_manager_.ConsumeOneConnectionId();
+ EXPECT_EQ(cid2, cid);
+ EXPECT_FALSE(cid_manager_.HasConnectionIdToConsume());
clock_.AdvanceTime(connection_id_expire_timeout * 0.1);
@@ -874,6 +890,9 @@ TEST_F(QuicSelfIssuedConnectionIdManagerTest,
EXPECT_CALL(cid_manager_visitor_, OnSelfIssuedConnectionIdRetired(cid0));
EXPECT_CALL(cid_manager_visitor_, OnSelfIssuedConnectionIdRetired(cid1));
alarm_factory_.FireAlarm(retire_self_issued_cid_alarm_);
+ EXPECT_FALSE(cid_manager_.IsConnectionIdInUse(cid0));
+ EXPECT_FALSE(cid_manager_.IsConnectionIdInUse(cid1));
+ EXPECT_TRUE(cid_manager_.IsConnectionIdInUse(cid2));
EXPECT_THAT(cid_manager_.GetUnretiredConnectionIds(),
ElementsAre(cid2, cid3));
EXPECT_FALSE(retire_self_issued_cid_alarm_->IsSet());
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection_stats.cc b/chromium/net/third_party/quiche/src/quic/core/quic_connection_stats.cc
index 3d1b3c422a8..fbaa20abd94 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_connection_stats.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_connection_stats.cc
@@ -34,8 +34,9 @@ std::ostream& operator<<(std::ostream& os, const QuicConnectionStats& s) {
os << " pto_count: " << s.pto_count;
os << " min_rtt_us: " << s.min_rtt_us;
os << " srtt_us: " << s.srtt_us;
- os << " max_packet_size: " << s.max_packet_size;
- os << " max_received_packet_size: " << s.max_received_packet_size;
+ os << " egress_mtu: " << s.egress_mtu;
+ os << " max_egress_mtu: " << s.max_egress_mtu;
+ os << " ingress_mtu: " << s.ingress_mtu;
os << " estimated_bandwidth: " << s.estimated_bandwidth;
os << " packets_reordered: " << s.packets_reordered;
os << " max_sequence_reordering: " << s.max_sequence_reordering;
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 06b7f5868bd..39fd5b087a6 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
@@ -103,8 +103,14 @@ struct QUIC_EXPORT_PRIVATE QuicConnectionStats {
int64_t min_rtt_us = 0; // Minimum RTT in microseconds.
int64_t srtt_us = 0; // Smoothed RTT in microseconds.
int64_t cwnd_bootstrapping_rtt_us = 0; // RTT used in cwnd_bootstrapping.
- QuicByteCount max_packet_size = 0;
- QuicByteCount max_received_packet_size = 0;
+ // The connection's |long_term_mtu_| used for sending packets, populated by
+ // QuicConnection::GetStats().
+ QuicByteCount egress_mtu = 0;
+ // The maximum |long_term_mtu_| the connection ever used.
+ QuicByteCount max_egress_mtu = 0;
+ // Size of the largest packet received from the peer, populated by
+ // QuicConnection::GetStats().
+ QuicByteCount ingress_mtu = 0;
QuicBandwidth estimated_bandwidth = QuicBandwidth::Zero();
// Reordering stats for received packets.
@@ -209,6 +215,10 @@ struct QUIC_EXPORT_PRIVATE QuicConnectionStats {
// which was canceled because the peer migrated again. Such migration is also
// counted as invalid peer migration.
size_t num_peer_migration_while_validating_default_path = 0;
+ // Number of NEW_CONNECTION_ID frames sent.
+ size_t num_new_connection_id_sent = 0;
+ // Number of RETIRE_CONNECTION_ID frames sent.
+ size_t num_retire_connection_id_sent = 0;
struct QUIC_NO_EXPORT TlsServerOperationStats {
bool success = false;
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 e2fba5b8325..fe2ff6cab6e 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
@@ -21,10 +21,12 @@
#include "quic/core/crypto/quic_decrypter.h"
#include "quic/core/crypto/quic_encrypter.h"
#include "quic/core/frames/quic_connection_close_frame.h"
+#include "quic/core/frames/quic_new_connection_id_frame.h"
#include "quic/core/frames/quic_path_response_frame.h"
#include "quic/core/quic_connection_id.h"
#include "quic/core/quic_constants.h"
#include "quic/core/quic_error_codes.h"
+#include "quic/core/quic_packet_creator.h"
#include "quic/core/quic_packets.h"
#include "quic/core/quic_path_validator.h"
#include "quic/core/quic_simple_buffer_allocator.h"
@@ -33,6 +35,7 @@
#include "quic/core/quic_versions.h"
#include "quic/platform/api/quic_expect_bug.h"
#include "quic/platform/api/quic_flags.h"
+#include "quic/platform/api/quic_ip_address.h"
#include "quic/platform/api/quic_logging.h"
#include "quic/platform/api/quic_reference_counted.h"
#include "quic/platform/api/quic_socket_address.h"
@@ -764,6 +767,12 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
void use_tagging_decrypter() { writer_->use_tagging_decrypter(); }
+ void SetClientConnectionId(const QuicConnectionId& client_connection_id) {
+ connection_.set_client_connection_id(client_connection_id);
+ writer_->framer()->framer()->SetExpectedClientConnectionIdLength(
+ client_connection_id.length());
+ }
+
void SetDecrypter(EncryptionLevel level,
std::unique_ptr<QuicDecrypter> decrypter) {
if (connection_.version().KnowsWhichDecrypterToUse()) {
@@ -1190,8 +1199,7 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
EncryptionLevel level) {
QuicPacketHeader header = ConstructPacketHeader(number, level);
QuicFrames frames;
- if (GetQuicReloadableFlag(quic_reject_unexpected_ietf_frame_types) &&
- VersionHasIetfQuicFrames(version().transport_version) &&
+ if (VersionHasIetfQuicFrames(version().transport_version) &&
(level == ENCRYPTION_INITIAL || level == ENCRYPTION_HANDSHAKE)) {
frames.push_back(QuicFrame(QuicPingFrame()));
frames.push_back(QuicFrame(QuicPaddingFrame(100)));
@@ -1420,8 +1428,10 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
EXPECT_TRUE(connection_.connected());
}
- void PathProbeTestInit(Perspective perspective) {
+ void PathProbeTestInit(Perspective perspective,
+ bool receive_new_server_connection_id = true) {
set_perspective(perspective);
+ connection_.CreateConnectionIdManager();
EXPECT_EQ(connection_.perspective(), perspective);
if (perspective == Perspective::IS_SERVER) {
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
@@ -1453,6 +1463,17 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
kPeerAddress, ENCRYPTION_FORWARD_SECURE);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
+ if (perspective == Perspective::IS_CLIENT &&
+ receive_new_server_connection_id) {
+ QuicNewConnectionIdFrame frame;
+ frame.connection_id = TestConnectionId(1234);
+ ASSERT_NE(frame.connection_id, connection_.connection_id());
+ frame.stateless_reset_token =
+ QuicUtils::GenerateStatelessResetToken(frame.connection_id);
+ frame.retire_prior_to = 0u;
+ frame.sequence_number = 1u;
+ connection_.OnNewConnectionIdFrame(frame);
+ }
}
void TestClientRetryHandling(bool invalid_retry_tag,
@@ -1691,13 +1712,8 @@ TEST_P(QuicConnectionTest, PeerPortChangeAtServer) {
EXPECT_CALL(visitor_, OnStreamFrame(_))
.WillOnce(Invoke(
[=]() { EXPECT_EQ(kPeerAddress, connection_.peer_address()); }))
- .WillOnce(Invoke([=]() {
- EXPECT_EQ((GetQuicReloadableFlag(quic_start_peer_migration_earlier) ||
- !GetParam().version.HasIetfQuicFrames()
- ? kNewPeerAddress
- : kPeerAddress),
- connection_.peer_address());
- }));
+ .WillOnce(Invoke(
+ [=]() { EXPECT_EQ(kNewPeerAddress, connection_.peer_address()); }));
QuicFrames frames;
frames.push_back(QuicFrame(frame1_));
ProcessFramesPacketWithAddresses(frames, kSelfAddress, kPeerAddress,
@@ -1765,13 +1781,8 @@ TEST_P(QuicConnectionTest, PeerIpAddressChangeAtServer) {
EXPECT_CALL(visitor_, OnStreamFrame(_))
.WillOnce(Invoke(
[=]() { EXPECT_EQ(kPeerAddress, connection_.peer_address()); }))
- .WillOnce(Invoke([=]() {
- EXPECT_EQ((GetQuicReloadableFlag(quic_start_peer_migration_earlier) ||
- !GetParam().version.HasIetfQuicFrames()
- ? kNewPeerAddress
- : kPeerAddress),
- connection_.peer_address());
- }));
+ .WillOnce(Invoke(
+ [=]() { EXPECT_EQ(kNewPeerAddress, connection_.peer_address()); }));
QuicFrames frames;
frames.push_back(QuicFrame(frame1_));
ProcessFramesPacketWithAddresses(frames, kSelfAddress, kPeerAddress,
@@ -1866,6 +1877,83 @@ TEST_P(QuicConnectionTest, PeerIpAddressChangeAtServer) {
EXPECT_EQ(1u, connection_.GetStats().num_validated_peer_migration);
}
+TEST_P(QuicConnectionTest, PeerIpAddressChangeAtServerWithMissingConnectionId) {
+ set_perspective(Perspective::IS_SERVER);
+ if (!connection_.connection_migration_use_new_cid()) {
+ return;
+ }
+ QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
+ EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
+
+ QuicConnectionId client_cid0 = TestConnectionId(1);
+ QuicConnectionId client_cid1 = TestConnectionId(3);
+ QuicConnectionId server_cid1;
+ SetClientConnectionId(client_cid0);
+ connection_.CreateConnectionIdManager();
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ // Prevent packets from being coalesced.
+ EXPECT_CALL(visitor_, GetHandshakeState())
+ .WillRepeatedly(Return(HANDSHAKE_CONFIRMED));
+ QuicConnectionPeer::SetAddressValidated(&connection_);
+
+ // Sends new server CID to client.
+ EXPECT_CALL(visitor_, OnServerConnectionIdIssued(_))
+ .WillOnce(
+ Invoke([&](const QuicConnectionId& cid) { server_cid1 = cid; }));
+ EXPECT_CALL(visitor_, SendNewConnectionId(_));
+ connection_.OnHandshakeComplete();
+
+ // 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());
+
+ const QuicSocketAddress kNewPeerAddress =
+ QuicSocketAddress(QuicIpAddress::Loopback4(), /*port=*/23456);
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(2);
+ QuicFrames frames;
+ frames.push_back(QuicFrame(frame1_));
+ ProcessFramesPacketWithAddresses(frames, kSelfAddress, kPeerAddress,
+ ENCRYPTION_FORWARD_SECURE);
+ EXPECT_EQ(kPeerAddress, connection_.peer_address());
+ EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
+
+ // Send some data to make connection has packets in flight.
+ connection_.SendStreamData3();
+ EXPECT_EQ(1u, writer_->packets_write_attempts());
+
+ // Process another packet with a different peer address on server side will
+ // start connection migration.
+ peer_creator_.SetServerConnectionId(server_cid1);
+ EXPECT_CALL(visitor_, OnConnectionMigration(IPV6_TO_IPV4_CHANGE)).Times(1);
+ // Do not propagate OnCanWrite() to session notifier.
+ EXPECT_CALL(visitor_, OnCanWrite()).Times(AtLeast(1u));
+
+ QuicFrames frames2;
+ frames2.push_back(QuicFrame(frame2_));
+ ProcessFramesPacketWithAddresses(frames2, kSelfAddress, kNewPeerAddress,
+ ENCRYPTION_FORWARD_SECURE);
+ EXPECT_EQ(kNewPeerAddress, connection_.peer_address());
+ EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
+
+ // Writing path response & reverse path challenge is blocked due to missing
+ // client connection ID, i.e., packets_write_attempts is unchanged.
+ EXPECT_EQ(1u, writer_->packets_write_attempts());
+
+ // Receives new client CID from client would unblock write.
+ QuicNewConnectionIdFrame new_cid_frame;
+ new_cid_frame.connection_id = client_cid1;
+ new_cid_frame.sequence_number = 1u;
+ new_cid_frame.retire_prior_to = 0u;
+ connection_.OnNewConnectionIdFrame(new_cid_frame);
+ connection_.SendStreamData3();
+
+ EXPECT_EQ(2u, writer_->packets_write_attempts());
+}
+
TEST_P(QuicConnectionTest, EffectivePeerAddressChangeAtServer) {
set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
@@ -1983,17 +2071,38 @@ TEST_P(QuicConnectionTest, EffectivePeerAddressChangeAtServer) {
TEST_P(QuicConnectionTest, ReversePathValidationFailureAtServer) {
set_perspective(Perspective::IS_SERVER);
- if (!connection_.validate_client_address()) {
+ if (!connection_.connection_migration_use_new_cid()) {
return;
}
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
+ SetClientConnectionId(TestConnectionId(1));
+ connection_.CreateConnectionIdManager();
connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
// Prevent packets from being coalesced.
EXPECT_CALL(visitor_, GetHandshakeState())
.WillRepeatedly(Return(HANDSHAKE_CONFIRMED));
QuicConnectionPeer::SetAddressValidated(&connection_);
+
+ QuicConnectionId client_cid0 = connection_.client_connection_id();
+ QuicConnectionId client_cid1 = TestConnectionId(2);
+ QuicConnectionId server_cid0 = connection_.connection_id();
+ QuicConnectionId server_cid1;
+ // Sends new server CID to client.
+ EXPECT_CALL(visitor_, OnServerConnectionIdIssued(_))
+ .WillOnce(
+ Invoke([&](const QuicConnectionId& cid) { server_cid1 = cid; }));
+ EXPECT_CALL(visitor_, SendNewConnectionId(_));
connection_.OnHandshakeComplete();
+ // Receives new client CID from client.
+ QuicNewConnectionIdFrame new_cid_frame;
+ new_cid_frame.connection_id = client_cid1;
+ new_cid_frame.sequence_number = 1u;
+ new_cid_frame.retire_prior_to = 0u;
+ connection_.OnNewConnectionIdFrame(new_cid_frame);
+ auto* packet_creator = QuicConnectionPeer::GetPacketCreator(&connection_);
+ ASSERT_EQ(packet_creator->GetDestinationConnectionId(), client_cid0);
+ ASSERT_EQ(packet_creator->GetSourceConnectionId(), server_cid0);
// Clear direct_peer_address.
QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
@@ -2008,13 +2117,8 @@ TEST_P(QuicConnectionTest, ReversePathValidationFailureAtServer) {
EXPECT_CALL(visitor_, OnStreamFrame(_))
.WillOnce(Invoke(
[=]() { EXPECT_EQ(kPeerAddress, connection_.peer_address()); }))
- .WillOnce(Invoke([=]() {
- EXPECT_EQ((GetQuicReloadableFlag(quic_start_peer_migration_earlier) ||
- !GetParam().version.HasIetfQuicFrames()
- ? kNewPeerAddress
- : kPeerAddress),
- connection_.peer_address());
- }));
+ .WillOnce(Invoke(
+ [=]() { EXPECT_EQ(kNewPeerAddress, connection_.peer_address()); }));
QuicFrames frames;
frames.push_back(QuicFrame(frame1_));
ProcessFramesPacketWithAddresses(frames, kSelfAddress, kPeerAddress,
@@ -2033,6 +2137,7 @@ TEST_P(QuicConnectionTest, ReversePathValidationFailureAtServer) {
frames2.push_back(QuicFrame(frame2_));
QuicPaddingFrame padding;
frames2.push_back(QuicFrame(padding));
+ peer_creator_.SetServerConnectionId(server_cid1);
ProcessFramesPacketWithAddresses(frames2, kSelfAddress, kNewPeerAddress,
ENCRYPTION_FORWARD_SECURE);
EXPECT_EQ(kNewPeerAddress, connection_.peer_address());
@@ -2046,6 +2151,15 @@ TEST_P(QuicConnectionTest, ReversePathValidationFailureAtServer) {
EXPECT_EQ(kNewPeerAddress, writer_->last_write_peer_address());
EXPECT_EQ(kNewPeerAddress, connection_.peer_address());
EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
+ const auto* default_path = QuicConnectionPeer::GetDefaultPath(&connection_);
+ const auto* alternative_path =
+ QuicConnectionPeer::GetAlternativePath(&connection_);
+ EXPECT_EQ(default_path->client_connection_id, client_cid1);
+ EXPECT_EQ(default_path->server_connection_id, server_cid1);
+ EXPECT_EQ(alternative_path->client_connection_id, client_cid0);
+ EXPECT_EQ(alternative_path->server_connection_id, server_cid0);
+ EXPECT_EQ(packet_creator->GetDestinationConnectionId(), client_cid1);
+ EXPECT_EQ(packet_creator->GetSourceConnectionId(), server_cid1);
for (size_t i = 0; i < QuicPathValidator::kMaxRetryTimes; ++i) {
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(3 * kInitialRttMs));
@@ -2072,6 +2186,19 @@ TEST_P(QuicConnectionTest, ReversePathValidationFailureAtServer) {
EXPECT_EQ(connection_.sent_packet_manager().GetSendAlgorithm(),
send_algorithm_);
EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
+
+ // Verify that default_path_ is reverted and alternative_path_ is cleared.
+ EXPECT_EQ(default_path->client_connection_id, client_cid0);
+ EXPECT_EQ(default_path->server_connection_id, server_cid0);
+ EXPECT_TRUE(alternative_path->server_connection_id.IsEmpty());
+ EXPECT_FALSE(alternative_path->stateless_reset_token_received);
+ auto* retire_peer_issued_cid_alarm =
+ connection_.GetRetirePeerIssuedConnectionIdAlarm();
+ ASSERT_TRUE(retire_peer_issued_cid_alarm->IsSet());
+ EXPECT_CALL(visitor_, SendRetireConnectionId(/*sequence_number=*/1u));
+ retire_peer_issued_cid_alarm->Fire();
+ EXPECT_EQ(packet_creator->GetDestinationConnectionId(), client_cid0);
+ EXPECT_EQ(packet_creator->GetSourceConnectionId(), server_cid0);
}
TEST_P(QuicConnectionTest, ReceivePathProbeWithNoAddressChangeAtServer) {
@@ -2184,10 +2311,12 @@ class TestQuicPathValidationContext : public QuicPathValidationContext {
class TestValidationResultDelegate : public QuicPathValidator::ResultDelegate {
public:
- TestValidationResultDelegate(const QuicSocketAddress& expected_self_address,
+ TestValidationResultDelegate(QuicConnection* connection,
+ const QuicSocketAddress& expected_self_address,
const QuicSocketAddress& expected_peer_address,
bool* success)
: QuicPathValidator::ResultDelegate(),
+ connection_(connection),
expected_self_address_(expected_self_address),
expected_peer_address_(expected_peer_address),
success_(success) {}
@@ -2202,10 +2331,14 @@ class TestValidationResultDelegate : public QuicPathValidator::ResultDelegate {
std::unique_ptr<QuicPathValidationContext> context) override {
EXPECT_EQ(expected_self_address_, context->self_address());
EXPECT_EQ(expected_peer_address_, context->peer_address());
+ if (connection_->perspective() == Perspective::IS_CLIENT) {
+ connection_->OnPathValidationFailureAtClient();
+ }
*success_ = false;
}
private:
+ QuicConnection* connection_;
QuicSocketAddress expected_self_address_;
QuicSocketAddress expected_peer_address_;
bool* success_;
@@ -2291,7 +2424,8 @@ TEST_P(QuicConnectionTest, ReceivePathProbingAtServer) {
std::make_unique<TestQuicPathValidationContext>(
connection_.self_address(), kNewPeerAddress, writer_.get()),
std::make_unique<TestValidationResultDelegate>(
- connection_.self_address(), kNewPeerAddress, &success));
+ &connection_, connection_.self_address(), kNewPeerAddress,
+ &success));
}
EXPECT_EQ((connection_.validate_client_address() ? 2 : 3) * bytes_sent,
QuicConnectionPeer::BytesSentOnAlternativePath(&connection_));
@@ -2836,8 +2970,7 @@ TEST_P(QuicConnectionTest, PacketsOutOfOrderWithAdditionsAndLeastAwaiting) {
TEST_P(QuicConnectionTest, RejectUnencryptedStreamData) {
// EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
if (!IsDefaultTestConfiguration() ||
- (GetQuicReloadableFlag(quic_reject_unexpected_ietf_frame_types) &&
- VersionHasIetfQuicFrames(version().transport_version))) {
+ VersionHasIetfQuicFrames(version().transport_version)) {
return;
}
@@ -3169,20 +3302,6 @@ TEST_P(QuicConnectionTest, TooManySentPackets) {
ProcessFramePacket(QuicFrame(QuicPingFrame()));
- if (!GetQuicReloadableFlag(
- quic_close_connection_with_too_many_outstanding_packets)) {
- // When the flag is false, the ping packet processed above shouldn't cause
- // the connection to close. But the ack packet below will.
- EXPECT_TRUE(connection_.connected());
-
- // Ack packet 1, which leaves more than the limit outstanding.
- EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
-
- // Nack the first packet and ack the rest, leaving a huge gap.
- QuicAckFrame frame1 = ConstructAckFrame(num_packets, 1);
- ProcessAckPacket(&frame1);
- }
-
TestConnectionCloseQuicErrorCode(QUIC_TOO_MANY_OUTSTANDING_SENT_PACKETS);
}
@@ -3390,15 +3509,15 @@ TEST_P(QuicConnectionTest, FramePackingNonCryptoThenCrypto) {
EXPECT_EQ(0u, connection_.NumQueuedPackets());
EXPECT_FALSE(connection_.HasQueuedData());
- // Parse the last packet and ensure it's the crypto stream frame.
- EXPECT_EQ(2u, writer_->frame_count());
- ASSERT_EQ(1u, writer_->padding_frames().size());
+ // Parse the last packet and ensure it contains a crypto stream frame.
+ EXPECT_LE(2u, writer_->frame_count());
+ ASSERT_LE(1u, writer_->padding_frames().size());
if (!QuicVersionUsesCryptoFrames(connection_.transport_version())) {
ASSERT_EQ(1u, writer_->stream_frames().size());
EXPECT_EQ(QuicUtils::GetCryptoStreamId(connection_.transport_version()),
writer_->stream_frames()[0]->stream_id);
} else {
- EXPECT_EQ(1u, writer_->crypto_frames().size());
+ EXPECT_LE(1u, writer_->crypto_frames().size());
}
}
@@ -7081,7 +7200,7 @@ TEST_P(QuicConnectionTest, CheckSendStats) {
stats.bytes_retransmitted);
EXPECT_EQ(3u, stats.packets_retransmitted);
EXPECT_EQ(1u, stats.rto_count);
- EXPECT_EQ(kDefaultMaxPacketSize, stats.max_packet_size);
+ EXPECT_EQ(kDefaultMaxPacketSize, stats.egress_mtu);
}
TEST_P(QuicConnectionTest, ProcessFramesIfPacketClosedConnection) {
@@ -7787,8 +7906,7 @@ TEST_P(QuicConnectionTest, ServerReceivesChloOnNonCryptoStream) {
EXPECT_CALL(visitor_,
OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
ForceProcessFramePacket(QuicFrame(frame1_));
- if (GetQuicReloadableFlag(quic_reject_unexpected_ietf_frame_types) &&
- VersionHasIetfQuicFrames(version().transport_version)) {
+ if (VersionHasIetfQuicFrames(version().transport_version)) {
// INITIAL packet should not contain STREAM frame.
TestConnectionCloseQuicErrorCode(IETF_QUIC_PROTOCOL_VIOLATION);
} else {
@@ -7810,8 +7928,7 @@ TEST_P(QuicConnectionTest, ClientReceivesRejOnNonCryptoStream) {
EXPECT_CALL(visitor_,
OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
ForceProcessFramePacket(QuicFrame(frame1_));
- if (GetQuicReloadableFlag(quic_reject_unexpected_ietf_frame_types) &&
- VersionHasIetfQuicFrames(version().transport_version)) {
+ if (VersionHasIetfQuicFrames(version().transport_version)) {
// INITIAL packet should not contain STREAM frame.
TestConnectionCloseQuicErrorCode(IETF_QUIC_PROTOCOL_VIOLATION);
} else {
@@ -8899,7 +9016,7 @@ TEST_P(QuicConnectionTest, ClientResponseToPathChallengeOnAlternativeSocket) {
std::make_unique<TestQuicPathValidationContext>(
kNewSelfAddress, connection_.peer_address(), &new_writer),
std::make_unique<TestValidationResultDelegate>(
- kNewSelfAddress, connection_.peer_address(), &success));
+ &connection_, kNewSelfAddress, connection_.peer_address(), &success));
// Receiving a PATH_CHALLENGE on the alternative path. Response to this
// PATH_CHALLENGE should be sent via the alternative writer.
@@ -9300,7 +9417,7 @@ TEST_P(QuicConnectionTest, ValidClientConnectionId) {
return;
}
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- connection_.set_client_connection_id(TestConnectionId(0x33));
+ SetClientConnectionId(TestConnectionId(0x33));
QuicPacketHeader header = ConstructPacketHeader(1, ENCRYPTION_FORWARD_SECURE);
header.destination_connection_id = TestConnectionId(0x33);
header.destination_connection_id_included = CONNECTION_ID_PRESENT;
@@ -9328,7 +9445,7 @@ TEST_P(QuicConnectionTest, InvalidClientConnectionId) {
if (!framer_.version().SupportsClientConnectionIds()) {
return;
}
- connection_.set_client_connection_id(TestConnectionId(0x33));
+ SetClientConnectionId(TestConnectionId(0x33));
QuicPacketHeader header = ConstructPacketHeader(1, ENCRYPTION_FORWARD_SECURE);
header.destination_connection_id = TestConnectionId(0xbad);
header.destination_connection_id_included = CONNECTION_ID_PRESENT;
@@ -11162,8 +11279,7 @@ TEST_P(QuicConnectionTest, ProcessUndecryptablePacketsBasedOnEncryptionLevel) {
std::make_unique<TaggingEncrypter>(0x01));
connection_.SetDefaultEncryptionLevel(ENCRYPTION_HANDSHAKE);
// Verify all ENCRYPTION_HANDSHAKE packets get processed.
- if (!GetQuicReloadableFlag(quic_reject_unexpected_ietf_frame_types) ||
- !VersionHasIetfQuicFrames(version().transport_version)) {
+ if (!VersionHasIetfQuicFrames(version().transport_version)) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(6);
}
connection_.GetProcessUndecryptablePacketsAlarm()->Fire();
@@ -11750,7 +11866,7 @@ TEST_P(QuicConnectionTest, PathValidationOnNewSocketSuccess) {
std::make_unique<TestQuicPathValidationContext>(
kNewSelfAddress, connection_.peer_address(), &new_writer),
std::make_unique<TestValidationResultDelegate>(
- kNewSelfAddress, connection_.peer_address(), &success));
+ &connection_, kNewSelfAddress, connection_.peer_address(), &success));
EXPECT_EQ(0u, writer_->packets_write_attempts());
QuicFrames frames;
@@ -11784,30 +11900,39 @@ TEST_P(QuicConnectionTest, NewPathValidationCancelsPreviousOne) {
std::make_unique<TestQuicPathValidationContext>(
kNewSelfAddress, connection_.peer_address(), &new_writer),
std::make_unique<TestValidationResultDelegate>(
- kNewSelfAddress, connection_.peer_address(), &success));
+ &connection_, kNewSelfAddress, connection_.peer_address(), &success));
EXPECT_EQ(0u, writer_->packets_write_attempts());
// Start another path validation request.
const QuicSocketAddress kNewSelfAddress2(QuicIpAddress::Any4(), 12346);
EXPECT_NE(kNewSelfAddress2, connection_.self_address());
TestPacketWriter new_writer2(version(), &clock_, Perspective::IS_CLIENT);
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
- .Times(AtLeast(1u))
- .WillOnce(Invoke([&]() {
- EXPECT_EQ(1u, new_writer2.packets_write_attempts());
- EXPECT_EQ(1u, new_writer2.path_challenge_frames().size());
- EXPECT_EQ(1u, new_writer2.padding_frames().size());
- EXPECT_EQ(kNewSelfAddress2.host(),
- new_writer2.last_write_source_address());
- }));
+ if (!connection_.connection_migration_use_new_cid()) {
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .Times(AtLeast(1u))
+ .WillOnce(Invoke([&]() {
+ EXPECT_EQ(1u, new_writer2.packets_write_attempts());
+ EXPECT_EQ(1u, new_writer2.path_challenge_frames().size());
+ EXPECT_EQ(1u, new_writer2.padding_frames().size());
+ EXPECT_EQ(kNewSelfAddress2.host(),
+ new_writer2.last_write_source_address());
+ }));
+ }
bool success2 = false;
connection_.ValidatePath(
std::make_unique<TestQuicPathValidationContext>(
kNewSelfAddress2, connection_.peer_address(), &new_writer2),
std::make_unique<TestValidationResultDelegate>(
- kNewSelfAddress2, connection_.peer_address(), &success2));
+ &connection_, kNewSelfAddress2, connection_.peer_address(),
+ &success2));
EXPECT_FALSE(success);
- EXPECT_TRUE(connection_.HasPendingPathValidation());
+ if (connection_.connection_migration_use_new_cid()) {
+ // There is no pening path validation as there is no available connection
+ // ID.
+ EXPECT_FALSE(connection_.HasPendingPathValidation());
+ } else {
+ EXPECT_TRUE(connection_.HasPendingPathValidation());
+ }
}
// Regression test for b/182571515.
@@ -11825,12 +11950,12 @@ TEST_P(QuicConnectionTest, PathValidationRetry) {
EXPECT_EQ(1u, writer_->padding_frames().size());
}));
bool success = true;
- connection_.ValidatePath(
- std::make_unique<TestQuicPathValidationContext>(
- connection_.self_address(), connection_.peer_address(),
- writer_.get()),
- std::make_unique<TestValidationResultDelegate>(
- connection_.self_address(), connection_.peer_address(), &success));
+ connection_.ValidatePath(std::make_unique<TestQuicPathValidationContext>(
+ connection_.self_address(),
+ connection_.peer_address(), writer_.get()),
+ std::make_unique<TestValidationResultDelegate>(
+ &connection_, connection_.self_address(),
+ connection_.peer_address(), &success));
EXPECT_EQ(1u, writer_->packets_write_attempts());
EXPECT_TRUE(connection_.HasPendingPathValidation());
@@ -11872,7 +11997,7 @@ TEST_P(QuicConnectionTest, PathValidationReceivesStatelessReset) {
std::make_unique<TestQuicPathValidationContext>(
kNewSelfAddress, connection_.peer_address(), &new_writer),
std::make_unique<TestValidationResultDelegate>(
- kNewSelfAddress, connection_.peer_address(), &success));
+ &connection_, kNewSelfAddress, connection_.peer_address(), &success));
EXPECT_EQ(0u, writer_->packets_write_attempts());
EXPECT_TRUE(connection_.HasPendingPathValidation());
@@ -11916,7 +12041,7 @@ TEST_P(QuicConnectionTest, SendPathChallengeUsingBlockedNewSocket) {
std::make_unique<TestQuicPathValidationContext>(
kNewSelfAddress, connection_.peer_address(), &new_writer),
std::make_unique<TestValidationResultDelegate>(
- kNewSelfAddress, connection_.peer_address(), &success));
+ &connection_, kNewSelfAddress, connection_.peer_address(), &success));
EXPECT_EQ(0u, writer_->packets_write_attempts());
new_writer.SetWritable();
@@ -11976,7 +12101,8 @@ TEST_P(QuicConnectionTest, SendPathChallengeUsingBlockedDefaultSocket) {
std::make_unique<TestQuicPathValidationContext>(
connection_.self_address(), kNewPeerAddress, writer_.get()),
std::make_unique<TestValidationResultDelegate>(
- connection_.self_address(), kNewPeerAddress, &success));
+ &connection_, connection_.self_address(), kNewPeerAddress,
+ &success));
}
EXPECT_EQ(1u, writer_->packets_write_attempts());
@@ -12020,7 +12146,7 @@ TEST_P(QuicConnectionTest, SendPathChallengeFailOnNewSocket) {
std::make_unique<TestQuicPathValidationContext>(
kNewSelfAddress, connection_.peer_address(), &new_writer),
std::make_unique<TestValidationResultDelegate>(
- kNewSelfAddress, connection_.peer_address(), &success));
+ &connection_, kNewSelfAddress, connection_.peer_address(), &success));
EXPECT_EQ(1u, new_writer.packets_write_attempts());
EXPECT_EQ(1u, new_writer.path_challenge_frames().size());
EXPECT_EQ(1u, new_writer.padding_frames().size());
@@ -12052,12 +12178,12 @@ TEST_P(QuicConnectionTest, SendPathChallengeFailOnDefaultPath) {
// packet creator.
bool success = false;
QuicConnection::ScopedPacketFlusher flusher(&connection_);
- connection_.ValidatePath(
- std::make_unique<TestQuicPathValidationContext>(
- connection_.self_address(), connection_.peer_address(),
- writer_.get()),
- std::make_unique<TestValidationResultDelegate>(
- connection_.self_address(), connection_.peer_address(), &success));
+ connection_.ValidatePath(std::make_unique<TestQuicPathValidationContext>(
+ connection_.self_address(),
+ connection_.peer_address(), writer_.get()),
+ std::make_unique<TestValidationResultDelegate>(
+ &connection_, connection_.self_address(),
+ connection_.peer_address(), &success));
}
EXPECT_EQ(1u, writer_->packets_write_attempts());
EXPECT_EQ(1u, writer_->path_challenge_frames().size());
@@ -12089,7 +12215,7 @@ TEST_P(QuicConnectionTest, SendPathChallengeFailOnAlternativePeerAddress) {
std::make_unique<TestQuicPathValidationContext>(
connection_.self_address(), kNewPeerAddress, writer_.get()),
std::make_unique<TestValidationResultDelegate>(
- connection_.self_address(), kNewPeerAddress, &success));
+ &connection_, connection_.self_address(), kNewPeerAddress, &success));
EXPECT_EQ(1u, writer_->packets_write_attempts());
EXPECT_FALSE(connection_.HasPendingPathValidation());
@@ -12120,7 +12246,7 @@ TEST_P(QuicConnectionTest,
std::make_unique<TestQuicPathValidationContext>(
connection_.self_address(), kNewPeerAddress, writer_.get()),
std::make_unique<TestValidationResultDelegate>(
- connection_.self_address(), kNewPeerAddress, &success));
+ &connection_, connection_.self_address(), kNewPeerAddress, &success));
EXPECT_TRUE(connection_.HasPendingPathValidation());
// Connection shouldn't be closed.
EXPECT_TRUE(connection_.connected());
@@ -12391,7 +12517,12 @@ TEST_P(QuicConnectionTest, FailToWritePathResponse) {
ProcessFramesPacketWithAddresses(frames, kSelfAddress, kNewPeerAddress,
ENCRYPTION_FORWARD_SECURE);
- EXPECT_EQ(
+ if (GetQuicReloadableFlag(quic_drop_unsent_path_response)) {
+ EXPECT_EQ(0u, QuicConnectionPeer::NumPendingPathChallengesToResponse(
+ &connection_));
+ return;
+ }
+ ASSERT_EQ(
1u, QuicConnectionPeer::NumPendingPathChallengesToResponse(&connection_));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1));
@@ -13444,6 +13575,9 @@ TEST_P(QuicConnectionTest, ServerHelloGetsReordered) {
}
TEST_P(QuicConnectionTest, MigratePath) {
+ EXPECT_CALL(visitor_, GetHandshakeState())
+ .Times(testing::AtMost(1))
+ .WillOnce(Return(HANDSHAKE_CONFIRMED));
EXPECT_CALL(visitor_, OnPathDegrading());
connection_.OnPathDegradingDetected();
const QuicSocketAddress kNewSelfAddress(QuicIpAddress::Any4(), 12345);
@@ -13472,7 +13606,7 @@ TEST_P(QuicConnectionTest, MigrateToNewPathDuringProbing) {
std::make_unique<TestQuicPathValidationContext>(
kNewSelfAddress, connection_.peer_address(), &new_writer),
std::make_unique<TestValidationResultDelegate>(
- kNewSelfAddress, connection_.peer_address(), &success));
+ &connection_, kNewSelfAddress, connection_.peer_address(), &success));
EXPECT_TRUE(connection_.HasPendingPathValidation());
EXPECT_TRUE(QuicConnectionPeer::IsAlternativePath(
&connection_, kNewSelfAddress, connection_.peer_address()));
@@ -13568,7 +13702,6 @@ TEST_P(QuicConnectionTest, NewTokenFrameInstigateAcks) {
if (!version().HasIetfQuicFrames()) {
return;
}
- SetQuicReloadableFlag(quic_enable_token_based_address_validation, true);
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
QuicNewTokenFrame* new_token = new QuicNewTokenFrame();
@@ -13583,7 +13716,6 @@ TEST_P(QuicConnectionTest, ServerClosesConnectionOnNewTokenFrame) {
if (!version().HasIetfQuicFrames()) {
return;
}
- SetQuicReloadableFlag(quic_enable_token_based_address_validation, true);
set_perspective(Perspective::IS_SERVER);
QuicNewTokenFrame* new_token = new QuicNewTokenFrame();
EXPECT_CALL(visitor_, OnNewTokenReceived(_)).Times(0);
@@ -13686,8 +13818,7 @@ TEST_P(QuicConnectionTest,
// Regression test for b/177312785
TEST_P(QuicConnectionTest, PeerMigrateBeforeHandshakeConfirm) {
- if (!VersionHasIetfQuicFrames(version().transport_version) ||
- !GetQuicReloadableFlag(quic_start_peer_migration_earlier)) {
+ if (!VersionHasIetfQuicFrames(version().transport_version)) {
return;
}
set_perspective(Perspective::IS_SERVER);
@@ -13755,11 +13886,34 @@ TEST_P(QuicConnectionTest, TryToFlushAckWithAckQueued) {
TEST_P(QuicConnectionTest, PathChallengeBeforePeerIpAddressChangeAtServer) {
set_perspective(Perspective::IS_SERVER);
- if (!connection_.validate_client_address()) {
+ if (!connection_.connection_migration_use_new_cid()) {
return;
}
PathProbeTestInit(Perspective::IS_SERVER);
+ SetClientConnectionId(TestConnectionId(1));
+ connection_.CreateConnectionIdManager();
+ QuicConnectionId server_cid0 = connection_.connection_id();
+ QuicConnectionId client_cid0 = connection_.client_connection_id();
+ QuicConnectionId client_cid1 = TestConnectionId(2);
+ QuicConnectionId server_cid1;
+ // Sends new server CID to client.
+ EXPECT_CALL(visitor_, OnServerConnectionIdIssued(_))
+ .WillOnce(
+ Invoke([&](const QuicConnectionId& cid) { server_cid1 = cid; }));
+ EXPECT_CALL(visitor_, SendNewConnectionId(_));
+ connection_.MaybeSendConnectionIdToClient();
+ // Receives new client CID from client.
+ QuicNewConnectionIdFrame new_cid_frame;
+ new_cid_frame.connection_id = client_cid1;
+ new_cid_frame.sequence_number = 1u;
+ new_cid_frame.retire_prior_to = 0u;
+ connection_.OnNewConnectionIdFrame(new_cid_frame);
+ auto* packet_creator = QuicConnectionPeer::GetPacketCreator(&connection_);
+ ASSERT_EQ(packet_creator->GetDestinationConnectionId(), client_cid0);
+ ASSERT_EQ(packet_creator->GetSourceConnectionId(), server_cid0);
+
+ peer_creator_.SetServerConnectionId(server_cid1);
const QuicSocketAddress kNewPeerAddress =
QuicSocketAddress(QuicIpAddress::Loopback4(), /*port=*/23456);
QuicPathFrameBuffer path_challenge_payload{0, 1, 2, 3, 4, 5, 6, 7};
@@ -13783,6 +13937,15 @@ TEST_P(QuicConnectionTest, PathChallengeBeforePeerIpAddressChangeAtServer) {
EXPECT_EQ(kPeerAddress, connection_.peer_address());
EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
EXPECT_TRUE(connection_.HasPendingPathValidation());
+ const auto* default_path = QuicConnectionPeer::GetDefaultPath(&connection_);
+ const auto* alternative_path =
+ QuicConnectionPeer::GetAlternativePath(&connection_);
+ EXPECT_EQ(default_path->client_connection_id, client_cid0);
+ EXPECT_EQ(default_path->server_connection_id, server_cid0);
+ EXPECT_EQ(alternative_path->client_connection_id, client_cid1);
+ EXPECT_EQ(alternative_path->server_connection_id, server_cid1);
+ EXPECT_EQ(packet_creator->GetDestinationConnectionId(), client_cid0);
+ EXPECT_EQ(packet_creator->GetSourceConnectionId(), server_cid0);
// Process another packet with a different peer address on server side will
// start connection migration.
@@ -13819,6 +13982,14 @@ TEST_P(QuicConnectionTest, PathChallengeBeforePeerIpAddressChangeAtServer) {
EXPECT_CALL(*send_algorithm_, InRecovery()).Times(AnyNumber());
EXPECT_CALL(*send_algorithm_, PopulateConnectionStats(_)).Times(AnyNumber());
connection_.SetSendAlgorithm(send_algorithm_);
+ EXPECT_EQ(default_path->client_connection_id, client_cid1);
+ EXPECT_EQ(default_path->server_connection_id, server_cid1);
+ // The previous default path is kept as alternative path before reverse path
+ // validation finishes.
+ EXPECT_EQ(alternative_path->client_connection_id, client_cid0);
+ EXPECT_EQ(alternative_path->server_connection_id, server_cid0);
+ EXPECT_EQ(packet_creator->GetDestinationConnectionId(), client_cid1);
+ EXPECT_EQ(packet_creator->GetSourceConnectionId(), server_cid1);
EXPECT_EQ(kNewPeerAddress, connection_.peer_address());
EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
@@ -13842,6 +14013,15 @@ TEST_P(QuicConnectionTest, PathChallengeBeforePeerIpAddressChangeAtServer) {
ProcessFramesPacketWithAddresses(frames3, kSelfAddress, kNewPeerAddress,
ENCRYPTION_FORWARD_SECURE);
EXPECT_EQ(NO_CHANGE, connection_.active_effective_peer_migration_type());
+ // Verify that alternative_path_ is cleared and the peer CID is retired.
+ EXPECT_TRUE(alternative_path->client_connection_id.IsEmpty());
+ EXPECT_TRUE(alternative_path->server_connection_id.IsEmpty());
+ EXPECT_FALSE(alternative_path->stateless_reset_token_received);
+ auto* retire_peer_issued_cid_alarm =
+ connection_.GetRetirePeerIssuedConnectionIdAlarm();
+ ASSERT_TRUE(retire_peer_issued_cid_alarm->IsSet());
+ EXPECT_CALL(visitor_, SendRetireConnectionId(/*sequence_number=*/0u));
+ retire_peer_issued_cid_alarm->Fire();
// Verify the anti-amplification limit is lifted by sending a packet larger
// than the anti-amplification limit.
@@ -13853,12 +14033,25 @@ TEST_P(QuicConnectionTest, PathChallengeBeforePeerIpAddressChangeAtServer) {
TEST_P(QuicConnectionTest,
PathValidationSucceedsBeforePeerIpAddressChangeAtServer) {
set_perspective(Perspective::IS_SERVER);
- if (!connection_.validate_client_address()) {
+ if (!connection_.connection_migration_use_new_cid()) {
return;
}
PathProbeTestInit(Perspective::IS_SERVER);
+ connection_.CreateConnectionIdManager();
+
+ QuicConnectionId server_cid0 = connection_.connection_id();
+ QuicConnectionId server_cid1;
+ // Sends new server CID to client.
+ EXPECT_CALL(visitor_, OnServerConnectionIdIssued(_))
+ .WillOnce(
+ Invoke([&](const QuicConnectionId& cid) { server_cid1 = cid; }));
+ EXPECT_CALL(visitor_, SendNewConnectionId(_));
+ connection_.MaybeSendConnectionIdToClient();
+ auto* packet_creator = QuicConnectionPeer::GetPacketCreator(&connection_);
+ ASSERT_EQ(packet_creator->GetSourceConnectionId(), server_cid0);
// Receive probing packet with new peer address.
+ peer_creator_.SetServerConnectionId(server_cid1);
const QuicSocketAddress kNewPeerAddress(QuicIpAddress::Loopback4(),
/*port=*/23456);
QuicPathFrameBuffer payload;
@@ -13883,6 +14076,12 @@ TEST_P(QuicConnectionTest,
ProcessFramesPacketWithAddresses(frames1, kSelfAddress, kNewPeerAddress,
ENCRYPTION_FORWARD_SECURE);
EXPECT_TRUE(connection_.HasPendingPathValidation());
+ const auto* default_path = QuicConnectionPeer::GetDefaultPath(&connection_);
+ const auto* alternative_path =
+ QuicConnectionPeer::GetAlternativePath(&connection_);
+ EXPECT_EQ(default_path->server_connection_id, server_cid0);
+ EXPECT_EQ(alternative_path->server_connection_id, server_cid1);
+ EXPECT_EQ(packet_creator->GetSourceConnectionId(), server_cid0);
// Receive PATH_RESPONSE should mark the new peer address validated.
QuicFrames frames3;
@@ -13920,6 +14119,12 @@ TEST_P(QuicConnectionTest,
EXPECT_NE(connection_.sent_packet_manager().GetSendAlgorithm(),
send_algorithm_);
+ EXPECT_EQ(default_path->server_connection_id, server_cid1);
+ EXPECT_EQ(packet_creator->GetSourceConnectionId(), server_cid1);
+ // Verify that alternative_path_ is cleared.
+ EXPECT_TRUE(alternative_path->server_connection_id.IsEmpty());
+ EXPECT_FALSE(alternative_path->stateless_reset_token_received);
+
// Switch to use the mock send algorithm.
send_algorithm_ = new StrictMock<MockSendAlgorithm>();
EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
@@ -14005,6 +14210,255 @@ TEST_P(QuicConnectionTest,
}
TEST_P(QuicConnectionTest,
+ PathValidationFailedOnClientDueToLackOfServerConnectionId) {
+ QuicConfig config;
+ config.SetConnectionOptionsToSend({kRVCM});
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ connection_.SetFromConfig(config);
+ if (!connection_.connection_migration_use_new_cid()) {
+ return;
+ }
+ PathProbeTestInit(Perspective::IS_CLIENT,
+ /*receive_new_server_connection_id=*/false);
+
+ const QuicSocketAddress kNewSelfAddress(QuicIpAddress::Loopback4(),
+ /*port=*/34567);
+
+ bool success;
+ connection_.ValidatePath(
+ std::make_unique<TestQuicPathValidationContext>(
+ kNewSelfAddress, connection_.peer_address(), writer_.get()),
+ std::make_unique<TestValidationResultDelegate>(
+ &connection_, kNewSelfAddress, connection_.peer_address(), &success));
+
+ EXPECT_FALSE(success);
+}
+
+TEST_P(QuicConnectionTest,
+ PathValidationFailedOnClientDueToLackOfClientConnectionIdTheSecondTime) {
+ QuicConfig config;
+ config.SetConnectionOptionsToSend({kRVCM});
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ connection_.SetFromConfig(config);
+ if (!connection_.connection_migration_use_new_cid()) {
+ return;
+ }
+ PathProbeTestInit(Perspective::IS_CLIENT,
+ /*receive_new_server_connection_id=*/false);
+ SetClientConnectionId(TestConnectionId(1));
+
+ // Make sure server connection ID is available for the 1st validation.
+ QuicConnectionId server_cid0 = connection_.connection_id();
+ QuicConnectionId server_cid1 = TestConnectionId(2);
+ QuicConnectionId server_cid2 = TestConnectionId(4);
+ QuicConnectionId client_cid1;
+ QuicNewConnectionIdFrame frame1;
+ frame1.connection_id = server_cid1;
+ frame1.sequence_number = 1u;
+ frame1.retire_prior_to = 0u;
+ frame1.stateless_reset_token =
+ QuicUtils::GenerateStatelessResetToken(frame1.connection_id);
+ connection_.OnNewConnectionIdFrame(frame1);
+ const auto* packet_creator =
+ QuicConnectionPeer::GetPacketCreator(&connection_);
+ ASSERT_EQ(packet_creator->GetDestinationConnectionId(), server_cid0);
+
+ // Client will issue a new client connection ID to server.
+ EXPECT_CALL(visitor_, SendNewConnectionId(_))
+ .WillOnce(Invoke([&](const QuicNewConnectionIdFrame& frame) {
+ client_cid1 = frame.connection_id;
+ }));
+
+ const QuicSocketAddress kSelfAddress1(QuicIpAddress::Any4(), 12345);
+ ASSERT_NE(kSelfAddress1, connection_.self_address());
+ bool success1;
+ connection_.ValidatePath(
+ std::make_unique<TestQuicPathValidationContext>(
+ kSelfAddress1, connection_.peer_address(), writer_.get()),
+ std::make_unique<TestValidationResultDelegate>(
+ &connection_, kSelfAddress1, connection_.peer_address(), &success1));
+
+ // Migrate upon 1st validation success.
+ TestPacketWriter new_writer(version(), &clock_, Perspective::IS_CLIENT);
+ ASSERT_TRUE(connection_.MigratePath(kSelfAddress1, connection_.peer_address(),
+ &new_writer, /*owns_writer=*/false));
+ QuicConnectionPeer::RetirePeerIssuedConnectionIdsNoLongerOnPath(&connection_);
+ const auto* default_path = QuicConnectionPeer::GetDefaultPath(&connection_);
+ EXPECT_EQ(default_path->client_connection_id, client_cid1);
+ EXPECT_EQ(default_path->server_connection_id, server_cid1);
+ EXPECT_EQ(default_path->stateless_reset_token, frame1.stateless_reset_token);
+ EXPECT_TRUE(default_path->stateless_reset_token_received);
+ const auto* alternative_path =
+ QuicConnectionPeer::GetAlternativePath(&connection_);
+ EXPECT_TRUE(alternative_path->client_connection_id.IsEmpty());
+ EXPECT_TRUE(alternative_path->server_connection_id.IsEmpty());
+ EXPECT_FALSE(alternative_path->stateless_reset_token_received);
+ ASSERT_EQ(packet_creator->GetDestinationConnectionId(), server_cid1);
+
+ // Client will retire server connection ID on old default_path.
+ auto* retire_peer_issued_cid_alarm =
+ connection_.GetRetirePeerIssuedConnectionIdAlarm();
+ ASSERT_TRUE(retire_peer_issued_cid_alarm->IsSet());
+ EXPECT_CALL(visitor_, SendRetireConnectionId(/*sequence_number=*/0u));
+ retire_peer_issued_cid_alarm->Fire();
+
+ // Another server connection ID is available to client.
+ QuicNewConnectionIdFrame frame2;
+ frame2.connection_id = server_cid2;
+ frame2.sequence_number = 2u;
+ frame2.retire_prior_to = 1u;
+ frame2.stateless_reset_token =
+ QuicUtils::GenerateStatelessResetToken(frame2.connection_id);
+ connection_.OnNewConnectionIdFrame(frame2);
+
+ const QuicSocketAddress kSelfAddress2(QuicIpAddress::Loopback4(),
+ /*port=*/45678);
+ bool success2;
+ connection_.ValidatePath(
+ std::make_unique<TestQuicPathValidationContext>(
+ kSelfAddress2, connection_.peer_address(), writer_.get()),
+ std::make_unique<TestValidationResultDelegate>(
+ &connection_, kSelfAddress2, connection_.peer_address(), &success2));
+ // Since server does not retire any client connection ID yet, 2nd validation
+ // would fail due to lack of client connection ID.
+ EXPECT_FALSE(success2);
+}
+
+TEST_P(QuicConnectionTest, ServerConnectionIdRetiredUponPathValidationFailure) {
+ QuicConfig config;
+ config.SetConnectionOptionsToSend({kRVCM});
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ connection_.SetFromConfig(config);
+ if (!connection_.connection_migration_use_new_cid()) {
+ return;
+ }
+ PathProbeTestInit(Perspective::IS_CLIENT);
+
+ // Make sure server connection ID is available for validation.
+ QuicNewConnectionIdFrame frame;
+ frame.connection_id = TestConnectionId(2);
+ frame.sequence_number = 1u;
+ frame.retire_prior_to = 0u;
+ frame.stateless_reset_token =
+ QuicUtils::GenerateStatelessResetToken(frame.connection_id);
+ connection_.OnNewConnectionIdFrame(frame);
+
+ const QuicSocketAddress kNewSelfAddress(QuicIpAddress::Loopback4(),
+ /*port=*/34567);
+ bool success;
+ connection_.ValidatePath(
+ std::make_unique<TestQuicPathValidationContext>(
+ kNewSelfAddress, connection_.peer_address(), writer_.get()),
+ std::make_unique<TestValidationResultDelegate>(
+ &connection_, kNewSelfAddress, connection_.peer_address(), &success));
+
+ auto* path_validator = QuicConnectionPeer::path_validator(&connection_);
+ path_validator->CancelPathValidation();
+ QuicConnectionPeer::RetirePeerIssuedConnectionIdsNoLongerOnPath(&connection_);
+ EXPECT_FALSE(success);
+ const auto* alternative_path =
+ QuicConnectionPeer::GetAlternativePath(&connection_);
+ EXPECT_TRUE(alternative_path->client_connection_id.IsEmpty());
+ EXPECT_TRUE(alternative_path->server_connection_id.IsEmpty());
+ EXPECT_FALSE(alternative_path->stateless_reset_token_received);
+
+ // Client will retire server connection ID on alternative_path.
+ auto* retire_peer_issued_cid_alarm =
+ connection_.GetRetirePeerIssuedConnectionIdAlarm();
+ ASSERT_TRUE(retire_peer_issued_cid_alarm->IsSet());
+ EXPECT_CALL(visitor_, SendRetireConnectionId(/*sequence_number=*/1u));
+ retire_peer_issued_cid_alarm->Fire();
+}
+
+TEST_P(QuicConnectionTest,
+ MigratePathDirectlyFailedDueToLackOfServerConnectionId) {
+ QuicConfig config;
+ config.SetConnectionOptionsToSend({kRVCM});
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ connection_.SetFromConfig(config);
+ if (!connection_.connection_migration_use_new_cid()) {
+ return;
+ }
+ PathProbeTestInit(Perspective::IS_CLIENT,
+ /*receive_new_server_connection_id=*/false);
+ const QuicSocketAddress kSelfAddress1(QuicIpAddress::Any4(), 12345);
+ ASSERT_NE(kSelfAddress1, connection_.self_address());
+
+ TestPacketWriter new_writer(version(), &clock_, Perspective::IS_CLIENT);
+ ASSERT_FALSE(connection_.MigratePath(kSelfAddress1,
+ connection_.peer_address(), &new_writer,
+ /*owns_writer=*/false));
+}
+
+TEST_P(QuicConnectionTest,
+ MigratePathDirectlyFailedDueToLackOfClientConnectionIdTheSecondTime) {
+ QuicConfig config;
+ config.SetConnectionOptionsToSend({kRVCM});
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ connection_.SetFromConfig(config);
+ if (!connection_.connection_migration_use_new_cid()) {
+ return;
+ }
+ PathProbeTestInit(Perspective::IS_CLIENT,
+ /*receive_new_server_connection_id=*/false);
+ SetClientConnectionId(TestConnectionId(1));
+
+ // Make sure server connection ID is available for the 1st migration.
+ QuicNewConnectionIdFrame frame1;
+ frame1.connection_id = TestConnectionId(2);
+ frame1.sequence_number = 1u;
+ frame1.retire_prior_to = 0u;
+ frame1.stateless_reset_token =
+ QuicUtils::GenerateStatelessResetToken(frame1.connection_id);
+ connection_.OnNewConnectionIdFrame(frame1);
+
+ // Client will issue a new client connection ID to server.
+ QuicConnectionId new_client_connection_id;
+ EXPECT_CALL(visitor_, SendNewConnectionId(_))
+ .WillOnce(Invoke([&](const QuicNewConnectionIdFrame& frame) {
+ new_client_connection_id = frame.connection_id;
+ }));
+
+ // 1st migration is successful.
+ const QuicSocketAddress kSelfAddress1(QuicIpAddress::Any4(), 12345);
+ ASSERT_NE(kSelfAddress1, connection_.self_address());
+ TestPacketWriter new_writer(version(), &clock_, Perspective::IS_CLIENT);
+ ASSERT_TRUE(connection_.MigratePath(kSelfAddress1, connection_.peer_address(),
+ &new_writer,
+ /*owns_writer=*/false));
+ QuicConnectionPeer::RetirePeerIssuedConnectionIdsNoLongerOnPath(&connection_);
+ const auto* default_path = QuicConnectionPeer::GetDefaultPath(&connection_);
+ EXPECT_EQ(default_path->client_connection_id, new_client_connection_id);
+ EXPECT_EQ(default_path->server_connection_id, frame1.connection_id);
+ EXPECT_EQ(default_path->stateless_reset_token, frame1.stateless_reset_token);
+ EXPECT_TRUE(default_path->stateless_reset_token_received);
+
+ // Client will retire server connection ID on old default_path.
+ auto* retire_peer_issued_cid_alarm =
+ connection_.GetRetirePeerIssuedConnectionIdAlarm();
+ ASSERT_TRUE(retire_peer_issued_cid_alarm->IsSet());
+ EXPECT_CALL(visitor_, SendRetireConnectionId(/*sequence_number=*/0u));
+ retire_peer_issued_cid_alarm->Fire();
+
+ // Another server connection ID is available to client.
+ QuicNewConnectionIdFrame frame2;
+ frame2.connection_id = TestConnectionId(4);
+ frame2.sequence_number = 2u;
+ frame2.retire_prior_to = 1u;
+ frame2.stateless_reset_token =
+ QuicUtils::GenerateStatelessResetToken(frame2.connection_id);
+ connection_.OnNewConnectionIdFrame(frame2);
+
+ // Since server does not retire any client connection ID yet, 2nd migration
+ // would fail due to lack of client connection ID.
+ const QuicSocketAddress kSelfAddress2(QuicIpAddress::Loopback4(),
+ /*port=*/45678);
+ ASSERT_FALSE(connection_.MigratePath(kSelfAddress2,
+ connection_.peer_address(), &new_writer,
+ /*owns_writer=*/false));
+}
+
+TEST_P(QuicConnectionTest,
CloseConnectionAfterReceiveNewConnectionIdFromPeerUsingEmptyCID) {
if (!version().HasIetfQuicFrames()) {
return;
@@ -14098,7 +14552,7 @@ TEST_P(QuicConnectionTest,
}
QuicConnectionPeer::EnableMultipleConnectionIdSupport(&connection_);
set_perspective(Perspective::IS_SERVER);
- connection_.set_client_connection_id(TestConnectionId(0));
+ SetClientConnectionId(TestConnectionId(0));
QuicNewConnectionIdFrame frame;
frame.sequence_number = 1u;
@@ -14129,9 +14583,71 @@ TEST_P(QuicConnectionTest,
TestConnectionId(2));
}
+TEST_P(
+ QuicConnectionTest,
+ ReplacePeerIssuedConnectionIdOnBothPathsTriggeredByNewConnectionIdFrame) {
+ if (!version().HasIetfQuicFrames() || !connection_.use_path_validator() ||
+ !connection_.use_connection_id_on_default_path() ||
+ !connection_.count_bytes_on_alternative_path_separately()) {
+ return;
+ }
+ QuicConnectionPeer::EnableMultipleConnectionIdSupport(&connection_);
+ PathProbeTestInit(Perspective::IS_SERVER);
+ SetClientConnectionId(TestConnectionId(0));
+
+ // Populate alternative_path_ with probing packet.
+ std::unique_ptr<SerializedPacket> probing_packet = ConstructProbingPacket();
+
+ std::unique_ptr<QuicReceivedPacket> received(ConstructReceivedPacket(
+ QuicEncryptedPacket(probing_packet->encrypted_buffer,
+ probing_packet->encrypted_length),
+ clock_.Now()));
+ QuicIpAddress new_host;
+ new_host.FromString("1.1.1.1");
+ ProcessReceivedPacket(kSelfAddress,
+ QuicSocketAddress(new_host, /*port=*/23456), *received);
+
+ EXPECT_EQ(
+ TestConnectionId(0),
+ QuicConnectionPeer::GetClientConnectionIdOnAlternativePath(&connection_));
+
+ QuicNewConnectionIdFrame frame;
+ frame.sequence_number = 1u;
+ frame.connection_id = TestConnectionId(1);
+ frame.stateless_reset_token =
+ QuicUtils::GenerateStatelessResetToken(frame.connection_id);
+ frame.retire_prior_to = 0u;
+
+ EXPECT_TRUE(connection_.OnNewConnectionIdFrame(frame));
+ auto* retire_peer_issued_cid_alarm =
+ connection_.GetRetirePeerIssuedConnectionIdAlarm();
+ ASSERT_FALSE(retire_peer_issued_cid_alarm->IsSet());
+
+ frame.sequence_number = 2u;
+ frame.connection_id = TestConnectionId(2);
+ frame.stateless_reset_token =
+ QuicUtils::GenerateStatelessResetToken(frame.connection_id);
+ frame.retire_prior_to = 1u; // CID associated with #1 will be retired.
+
+ EXPECT_TRUE(connection_.OnNewConnectionIdFrame(frame));
+ ASSERT_TRUE(retire_peer_issued_cid_alarm->IsSet());
+ EXPECT_EQ(connection_.client_connection_id(), TestConnectionId(0));
+
+ EXPECT_CALL(visitor_, SendRetireConnectionId(/*sequence_number=*/0u));
+ retire_peer_issued_cid_alarm->Fire();
+ EXPECT_EQ(connection_.client_connection_id(), TestConnectionId(2));
+ EXPECT_EQ(connection_.packet_creator().GetDestinationConnectionId(),
+ TestConnectionId(2));
+ // Clean up alternative path connection ID.
+ EXPECT_EQ(
+ TestConnectionId(2),
+ QuicConnectionPeer::GetClientConnectionIdOnAlternativePath(&connection_));
+}
+
TEST_P(QuicConnectionTest,
CloseConnectionAfterReceiveRetireConnectionIdWhenNoCIDIssued) {
- if (!version().HasIetfQuicFrames()) {
+ if (!version().HasIetfQuicFrames() ||
+ GetQuicReloadableFlag(quic_use_connection_id_on_default_path_v2)) {
return;
}
QuicConnectionPeer::EnableMultipleConnectionIdSupport(&connection_);
@@ -14151,7 +14667,8 @@ TEST_P(QuicConnectionTest,
}
TEST_P(QuicConnectionTest, RetireConnectionIdFrameResultsInError) {
- if (!version().HasIetfQuicFrames()) {
+ if (!version().HasIetfQuicFrames() ||
+ GetQuicReloadableFlag(quic_use_connection_id_on_default_path_v2)) {
return;
}
QuicConnectionPeer::EnableMultipleConnectionIdSupport(&connection_);
@@ -14175,8 +14692,40 @@ TEST_P(QuicConnectionTest, RetireConnectionIdFrameResultsInError) {
IsError(IETF_QUIC_PROTOCOL_VIOLATION));
}
+TEST_P(QuicConnectionTest,
+ ServerRetireSelfIssuedConnectionIdWithoutSendingNewConnectionIdBefore) {
+ if (!connection_.support_multiple_connection_ids()) {
+ return;
+ }
+ QuicConnectionPeer::EnableMultipleConnectionIdSupport(&connection_);
+ set_perspective(Perspective::IS_SERVER);
+ connection_.CreateConnectionIdManager();
+
+ auto* retire_self_issued_cid_alarm =
+ connection_.GetRetireSelfIssuedConnectionIdAlarm();
+ ASSERT_FALSE(retire_self_issued_cid_alarm->IsSet());
+
+ QuicConnectionId cid0 = connection_id_;
+ QuicRetireConnectionIdFrame frame;
+ frame.sequence_number = 0u;
+ if (!GetQuicReloadableFlag(quic_use_connection_id_on_default_path_v2) ||
+ connection_.connection_migration_use_new_cid()) {
+ EXPECT_CALL(visitor_, OnServerConnectionIdIssued(_)).Times(2);
+ EXPECT_CALL(visitor_, SendNewConnectionId(_)).Times(2);
+ }
+ EXPECT_TRUE(connection_.OnRetireConnectionIdFrame(frame));
+ if (!GetQuicReloadableFlag(quic_use_connection_id_on_default_path_v2)) {
+ ASSERT_TRUE(retire_self_issued_cid_alarm->IsSet());
+ // cid0 is retired when the retire CID alarm fires.
+ if (!GetQuicReloadableFlag(quic_use_connection_id_on_default_path_v2))
+ EXPECT_CALL(visitor_, OnServerConnectionIdRetired(cid0));
+ retire_self_issued_cid_alarm->Fire();
+ }
+}
+
TEST_P(QuicConnectionTest, ServerRetireSelfIssuedConnectionId) {
- if (!version().HasIetfQuicFrames()) {
+ if (!version().HasIetfQuicFrames() ||
+ GetQuicReloadableFlag(quic_use_connection_id_on_default_path_v2)) {
return;
}
QuicConnectionPeer::EnableMultipleConnectionIdSupport(&connection_);
@@ -14219,6 +14768,121 @@ TEST_P(QuicConnectionTest, ServerRetireSelfIssuedConnectionId) {
ElementsAre(cid1, cid2));
}
+TEST_P(QuicConnectionTest, PatchMissingClientConnectionIdOntoAlternativePath) {
+ if (!version().HasIetfQuicFrames() ||
+ !connection_.support_multiple_connection_ids() ||
+ !connection_.use_connection_id_on_default_path()) {
+ return;
+ }
+ set_perspective(Perspective::IS_SERVER);
+ connection_.CreateConnectionIdManager();
+ connection_.set_client_connection_id(TestConnectionId(1));
+
+ // Set up the state after path probing.
+ const auto* default_path = QuicConnectionPeer::GetDefaultPath(&connection_);
+ auto* alternative_path = QuicConnectionPeer::GetAlternativePath(&connection_);
+ QuicIpAddress new_host;
+ new_host.FromString("12.12.12.12");
+ alternative_path->self_address = default_path->self_address;
+ alternative_path->peer_address = QuicSocketAddress(new_host, 12345);
+ alternative_path->server_connection_id = TestConnectionId(3);
+ ASSERT_TRUE(alternative_path->client_connection_id.IsEmpty());
+ ASSERT_FALSE(alternative_path->stateless_reset_token_received);
+
+ QuicNewConnectionIdFrame frame;
+ frame.sequence_number = 1u;
+ frame.connection_id = TestConnectionId(5);
+ frame.stateless_reset_token =
+ QuicUtils::GenerateStatelessResetToken(frame.connection_id);
+ frame.retire_prior_to = 0u;
+ // New ID is patched onto the alternative path when the needed
+ // NEW_CONNECTION_ID frame is received after PATH_CHALLENGE frame.
+ connection_.OnNewConnectionIdFrame(frame);
+
+ ASSERT_EQ(alternative_path->client_connection_id, frame.connection_id);
+ ASSERT_EQ(alternative_path->stateless_reset_token,
+ frame.stateless_reset_token);
+ ASSERT_TRUE(alternative_path->stateless_reset_token_received);
+}
+
+TEST_P(QuicConnectionTest, PatchMissingClientConnectionIdOntoDefaultPath) {
+ if (!version().HasIetfQuicFrames() ||
+ !connection_.support_multiple_connection_ids() ||
+ !connection_.use_connection_id_on_default_path()) {
+ return;
+ }
+ set_perspective(Perspective::IS_SERVER);
+ connection_.CreateConnectionIdManager();
+ connection_.set_client_connection_id(TestConnectionId(1));
+
+ // Set up the state after peer migration without probing.
+ auto* default_path = QuicConnectionPeer::GetDefaultPath(&connection_);
+ auto* alternative_path = QuicConnectionPeer::GetAlternativePath(&connection_);
+ auto* packet_creator = QuicConnectionPeer::GetPacketCreator(&connection_);
+ *alternative_path = std::move(*default_path);
+ QuicIpAddress new_host;
+ new_host.FromString("12.12.12.12");
+ default_path->self_address = default_path->self_address;
+ default_path->peer_address = QuicSocketAddress(new_host, 12345);
+ default_path->server_connection_id = TestConnectionId(3);
+ packet_creator->SetDefaultPeerAddress(default_path->peer_address);
+ packet_creator->SetServerConnectionId(default_path->server_connection_id);
+ packet_creator->SetClientConnectionId(default_path->client_connection_id);
+
+ ASSERT_FALSE(default_path->validated);
+ ASSERT_TRUE(default_path->client_connection_id.IsEmpty());
+ ASSERT_FALSE(default_path->stateless_reset_token_received);
+
+ QuicNewConnectionIdFrame frame;
+ frame.sequence_number = 1u;
+ frame.connection_id = TestConnectionId(5);
+ frame.stateless_reset_token =
+ QuicUtils::GenerateStatelessResetToken(frame.connection_id);
+ frame.retire_prior_to = 0u;
+ // New ID is patched onto the default path when the needed
+ // NEW_CONNECTION_ID frame is received after PATH_CHALLENGE frame.
+ connection_.OnNewConnectionIdFrame(frame);
+
+ ASSERT_EQ(default_path->client_connection_id, frame.connection_id);
+ ASSERT_EQ(default_path->stateless_reset_token, frame.stateless_reset_token);
+ ASSERT_TRUE(default_path->stateless_reset_token_received);
+ ASSERT_EQ(packet_creator->GetDestinationConnectionId(), frame.connection_id);
+}
+
+TEST_P(QuicConnectionTest, ShouldGeneratePacketBlockedByMissingConnectionId) {
+ if (!version().HasIetfQuicFrames() ||
+ !connection_.support_multiple_connection_ids()) {
+ return;
+ }
+ set_perspective(Perspective::IS_SERVER);
+ connection_.set_client_connection_id(TestConnectionId(1));
+ connection_.CreateConnectionIdManager();
+ if (version().SupportsAntiAmplificationLimit()) {
+ QuicConnectionPeer::SetAddressValidated(&connection_);
+ }
+
+ ASSERT_TRUE(
+ connection_.ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA, NOT_HANDSHAKE));
+
+ QuicPacketCreator* packet_creator =
+ QuicConnectionPeer::GetPacketCreator(&connection_);
+ QuicIpAddress peer_host1;
+ peer_host1.FromString("12.12.12.12");
+ QuicSocketAddress peer_address1(peer_host1, 1235);
+
+ {
+ // No connection ID is available as context is created without any.
+ QuicPacketCreator::ScopedPeerAddressContext context(
+ packet_creator, peer_address1, EmptyQuicConnectionId(),
+ EmptyQuicConnectionId(),
+ /*update_connection_id=*/true);
+ ASSERT_FALSE(connection_.ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
+ NOT_HANDSHAKE));
+ }
+ ASSERT_TRUE(
+ connection_.ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA, NOT_HANDSHAKE));
+}
+
// Regression test for b/182571515
TEST_P(QuicConnectionTest, LostDataThenGetAcknowledged) {
set_perspective(Perspective::IS_SERVER);
@@ -14278,6 +14942,53 @@ TEST_P(QuicConnectionTest, LostDataThenGetAcknowledged) {
}
}
+TEST_P(QuicConnectionTest, PtoSendStreamData) {
+ if (!connection_.SupportsMultiplePacketNumberSpaces()) {
+ return;
+ }
+ set_perspective(Perspective::IS_SERVER);
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ EXPECT_CALL(visitor_, OnCryptoFrame(_)).Times(AnyNumber());
+ }
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
+ use_tagging_decrypter();
+ ProcessCryptoPacketAtLevel(1, ENCRYPTION_INITIAL);
+ EXPECT_TRUE(connection_.HasPendingAcks());
+
+ connection_.SetEncrypter(ENCRYPTION_INITIAL,
+ std::make_unique<TaggingEncrypter>(0x01));
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
+ // Send INITIAL 1.
+ connection_.SendCryptoDataWithString("foo", 0, ENCRYPTION_INITIAL);
+
+ connection_.SetEncrypter(ENCRYPTION_HANDSHAKE,
+ std::make_unique<TaggingEncrypter>(0x02));
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_HANDSHAKE);
+ SetDecrypter(ENCRYPTION_HANDSHAKE,
+ std::make_unique<StrictTaggingDecrypter>(0x02));
+ // Send HANDSHAKE packets.
+ EXPECT_CALL(visitor_, OnHandshakePacketSent()).Times(1);
+ connection_.SendCryptoDataWithString("foo", 0, ENCRYPTION_HANDSHAKE);
+
+ connection_.SetEncrypter(ENCRYPTION_FORWARD_SECURE,
+ std::make_unique<TaggingEncrypter>(0x03));
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+
+ // Send half RTT packet with congestion control blocked.
+ EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(false));
+ connection_.SendStreamDataWithString(2, std::string(1500, 'a'), 0, NO_FIN);
+
+ ASSERT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
+ connection_.GetRetransmissionAlarm()->Fire();
+ if (GetQuicReloadableFlag(quic_donot_pto_half_rtt_data)) {
+ // Verify INITIAL and HANDSHAKE get retransmitted.
+ EXPECT_EQ(0x02020202u, writer_->final_bytes_of_last_packet());
+ } else {
+ // Application data preempts handshake data when PTO fires.
+ EXPECT_EQ(0x03030303u, writer_->final_bytes_of_last_packet());
+ }
+}
+
} // namespace
} // namespace test
} // namespace quic
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 1bb37035912..48d228bff31 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,10 +8,11 @@
#include <cstdint>
#include <string>
+#include "absl/container/flat_hash_map.h"
#include "quic/core/frames/quic_frame.h"
-#include "quic/core/quic_circular_deque.h"
#include "quic/core/quic_connection_id.h"
#include "quic/core/quic_types.h"
+#include "common/quiche_circular_deque.h"
namespace quic {
@@ -163,7 +164,7 @@ class QUIC_EXPORT_PRIVATE QuicControlFrameManager {
// frame.
void WriteOrBufferQuicFrame(QuicFrame frame);
- QuicCircularDeque<QuicFrame> control_frames_;
+ quiche::QuicheCircularDeque<QuicFrame> control_frames_;
// Id of latest saved control frame. 0 if no control frame has been saved.
QuicControlFrameId last_control_frame_id_;
@@ -182,7 +183,7 @@ class QUIC_EXPORT_PRIVATE QuicControlFrameManager {
DelegateInterface* delegate_;
// Last sent window update frame for each stream.
- QuicSmallMap<QuicStreamId, QuicControlFrameId, 10> window_update_frames_;
+ absl::flat_hash_map<QuicStreamId, QuicControlFrameId> window_update_frames_;
};
} // namespace quic
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 fc9be1764a2..1dd68995e2f 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
@@ -11,7 +11,7 @@
#include "absl/strings/string_view.h"
#include "third_party/boringssl/src/include/openssl/sha.h"
#include "quic/platform/api/quic_flag_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
+#include "common/quiche_text_utils.h"
namespace quic {
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 88fdda9d6c2..4e07f34b616 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
@@ -354,8 +354,7 @@ class QuicCryptoServerStreamTestWithFakeProofSource
};
// Regression test for b/35422225, in which multiple CHLOs arriving on the same
-// 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.
+// connection in close succession could cause a crash.
TEST_F(QuicCryptoServerStreamTestWithFakeProofSource, MultipleChlo) {
Initialize();
GetFakeProofSource()->Activate();
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
index 286aeae6bf8..4d3aa2f17f3 100644
--- 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
@@ -8,10 +8,10 @@
#include <memory>
#include "absl/types/optional.h"
-#include "quic/core/quic_circular_deque.h"
#include "quic/core/quic_time.h"
#include "quic/core/quic_types.h"
#include "quic/platform/api/quic_mem_slice.h"
+#include "common/quiche_circular_deque.h"
namespace quic {
@@ -80,7 +80,7 @@ class QUIC_EXPORT_PRIVATE QuicDatagramQueue {
const QuicClock* clock_;
QuicTime::Delta max_time_in_queue_ = QuicTime::Delta::Zero();
- QuicCircularDeque<Datagram> queue_;
+ quiche::QuicheCircularDeque<Datagram> queue_;
std::unique_ptr<Observer> observer_;
};
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 0ed002a6850..e1a999c706a 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
@@ -26,7 +26,7 @@
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
#include "quic/platform/api/quic_stack_trace.h"
-#include "common/platform/api/quiche_text_utils.h"
+#include "common/quiche_text_utils.h"
namespace quic {
@@ -331,9 +331,6 @@ QuicDispatcher::QuicDispatcher(
expected_server_connection_id_length_(
expected_server_connection_id_length),
should_update_expected_server_connection_id_length_(false) {
- if (use_reference_counted_session_map_) {
- QUIC_RESTART_FLAG_COUNT(quic_use_reference_counted_sesssion_map);
- }
QUIC_BUG_IF(quic_bug_12724_1, GetSupportedVersions().empty())
<< "Trying to create dispatcher without any supported versions";
QUIC_DLOG(INFO) << "Created QuicDispatcher with versions: "
@@ -341,15 +338,10 @@ QuicDispatcher::QuicDispatcher(
}
QuicDispatcher::~QuicDispatcher() {
- if (use_reference_counted_session_map_) {
- reference_counted_session_map_.clear();
- closed_ref_counted_session_list_.clear();
- if (support_multiple_cid_per_connection_) {
- num_sessions_in_session_map_ = 0;
- }
- } else {
- session_map_.clear();
- closed_session_list_.clear();
+ reference_counted_session_map_.clear();
+ closed_ref_counted_session_list_.clear();
+ if (support_multiple_cid_per_connection_) {
+ num_sessions_in_session_map_ = 0;
}
}
@@ -510,60 +502,45 @@ bool QuicDispatcher::MaybeDispatchPacket(
return true;
}
+ if (GetQuicReloadableFlag(quic_discard_packets_with_invalid_cid)) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_discard_packets_with_invalid_cid);
+ if (packet_info.version_flag && packet_info.version.IsKnown() &&
+ !QuicUtils::IsConnectionIdLengthValidForVersion(
+ server_connection_id.length(),
+ packet_info.version.transport_version)) {
+ QUIC_DLOG(INFO) << "Packet with destination connection ID "
+ << server_connection_id << " is invalid with version "
+ << packet_info.version;
+ // Drop the packet silently.
+ QUIC_CODE_COUNT(quic_dropped_invalid_initial_connection_id);
+ return true;
+ }
+ }
+
// Packets with connection IDs for active connections are processed
// immediately.
- if (use_reference_counted_session_map_) {
- auto it = reference_counted_session_map_.find(server_connection_id);
- if (it != reference_counted_session_map_.end()) {
- QUICHE_DCHECK(
- !buffered_packets_.HasBufferedPackets(server_connection_id));
- if (packet_info.version_flag &&
- packet_info.version != it->second->version() &&
- packet_info.version == LegacyVersionForEncapsulation()) {
- // This packet is using the Legacy Version Encapsulation version but the
- // corresponding session isn't, attempt extraction of inner packet.
- ChloAlpnSniExtractor alpn_extractor;
- if (ChloExtractor::Extract(packet_info.packet, packet_info.version,
- config_->create_session_tag_indicators(),
- &alpn_extractor,
- server_connection_id.length())) {
- if (MaybeHandleLegacyVersionEncapsulation(this, &alpn_extractor,
- packet_info)) {
- return true;
- }
+ auto it = reference_counted_session_map_.find(server_connection_id);
+ if (it != reference_counted_session_map_.end()) {
+ QUICHE_DCHECK(!buffered_packets_.HasBufferedPackets(server_connection_id));
+ if (packet_info.version_flag &&
+ packet_info.version != it->second->version() &&
+ packet_info.version == LegacyVersionForEncapsulation()) {
+ // This packet is using the Legacy Version Encapsulation version but the
+ // corresponding session isn't, attempt extraction of inner packet.
+ ChloAlpnSniExtractor alpn_extractor;
+ if (ChloExtractor::Extract(packet_info.packet, packet_info.version,
+ config_->create_session_tag_indicators(),
+ &alpn_extractor,
+ server_connection_id.length())) {
+ if (MaybeHandleLegacyVersionEncapsulation(this, &alpn_extractor,
+ packet_info)) {
+ return true;
}
}
- it->second->ProcessUdpPacket(packet_info.self_address,
- packet_info.peer_address,
- packet_info.packet);
- return true;
- }
- } else {
- auto it = session_map_.find(server_connection_id);
- if (it != session_map_.end()) {
- QUICHE_DCHECK(
- !buffered_packets_.HasBufferedPackets(server_connection_id));
- if (packet_info.version_flag &&
- packet_info.version != it->second->version() &&
- packet_info.version == LegacyVersionForEncapsulation()) {
- // This packet is using the Legacy Version Encapsulation version but the
- // corresponding session isn't, attempt extraction of inner packet.
- ChloAlpnSniExtractor alpn_extractor;
- if (ChloExtractor::Extract(packet_info.packet, packet_info.version,
- config_->create_session_tag_indicators(),
- &alpn_extractor,
- server_connection_id.length())) {
- if (MaybeHandleLegacyVersionEncapsulation(this, &alpn_extractor,
- packet_info)) {
- return true;
- }
- }
- }
- it->second->ProcessUdpPacket(packet_info.self_address,
- packet_info.peer_address,
- packet_info.packet);
- return true;
}
+ it->second->ProcessUdpPacket(packet_info.self_address,
+ packet_info.peer_address, packet_info.packet);
+ return true;
}
if (packet_info.version.IsKnown()) {
// We did not find the connection ID, check if we've replaced it.
@@ -575,28 +552,15 @@ bool QuicDispatcher::MaybeDispatchPacket(
QuicConnectionId replaced_connection_id = MaybeReplaceServerConnectionId(
server_connection_id, packet_info.version);
if (replaced_connection_id != server_connection_id) {
- if (use_reference_counted_session_map_) {
- // Search for the replacement.
- auto it2 = reference_counted_session_map_.find(replaced_connection_id);
- if (it2 != reference_counted_session_map_.end()) {
- QUICHE_DCHECK(
- !buffered_packets_.HasBufferedPackets(replaced_connection_id));
- it2->second->ProcessUdpPacket(packet_info.self_address,
- packet_info.peer_address,
- packet_info.packet);
- return true;
- }
- } else {
- // Search for the replacement.
- auto it2 = session_map_.find(replaced_connection_id);
- if (it2 != session_map_.end()) {
- QUICHE_DCHECK(
- !buffered_packets_.HasBufferedPackets(replaced_connection_id));
- it2->second->ProcessUdpPacket(packet_info.self_address,
- packet_info.peer_address,
- packet_info.packet);
- return true;
- }
+ // Search for the replacement.
+ auto it2 = reference_counted_session_map_.find(replaced_connection_id);
+ if (it2 != reference_counted_session_map_.end()) {
+ QUICHE_DCHECK(
+ !buffered_packets_.HasBufferedPackets(replaced_connection_id));
+ it2->second->ProcessUdpPacket(packet_info.self_address,
+ packet_info.peer_address,
+ packet_info.packet);
+ return true;
}
}
}
@@ -812,9 +776,9 @@ QuicDispatcher::QuicPacketFate QuicDispatcher::ValidityChecks(
void QuicDispatcher::CleanUpSession(QuicConnectionId server_connection_id,
QuicConnection* connection,
- QuicErrorCode error,
- const std::string& error_details,
- ConnectionCloseSource source) {
+ QuicErrorCode /*error*/,
+ const std::string& /*error_details*/,
+ ConnectionCloseSource /*source*/) {
write_blocked_list_.erase(connection);
QuicTimeWaitListManager::TimeWaitAction action =
QuicTimeWaitListManager::SEND_STATELESS_RESET;
@@ -823,14 +787,8 @@ void QuicDispatcher::CleanUpSession(QuicConnectionId server_connection_id,
action = QuicTimeWaitListManager::SEND_CONNECTION_CLOSE_PACKETS;
} else {
if (!connection->IsHandshakeComplete()) {
- const bool fix_dispatcher_sent_error_code =
- GetQuicReloadableFlag(quic_fix_dispatcher_sent_error_code) &&
- source == ConnectionCloseSource::FROM_SELF;
// TODO(fayang): Do not serialize connection close packet if the
// connection is closed by the client.
- if (fix_dispatcher_sent_error_code) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_fix_dispatcher_sent_error_code);
- }
if (!connection->version().HasIetfInvariantHeader()) {
QUIC_CODE_COUNT(gquic_add_to_time_wait_list_with_handshake_failed);
} else {
@@ -845,10 +803,8 @@ void QuicDispatcher::CleanUpSession(QuicConnectionId server_connection_id,
server_connection_id, connection->version(), helper_.get(),
time_wait_list_manager_.get());
terminator.CloseConnection(
- fix_dispatcher_sent_error_code ? error : QUIC_HANDSHAKE_FAILED,
- fix_dispatcher_sent_error_code
- ? error_details
- : "Connection is closed by server before handshake confirmed",
+ QUIC_HANDSHAKE_FAILED,
+ "Connection is closed by server before handshake confirmed",
connection->version().HasIetfInvariantHeader(),
connection->GetActiveServerConnectionIds());
} else {
@@ -862,11 +818,8 @@ void QuicDispatcher::CleanUpSession(QuicConnectionId server_connection_id,
: GOOGLE_QUIC_PACKET,
/*version_flag=*/true,
connection->version().HasLengthPrefixedConnectionIds(),
- connection->version(),
- fix_dispatcher_sent_error_code ? error : QUIC_HANDSHAKE_FAILED,
- fix_dispatcher_sent_error_code
- ? error_details
- : "Connection is closed by server before handshake confirmed",
+ connection->version(), QUIC_HANDSHAKE_FAILED,
+ "Connection is closed by server before handshake confirmed",
// Although it is our intention to send termination packets, the
// |action| argument is not used by this call to
// StatelesslyTerminateConnection().
@@ -898,18 +851,12 @@ void QuicDispatcher::StopAcceptingNewConnections() {
void QuicDispatcher::PerformActionOnActiveSessions(
std::function<void(QuicSession*)> operation) const {
- if (use_reference_counted_session_map_) {
- absl::flat_hash_set<QuicSession*> visited_session;
- visited_session.reserve(reference_counted_session_map_.size());
- for (auto const& kv : reference_counted_session_map_) {
- QuicSession* session = kv.second.get();
- if (visited_session.insert(session).second) {
- operation(session);
- }
- }
- } else {
- for (auto const& kv : session_map_) {
- operation(kv.second.get());
+ absl::flat_hash_set<QuicSession*> visited_session;
+ visited_session.reserve(reference_counted_session_map_.size());
+ for (auto const& kv : reference_counted_session_map_) {
+ QuicSession* session = kv.second.get();
+ if (visited_session.insert(session).second) {
+ operation(session);
}
}
}
@@ -917,7 +864,6 @@ void QuicDispatcher::PerformActionOnActiveSessions(
// Get a snapshot of all sessions.
std::vector<std::shared_ptr<QuicSession>> QuicDispatcher::GetSessionsSnapshot()
const {
- QUICHE_DCHECK(use_reference_counted_session_map_);
std::vector<std::shared_ptr<QuicSession>> snapshot;
snapshot.reserve(reference_counted_session_map_.size());
absl::flat_hash_set<QuicSession*> visited_session;
@@ -937,29 +883,16 @@ std::unique_ptr<QuicPerPacketContext> QuicDispatcher::GetPerPacketContext()
}
void QuicDispatcher::DeleteSessions() {
- if (use_reference_counted_session_map_) {
- if (!write_blocked_list_.empty()) {
- for (const auto& session : closed_ref_counted_session_list_) {
- if (write_blocked_list_.erase(session->connection()) != 0) {
- QUIC_BUG(quic_bug_12724_2)
- << "QuicConnection was in WriteBlockedList before destruction "
- << session->connection()->connection_id();
- }
+ if (!write_blocked_list_.empty()) {
+ for (const auto& session : closed_ref_counted_session_list_) {
+ if (write_blocked_list_.erase(session->connection()) != 0) {
+ QUIC_BUG(quic_bug_12724_2)
+ << "QuicConnection was in WriteBlockedList before destruction "
+ << session->connection()->connection_id();
}
}
- closed_ref_counted_session_list_.clear();
- } else {
- 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(quic_bug_12724_3)
- << "QuicConnection was in WriteBlockedList before destruction "
- << session->connection()->connection_id();
- }
- }
- }
- closed_session_list_.clear();
}
+ closed_ref_counted_session_list_.clear();
}
void QuicDispatcher::OnCanWrite() {
@@ -995,28 +928,15 @@ bool QuicDispatcher::HasPendingWrites() const {
}
void QuicDispatcher::Shutdown() {
- if (use_reference_counted_session_map_) {
- while (!reference_counted_session_map_.empty()) {
- QuicSession* session =
- reference_counted_session_map_.begin()->second.get();
- session->connection()->CloseConnection(
- QUIC_PEER_GOING_AWAY, "Server shutdown imminent",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- // Validate that the session removes itself from the session map on close.
- QUICHE_DCHECK(reference_counted_session_map_.empty() ||
- reference_counted_session_map_.begin()->second.get() !=
- session);
- }
- } else {
- while (!session_map_.empty()) {
- QuicSession* session = session_map_.begin()->second.get();
- session->connection()->CloseConnection(
- QUIC_PEER_GOING_AWAY, "Server shutdown imminent",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- // Validate that the session removes itself from the session map on close.
- QUICHE_DCHECK(session_map_.empty() ||
- session_map_.begin()->second.get() != session);
- }
+ while (!reference_counted_session_map_.empty()) {
+ QuicSession* session = reference_counted_session_map_.begin()->second.get();
+ session->connection()->CloseConnection(
+ QUIC_PEER_GOING_AWAY, "Server shutdown imminent",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ // Validate that the session removes itself from the session map on close.
+ QUICHE_DCHECK(reference_counted_session_map_.empty() ||
+ reference_counted_session_map_.begin()->second.get() !=
+ session);
}
DeleteSessions();
}
@@ -1025,72 +945,41 @@ void QuicDispatcher::OnConnectionClosed(QuicConnectionId server_connection_id,
QuicErrorCode error,
const std::string& error_details,
ConnectionCloseSource source) {
- if (use_reference_counted_session_map_) {
- auto it = reference_counted_session_map_.find(server_connection_id);
- if (it == reference_counted_session_map_.end()) {
- QUIC_BUG(quic_bug_10287_3)
- << "ConnectionId " << server_connection_id
- << " does not exist in the session map. Error: "
- << QuicErrorCodeToString(error);
- QUIC_BUG(quic_bug_10287_4) << QuicStackTrace();
- return;
- }
+ auto it = reference_counted_session_map_.find(server_connection_id);
+ if (it == reference_counted_session_map_.end()) {
+ QUIC_BUG(quic_bug_10287_3) << "ConnectionId " << server_connection_id
+ << " does not exist in the session map. Error: "
+ << QuicErrorCodeToString(error);
+ QUIC_BUG(quic_bug_10287_4) << QuicStackTrace();
+ return;
+ }
- QUIC_DLOG_IF(INFO, error != QUIC_NO_ERROR)
- << "Closing connection (" << server_connection_id
- << ") due to error: " << QuicErrorCodeToString(error)
- << ", with details: " << error_details;
-
- QuicConnection* connection = it->second->connection();
- if (ShouldDestroySessionAsynchronously()) {
- // Set up alarm to fire immediately to bring destruction of this session
- // out of current call stack.
- if (closed_ref_counted_session_list_.empty()) {
- delete_sessions_alarm_->Update(helper()->GetClock()->ApproximateNow(),
- QuicTime::Delta::Zero());
- }
- closed_ref_counted_session_list_.push_back(std::move(it->second));
+ QUIC_DLOG_IF(INFO, error != QUIC_NO_ERROR)
+ << "Closing connection (" << server_connection_id
+ << ") due to error: " << QuicErrorCodeToString(error)
+ << ", with details: " << error_details;
+
+ QuicConnection* connection = it->second->connection();
+ if (ShouldDestroySessionAsynchronously()) {
+ // Set up alarm to fire immediately to bring destruction of this session
+ // out of current call stack.
+ if (closed_ref_counted_session_list_.empty()) {
+ delete_sessions_alarm_->Update(helper()->GetClock()->ApproximateNow(),
+ QuicTime::Delta::Zero());
}
- CleanUpSession(it->first, connection, error, error_details, source);
- if (support_multiple_cid_per_connection_) {
- QUIC_RESTART_FLAG_COUNT_N(
- quic_dispatcher_support_multiple_cid_per_connection_v2, 1, 2);
- for (const QuicConnectionId& cid :
- connection->GetActiveServerConnectionIds()) {
- reference_counted_session_map_.erase(cid);
- }
- --num_sessions_in_session_map_;
- } else {
- reference_counted_session_map_.erase(it);
+ closed_ref_counted_session_list_.push_back(std::move(it->second));
+ }
+ CleanUpSession(it->first, connection, error, error_details, source);
+ if (support_multiple_cid_per_connection_) {
+ QUIC_RESTART_FLAG_COUNT_N(
+ quic_dispatcher_support_multiple_cid_per_connection_v2, 1, 2);
+ for (const QuicConnectionId& cid :
+ connection->GetActiveServerConnectionIds()) {
+ reference_counted_session_map_.erase(cid);
}
+ --num_sessions_in_session_map_;
} else {
- auto it = session_map_.find(server_connection_id);
- if (it == session_map_.end()) {
- QUIC_BUG(quic_bug_10287_5)
- << "ConnectionId " << server_connection_id
- << " does not exist in the session map. Error: "
- << QuicErrorCodeToString(error);
- QUIC_BUG(quic_bug_10287_6) << QuicStackTrace();
- return;
- }
-
- QUIC_DLOG_IF(INFO, error != QUIC_NO_ERROR)
- << "Closing connection (" << server_connection_id
- << ") due to error: " << QuicErrorCodeToString(error)
- << ", with details: " << error_details;
-
- QuicConnection* connection = it->second->connection();
- if (ShouldDestroySessionAsynchronously()) {
- // Set up alarm to fire immediately to bring destruction of this session
- // out of current call stack.
- if (closed_session_list_.empty()) {
- delete_sessions_alarm_->Update(helper()->GetClock()->ApproximateNow(),
- QuicTime::Delta::Zero());
- }
- closed_session_list_.push_back(std::move(it->second));
- }
- CleanUpSession(it->first, connection, error, error_details, source);
- session_map_.erase(it);
+ reference_counted_session_map_.erase(it);
}
}
@@ -1126,6 +1015,7 @@ void QuicDispatcher::OnNewConnectionIdSent(
<< server_connection_id << " new_connection_id: " << new_connection_id;
return;
}
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 5, 5);
auto insertion_result = reference_counted_session_map_.insert(
std::make_pair(new_connection_id, it->second));
QUICHE_DCHECK(insertion_result.second);
@@ -1250,28 +1140,18 @@ void QuicDispatcher::ProcessBufferedChlos(size_t max_connections_to_create) {
}
QUIC_DLOG(INFO) << "Created new session for " << server_connection_id;
- if (use_reference_counted_session_map_) {
- auto insertion_result = reference_counted_session_map_.insert(
- std::make_pair(server_connection_id,
- std::shared_ptr<QuicSession>(std::move(session))));
- if (!insertion_result.second) {
- QUIC_BUG(quic_bug_12724_5)
- << "Tried to add a session to session_map with existing connection "
- "id: "
- << server_connection_id;
- } else if (support_multiple_cid_per_connection_) {
- ++num_sessions_in_session_map_;
- }
- DeliverPacketsToSession(packets, insertion_result.first->second.get());
- } else {
- auto insertion_result = session_map_.insert(
- std::make_pair(server_connection_id, std::move(session)));
- QUIC_BUG_IF(quic_bug_12724_6, !insertion_result.second)
+ auto insertion_result = reference_counted_session_map_.insert(
+ std::make_pair(server_connection_id,
+ std::shared_ptr<QuicSession>(std::move(session))));
+ if (!insertion_result.second) {
+ QUIC_BUG(quic_bug_12724_5)
<< "Tried to add a session to session_map with existing connection "
"id: "
<< server_connection_id;
- DeliverPacketsToSession(packets, insertion_result.first->second.get());
+ } else if (support_multiple_cid_per_connection_) {
+ ++num_sessions_in_session_map_;
}
+ DeliverPacketsToSession(packets, insertion_result.first->second.get());
}
}
@@ -1370,28 +1250,18 @@ void QuicDispatcher::ProcessChlo(const std::vector<std::string>& alpns,
<< packet_info->destination_connection_id;
QuicSession* session_ptr;
- if (use_reference_counted_session_map_) {
- auto insertion_result =
- reference_counted_session_map_.insert(std::make_pair(
- packet_info->destination_connection_id,
- std::shared_ptr<QuicSession>(std::move(session.release()))));
- if (!insertion_result.second) {
- QUIC_BUG(quic_bug_10287_9)
- << "Tried to add a session to session_map with existing "
- "connection id: "
- << packet_info->destination_connection_id;
- } else if (support_multiple_cid_per_connection_) {
- ++num_sessions_in_session_map_;
- }
- session_ptr = insertion_result.first->second.get();
- } else {
- auto insertion_result = session_map_.insert(std::make_pair(
- packet_info->destination_connection_id, std::move(session)));
- QUIC_BUG_IF(quic_bug_12724_8, !insertion_result.second)
- << "Tried to add a session to session_map with existing connection id: "
+ auto insertion_result = reference_counted_session_map_.insert(std::make_pair(
+ packet_info->destination_connection_id,
+ std::shared_ptr<QuicSession>(std::move(session.release()))));
+ if (!insertion_result.second) {
+ QUIC_BUG(quic_bug_10287_9)
+ << "Tried to add a session to session_map with existing "
+ "connection id: "
<< packet_info->destination_connection_id;
- session_ptr = insertion_result.first->second.get();
+ } else if (support_multiple_cid_per_connection_) {
+ ++num_sessions_in_session_map_;
}
+ session_ptr = insertion_result.first->second.get();
std::list<BufferedPacket> packets =
buffered_packets_.DeliverPackets(packet_info->destination_connection_id)
.buffered_packets;
@@ -1449,7 +1319,7 @@ bool QuicDispatcher::IsSupportedVersion(const ParsedQuicVersion version) {
void QuicDispatcher::MaybeResetPacketsWithNoVersion(
const ReceivedPacketInfo& packet_info) {
QUICHE_DCHECK(!packet_info.version_flag);
- if (GetQuicReloadableFlag(quic_fix_stateless_reset) &&
+ if (GetQuicRestartFlag(quic_fix_stateless_reset2) &&
packet_info.form != GOOGLE_QUIC_PACKET) {
// Drop IETF packets smaller than the minimal stateless reset length.
if (packet_info.packet.length() <=
@@ -1481,9 +1351,7 @@ size_t QuicDispatcher::NumSessions() const {
if (support_multiple_cid_per_connection_) {
return num_sessions_in_session_map_;
}
- return use_reference_counted_session_map_
- ? reference_counted_session_map_.size()
- : session_map_.size();
+ return reference_counted_session_map_.size();
}
} // namespace quic
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 81749543d4d..053f856da98 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
@@ -166,10 +166,6 @@ class QUIC_NO_EXPORT QuicDispatcher
bool accept_new_connections() const { return accept_new_connections_; }
- bool use_reference_counted_session_map() const {
- return use_reference_counted_session_map_;
- }
-
bool support_multiple_cid_per_connection() const {
return support_multiple_cid_per_connection_;
}
@@ -457,10 +453,7 @@ class QUIC_NO_EXPORT QuicDispatcher
// destination connection ID length of all IETF long headers.
bool should_update_expected_server_connection_id_length_;
- const bool use_reference_counted_session_map_ =
- GetQuicRestartFlag(quic_use_reference_counted_sesssion_map);
const bool support_multiple_cid_per_connection_ =
- use_reference_counted_session_map_ &&
GetQuicRestartFlag(quic_time_wait_list_support_multiple_cid_v2) &&
GetQuicRestartFlag(
quic_dispatcher_support_multiple_cid_per_connection_v2);
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 3df8a76965d..5a7a709f91b 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
@@ -167,6 +167,7 @@ class TestDispatcher : public QuicDispatcher {
std::string custom_packet_context_;
+ using QuicDispatcher::MaybeDispatchPacket;
using QuicDispatcher::SetAllowShortInitialServerConnectionIds;
using QuicDispatcher::writer;
@@ -1101,6 +1102,31 @@ TEST_P(QuicDispatcherTestAllVersions,
ProcessFirstFlight(client_address, EmptyQuicConnectionId());
}
+TEST_P(QuicDispatcherTestAllVersions,
+ DropPacketWithKnownVersionAndInvalidInitialConnectionId) {
+ SetQuicReloadableFlag(quic_discard_packets_with_invalid_cid, true);
+ CreateTimeWaitListManager();
+
+ QuicSocketAddress server_address;
+ QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
+
+ // dispatcher_ should drop this packet with invalid connection ID.
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
+ EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _, _))
+ .Times(0);
+ EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _))
+ .Times(0);
+ absl::string_view cid_str = "123456789abcdefg123456789abcdefg";
+ QuicConnectionId invalid_connection_id(cid_str.data(), cid_str.length());
+ QuicReceivedPacket packet("packet", 6, QuicTime::Zero());
+ ReceivedPacketInfo packet_info(server_address, client_address, packet);
+ packet_info.version_flag = true;
+ packet_info.version = version_;
+ packet_info.destination_connection_id = invalid_connection_id;
+
+ ASSERT_TRUE(dispatcher_->MaybeDispatchPacket(packet_info));
+}
+
void QuicDispatcherTestBase::
TestVersionNegotiationForUnknownVersionInvalidShortInitialConnectionId(
const QuicConnectionId& server_connection_id,
@@ -1976,7 +2002,6 @@ class QuicDispatcherSupportMultipleConnectionIdPerConnectionTest
public:
QuicDispatcherSupportMultipleConnectionIdPerConnectionTest()
: QuicDispatcherTestBase(crypto_test_utils::ProofSourceForTesting()) {
- SetQuicRestartFlag(quic_use_reference_counted_sesssion_map, true);
SetQuicRestartFlag(quic_time_wait_list_support_multiple_cid_v2, true);
SetQuicRestartFlag(quic_dispatcher_support_multiple_cid_per_connection_v2,
true);
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 32816b869cf..9fa422f578c 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
@@ -459,8 +459,12 @@ enum QuicErrorCode {
// Received multiple close offset.
QUIC_STREAM_MULTIPLE_OFFSET = 130,
- // Internal error codes for HTTP/3 errors.
+ // HTTP/3 errors.
+
+ // Frame payload larger than what HttpDecoder is willing to buffer.
QUIC_HTTP_FRAME_TOO_LARGE = 131,
+ // Malformed HTTP/3 frame, or PUSH_PROMISE or CANCEL_PUSH received (which is
+ // an error because MAX_PUSH_ID is never sent).
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,
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_flags_list.h b/chromium/net/third_party/quiche/src/quic/core/quic_flags_list.h
index 910db544eff..df0df50f3fc 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_flags_list.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_flags_list.h
@@ -4,77 +4,135 @@
// This file is autogenerated by the QUICHE Copybara export script.
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_abort_qpack_on_stream_reset, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_accept_empty_stream_frame_with_no_fin, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_ack_delay_alarm_granularity, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_add_stream_info_to_idle_close_detail, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_allocate_stream_sequencer_buffer_blocks_on_demand, false)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_allow_client_enabled_bbr_v2, false)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_alps_include_scheme_in_origin, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_and_tls_allow_sni_without_dots, false)
+#ifdef QUIC_FLAG
+
+QUIC_FLAG(FLAGS_quic_restart_flag_dont_fetch_quic_private_keys_from_leto, false)
+
+QUIC_FLAG(FLAGS_quic_restart_flag_quic_offload_pacing_to_usps2, false)
+// A testonly reloadable flag that will always default to false.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_testonly_default_false, false)
+// A testonly reloadable flag that will always default to true.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_testonly_default_true, true)
+// A testonly restart flag that will always default to false.
+QUIC_FLAG(FLAGS_quic_restart_flag_quic_testonly_default_false, false)
+// A testonly restart flag that will always default to true.
+QUIC_FLAG(FLAGS_quic_restart_flag_quic_testonly_default_true, true)
+// Fix QUIC BBRv2\'s bandwidth_lo modes to better approximate packet conservation.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_fix_bw_lo_mode2, false)
+// If true, GFE will consider SNI values which do not contain dots (instead of throwing them away - see b/176998377).
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_and_tls_allow_sni_without_dots, true)
+// If true, QUIC BBRv2\'s PROBE_BW mode will not reduce cwnd below BDP+ack_height.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_avoid_too_low_probe_bw_cwnd, false)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_fix_bw_lo_mode, false)
+// If true, QUIC will default enable MTU discovery at server, with a target of 1450 bytes.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_enable_mtu_discovery_at_server, false)
+// If true, QuicBatchWriterBase will mark the writer as blocked when the write status is WRITE_STATUS_BLOCKED_DATA_BUFFERED.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_batch_writer_fix_write_blocked, true)
+// If true, QuicGsoBatchWriter will support release time if it is available and the process has the permission to do so.
+QUIC_FLAG(FLAGS_quic_restart_flag_quic_support_release_time_for_gso, false)
+// If true, TlsHandshaker::AdvanceHandshake will retry SSL_do_handshake when entered early data.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_tls_retry_handshake_on_early_data, true)
+// If true, TlsServerHandshaker will install a packet flusher when async operation completes.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_add_packet_flusher_on_async_op_done, true)
+// If true, TlsServerHandshaker will use handshake hints(if present) to speed up handshakes.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_tls_server_use_handshake_hints, true)
+// If true, abort async QPACK header decompression in QuicSpdyStream::Reset() and in QuicSpdyStream::OnStreamReset().
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_abort_qpack_on_stream_reset, true)
+// If true, ack frequency frame can be sent from server to client.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_can_send_ack_frequency, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_close_connection_with_too_many_outstanding_packets, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_connection_support_multiple_cids_v2, false)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_conservative_bursts, false)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_conservative_cwnd_and_pacing_gains, false)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_count_bytes_on_alternative_path_seperately, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_crypto_postpone_cert_validate_for_server, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_enable_5rto_blackhole_detection2, true)
+// If true, allow client to enable BBRv2 on server via connection option \'B2ON\'.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_allow_client_enabled_bbr_v2, false)
+// If true, close read side but not write side in QuicSpdyStream::OnStreamReset().
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_on_stream_reset, true)
+// If true, default on PTO which unifies TLP + RTO loss recovery.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_on_pto, false)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_to_bbr, false)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_to_bbr_v2, false)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_delay_initial_ack, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_server_blackhole_detection, false)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_draft_29, false)
+// If true, default-enable 5RTO blachole detection.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_enable_5rto_blackhole_detection2, true)
+// If true, determine stateless reset packet length based on the received packet length.
+QUIC_FLAG(FLAGS_quic_restart_flag_quic_fix_stateless_reset2, false)
+// If true, disable QUIC version Q043.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_q043, false)
+// If true, disable QUIC version Q046.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_q046, false)
+// If true, disable QUIC version Q050.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_q050, false)
+// If true, disable QUIC version h3-29.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_draft_29, false)
+// If true, disable QUIC version h3-T051.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_t051, false)
+// If true, disable blackhole detection on server side.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_server_blackhole_detection, false)
+// If true, discard INITIAL packet if the key has been dropped.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_discard_initial_packet_with_key_dropped, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_do_not_synthesize_source_cid_for_short_header, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_donot_reset_ideal_next_packet_send_time, false)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_donot_write_mid_packet_processing, false)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_enable_alps_client, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_enable_alps_server, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_enable_mtu_discovery_at_server, false)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_enable_server_on_wire_ping, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_enable_token_based_address_validation, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_enable_version_rfcv1, false)
+// If true, do not bundle 2nd ACK with connection close if there is an ACK queued.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_single_ack_in_packet2, false)
+// If true, do not count bytes sent/received on the alternative path into the bytes sent/received on the default path.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_count_bytes_on_alternative_path_seperately, true)
+// If true, do not send control frames before encryption is established.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_encrypted_control_frames, false)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_encrypted_goaway, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_dispatcher_sent_error_code, false)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_key_update_on_first_packet, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_on_stream_reset, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_stateless_reset, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_willing_and_able_to_write2, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_h3_datagram, false)
+// If true, do not send stream data when PTO fires.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_donot_pto_half_rtt_data, true)
+// If true, do not write stream data and control frames in the middle of packet processing.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_donot_write_mid_packet_processing, true)
+// If true, drop unsent PATH_RESPONSEs and rely on peer\'s retry.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_drop_unsent_path_response, true)
+// If true, enable QUIC version h3 (RFCv1).
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_enable_version_rfcv1, false)
+// If true, enable server retransmittable on wire PING.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_enable_server_on_wire_ping, true)
+// If true, include stream information in idle timeout connection close detail.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_add_stream_info_to_idle_close_detail, true)
+// If true, increase the size of stream sequencer buffer block container on demand.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_allocate_stream_sequencer_buffer_blocks_on_demand, false)
+// If true, pass the received PATH_RESPONSE payload to path validator to move forward the path validation.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_pass_path_response_to_validator, false)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_preempt_stream_data_with_handshake_packet, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_reject_unexpected_ietf_frame_types, true)
+// If true, quic connection sends/recieives NewConnectionId & RetireConnectionId frames.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_connection_support_multiple_cids_v4, true)
+// If true, quic dispatcher discards packets with invalid server connection ID.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_discard_packets_with_invalid_cid, false)
+// If true, quic dispatcher supports one connection to use multiple connection IDs.
+QUIC_FLAG(FLAGS_quic_restart_flag_quic_dispatcher_support_multiple_cid_per_connection_v2, true)
+// If true, require handshake confirmation for QUIC connections, functionally disabling 0-rtt handshakes.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_require_handshake_confirmation, false)
+// If true, send PATH_RESPONSE upon receiving PATH_CHALLENGE regardless of perspective. --gfe2_reloadable_flag_quic_start_peer_migration_earlier has to be true before turn on this flag.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_send_path_response2, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_send_timestamps, false)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_send_tls_crypto_error_code, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_server_reverse_validate_new_path3, false)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_single_ack_in_packet2, false)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_start_peer_migration_earlier, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_testonly_default_false, false)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_testonly_default_true, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_tls_use_normalized_sni_for_cert_selectioon, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_tls_use_per_handshaker_proof_source, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_tls_retry_handshake_on_early_data, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_unified_iw_options, false)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_unify_stop_sending, true)
+// If true, set burst token to 2 in cwnd bootstrapping experiment.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_conservative_bursts, false)
+// If true, signal error in HttpDecoder upon receiving a PUSH_PROMISE or CANCEL_PUSH frame.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_error_on_http3_push, true)
+// If true, stop resetting ideal_next_packet_send_time_ in pacing sender.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_donot_reset_ideal_next_packet_send_time, false)
+// If true, time_wait_list can support multiple connection IDs.
+QUIC_FLAG(FLAGS_quic_restart_flag_quic_time_wait_list_support_multiple_cid_v2, true)
+// If true, treat old (pre-draft02) PRIORITY_UPDATE frame as unknown frame.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_ignore_old_priority_update_frame, true)
+// If true, upon receiving path challenge, send path response and reverse path challenge in the same function.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_group_path_response_and_challenge_sending_closer, false)
+// If true, use BBRv2 as the default congestion controller. Takes precedence over --quic_default_to_bbr.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_to_bbr_v2, false)
+// If true, use ScopedEncryptionLevelContext when sending data.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_use_encryption_level_context, true)
+// If true, use WriteOrBufferDataAtLevel to send crypto data. Existing WriteOrBufferData is used to send application data.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_use_write_or_buffer_data_at_level, false)
-QUIC_FLAG(FLAGS_quic_restart_flag_dont_fetch_quic_private_keys_from_leto, false)
-QUIC_FLAG(FLAGS_quic_restart_flag_quic_dispatcher_support_multiple_cid_per_connection_v2, true)
-QUIC_FLAG(FLAGS_quic_restart_flag_quic_offload_pacing_to_usps2, false)
-QUIC_FLAG(FLAGS_quic_restart_flag_quic_session_tickets_always_enabled, true)
-QUIC_FLAG(FLAGS_quic_restart_flag_quic_support_release_time_for_gso, false)
-QUIC_FLAG(FLAGS_quic_restart_flag_quic_testonly_default_false, false)
-QUIC_FLAG(FLAGS_quic_restart_flag_quic_testonly_default_true, true)
-QUIC_FLAG(FLAGS_quic_restart_flag_quic_time_wait_list_support_multiple_cid_v2, true)
-QUIC_FLAG(FLAGS_quic_restart_flag_quic_use_reference_counted_sesssion_map, true)
+// If true, use new connection ID in connection migration.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_connection_migration_use_new_cid_v2, false)
+// If true, use the connection ID and stateless reset token on default PathState.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_use_connection_id_on_default_path_v2, true)
+// If true, uses conservative cwnd gain and pacing gain when cwnd gets bootstrapped.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_conservative_cwnd_and_pacing_gains, false)
+// If true, validate that peer owns the new address once the server detects peer migration or is probed from that address, and also apply anti-amplification limit while sending to that address.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_server_reverse_validate_new_path3, false)
+// If ture, replace the incoming_connection_ids check with original_destination_connection_id check.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_deprecate_incoming_connection_ids, true)
+// When the STMP connection option is sent by the client, timestamps in the QUIC ACK frame are sent and processed.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_send_timestamps, false)
+// When true, QuicSpdySession supports draft-ietf-masque-h3-datagram.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_h3_datagram, false)
+// When true, defaults to BBR congestion control instead of Cubic.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_to_bbr, false)
+// When true, makes the QUIC BBRv2 bw_lo modes more similar to standard BBRv2.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_fix_bw_lo_mode, true)
+// When true, set the initial congestion control window from connection options in QuicSentPacketManager rather than TcpCubicSenderBytes.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_unified_iw_options, false)
+
+#endif
+
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 c5de97be541..e186ce33ecb 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
@@ -49,7 +49,7 @@
#include "quic/platform/api/quic_logging.h"
#include "quic/platform/api/quic_map_util.h"
#include "quic/platform/api/quic_stack_trace.h"
-#include "common/platform/api/quiche_text_utils.h"
+#include "common/quiche_text_utils.h"
namespace quic {
@@ -435,10 +435,6 @@ QuicFramer::QuicFramer(const ParsedQuicVersionVector& supported_versions,
version_ = supported_versions_[0];
QUICHE_DCHECK(version_.IsKnown())
<< ParsedQuicVersionVectorToString(supported_versions_);
- if (do_not_synthesize_source_cid_for_short_header_) {
- QUIC_RELOADABLE_FLAG_COUNT_N(
- quic_do_not_synthesize_source_cid_for_short_header, 1, 3);
- }
}
QuicFramer::~QuicFramer() {}
@@ -1309,9 +1305,9 @@ std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildIetfStatelessResetPacket(
size_t received_packet_length,
StatelessResetToken stateless_reset_token) {
QUIC_DVLOG(1) << "Building IETF stateless reset packet.";
- if (GetQuicReloadableFlag(quic_fix_stateless_reset)) {
+ if (GetQuicRestartFlag(quic_fix_stateless_reset2)) {
if (received_packet_length <= GetMinStatelessResetPacketLength()) {
- QUIC_BUG(362045737_1)
+ QUICHE_DLOG(ERROR)
<< "Tried to build stateless reset packet with received packet "
"length "
<< received_packet_length;
@@ -1344,7 +1340,7 @@ std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildIetfStatelessResetPacket(
QUIC_BUG(362045737_3) << "Failed to write stateless reset token";
return nullptr;
}
- QUIC_RELOADABLE_FLAG_COUNT(quic_fix_stateless_reset);
+ QUIC_RESTART_FLAG_COUNT(quic_fix_stateless_reset2);
return std::make_unique<QuicEncryptedPacket>(buffer.release(), len,
/*owns_buffer=*/true);
}
@@ -2774,7 +2770,6 @@ bool QuicFramer::ProcessAndValidateIetfConnectionIdLength(
bool QuicFramer::ValidateReceivedConnectionIds(const QuicPacketHeader& header) {
bool skip_server_connection_id_validation =
- do_not_synthesize_source_cid_for_short_header_ &&
perspective_ == Perspective::IS_CLIENT &&
header.form == IETF_QUIC_SHORT_HEADER_PACKET;
if (!skip_server_connection_id_validation &&
@@ -2786,13 +2781,8 @@ bool QuicFramer::ValidateReceivedConnectionIds(const QuicPacketHeader& header) {
}
bool skip_client_connection_id_validation =
- do_not_synthesize_source_cid_for_short_header_ &&
perspective_ == Perspective::IS_SERVER &&
header.form == IETF_QUIC_SHORT_HEADER_PACKET;
- if (skip_client_connection_id_validation) {
- QUIC_RELOADABLE_FLAG_COUNT_N(
- quic_do_not_synthesize_source_cid_for_short_header, 2, 3);
- }
if (!skip_client_connection_id_validation &&
version_.SupportsClientConnectionIds() &&
!QuicUtils::IsConnectionIdValidForVersion(
@@ -2829,15 +2819,6 @@ bool QuicFramer::ProcessIetfPacketHeader(QuicDataReader* reader,
header->destination_connection_id_included = CONNECTION_ID_PRESENT;
header->source_connection_id_included =
header->version_flag ? CONNECTION_ID_PRESENT : CONNECTION_ID_ABSENT;
- if (!do_not_synthesize_source_cid_for_short_header_ &&
- header->source_connection_id_included == CONNECTION_ID_ABSENT) {
- QUICHE_DCHECK(header->source_connection_id.IsEmpty());
- if (perspective_ == Perspective::IS_CLIENT) {
- header->source_connection_id = last_serialized_server_connection_id_;
- } else {
- header->source_connection_id = last_serialized_client_connection_id_;
- }
- }
if (!ValidateReceivedConnectionIds(*header)) {
return false;
@@ -2925,13 +2906,6 @@ bool QuicFramer::ProcessIetfPacketHeader(QuicDataReader* reader,
set_detailed_error("Client connection ID not supported in this version.");
return false;
}
- if (!do_not_synthesize_source_cid_for_short_header_) {
- if (perspective_ == Perspective::IS_CLIENT) {
- header->source_connection_id = last_serialized_server_connection_id_;
- } else {
- header->source_connection_id = last_serialized_client_connection_id_;
- }
- }
}
return ValidateReceivedConnectionIds(*header);
@@ -3232,20 +3206,14 @@ bool QuicFramer::ProcessIetfFrameData(QuicDataReader* reader,
set_detailed_error("Unable to read frame type.");
return RaiseError(QUIC_INVALID_FRAME_DATA);
}
- if (reject_unexpected_ietf_frame_types_) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_reject_unexpected_ietf_frame_types, 1,
- 2);
- if (!IsIetfFrameTypeExpectedForEncryptionLevel(frame_type,
- decrypted_level)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_reject_unexpected_ietf_frame_types, 2,
- 2);
- set_detailed_error(absl::StrCat(
- "IETF frame type ",
- QuicIetfFrameTypeString(static_cast<QuicIetfFrameType>(frame_type)),
- " is unexpected at encryption level ",
- EncryptionLevelToString(decrypted_level)));
- return RaiseError(IETF_QUIC_PROTOCOL_VIOLATION);
- }
+ if (!IsIetfFrameTypeExpectedForEncryptionLevel(frame_type,
+ decrypted_level)) {
+ set_detailed_error(absl::StrCat(
+ "IETF frame type ",
+ QuicIetfFrameTypeString(static_cast<QuicIetfFrameType>(frame_type)),
+ " is unexpected at encryption level ",
+ EncryptionLevelToString(decrypted_level)));
+ return RaiseError(IETF_QUIC_PROTOCOL_VIOLATION);
}
current_received_frame_type_ = frame_type;
@@ -4872,10 +4840,8 @@ bool QuicFramer::DecryptPayload(size_t udp_packet_length,
if ((current_key_phase_first_received_packet_number_.IsInitialized() &&
header.packet_number >
current_key_phase_first_received_packet_number_) ||
- (GetQuicReloadableFlag(quic_fix_key_update_on_first_packet) &&
- !current_key_phase_first_received_packet_number_.IsInitialized() &&
+ (!current_key_phase_first_received_packet_number_.IsInitialized() &&
!key_update_performed_)) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_fix_key_update_on_first_packet);
if (!next_decrypter_) {
next_decrypter_ =
visitor_->AdvanceKeysAndCreateCurrentOneRttDecrypter();
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 e27c7f0727e..2920db351c4 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
@@ -634,6 +634,8 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
Perspective perspective() const { return perspective_; }
+ QuicStreamFrameDataProducer* data_producer() const { return data_producer_; }
+
void set_data_producer(QuicStreamFrameDataProducer* data_producer) {
data_producer_ = data_producer;
}
@@ -714,10 +716,6 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
drop_incoming_retry_packets_ = drop_incoming_retry_packets;
}
- bool do_not_synthesize_source_cid_for_short_header() const {
- return do_not_synthesize_source_cid_for_short_header_;
- }
-
private:
friend class test::QuicFramerPeer;
@@ -1174,14 +1172,6 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
// Indicates whether received RETRY packets should be dropped.
bool drop_incoming_retry_packets_ = false;
- bool reject_unexpected_ietf_frame_types_ =
- GetQuicReloadableFlag(quic_reject_unexpected_ietf_frame_types);
-
- // Indicates whether source connection ID should be synthesized when read
- // short header packet.
- const bool do_not_synthesize_source_cid_for_short_header_ =
- GetQuicReloadableFlag(quic_do_not_synthesize_source_cid_for_short_header);
-
// The length in bytes of the last packet number written to an IETF-framed
// packet.
size_t last_written_packet_number_length_;
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 048a4b72ffb..63a1ad5ed4f 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
@@ -34,7 +34,6 @@
#include "quic/test_tools/quic_framer_peer.h"
#include "quic/test_tools/quic_test_utils.h"
#include "quic/test_tools/simple_data_producer.h"
-#include "common/platform/api/quiche_text_utils.h"
#include "common/test_tools/quiche_test_utils.h"
using testing::_;
@@ -1479,9 +1478,6 @@ TEST_P(QuicFramerTest, ClientConnectionIdFromShortHeaderToClient) {
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
- if (!framer_.do_not_synthesize_source_cid_for_short_header()) {
- EXPECT_EQ(TestConnectionId(0x33), visitor_.header_->source_connection_id);
- }
}
// In short header packets from client to server, the client connection ID
@@ -1515,9 +1511,6 @@ TEST_P(QuicFramerTest, ClientConnectionIdFromShortHeaderToServer) {
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
- if (!framer_.do_not_synthesize_source_cid_for_short_header()) {
- EXPECT_EQ(TestConnectionId(0x33), visitor_.header_->source_connection_id);
- }
}
TEST_P(QuicFramerTest, PacketHeaderWith0ByteConnectionId) {
@@ -1567,9 +1560,6 @@ TEST_P(QuicFramerTest, PacketHeaderWith0ByteConnectionId) {
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
EXPECT_THAT(framer_.error(), IsError(QUIC_MISSING_PAYLOAD));
ASSERT_TRUE(visitor_.header_.get());
- if (!framer_.do_not_synthesize_source_cid_for_short_header()) {
- EXPECT_EQ(FramerTestConnectionId(), visitor_.header_->source_connection_id);
- }
EXPECT_FALSE(visitor_.header_->reset_flag);
EXPECT_FALSE(visitor_.header_->version_flag);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
@@ -9248,7 +9238,7 @@ TEST_P(QuicFramerTest, BuildPublicResetPacketWithEndpointId) {
}
TEST_P(QuicFramerTest, BuildIetfStatelessResetPacket) {
- if (GetQuicReloadableFlag(quic_fix_stateless_reset)) {
+ if (GetQuicRestartFlag(quic_fix_stateless_reset2)) {
// clang-format off
unsigned char packet[] = {
// 1st byte 01XX XXXX
@@ -9282,13 +9272,12 @@ TEST_P(QuicFramerTest, BuildIetfStatelessResetPacket) {
// Packets with length <= minimal stateless reset does not trigger stateless
// reset.
- EXPECT_QUIC_BUG(
- std::unique_ptr<QuicEncryptedPacket> data2(
- framer_.BuildIetfStatelessResetPacket(
- FramerTestConnectionId(),
- QuicFramer::GetMinStatelessResetPacketLength(),
- kTestStatelessResetToken)),
- "Tried to build stateless reset packet with received packet length");
+ std::unique_ptr<QuicEncryptedPacket> data2(
+ framer_.BuildIetfStatelessResetPacket(
+ FramerTestConnectionId(),
+ QuicFramer::GetMinStatelessResetPacketLength(),
+ kTestStatelessResetToken));
+ ASSERT_FALSE(data2);
// Do not send stateless reset >= minimal stateless reset + 1 + max
// connection ID length.
@@ -15230,7 +15219,6 @@ TEST_P(QuicFramerTest, KeyUpdateOnFirstReceivedPacket) {
// Key update is only used in QUIC+TLS.
return;
}
- SetQuicReloadableFlag(quic_fix_key_update_on_first_packet, true);
ASSERT_TRUE(framer_.version().KnowsWhichDecrypterToUse());
// Doesn't use SetDecrypterLevel since we want to use StrictTaggingDecrypter
// instead of TestDecrypter.
@@ -15262,8 +15250,7 @@ TEST_P(QuicFramerTest, KeyUpdateOnFirstReceivedPacket) {
}
TEST_P(QuicFramerTest, ErrorWhenUnexpectedFrameTypeEncountered) {
- if (!GetQuicReloadableFlag(quic_reject_unexpected_ietf_frame_types) ||
- !VersionHasIetfQuicFrames(framer_.transport_version()) ||
+ if (!VersionHasIetfQuicFrames(framer_.transport_version()) ||
!QuicVersionHasLongHeaderLengths(framer_.transport_version()) ||
!framer_.version().HasLongHeaderLengths()) {
return;
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
index ba27aa9d8f5..274c2e384df 100644
--- 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
@@ -8,12 +8,12 @@
#include <algorithm>
#include "absl/types/optional.h"
-#include "quic/core/quic_circular_deque.h"
#include "quic/core/quic_interval.h"
#include "quic/core/quic_types.h"
#include "quic/platform/api/quic_bug_tracker.h"
#include "quic/platform/api/quic_export.h"
#include "quic/platform/api/quic_logging.h"
+#include "common/quiche_circular_deque.h"
namespace quic {
@@ -137,7 +137,7 @@ class QuicIntervalDequePeer;
// // cached_index -> 1
// // container -> {{2, [25, 30)}, {3, [35, 50)}}
-template <class T, class C = QUIC_NO_EXPORT QuicCircularDeque<T>>
+template <class T, class C = QUIC_NO_EXPORT quiche::QuicheCircularDeque<T>>
class QUIC_NO_EXPORT QuicIntervalDeque {
public:
class QUIC_NO_EXPORT Iterator {
@@ -363,7 +363,7 @@ void QuicIntervalDeque<T, C>::PushBackUniversal(U&& item) {
// Adding an empty interval is a bug.
if (interval.Empty()) {
QUIC_BUG(quic_bug_10862_3)
- << "Trying to save empty interval to QuicCircularDeque.";
+ << "Trying to save empty interval to quiche::QuicheCircularDeque.";
return;
}
container_.push_back(std::forward<U>(item));
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_legacy_version_encapsulator.cc b/chromium/net/third_party/quiche/src/quic/core/quic_legacy_version_encapsulator.cc
index 27dbb9b48a8..11d2293bee5 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_legacy_version_encapsulator.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_legacy_version_encapsulator.cc
@@ -7,7 +7,6 @@
#include "quic/core/crypto/crypto_protocol.h"
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_bug_tracker.h"
-#include "common/platform/api/quiche_text_utils.h"
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_legacy_version_encapsulator_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_legacy_version_encapsulator_test.cc
index 1d855f2f55d..2f74d3ac7e7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_legacy_version_encapsulator_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_legacy_version_encapsulator_test.cc
@@ -9,7 +9,6 @@
#include "quic/platform/api/quic_expect_bug.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/quic_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
namespace quic {
namespace test {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_linux_socket_utils.h b/chromium/net/third_party/quiche/src/quic/core/quic_linux_socket_utils.h
index 14c26dc8d73..5bbd875180b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_linux_socket_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_linux_socket_utils.h
@@ -148,7 +148,7 @@ struct QUIC_EXPORT_PRIVATE BufferedWrite {
// multiple packets at once via ::sendmmsg.
//
// Example:
-// QuicCircularDeque<BufferedWrite> buffered_writes;
+// quiche::QuicheCircularDeque<BufferedWrite> buffered_writes;
// ... (Populate buffered_writes) ...
//
// QuicMMsgHdr mhdr(
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_linux_socket_utils_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_linux_socket_utils_test.cc
index 84259583063..588c2be8480 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_linux_socket_utils_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_linux_socket_utils_test.cc
@@ -12,9 +12,9 @@
#include <string>
-#include "quic/core/quic_circular_deque.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/quic_mock_syscall_wrapper.h"
+#include "common/quiche_circular_deque.h"
using testing::_;
using testing::InSequence;
@@ -28,8 +28,8 @@ class QuicLinuxSocketUtilsTest : public QuicTest {
protected:
WriteResult TestWriteMultiplePackets(
int fd,
- const QuicCircularDeque<BufferedWrite>::const_iterator& first,
- const QuicCircularDeque<BufferedWrite>::const_iterator& last,
+ const quiche::QuicheCircularDeque<BufferedWrite>::const_iterator& first,
+ const quiche::QuicheCircularDeque<BufferedWrite>::const_iterator& last,
int* num_packets_sent) {
QuicMMsgHdr mhdr(
first, last, kCmsgSpaceForIp,
@@ -171,7 +171,7 @@ TEST_F(QuicLinuxSocketUtilsTest, QuicMsgHdr) {
}
TEST_F(QuicLinuxSocketUtilsTest, QuicMMsgHdr) {
- QuicCircularDeque<BufferedWrite> buffered_writes;
+ quiche::QuicheCircularDeque<BufferedWrite> buffered_writes;
char packet_buf1[1024];
char packet_buf2[512];
buffered_writes.emplace_back(
@@ -205,7 +205,7 @@ TEST_F(QuicLinuxSocketUtilsTest, QuicMMsgHdr) {
TEST_F(QuicLinuxSocketUtilsTest, WriteMultiplePackets_NoPacketsToSend) {
int num_packets_sent;
- QuicCircularDeque<BufferedWrite> buffered_writes;
+ quiche::QuicheCircularDeque<BufferedWrite> buffered_writes;
EXPECT_CALL(mock_syscalls_, Sendmmsg(_, _, _, _)).Times(0);
@@ -216,7 +216,7 @@ TEST_F(QuicLinuxSocketUtilsTest, WriteMultiplePackets_NoPacketsToSend) {
TEST_F(QuicLinuxSocketUtilsTest, WriteMultiplePackets_WriteBlocked) {
int num_packets_sent;
- QuicCircularDeque<BufferedWrite> buffered_writes;
+ quiche::QuicheCircularDeque<BufferedWrite> buffered_writes;
buffered_writes.emplace_back(nullptr, 0, QuicIpAddress(),
QuicSocketAddress(QuicIpAddress::Any4(), 0));
@@ -235,7 +235,7 @@ TEST_F(QuicLinuxSocketUtilsTest, WriteMultiplePackets_WriteBlocked) {
TEST_F(QuicLinuxSocketUtilsTest, WriteMultiplePackets_WriteError) {
int num_packets_sent;
- QuicCircularDeque<BufferedWrite> buffered_writes;
+ quiche::QuicheCircularDeque<BufferedWrite> buffered_writes;
buffered_writes.emplace_back(nullptr, 0, QuicIpAddress(),
QuicSocketAddress(QuicIpAddress::Any4(), 0));
@@ -254,7 +254,7 @@ TEST_F(QuicLinuxSocketUtilsTest, WriteMultiplePackets_WriteError) {
TEST_F(QuicLinuxSocketUtilsTest, WriteMultiplePackets_WriteSuccess) {
int num_packets_sent;
- QuicCircularDeque<BufferedWrite> buffered_writes;
+ quiche::QuicheCircularDeque<BufferedWrite> buffered_writes;
const int kNumBufferedWrites = 10;
static_assert(kNumBufferedWrites < 256, "Must be less than 256");
std::vector<std::string> buffer_holder;
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 42aebe5ce4b..cbca89dae55 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
@@ -15,10 +15,12 @@
#include "absl/base/optimization.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
#include "quic/core/crypto/crypto_protocol.h"
#include "quic/core/frames/quic_frame.h"
#include "quic/core/frames/quic_path_challenge_frame.h"
#include "quic/core/frames/quic_stream_frame.h"
+#include "quic/core/quic_chaos_protector.h"
#include "quic/core/quic_connection_id.h"
#include "quic/core/quic_constants.h"
#include "quic/core/quic_data_writer.h"
@@ -32,7 +34,6 @@
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
#include "quic/platform/api/quic_server_stats.h"
-#include "common/platform/api/quiche_text_utils.h"
namespace quic {
namespace {
@@ -133,7 +134,8 @@ QuicPacketCreator::QuicPacketCreator(QuicConnectionId server_connection_id,
flusher_attached_(false),
fully_pad_crypto_handshake_packets_(true),
latched_hard_max_packet_length_(0),
- max_datagram_frame_size_(0) {
+ max_datagram_frame_size_(0),
+ chaos_protection_enabled_(false) {
SetMaxPacketLength(kDefaultMaxPacketSize);
if (!framer_->version().UsesTls()) {
// QUIC+TLS negotiates the maximum datagram frame size via the
@@ -159,21 +161,21 @@ bool QuicPacketCreator::CanSetMaxPacketLength() const {
}
void QuicPacketCreator::SetMaxPacketLength(QuicByteCount length) {
- QUICHE_DCHECK(CanSetMaxPacketLength());
+ QUICHE_DCHECK(CanSetMaxPacketLength()) << ENDPOINT;
// Avoid recomputing |max_plaintext_size_| if the length does not actually
// change.
if (length == max_packet_length_) {
return;
}
- QUIC_DVLOG(1) << "Updating packet creator max packet length from "
+ QUIC_DVLOG(1) << ENDPOINT << "Updating packet creator max packet length from "
<< max_packet_length_ << " to " << length;
max_packet_length_ = length;
max_plaintext_size_ = framer_->GetMaxPlaintextSize(max_packet_length_);
QUIC_BUG_IF(quic_bug_12398_2, max_plaintext_size_ - PacketHeaderSize() <
MinPlaintextPacketSize(framer_->version()))
- << "Attempted to set max packet length too small";
+ << ENDPOINT << "Attempted to set max packet length too small";
}
void QuicPacketCreator::SetMaxDatagramFrameSize(
@@ -192,7 +194,7 @@ void QuicPacketCreator::SetMaxDatagramFrameSize(
}
void QuicPacketCreator::SetSoftMaxPacketLength(QuicByteCount length) {
- QUICHE_DCHECK(CanSetMaxPacketLength());
+ QUICHE_DCHECK(CanSetMaxPacketLength()) << ENDPOINT;
if (length > max_packet_length_) {
QUIC_BUG(quic_bug_10752_2)
<< ENDPOINT
@@ -204,11 +206,12 @@ void QuicPacketCreator::SetSoftMaxPacketLength(QuicByteCount length) {
PacketHeaderSize() + MinPlaintextPacketSize(framer_->version())) {
// Please note: this would not guarantee to fit next packet if the size of
// packet header increases (e.g., encryption level changes).
- QUIC_DLOG(INFO) << length << " is too small to fit packet header";
+ QUIC_DLOG(INFO) << ENDPOINT << length
+ << " is too small to fit packet header";
RemoveSoftMaxPacketLength();
return;
}
- QUIC_DVLOG(1) << "Setting soft max packet length to: " << length;
+ QUIC_DVLOG(1) << ENDPOINT << "Setting soft max packet length to: " << length;
latched_hard_max_packet_length_ = max_packet_length_;
max_packet_length_ = length;
max_plaintext_size_ = framer_->GetMaxPlaintextSize(length);
@@ -218,18 +221,18 @@ void QuicPacketCreator::SetSoftMaxPacketLength(QuicByteCount length) {
// A packet that is already open might send kQuicVersionSize bytes less than the
// maximum packet size if we stop sending version before it is serialized.
void QuicPacketCreator::StopSendingVersion() {
- QUICHE_DCHECK(send_version_in_packet_);
- QUICHE_DCHECK(!version().HasIetfInvariantHeader());
+ QUICHE_DCHECK(send_version_in_packet_) << ENDPOINT;
+ QUICHE_DCHECK(!version().HasIetfInvariantHeader()) << ENDPOINT;
send_version_in_packet_ = false;
if (packet_size_ > 0) {
- QUICHE_DCHECK_LT(kQuicVersionSize, packet_size_);
+ QUICHE_DCHECK_LT(kQuicVersionSize, packet_size_) << ENDPOINT;
packet_size_ -= kQuicVersionSize;
}
}
void QuicPacketCreator::SetDiversificationNonce(
const DiversificationNonce& nonce) {
- QUICHE_DCHECK(!have_diversification_nonce_);
+ QUICHE_DCHECK(!have_diversification_nonce_) << ENDPOINT;
have_diversification_nonce_ = true;
diversification_nonce_ = nonce;
}
@@ -240,14 +243,16 @@ void QuicPacketCreator::UpdatePacketNumberLength(
if (!queued_frames_.empty()) {
// Don't change creator state if there are frames queued.
QUIC_BUG(quic_bug_10752_3)
- << "Called UpdatePacketNumberLength with " << queued_frames_.size()
+ << ENDPOINT << "Called UpdatePacketNumberLength with "
+ << queued_frames_.size()
<< " queued_frames. First frame type:" << queued_frames_.front().type
<< " last frame type:" << queued_frames_.back().type;
return;
}
const QuicPacketNumber next_packet_number = NextSendingPacketNumber();
- QUICHE_DCHECK_LE(least_packet_awaited_by_peer, next_packet_number);
+ QUICHE_DCHECK_LE(least_packet_awaited_by_peer, next_packet_number)
+ << ENDPOINT;
const uint64_t current_delta =
next_packet_number - least_packet_awaited_by_peer;
const uint64_t delta = std::max(current_delta, max_packets_in_flight);
@@ -273,7 +278,8 @@ void QuicPacketCreator::SkipNPacketNumbers(
if (!queued_frames_.empty()) {
// Don't change creator state if there are frames queued.
QUIC_BUG(quic_bug_10752_4)
- << "Called SkipNPacketNumbers with " << queued_frames_.size()
+ << ENDPOINT << "Called SkipNPacketNumbers with "
+ << queued_frames_.size()
<< " queued_frames. First frame type:" << queued_frames_.front().type
<< " last frame type:" << queued_frames_.back().type;
return;
@@ -281,7 +287,7 @@ void QuicPacketCreator::SkipNPacketNumbers(
if (packet_.packet_number > packet_.packet_number + count) {
// Skipping count packet numbers causes packet number wrapping around,
// reject it.
- QUIC_LOG(WARNING) << "Skipping " << count
+ QUIC_LOG(WARNING) << ENDPOINT << "Skipping " << count
<< " packet numbers causes packet number wrapping "
"around, least_packet_awaited_by_peer: "
<< least_packet_awaited_by_peer
@@ -300,7 +306,7 @@ bool QuicPacketCreator::ConsumeCryptoDataToFillCurrentPacket(
bool needs_full_padding,
TransmissionType transmission_type,
QuicFrame* frame) {
- QUIC_DVLOG(2) << "ConsumeCryptoDataToFillCurrentPacket " << level
+ QUIC_DVLOG(2) << ENDPOINT << "ConsumeCryptoDataToFillCurrentPacket " << level
<< " write_length " << write_length << " offset " << offset
<< (needs_full_padding ? " needs_full_padding" : "") << " "
<< transmission_type;
@@ -338,7 +344,7 @@ bool QuicPacketCreator::ConsumeDataToFillCurrentPacket(
const std::string error_details =
"Client hello won't fit in a single packet.";
QUIC_BUG(quic_bug_10752_5)
- << error_details << " Constructed stream frame length: "
+ << ENDPOINT << error_details << " Constructed stream frame length: "
<< frame->stream_frame.data_length << " CHLO length: " << data_size;
delegate_->OnUnrecoverableError(QUIC_CRYPTO_CHLO_TOO_LARGE, error_details);
return false;
@@ -422,16 +428,17 @@ void QuicPacketCreator::CreateStreamFrame(QuicStreamId id,
GetSourceConnectionIdLength(), kIncludeVersion,
IncludeNonceInPublicHeader(), PACKET_6BYTE_PACKET_NUMBER,
GetRetryTokenLengthLength(), GetLengthLength(), offset) ||
- latched_hard_max_packet_length_ > 0);
+ latched_hard_max_packet_length_ > 0)
+ << ENDPOINT;
QUIC_BUG_IF(quic_bug_12398_3, !HasRoomForStreamFrame(id, offset, data_size))
- << "No room for Stream frame, BytesFree: " << BytesFree()
+ << ENDPOINT << "No room for Stream frame, BytesFree: " << BytesFree()
<< " MinStreamFrameSize: "
<< QuicFramer::GetMinStreamFrameSize(framer_->transport_version(), id,
offset, true, data_size);
QUIC_BUG_IF(quic_bug_12398_4, data_size == 0 && !fin)
- << "Creating a stream frame for stream ID:" << id
+ << ENDPOINT << "Creating a stream frame for stream ID:" << id
<< " with no data or fin.";
size_t min_frame_size = QuicFramer::GetMinStreamFrameSize(
framer_->transport_version(), id, offset,
@@ -472,7 +479,7 @@ void QuicPacketCreator::FlushCurrentPacket() {
external_buffer.release_buffer = nullptr;
}
- QUICHE_DCHECK_EQ(nullptr, packet_.encrypted_buffer);
+ QUICHE_DCHECK_EQ(nullptr, packet_.encrypted_buffer) << ENDPOINT;
if (!SerializePacket(std::move(external_buffer), kMaxOutgoingPacketSize)) {
return;
}
@@ -480,7 +487,8 @@ void QuicPacketCreator::FlushCurrentPacket() {
}
void QuicPacketCreator::OnSerializedPacket() {
- QUIC_BUG_IF(quic_bug_12398_5, packet_.encrypted_buffer == nullptr);
+ QUIC_BUG_IF(quic_bug_12398_5, packet_.encrypted_buffer == nullptr)
+ << ENDPOINT;
SerializedPacket packet(std::move(packet_));
ClearPacket();
@@ -499,10 +507,10 @@ void QuicPacketCreator::ClearPacket() {
packet_.has_message = false;
packet_.fate = SEND_TO_WRITER;
QUIC_BUG_IF(quic_bug_12398_6, packet_.release_encrypted_buffer != nullptr)
- << "packet_.release_encrypted_buffer should be empty";
+ << ENDPOINT << "packet_.release_encrypted_buffer should be empty";
packet_.release_encrypted_buffer = nullptr;
- QUICHE_DCHECK(packet_.retransmittable_frames.empty());
- QUICHE_DCHECK(packet_.nonretransmittable_frames.empty());
+ QUICHE_DCHECK(packet_.retransmittable_frames.empty()) << ENDPOINT;
+ QUICHE_DCHECK(packet_.nonretransmittable_frames.empty()) << ENDPOINT;
packet_.largest_acked.Clear();
needs_full_padding_ = false;
}
@@ -515,6 +523,7 @@ size_t QuicPacketCreator::ReserializeInitialPacketInCoalescedPacket(
QUIC_BUG_IF(quic_bug_12398_7, packet.encryption_level != ENCRYPTION_INITIAL);
QUIC_BUG_IF(quic_bug_12398_8, packet.nonretransmittable_frames.empty() &&
packet.retransmittable_frames.empty())
+ << ENDPOINT
<< "Attempt to serialize empty ENCRYPTION_INITIAL packet in coalesced "
"packet";
ScopedPacketContextSwitcher switcher(
@@ -523,13 +532,15 @@ size_t QuicPacketCreator::ReserializeInitialPacketInCoalescedPacket(
packet.packet_number_length, packet.encryption_level, &packet_);
for (const QuicFrame& frame : packet.nonretransmittable_frames) {
if (!AddFrame(frame, packet.transmission_type)) {
- QUIC_BUG(quic_bug_10752_6) << "Failed to serialize frame: " << frame;
+ QUIC_BUG(quic_bug_10752_6)
+ << ENDPOINT << "Failed to serialize frame: " << frame;
return 0;
}
}
for (const QuicFrame& frame : packet.retransmittable_frames) {
if (!AddFrame(frame, packet.transmission_type)) {
- QUIC_BUG(quic_bug_10752_7) << "Failed to serialize frame: " << frame;
+ QUIC_BUG(quic_bug_10752_7)
+ << ENDPOINT << "Failed to serialize frame: " << frame;
return 0;
}
}
@@ -539,7 +550,7 @@ size_t QuicPacketCreator::ReserializeInitialPacketInCoalescedPacket(
if (!AddFrame(QuicFrame(QuicPaddingFrame(padding_size)),
packet.transmission_type)) {
QUIC_BUG(quic_bug_10752_8)
- << "Failed to add padding of size " << padding_size
+ << ENDPOINT << "Failed to add padding of size " << padding_size
<< " when serializing ENCRYPTION_INITIAL "
"packet in coalesced packet";
return 0;
@@ -566,8 +577,9 @@ void QuicPacketCreator::CreateAndSerializeStreamFrame(
TransmissionType transmission_type,
size_t* num_bytes_consumed) {
// TODO(b/167222597): consider using ScopedSerializationFailureHandler.
- QUICHE_DCHECK(queued_frames_.empty());
- QUICHE_DCHECK(!QuicUtils::IsCryptoStreamId(transport_version(), id));
+ QUICHE_DCHECK(queued_frames_.empty()) << ENDPOINT;
+ QUICHE_DCHECK(!QuicUtils::IsCryptoStreamId(transport_version(), id))
+ << ENDPOINT;
// Write out the packet header
QuicPacketHeader header;
FillPacketHeader(&header);
@@ -590,13 +602,13 @@ void QuicPacketCreator::CreateAndSerializeStreamFrame(
QuicDataWriter writer(kMaxOutgoingPacketSize, encrypted_buffer);
size_t length_field_offset = 0;
if (!framer_->AppendPacketHeader(header, &writer, &length_field_offset)) {
- QUIC_BUG(quic_bug_10752_9) << "AppendPacketHeader failed";
+ QUIC_BUG(quic_bug_10752_9) << ENDPOINT << "AppendPacketHeader failed";
return;
}
// Create a Stream frame with the remaining space.
QUIC_BUG_IF(quic_bug_12398_9, iov_offset == write_length && !fin)
- << "Creating a stream frame with no data or fin.";
+ << ENDPOINT << "Creating a stream frame with no data or fin.";
const size_t remaining_data_size = write_length - iov_offset;
size_t min_frame_size = QuicFramer::GetMinStreamFrameSize(
framer_->transport_version(), id, stream_offset,
@@ -631,18 +643,18 @@ void QuicPacketCreator::CreateAndSerializeStreamFrame(
// into one method that takes a QuicStreamFrame, if warranted.
bool omit_frame_length = !needs_padding;
if (!framer_->AppendTypeByte(QuicFrame(frame), omit_frame_length, &writer)) {
- QUIC_BUG(quic_bug_10752_10) << "AppendTypeByte failed";
+ QUIC_BUG(quic_bug_10752_10) << ENDPOINT << "AppendTypeByte failed";
return;
}
if (!framer_->AppendStreamFrame(frame, omit_frame_length, &writer)) {
- QUIC_BUG(quic_bug_10752_11) << "AppendStreamFrame failed";
+ QUIC_BUG(quic_bug_10752_11) << ENDPOINT << "AppendStreamFrame failed";
return;
}
if (needs_padding &&
plaintext_bytes_written < MinPlaintextPacketSize(framer_->version()) &&
!writer.WritePaddingBytes(MinPlaintextPacketSize(framer_->version()) -
plaintext_bytes_written)) {
- QUIC_BUG(quic_bug_10752_12) << "Unable to add padding bytes";
+ QUIC_BUG(quic_bug_10752_12) << ENDPOINT << "Unable to add padding bytes";
return;
}
@@ -655,14 +667,15 @@ void QuicPacketCreator::CreateAndSerializeStreamFrame(
QUICHE_DCHECK(packet_.encryption_level == ENCRYPTION_FORWARD_SECURE ||
packet_.encryption_level == ENCRYPTION_ZERO_RTT)
- << packet_.encryption_level;
+ << ENDPOINT << packet_.encryption_level;
size_t encrypted_length = framer_->EncryptInPlace(
packet_.encryption_level, packet_.packet_number,
GetStartOfEncryptedData(framer_->transport_version(), header),
writer.length(), kMaxOutgoingPacketSize, encrypted_buffer);
if (encrypted_length == 0) {
QUIC_BUG(quic_bug_10752_13)
- << "Failed to encrypt packet number " << header.packet_number;
+ << ENDPOINT << "Failed to encrypt packet number "
+ << header.packet_number;
return;
}
// TODO(ianswett): Optimize the storage so RetransmitableFrames can be
@@ -724,7 +737,6 @@ size_t QuicPacketCreator::ExpansionOnNewFrameWithLastFrame(
}
size_t QuicPacketCreator::BytesFree() const {
- QUICHE_DCHECK_GE(max_plaintext_size_, PacketSize());
return max_plaintext_size_ -
std::min(max_plaintext_size_, PacketSize() + ExpansionOnNewFrame());
}
@@ -743,22 +755,51 @@ bool QuicPacketCreator::AddPaddedSavedFrame(
return false;
}
+absl::optional<size_t>
+QuicPacketCreator::MaybeBuildDataPacketWithChaosProtection(
+ const QuicPacketHeader& header,
+ char* buffer) {
+ if (!chaos_protection_enabled_ ||
+ packet_.encryption_level != ENCRYPTION_INITIAL ||
+ !framer_->version().UsesCryptoFrames() || queued_frames_.size() != 2u ||
+ queued_frames_[0].type != CRYPTO_FRAME ||
+ queued_frames_[1].type != PADDING_FRAME ||
+ // Do not perform chaos protection if we do not have a known number of
+ // padding bytes to work with.
+ queued_frames_[1].padding_frame.num_padding_bytes <= 0 ||
+ // Chaos protection relies on the framer using a crypto data producer,
+ // which is always the case in practice.
+ framer_->data_producer() == nullptr) {
+ return absl::nullopt;
+ }
+ const QuicCryptoFrame& crypto_frame = *queued_frames_[0].crypto_frame;
+ if (packet_.encryption_level != crypto_frame.level) {
+ QUIC_BUG(chaos frame level)
+ << ENDPOINT << packet_.encryption_level << " != " << crypto_frame.level;
+ return absl::nullopt;
+ }
+ QuicChaosProtector chaos_protector(
+ crypto_frame, queued_frames_[1].padding_frame.num_padding_bytes,
+ packet_size_, framer_, random_);
+ return chaos_protector.BuildDataPacket(header, buffer);
+}
+
bool QuicPacketCreator::SerializePacket(QuicOwnedPacketBuffer encrypted_buffer,
size_t encrypted_buffer_len) {
if (packet_.encrypted_buffer != nullptr) {
const std::string error_details =
"Packet's encrypted buffer is not empty before serialization";
- QUIC_BUG(quic_bug_10752_14) << error_details;
+ QUIC_BUG(quic_bug_10752_14) << ENDPOINT << error_details;
delegate_->OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET,
error_details);
return false;
}
ScopedSerializationFailureHandler handler(this);
- QUICHE_DCHECK_LT(0u, encrypted_buffer_len);
+ QUICHE_DCHECK_LT(0u, encrypted_buffer_len) << ENDPOINT;
QUIC_BUG_IF(quic_bug_12398_10,
queued_frames_.empty() && pending_padding_bytes_ == 0)
- << "Attempt to serialize empty packet";
+ << ENDPOINT << "Attempt to serialize empty packet";
QuicPacketHeader header;
// FillPacketHeader increments packet_number_.
FillPacketHeader(&header);
@@ -789,15 +830,25 @@ bool QuicPacketCreator::SerializePacket(QuicOwnedPacketBuffer encrypted_buffer,
return false;
}
- QUICHE_DCHECK_GE(max_plaintext_size_, packet_size_);
+ QUICHE_DCHECK_GE(max_plaintext_size_, packet_size_) << ENDPOINT;
// Use the packet_size_ instead of the buffer size to ensure smaller
// packet sizes are properly used.
- size_t length =
- framer_->BuildDataPacket(header, queued_frames_, encrypted_buffer.buffer,
- packet_size_, packet_.encryption_level);
+
+ size_t length;
+ absl::optional<size_t> length_with_chaos_protection =
+ MaybeBuildDataPacketWithChaosProtection(header, encrypted_buffer.buffer);
+ if (length_with_chaos_protection.has_value()) {
+ length = length_with_chaos_protection.value();
+ } else {
+ length = framer_->BuildDataPacket(header, queued_frames_,
+ encrypted_buffer.buffer, packet_size_,
+ packet_.encryption_level);
+ }
+
if (length == 0) {
QUIC_BUG(quic_bug_10752_16)
- << "Failed to serialize " << QuicFramesToString(queued_frames_)
+ << ENDPOINT << "Failed to serialize "
+ << QuicFramesToString(queued_frames_)
<< " at encryption_level: " << packet_.encryption_level
<< ", needs_full_padding_: " << needs_full_padding_
<< ", pending_padding_bytes_: " << pending_padding_bytes_
@@ -818,7 +869,7 @@ bool QuicPacketCreator::SerializePacket(QuicOwnedPacketBuffer encrypted_buffer,
// Because of possible truncation, we can't be confident that our
// packet size calculation worked correctly.
if (!possibly_truncated_by_length) {
- QUICHE_DCHECK_EQ(packet_size_, length);
+ QUICHE_DCHECK_EQ(packet_size_, length) << ENDPOINT;
}
const size_t encrypted_length = framer_->EncryptInPlace(
packet_.encryption_level, packet_.packet_number,
@@ -826,7 +877,8 @@ bool QuicPacketCreator::SerializePacket(QuicOwnedPacketBuffer encrypted_buffer,
encrypted_buffer_len, encrypted_buffer.buffer);
if (encrypted_length == 0) {
QUIC_BUG(quic_bug_10752_17)
- << "Failed to encrypt packet number " << packet_.packet_number;
+ << ENDPOINT << "Failed to encrypt packet number "
+ << packet_.packet_number;
return false;
}
@@ -843,6 +895,7 @@ std::unique_ptr<SerializedPacket>
QuicPacketCreator::SerializeConnectivityProbingPacket() {
QUIC_BUG_IF(quic_bug_12398_11,
VersionHasIetfQuicFrames(framer_->transport_version()))
+ << ENDPOINT
<< "Must not be version 99 to serialize padded ping connectivity probe";
RemoveSoftMaxPacketLength();
QuicPacketHeader header;
@@ -855,14 +908,15 @@ QuicPacketCreator::SerializeConnectivityProbingPacket() {
std::unique_ptr<char[]> buffer(new char[kMaxOutgoingPacketSize]);
size_t length = BuildConnectivityProbingPacket(
header, buffer.get(), max_plaintext_size_, packet_.encryption_level);
- QUICHE_DCHECK(length);
+ QUICHE_DCHECK(length) << ENDPOINT;
- QUICHE_DCHECK_EQ(packet_.encryption_level, ENCRYPTION_FORWARD_SECURE);
+ QUICHE_DCHECK_EQ(packet_.encryption_level, ENCRYPTION_FORWARD_SECURE)
+ << ENDPOINT;
const size_t encrypted_length = framer_->EncryptInPlace(
packet_.encryption_level, packet_.packet_number,
GetStartOfEncryptedData(framer_->transport_version(), header), length,
kMaxOutgoingPacketSize, buffer.get());
- QUICHE_DCHECK(encrypted_length);
+ QUICHE_DCHECK(encrypted_length) << ENDPOINT;
std::unique_ptr<SerializedPacket> serialize_packet(new SerializedPacket(
header.packet_number, header.packet_number_length, buffer.release(),
@@ -882,6 +936,7 @@ QuicPacketCreator::SerializePathChallengeConnectivityProbingPacket(
const QuicPathFrameBuffer& payload) {
QUIC_BUG_IF(quic_bug_12398_12,
!VersionHasIetfQuicFrames(framer_->transport_version()))
+ << ENDPOINT
<< "Must be version 99 to serialize path challenge connectivity probe, "
"is version "
<< framer_->transport_version();
@@ -896,14 +951,15 @@ QuicPacketCreator::SerializePathChallengeConnectivityProbingPacket(
size_t length =
BuildPaddedPathChallengePacket(header, buffer.get(), max_plaintext_size_,
payload, packet_.encryption_level);
- QUICHE_DCHECK(length);
+ QUICHE_DCHECK(length) << ENDPOINT;
- QUICHE_DCHECK_EQ(packet_.encryption_level, ENCRYPTION_FORWARD_SECURE);
+ QUICHE_DCHECK_EQ(packet_.encryption_level, ENCRYPTION_FORWARD_SECURE)
+ << ENDPOINT;
const size_t encrypted_length = framer_->EncryptInPlace(
packet_.encryption_level, packet_.packet_number,
GetStartOfEncryptedData(framer_->transport_version(), header), length,
kMaxOutgoingPacketSize, buffer.get());
- QUICHE_DCHECK(encrypted_length);
+ QUICHE_DCHECK(encrypted_length) << ENDPOINT;
std::unique_ptr<SerializedPacket> serialize_packet(
new SerializedPacket(header.packet_number, header.packet_number_length,
@@ -921,10 +977,11 @@ QuicPacketCreator::SerializePathChallengeConnectivityProbingPacket(
std::unique_ptr<SerializedPacket>
QuicPacketCreator::SerializePathResponseConnectivityProbingPacket(
- const QuicCircularDeque<QuicPathFrameBuffer>& payloads,
+ const quiche::QuicheCircularDeque<QuicPathFrameBuffer>& payloads,
const bool is_padded) {
QUIC_BUG_IF(quic_bug_12398_13,
!VersionHasIetfQuicFrames(framer_->transport_version()))
+ << ENDPOINT
<< "Must be version 99 to serialize path response connectivity probe, is "
"version "
<< framer_->transport_version();
@@ -939,14 +996,15 @@ QuicPacketCreator::SerializePathResponseConnectivityProbingPacket(
size_t length =
BuildPathResponsePacket(header, buffer.get(), max_plaintext_size_,
payloads, is_padded, packet_.encryption_level);
- QUICHE_DCHECK(length);
+ QUICHE_DCHECK(length) << ENDPOINT;
- QUICHE_DCHECK_EQ(packet_.encryption_level, ENCRYPTION_FORWARD_SECURE);
+ QUICHE_DCHECK_EQ(packet_.encryption_level, ENCRYPTION_FORWARD_SECURE)
+ << ENDPOINT;
const size_t encrypted_length = framer_->EncryptInPlace(
packet_.encryption_level, packet_.packet_number,
GetStartOfEncryptedData(framer_->transport_version(), header), length,
kMaxOutgoingPacketSize, buffer.get());
- QUICHE_DCHECK(encrypted_length);
+ QUICHE_DCHECK(encrypted_length) << ENDPOINT;
std::unique_ptr<SerializedPacket> serialize_packet(
new SerializedPacket(header.packet_number, header.packet_number_length,
@@ -968,7 +1026,8 @@ size_t QuicPacketCreator::BuildPaddedPathChallengePacket(
size_t packet_length,
const QuicPathFrameBuffer& payload,
EncryptionLevel level) {
- QUICHE_DCHECK(VersionHasIetfQuicFrames(framer_->transport_version()));
+ QUICHE_DCHECK(VersionHasIetfQuicFrames(framer_->transport_version()))
+ << ENDPOINT;
QuicFrames frames;
// Write a PATH_CHALLENGE frame, which has a random 8-byte payload
@@ -991,15 +1050,17 @@ size_t QuicPacketCreator::BuildPathResponsePacket(
const QuicPacketHeader& header,
char* buffer,
size_t packet_length,
- const QuicCircularDeque<QuicPathFrameBuffer>& payloads,
+ const quiche::QuicheCircularDeque<QuicPathFrameBuffer>& payloads,
const bool is_padded,
EncryptionLevel level) {
if (payloads.empty()) {
QUIC_BUG(quic_bug_12398_14)
+ << ENDPOINT
<< "Attempt to generate connectivity response with no request payloads";
return 0;
}
- QUICHE_DCHECK(VersionHasIetfQuicFrames(framer_->transport_version()));
+ QUICHE_DCHECK(VersionHasIetfQuicFrames(framer_->transport_version()))
+ << ENDPOINT;
std::vector<std::unique_ptr<QuicPathResponseFrame>> path_response_frames;
for (const QuicPathFrameBuffer& payload : payloads) {
@@ -1052,12 +1113,12 @@ size_t QuicPacketCreator::SerializeCoalescedPacket(
size_t buffer_len) {
if (HasPendingFrames()) {
QUIC_BUG(quic_bug_10752_18)
- << "Try to serialize coalesced packet with pending frames";
+ << ENDPOINT << "Try to serialize coalesced packet with pending frames";
return 0;
}
RemoveSoftMaxPacketLength();
QUIC_BUG_IF(quic_bug_12398_15, coalesced.length() == 0)
- << "Attempt to serialize empty coalesced packet";
+ << ENDPOINT << "Attempt to serialize empty coalesced packet";
size_t packet_length = 0;
if (coalesced.initial_packet() != nullptr) {
// Padding coalesced packet containing initial packet to full.
@@ -1073,6 +1134,7 @@ size_t QuicPacketCreator::SerializeCoalescedPacket(
*coalesced.initial_packet(), padding_size, buffer, buffer_len);
if (initial_length == 0) {
QUIC_BUG(quic_bug_10752_19)
+ << ENDPOINT
<< "Failed to reserialize ENCRYPTION_INITIAL packet in "
"coalesced packet";
return 0;
@@ -1141,7 +1203,8 @@ QuicConnectionIdIncluded QuicPacketCreator::GetSourceConnectionIdIncluded()
QuicConnectionIdLength QuicPacketCreator::GetDestinationConnectionIdLength()
const {
QUICHE_DCHECK(QuicUtils::IsConnectionIdValidForVersion(server_connection_id_,
- transport_version()));
+ transport_version()))
+ << ENDPOINT;
return GetDestinationConnectionIdIncluded() == CONNECTION_ID_PRESENT
? static_cast<QuicConnectionIdLength>(
GetDestinationConnectionId().length())
@@ -1150,7 +1213,8 @@ QuicConnectionIdLength QuicPacketCreator::GetDestinationConnectionIdLength()
QuicConnectionIdLength QuicPacketCreator::GetSourceConnectionIdLength() const {
QUICHE_DCHECK(QuicUtils::IsConnectionIdValidForVersion(server_connection_id_,
- transport_version()));
+ transport_version()))
+ << ENDPOINT;
return GetSourceConnectionIdIncluded() == CONNECTION_ID_PRESENT
? static_cast<QuicConnectionIdLength>(
GetSourceConnectionId().length())
@@ -1201,8 +1265,10 @@ bool QuicPacketCreator::ConsumeRetransmittableControlFrame(
QUIC_BUG_IF(quic_bug_12398_16, IsControlFrame(frame.type) &&
!GetControlFrameId(frame) &&
frame.type != PING_FRAME)
+ << ENDPOINT
<< "Adding a control frame with no control frame id: " << frame;
- QUICHE_DCHECK(QuicUtils::IsRetransmittableFrame(frame.type)) << frame;
+ QUICHE_DCHECK(QuicUtils::IsRetransmittableFrame(frame.type))
+ << ENDPOINT << frame;
MaybeBundleAckOpportunistically();
if (HasPendingFrames()) {
if (AddFrame(frame, next_transmission_type_)) {
@@ -1210,7 +1276,7 @@ bool QuicPacketCreator::ConsumeRetransmittableControlFrame(
return true;
}
}
- QUICHE_DCHECK(!HasPendingFrames());
+ QUICHE_DCHECK(!HasPendingFrames()) << ENDPOINT;
if (frame.type != PING_FRAME && frame.type != CONNECTION_CLOSE_FRAME &&
!delegate_->ShouldGeneratePacket(HAS_RETRANSMITTABLE_DATA,
NOT_HANDSHAKE)) {
@@ -1219,7 +1285,7 @@ bool QuicPacketCreator::ConsumeRetransmittableControlFrame(
}
const bool success = AddFrame(frame, next_transmission_type_);
QUIC_BUG_IF(quic_bug_10752_20, !success)
- << "Failed to add frame:" << frame
+ << ENDPOINT << "Failed to add frame:" << frame
<< " transmission_type:" << next_transmission_type_;
return success;
}
@@ -1229,13 +1295,14 @@ QuicConsumedData QuicPacketCreator::ConsumeData(QuicStreamId id,
QuicStreamOffset offset,
StreamSendingState state) {
QUIC_BUG_IF(quic_bug_10752_21, !flusher_attached_)
+ << ENDPOINT
<< "Packet flusher is not attached when "
"generator tries to write stream data.";
bool has_handshake = QuicUtils::IsCryptoStreamId(transport_version(), id);
MaybeBundleAckOpportunistically();
bool fin = state != NO_FIN;
QUIC_BUG_IF(quic_bug_12398_17, has_handshake && fin)
- << "Handshake packets should never send a fin";
+ << ENDPOINT << "Handshake packets should never send a fin";
// To make reasoning about crypto frames easier, we don't combine them with
// other retransmittable frames in a single packet.
if (has_handshake && HasPendingRetransmittableFrames()) {
@@ -1250,7 +1317,8 @@ QuicConsumedData QuicPacketCreator::ConsumeData(QuicStreamId id,
}
if (!fin && (write_length == 0)) {
- QUIC_BUG(quic_bug_10752_22) << "Attempt to consume empty data without FIN.";
+ QUIC_BUG(quic_bug_10752_22)
+ << ENDPOINT << "Attempt to consume empty data without FIN.";
return QuicConsumedData(0, false);
}
// We determine if we can enter the fast path before executing
@@ -1273,7 +1341,8 @@ QuicConsumedData QuicPacketCreator::ConsumeData(QuicStreamId id,
next_transmission_type_, &frame)) {
// The creator is always flushed if there's not enough room for a new
// stream frame before ConsumeData, so ConsumeData should always succeed.
- QUIC_BUG(quic_bug_10752_23) << "Failed to ConsumeData, stream:" << id;
+ QUIC_BUG(quic_bug_10752_23)
+ << ENDPOINT << "Failed to ConsumeData, stream:" << id;
return QuicConsumedData(0, false);
}
@@ -1285,7 +1354,8 @@ QuicConsumedData QuicPacketCreator::ConsumeData(QuicStreamId id,
AddRandomPadding();
}
QUICHE_DCHECK(total_bytes_consumed == write_length ||
- (bytes_consumed > 0 && HasPendingFrames()));
+ (bytes_consumed > 0 && HasPendingFrames()))
+ << ENDPOINT;
if (total_bytes_consumed == write_length) {
// We're done writing the data. Exit the loop.
@@ -1320,7 +1390,8 @@ QuicConsumedData QuicPacketCreator::ConsumeDataFastPath(
QuicStreamOffset offset,
bool fin,
size_t total_bytes_consumed) {
- QUICHE_DCHECK(!QuicUtils::IsCryptoStreamId(transport_version(), id));
+ QUICHE_DCHECK(!QuicUtils::IsCryptoStreamId(transport_version(), id))
+ << ENDPOINT;
if (AttemptingToSendUnencryptedStreamData()) {
return QuicConsumedData(total_bytes_consumed,
fin && (total_bytes_consumed == write_length));
@@ -1337,7 +1408,7 @@ QuicConsumedData QuicPacketCreator::ConsumeDataFastPath(
if (bytes_consumed == 0) {
const std::string error_details =
"Failed in CreateAndSerializeStreamFrame.";
- QUIC_BUG(quic_bug_10752_24) << error_details;
+ QUIC_BUG(quic_bug_10752_24) << ENDPOINT << error_details;
delegate_->OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET,
error_details);
break;
@@ -1352,9 +1423,10 @@ QuicConsumedData QuicPacketCreator::ConsumeDataFastPath(
size_t QuicPacketCreator::ConsumeCryptoData(EncryptionLevel level,
size_t write_length,
QuicStreamOffset offset) {
- QUIC_DVLOG(2) << "ConsumeCryptoData " << level << " write_length "
+ QUIC_DVLOG(2) << ENDPOINT << "ConsumeCryptoData " << level << " write_length "
<< write_length << " offset " << offset;
QUIC_BUG_IF(quic_bug_10752_25, !flusher_attached_)
+ << ENDPOINT
<< "Packet flusher is not attached when "
"generator tries to write crypto data.";
MaybeBundleAckOpportunistically();
@@ -1381,7 +1453,7 @@ size_t QuicPacketCreator::ConsumeCryptoData(EncryptionLevel level,
// assuming here that they won't occupy so much of the packet that a
// CRYPTO frame won't fit.
QUIC_BUG(quic_bug_10752_26)
- << "Failed to ConsumeCryptoData at level " << level;
+ << ENDPOINT << "Failed to ConsumeCryptoData at level " << level;
return 0;
}
total_bytes_consumed += frame.crypto_frame->data_length;
@@ -1398,6 +1470,7 @@ void QuicPacketCreator::GenerateMtuDiscoveryPacket(QuicByteCount target_mtu) {
// MTU discovery frames must be sent by themselves.
if (!CanSetMaxPacketLength()) {
QUIC_BUG(quic_bug_10752_27)
+ << ENDPOINT
<< "MTU discovery packets should only be sent when no other "
<< "frames needs to be sent.";
return;
@@ -1416,7 +1489,7 @@ void QuicPacketCreator::GenerateMtuDiscoveryPacket(QuicByteCount target_mtu) {
// The only reason AddFrame can fail is that the packet is too full to fit in
// a ping. This is not possible for any sane MTU.
QUIC_BUG_IF(quic_bug_10752_28, !success)
- << "Failed to send path MTU target_mtu:" << target_mtu
+ << ENDPOINT << "Failed to send path MTU target_mtu:" << target_mtu
<< " transmission_type:" << next_transmission_type_;
// Reset the packet length back.
@@ -1435,12 +1508,13 @@ void QuicPacketCreator::MaybeBundleAckOpportunistically() {
const bool flushed =
FlushAckFrame(delegate_->MaybeBundleAckOpportunistically());
QUIC_BUG_IF(quic_bug_10752_29, !flushed)
- << "Failed to flush ACK frame. encryption_level:"
+ << ENDPOINT << "Failed to flush ACK frame. encryption_level:"
<< packet_.encryption_level;
}
bool QuicPacketCreator::FlushAckFrame(const QuicFrames& frames) {
QUIC_BUG_IF(quic_bug_10752_30, !flusher_attached_)
+ << ENDPOINT
<< "Packet flusher is not attached when "
"generator tries to send ACK frame.";
// MaybeBundleAckOpportunistically could be called nestedly when sending a
@@ -1448,16 +1522,18 @@ bool QuicPacketCreator::FlushAckFrame(const QuicFrames& frames) {
QUIC_BUG_IF(quic_bug_12398_18,
GetQuicReloadableFlag(quic_single_ack_in_packet2) &&
!frames.empty() && has_ack())
- << "Trying to flush " << frames << " when there is ACK queued";
+ << ENDPOINT << "Trying to flush " << frames
+ << " when there is ACK queued";
for (const auto& frame : frames) {
- QUICHE_DCHECK(frame.type == ACK_FRAME || frame.type == STOP_WAITING_FRAME);
+ QUICHE_DCHECK(frame.type == ACK_FRAME || frame.type == STOP_WAITING_FRAME)
+ << ENDPOINT;
if (HasPendingFrames()) {
if (AddFrame(frame, next_transmission_type_)) {
// There is pending frames and current frame fits.
continue;
}
}
- QUICHE_DCHECK(!HasPendingFrames());
+ QUICHE_DCHECK(!HasPendingFrames()) << ENDPOINT;
// There is no pending frames, consult the delegate whether a packet can be
// generated.
if (!delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
@@ -1465,7 +1541,8 @@ bool QuicPacketCreator::FlushAckFrame(const QuicFrames& frames) {
return false;
}
const bool success = AddFrame(frame, next_transmission_type_);
- QUIC_BUG_IF(quic_bug_10752_31, !success) << "Failed to flush " << frame;
+ QUIC_BUG_IF(quic_bug_10752_31, !success)
+ << ENDPOINT << "Failed to flush " << frame;
}
return true;
}
@@ -1488,7 +1565,7 @@ void QuicPacketCreator::Flush() {
if (GetQuicFlag(FLAGS_quic_export_write_path_stats_at_server)) {
if (!write_start_packet_number_.IsInitialized()) {
QUIC_BUG(quic_bug_10752_32)
- << "write_start_packet_number is not initialized";
+ << ENDPOINT << "write_start_packet_number is not initialized";
return;
}
QUIC_SERVER_HISTOGRAM_COUNTS(
@@ -1522,6 +1599,7 @@ void QuicPacketCreator::SetTransmissionType(TransmissionType type) {
MessageStatus QuicPacketCreator::AddMessageFrame(QuicMessageId message_id,
QuicMemSliceSpan message) {
QUIC_BUG_IF(quic_bug_10752_33, !flusher_attached_)
+ << ENDPOINT
<< "Packet flusher is not attached when "
"generator tries to add message frame.";
MaybeBundleAckOpportunistically();
@@ -1535,7 +1613,8 @@ MessageStatus QuicPacketCreator::AddMessageFrame(QuicMessageId message_id,
QuicMessageFrame* frame = new QuicMessageFrame(message_id, message);
const bool success = AddFrame(QuicFrame(frame), next_transmission_type_);
if (!success) {
- QUIC_BUG(quic_bug_10752_34) << "Failed to send message " << message_id;
+ QUIC_BUG(quic_bug_10752_34)
+ << ENDPOINT << "Failed to send message " << message_id;
delete frame;
return MESSAGE_STATUS_INTERNAL_ERROR;
}
@@ -1564,7 +1643,8 @@ void QuicPacketCreator::FillPacketHeader(QuicPacketHeader* header) {
header->reset_flag = false;
header->version_flag = IncludeVersionInHeader();
if (IncludeNonceInPublicHeader()) {
- QUICHE_DCHECK_EQ(Perspective::IS_SERVER, framer_->perspective());
+ QUICHE_DCHECK_EQ(Perspective::IS_SERVER, framer_->perspective())
+ << ENDPOINT;
header->nonce = &diversification_nonce_;
} else {
header->nonce = nullptr;
@@ -1640,7 +1720,8 @@ bool QuicPacketCreator::AddFrame(const QuicFrame& frame,
frame.type != MESSAGE_FRAME && frame.type != NEW_TOKEN_FRAME &&
frame.type != RETIRE_CONNECTION_ID_FRAME &&
frame.type != ACK_FREQUENCY_FRAME))
- << frame.type << " not allowed at " << packet_.encryption_level;
+ << ENDPOINT << frame.type << " not allowed at "
+ << packet_.encryption_level;
if (frame.type == STREAM_FRAME) {
if (MaybeCoalesceStreamFrame(frame.stream_frame)) {
@@ -1656,7 +1737,7 @@ bool QuicPacketCreator::AddFrame(const QuicFrame& frame,
QUICHE_DCHECK(frame.type != ACK_FRAME || (!frame.ack_frame->packets.Empty() &&
frame.ack_frame->packets.Max() ==
frame.ack_frame->largest_acked))
- << "Invalid ACK frame: " << frame;
+ << ENDPOINT << "Invalid ACK frame: " << frame;
size_t frame_len = GetSerializedFrameLength(frame);
if (frame_len == 0 && RemoveSoftMaxPacketLength()) {
@@ -1664,7 +1745,8 @@ bool QuicPacketCreator::AddFrame(const QuicFrame& frame,
frame_len = GetSerializedFrameLength(frame);
}
if (frame_len == 0) {
- QUIC_DVLOG(1) << "Flushing because current open packet is full when adding "
+ QUIC_DVLOG(1) << ENDPOINT
+ << "Flushing because current open packet is full when adding "
<< frame;
FlushCurrentPacket();
return false;
@@ -1672,7 +1754,7 @@ bool QuicPacketCreator::AddFrame(const QuicFrame& frame,
if (queued_frames_.empty()) {
packet_size_ = PacketHeaderSize();
}
- QUICHE_DCHECK_LT(0u, packet_size_);
+ QUICHE_DCHECK_LT(0u, packet_size_) << ENDPOINT;
packet_size_ += ExpansionOnNewFrame() + frame_len;
@@ -1749,12 +1831,14 @@ bool QuicPacketCreator::MaybeCoalesceStreamFrame(const QuicStreamFrame& frame) {
// The back of retransmittable frames must be the same as the original
// queued frames' back.
- QUICHE_DCHECK_EQ(packet_.retransmittable_frames.back().type, STREAM_FRAME);
+ QUICHE_DCHECK_EQ(packet_.retransmittable_frames.back().type, STREAM_FRAME)
+ << ENDPOINT;
QuicStreamFrame* retransmittable =
&packet_.retransmittable_frames.back().stream_frame;
- QUICHE_DCHECK_EQ(retransmittable->stream_id, frame.stream_id);
+ QUICHE_DCHECK_EQ(retransmittable->stream_id, frame.stream_id) << ENDPOINT;
QUICHE_DCHECK_EQ(retransmittable->offset + retransmittable->data_length,
- frame.offset);
+ frame.offset)
+ << ENDPOINT;
retransmittable->data_length = candidate->data_length;
retransmittable->fin = candidate->fin;
packet_size_ += frame.data_length;
@@ -1771,7 +1855,7 @@ bool QuicPacketCreator::RemoveSoftMaxPacketLength() {
if (!CanSetMaxPacketLength()) {
return false;
}
- QUIC_DVLOG(1) << "Restoring max packet length to: "
+ QUIC_DVLOG(1) << ENDPOINT << "Restoring max packet length to: "
<< latched_hard_max_packet_length_;
SetMaxPacketLength(latched_hard_max_packet_length_);
// Reset latched_max_packet_length_.
@@ -1814,7 +1898,7 @@ void QuicPacketCreator::MaybeAddPadding() {
bool success = AddFrame(QuicFrame(QuicPaddingFrame(padding_bytes)),
packet_.transmission_type);
QUIC_BUG_IF(quic_bug_10752_36, !success)
- << "Failed to add padding_bytes: " << padding_bytes
+ << ENDPOINT << "Failed to add padding_bytes: " << padding_bytes
<< " transmission_type: " << packet_.transmission_type;
}
@@ -1848,9 +1932,11 @@ bool QuicPacketCreator::StreamFrameIsClientHello(
void QuicPacketCreator::SetServerConnectionIdIncluded(
QuicConnectionIdIncluded server_connection_id_included) {
QUICHE_DCHECK(server_connection_id_included == CONNECTION_ID_PRESENT ||
- server_connection_id_included == CONNECTION_ID_ABSENT);
+ server_connection_id_included == CONNECTION_ID_ABSENT)
+ << ENDPOINT;
QUICHE_DCHECK(framer_->perspective() == Perspective::IS_SERVER ||
- server_connection_id_included != CONNECTION_ID_ABSENT);
+ server_connection_id_included != CONNECTION_ID_ABSENT)
+ << ENDPOINT;
server_connection_id_included_ = server_connection_id_included;
}
@@ -1862,7 +1948,8 @@ void QuicPacketCreator::SetServerConnectionId(
void QuicPacketCreator::SetClientConnectionId(
QuicConnectionId client_connection_id) {
QUICHE_DCHECK(client_connection_id.IsEmpty() ||
- framer_->version().SupportsClientConnectionIds());
+ framer_->version().SupportsClientConnectionIds())
+ << ENDPOINT;
client_connection_id_ = client_connection_id;
}
@@ -1928,7 +2015,8 @@ QuicPacketLength QuicPacketCreator::GetGuaranteedLargestMessagePayload() const {
const QuicPacketLength largest_payload =
largest_frame - std::min(largest_frame, kQuicFrameTypeSize);
// This must always be less than or equal to GetCurrentLargestMessagePayload.
- QUICHE_DCHECK_LE(largest_payload, GetCurrentLargestMessagePayload());
+ QUICHE_DCHECK_LE(largest_payload, GetCurrentLargestMessagePayload())
+ << ENDPOINT;
return largest_payload;
}
@@ -1940,7 +2028,7 @@ bool QuicPacketCreator::AttemptingToSendUnencryptedStreamData() {
const std::string error_details =
absl::StrCat("Cannot send stream data with level: ",
EncryptionLevelToString(packet_.encryption_level));
- QUIC_BUG(quic_bug_10752_37) << error_details;
+ QUIC_BUG(quic_bug_10752_37) << ENDPOINT << error_details;
delegate_->OnUnrecoverableError(QUIC_ATTEMPT_TO_SEND_UNENCRYPTED_STREAM_DATA,
error_details);
return true;
@@ -2005,19 +2093,56 @@ void QuicPacketCreator::SetDefaultPeerAddress(QuicSocketAddress address) {
}
}
+#define ENDPOINT2 \
+ (creator_->framer_->perspective() == Perspective::IS_SERVER ? "Server: " \
+ : "Client: ")
+
+QuicPacketCreator::ScopedPeerAddressContext::ScopedPeerAddressContext(
+ QuicPacketCreator* creator,
+ QuicSocketAddress address,
+ bool update_connection_id)
+ : ScopedPeerAddressContext(creator,
+ address,
+ EmptyQuicConnectionId(),
+ EmptyQuicConnectionId(),
+ update_connection_id) {}
+
QuicPacketCreator::ScopedPeerAddressContext::ScopedPeerAddressContext(
QuicPacketCreator* creator,
- QuicSocketAddress address)
- : creator_(creator), old_peer_address_(creator_->packet_.peer_address) {
- QUIC_BUG_IF(quic_bug_12398_19,
- !creator_->packet_.peer_address.IsInitialized())
- << "Context is used before seralized packet's peer address is "
+ QuicSocketAddress address,
+ const QuicConnectionId& client_connection_id,
+ const QuicConnectionId& server_connection_id,
+ bool update_connection_id)
+ : creator_(creator),
+ old_peer_address_(creator_->packet_.peer_address),
+ old_client_connection_id_(creator_->GetClientConnectionId()),
+ old_server_connection_id_(creator_->GetServerConnectionId()),
+ update_connection_id_(update_connection_id) {
+ QUIC_BUG_IF(quic_bug_12398_19, !old_peer_address_.IsInitialized())
+ << ENDPOINT2
+ << "Context is used before serialized packet's peer address is "
"initialized.";
creator_->SetDefaultPeerAddress(address);
+ if (update_connection_id_) {
+ // Flush current packet if connection ID length changes.
+ if (address == old_peer_address_ &&
+ ((client_connection_id.length() !=
+ old_client_connection_id_.length()) ||
+ (server_connection_id.length() !=
+ old_server_connection_id_.length()))) {
+ creator_->FlushCurrentPacket();
+ }
+ creator_->SetClientConnectionId(client_connection_id);
+ creator_->SetServerConnectionId(server_connection_id);
+ }
}
QuicPacketCreator::ScopedPeerAddressContext::~ScopedPeerAddressContext() {
creator_->SetDefaultPeerAddress(old_peer_address_);
+ if (update_connection_id_) {
+ creator_->SetClientConnectionId(old_client_connection_id_);
+ creator_->SetServerConnectionId(old_server_connection_id_);
+ }
}
QuicPacketCreator::ScopedSerializationFailureHandler::
@@ -2034,16 +2159,19 @@ QuicPacketCreator::ScopedSerializationFailureHandler::
if (creator_->packet_.encrypted_buffer == nullptr) {
const std::string error_details = "Failed to SerializePacket.";
- QUIC_BUG(quic_bug_10752_38) << error_details;
+ QUIC_BUG(quic_bug_10752_38) << ENDPOINT2 << error_details;
creator_->delegate_->OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET,
error_details);
}
}
+#undef ENDPOINT2
+
void QuicPacketCreator::set_encryption_level(EncryptionLevel level) {
QUICHE_DCHECK(level == packet_.encryption_level || !HasPendingFrames())
- << "Cannot update encryption level from " << packet_.encryption_level
- << " to " << level << " when we already have pending frames: "
+ << ENDPOINT << "Cannot update encryption level from "
+ << packet_.encryption_level << " to " << level
+ << " when we already have pending frames: "
<< QuicFramesToString(queued_frames_);
packet_.encryption_level = level;
}
@@ -2054,6 +2182,7 @@ void QuicPacketCreator::AddPathChallengeFrame(
// AddFrame(). Sort out test helper functions and peer class that don't
// enforce this check.
QUIC_BUG_IF(quic_bug_10752_39, !flusher_attached_)
+ << ENDPOINT
<< "Packet flusher is not attached when "
"generator tries to write stream data.";
// Write a PATH_CHALLENGE frame, which has a random 8-byte payload.
@@ -2094,13 +2223,13 @@ bool QuicPacketCreator::AddPaddedFrameWithRetry(const QuicFrame& frame) {
}
}
// Frame was not queued but queued frames were flushed.
- QUICHE_DCHECK(!HasPendingFrames());
+ QUICHE_DCHECK(!HasPendingFrames()) << ENDPOINT;
if (!delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
NOT_HANDSHAKE)) {
return false;
}
bool success = AddPaddedSavedFrame(frame, NOT_RETRANSMISSION);
- QUIC_BUG_IF(quic_bug_12398_20, !success);
+ QUIC_BUG_IF(quic_bug_12398_20, !success) << ENDPOINT;
return true;
}
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 5e0c65e35fc..d4a58055282 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
@@ -22,13 +22,15 @@
#include "absl/base/attributes.h"
#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
#include "quic/core/frames/quic_stream_frame.h"
-#include "quic/core/quic_circular_deque.h"
#include "quic/core/quic_coalesced_packet.h"
+#include "quic/core/quic_connection_id.h"
#include "quic/core/quic_framer.h"
#include "quic/core/quic_packets.h"
#include "quic/core/quic_types.h"
#include "quic/platform/api/quic_export.h"
+#include "common/quiche_circular_deque.h"
namespace quic {
namespace test {
@@ -83,18 +85,28 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
virtual void OnStreamFrameCoalesced(const QuicStreamFrame& /*frame*/) {}
};
- // Set the peer address which the serialized packet will be sent to during the
- // scope of this object. Upon exiting the scope, the original peer address is
- // restored.
+ // Set the peer address and connection IDs with which the serialized packet
+ // will be sent to during the scope of this object. Upon exiting the scope,
+ // the original peer address and connection IDs are restored.
class QUIC_EXPORT_PRIVATE ScopedPeerAddressContext {
public:
ScopedPeerAddressContext(QuicPacketCreator* creator,
- QuicSocketAddress address);
+ QuicSocketAddress address,
+ bool update_connection_id);
+
+ ScopedPeerAddressContext(QuicPacketCreator* creator,
+ QuicSocketAddress address,
+ const QuicConnectionId& client_connection_id,
+ const QuicConnectionId& server_connection_id,
+ bool update_connection_id);
~ScopedPeerAddressContext();
private:
QuicPacketCreator* creator_;
QuicSocketAddress old_peer_address_;
+ QuicConnectionId old_client_connection_id_;
+ QuicConnectionId old_server_connection_id_;
+ bool update_connection_id_;
};
QuicPacketCreator(QuicConnectionId server_connection_id,
@@ -247,7 +259,7 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// |payloads| is cleared.
std::unique_ptr<SerializedPacket>
SerializePathResponseConnectivityProbingPacket(
- const QuicCircularDeque<QuicPathFrameBuffer>& payloads,
+ const quiche::QuicheCircularDeque<QuicPathFrameBuffer>& payloads,
const bool is_padded);
// Add PATH_RESPONSE to current packet, flush before or afterwards if needed.
@@ -261,6 +273,16 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// Returns a dummy packet that is valid but contains no useful information.
static SerializedPacket NoPacket();
+ // Returns the server connection ID to send over the wire.
+ const QuicConnectionId& GetServerConnectionId() const {
+ return server_connection_id_;
+ }
+
+ // Returns the client connection ID to send over the wire.
+ const QuicConnectionId& GetClientConnectionId() const {
+ return client_connection_id_;
+ }
+
// Returns the destination connection ID to send over the wire.
QuicConnectionId GetDestinationConnectionId() const;
@@ -287,6 +309,11 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
void set_encryption_level(EncryptionLevel level);
EncryptionLevel encryption_level() { return packet_.encryption_level; }
+ // Sets whether initial packets are protected with chaos.
+ void set_chaos_protection_enabled(bool chaos_protection_enabled) {
+ chaos_protection_enabled_ = chaos_protection_enabled;
+ }
+
// packet number of the last created packet, or 0 if no packets have been
// created.
QuicPacketNumber packet_number() const { return packet_.packet_number; }
@@ -444,7 +471,7 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
const QuicPacketHeader& header,
char* buffer,
size_t packet_length,
- const QuicCircularDeque<QuicPathFrameBuffer>& payloads,
+ const quiche::QuicheCircularDeque<QuicPathFrameBuffer>& payloads,
const bool is_padded,
EncryptionLevel level);
@@ -487,6 +514,13 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
QuicPacketCreator* creator_; // Unowned.
};
+ // Attempts to build a data packet with chaos protection. If this packet isn't
+ // supposed to be protected or if serialization fails then absl::nullopt is
+ // returned. Otherwise returns the serialized length.
+ absl::optional<size_t> MaybeBuildDataPacketWithChaosProtection(
+ const QuicPacketHeader& header,
+ char* buffer);
+
// Creates a stream frame which fits into the current open packet. If
// |data_size| is 0 and fin is true, the expected behavior is to consume
// the fin.
@@ -671,6 +705,9 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// accept. There is no limit for QUIC_CRYPTO connections, but QUIC+TLS
// negotiates this during the handshake.
QuicByteCount max_datagram_frame_size_;
+
+ // Whether to attempt protecting initial packets with chaos.
+ bool chaos_protection_enabled_;
};
} // namespace quic
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 5986bd2890f..57d1018d94c 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
@@ -19,6 +19,7 @@
#include "quic/core/crypto/quic_decrypter.h"
#include "quic/core/crypto/quic_encrypter.h"
#include "quic/core/frames/quic_stream_frame.h"
+#include "quic/core/quic_connection_id.h"
#include "quic/core/quic_data_writer.h"
#include "quic/core/quic_simple_buffer_allocator.h"
#include "quic/core/quic_types.h"
@@ -34,13 +35,14 @@
#include "quic/test_tools/simple_quic_framer.h"
#include "common/test_tools/quiche_test_utils.h"
-using testing::_;
-using testing::DoAll;
-using testing::InSequence;
-using testing::Invoke;
-using testing::Return;
-using testing::SaveArg;
-using testing::StrictMock;
+using ::testing::_;
+using ::testing::AtLeast;
+using ::testing::DoAll;
+using ::testing::InSequence;
+using ::testing::Invoke;
+using ::testing::Return;
+using ::testing::SaveArg;
+using ::testing::StrictMock;
namespace quic {
namespace test {
@@ -269,6 +271,8 @@ class QuicPacketCreatorTest : public QuicTestWithParam<TestParams> {
n * 2;
}
+ void TestChaosProtection(bool enabled);
+
static constexpr QuicStreamOffset kOffset = 0u;
char buffer_[kMaxOutgoingPacketSize];
@@ -751,7 +755,7 @@ TEST_P(QuicPacketCreatorTest, BuildPathResponsePacket1ResponseUnpadded) {
};
// clang-format on
std::unique_ptr<char[]> buffer(new char[kMaxOutgoingPacketSize]);
- QuicCircularDeque<QuicPathFrameBuffer> payloads;
+ quiche::QuicheCircularDeque<QuicPathFrameBuffer> payloads;
payloads.push_back(payload0);
size_t length = creator_.BuildPathResponsePacket(
header, buffer.get(), ABSL_ARRAYSIZE(packet), payloads,
@@ -798,7 +802,7 @@ TEST_P(QuicPacketCreatorTest, BuildPathResponsePacket1ResponsePadded) {
};
// clang-format on
std::unique_ptr<char[]> buffer(new char[kMaxOutgoingPacketSize]);
- QuicCircularDeque<QuicPathFrameBuffer> payloads;
+ quiche::QuicheCircularDeque<QuicPathFrameBuffer> payloads;
payloads.push_back(payload0);
size_t length = creator_.BuildPathResponsePacket(
header, buffer.get(), ABSL_ARRAYSIZE(packet), payloads,
@@ -848,7 +852,7 @@ TEST_P(QuicPacketCreatorTest, BuildPathResponsePacket3ResponsesUnpadded) {
// clang-format on
std::unique_ptr<char[]> buffer(new char[kMaxOutgoingPacketSize]);
- QuicCircularDeque<QuicPathFrameBuffer> payloads;
+ quiche::QuicheCircularDeque<QuicPathFrameBuffer> payloads;
payloads.push_back(payload0);
payloads.push_back(payload1);
payloads.push_back(payload2);
@@ -902,7 +906,7 @@ TEST_P(QuicPacketCreatorTest, BuildPathResponsePacket3ResponsesPadded) {
// clang-format on
std::unique_ptr<char[]> buffer(new char[kMaxOutgoingPacketSize]);
- QuicCircularDeque<QuicPathFrameBuffer> payloads;
+ quiche::QuicheCircularDeque<QuicPathFrameBuffer> payloads;
payloads.push_back(payload0);
payloads.push_back(payload1);
payloads.push_back(payload2);
@@ -987,7 +991,7 @@ TEST_P(QuicPacketCreatorTest, SerializePathResponseProbePacket1PayloadPadded) {
creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
- QuicCircularDeque<QuicPathFrameBuffer> payloads;
+ quiche::QuicheCircularDeque<QuicPathFrameBuffer> payloads;
payloads.push_back(payload0);
std::unique_ptr<SerializedPacket> encrypted(
@@ -1017,7 +1021,7 @@ TEST_P(QuicPacketCreatorTest,
creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
- QuicCircularDeque<QuicPathFrameBuffer> payloads;
+ quiche::QuicheCircularDeque<QuicPathFrameBuffer> payloads;
payloads.push_back(payload0);
std::unique_ptr<SerializedPacket> encrypted(
@@ -1047,7 +1051,7 @@ TEST_P(QuicPacketCreatorTest, SerializePathResponseProbePacket2PayloadsPadded) {
creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
- QuicCircularDeque<QuicPathFrameBuffer> payloads;
+ quiche::QuicheCircularDeque<QuicPathFrameBuffer> payloads;
payloads.push_back(payload0);
payloads.push_back(payload1);
@@ -1080,7 +1084,7 @@ TEST_P(QuicPacketCreatorTest,
creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
- QuicCircularDeque<QuicPathFrameBuffer> payloads;
+ quiche::QuicheCircularDeque<QuicPathFrameBuffer> payloads;
payloads.push_back(payload0);
payloads.push_back(payload1);
@@ -1113,7 +1117,7 @@ TEST_P(QuicPacketCreatorTest, SerializePathResponseProbePacket3PayloadsPadded) {
creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
- QuicCircularDeque<QuicPathFrameBuffer> payloads;
+ quiche::QuicheCircularDeque<QuicPathFrameBuffer> payloads;
payloads.push_back(payload0);
payloads.push_back(payload1);
payloads.push_back(payload2);
@@ -1149,7 +1153,7 @@ TEST_P(QuicPacketCreatorTest,
creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
- QuicCircularDeque<QuicPathFrameBuffer> payloads;
+ quiche::QuicheCircularDeque<QuicPathFrameBuffer> payloads;
payloads.push_back(payload0);
payloads.push_back(payload1);
payloads.push_back(payload2);
@@ -1311,7 +1315,7 @@ TEST_P(QuicPacketCreatorTest, SerializeFrameShortData) {
if (!GetParam().version_serialization) {
creator_.StopSendingVersion();
}
- std::string data("a");
+ std::string data("Hello World!");
if (!QuicVersionUsesCryptoFrames(client_framer_.transport_version())) {
QuicStreamFrame stream_frame(
QuicUtils::GetCryptoStreamId(client_framer_.transport_version()),
@@ -1338,15 +1342,51 @@ TEST_P(QuicPacketCreatorTest, SerializeFrameShortData) {
} else {
EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
}
- if (client_framer_.version().HasHeaderProtection()) {
- EXPECT_CALL(framer_visitor_, OnPaddingFrame(_));
- }
EXPECT_CALL(framer_visitor_, OnPacketComplete());
}
ProcessPacket(serialized);
EXPECT_EQ(GetParam().version_serialization, header.version_flag);
}
+void QuicPacketCreatorTest::TestChaosProtection(bool enabled) {
+ if (!GetParam().version.UsesCryptoFrames()) {
+ return;
+ }
+ MockRandom mock_random(2);
+ QuicPacketCreatorPeer::SetRandom(&creator_, &mock_random);
+ creator_.set_chaos_protection_enabled(enabled);
+ std::string data("ChAoS_ThEoRy!");
+ producer_.SaveCryptoData(ENCRYPTION_INITIAL, 0, data);
+ frames_.push_back(
+ QuicFrame(new QuicCryptoFrame(ENCRYPTION_INITIAL, 0, data.length())));
+ frames_.push_back(QuicFrame(QuicPaddingFrame(33)));
+ SerializedPacket serialized = SerializeAllFrames(frames_);
+ EXPECT_CALL(framer_visitor_, OnPacket());
+ EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_));
+ EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
+ EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_, _));
+ EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
+ if (enabled) {
+ EXPECT_CALL(framer_visitor_, OnCryptoFrame(_)).Times(AtLeast(2));
+ EXPECT_CALL(framer_visitor_, OnPaddingFrame(_)).Times(AtLeast(2));
+ EXPECT_CALL(framer_visitor_, OnPingFrame(_)).Times(AtLeast(1));
+ } else {
+ EXPECT_CALL(framer_visitor_, OnCryptoFrame(_)).Times(1);
+ EXPECT_CALL(framer_visitor_, OnPaddingFrame(_)).Times(1);
+ EXPECT_CALL(framer_visitor_, OnPingFrame(_)).Times(0);
+ }
+ EXPECT_CALL(framer_visitor_, OnPacketComplete());
+ ProcessPacket(serialized);
+}
+
+TEST_P(QuicPacketCreatorTest, ChaosProtectionEnabled) {
+ TestChaosProtection(/*enabled=*/true);
+}
+
+TEST_P(QuicPacketCreatorTest, ChaosProtectionDisabled) {
+ TestChaosProtection(/*enabled=*/false);
+}
+
TEST_P(QuicPacketCreatorTest, ConsumeDataLargerThanOneStreamFrame) {
if (!GetParam().version_serialization) {
creator_.StopSendingVersion();
@@ -1954,17 +1994,7 @@ TEST_P(QuicPacketCreatorTest, RetryToken) {
creator_.SetRetryToken(
std::string(retry_token_bytes, sizeof(retry_token_bytes)));
- std::string data("a");
- if (!QuicVersionUsesCryptoFrames(client_framer_.transport_version())) {
- QuicStreamFrame stream_frame(
- QuicUtils::GetCryptoStreamId(client_framer_.transport_version()),
- /*fin=*/false, 0u, absl::string_view());
- frames_.push_back(QuicFrame(stream_frame));
- } else {
- producer_.SaveCryptoData(ENCRYPTION_INITIAL, 0, data);
- frames_.push_back(
- QuicFrame(new QuicCryptoFrame(ENCRYPTION_INITIAL, 0, data.length())));
- }
+ frames_.push_back(QuicFrame(QuicPingFrame()));
SerializedPacket serialized = SerializeAllFrames(frames_);
QuicPacketHeader header;
@@ -1976,11 +2006,7 @@ TEST_P(QuicPacketCreatorTest, RetryToken) {
EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_, _));
EXPECT_CALL(framer_visitor_, OnPacketHeader(_))
.WillOnce(DoAll(SaveArg<0>(&header), Return(true)));
- if (QuicVersionUsesCryptoFrames(client_framer_.transport_version())) {
- EXPECT_CALL(framer_visitor_, OnCryptoFrame(_));
- } else {
- EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
- }
+ EXPECT_CALL(framer_visitor_, OnPingFrame(_));
if (client_framer_.version().HasHeaderProtection()) {
EXPECT_CALL(framer_visitor_, OnPaddingFrame(_));
}
@@ -2261,6 +2287,32 @@ TEST_P(QuicPacketCreatorTest, SoftMaxPacketLength) {
EXPECT_TRUE(creator_.HasPendingFrames());
}
+TEST_P(QuicPacketCreatorTest,
+ ChangingEncryptionLevelRemovesSoftMaxPacketLength) {
+ if (!client_framer_.version().CanSendCoalescedPackets()) {
+ return;
+ }
+ // First set encryption level to forward secure which has the shortest header.
+ creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
+ const QuicByteCount previous_max_packet_length = creator_.max_packet_length();
+ const size_t min_acceptable_packet_size =
+ GetPacketHeaderOverhead(client_framer_.transport_version()) +
+ QuicPacketCreator::MinPlaintextPacketSize(client_framer_.version()) +
+ GetEncryptionOverhead();
+ // Then set the soft max packet length to the lowest allowed value.
+ creator_.SetSoftMaxPacketLength(min_acceptable_packet_size);
+ // Make sure that the low value was accepted.
+ EXPECT_EQ(creator_.max_packet_length(), min_acceptable_packet_size);
+ // Now set the encryption level to handshake which increases the header size.
+ creator_.set_encryption_level(ENCRYPTION_HANDSHAKE);
+ // Make sure that adding a frame removes the the soft max packet length.
+ QuicAckFrame ack_frame(InitAckFrame(1));
+ frames_.push_back(QuicFrame(&ack_frame));
+ SerializedPacket serialized = SerializeAllFrames(frames_);
+ EXPECT_EQ(serialized.encryption_level, ENCRYPTION_HANDSHAKE);
+ EXPECT_EQ(creator_.max_packet_length(), previous_max_packet_length);
+}
+
class MockDelegate : public QuicPacketCreator::DelegateInterface {
public:
MockDelegate() {}
@@ -3811,8 +3863,12 @@ TEST_F(QuicPacketCreatorMultiplePacketsTest, ExtraPaddingNeeded) {
TEST_F(QuicPacketCreatorMultiplePacketsTest,
PeerAddressContextWithSameAddress) {
+ QuicConnectionId client_connection_id = TestConnectionId(1);
+ QuicConnectionId server_connection_id = TestConnectionId(2);
QuicSocketAddress peer_addr(QuicIpAddress::Any4(), 12345);
creator_.SetDefaultPeerAddress(peer_addr);
+ creator_.SetClientConnectionId(client_connection_id);
+ creator_.SetServerConnectionId(server_connection_id);
// Send some stream data.
MakeIOVector("foo", &iov_);
EXPECT_CALL(delegate_, ShouldGeneratePacket(_, _))
@@ -3824,8 +3880,12 @@ TEST_F(QuicPacketCreatorMultiplePacketsTest,
EXPECT_EQ(3u, consumed.bytes_consumed);
EXPECT_TRUE(creator_.HasPendingFrames());
{
- // Set a different address via context which should trigger flush.
- QuicPacketCreator::ScopedPeerAddressContext context(&creator_, peer_addr);
+ // Set the same address via context which should not trigger flush.
+ QuicPacketCreator::ScopedPeerAddressContext context(
+ &creator_, peer_addr, client_connection_id, server_connection_id,
+ /*update_connection_id=*/true);
+ ASSERT_EQ(client_connection_id, creator_.GetClientConnectionId());
+ ASSERT_EQ(server_connection_id, creator_.GetServerConnectionId());
EXPECT_TRUE(creator_.HasPendingFrames());
// Queue another STREAM_FRAME.
QuicConsumedData consumed = creator_.ConsumeData(
@@ -3874,8 +3934,14 @@ TEST_F(QuicPacketCreatorMultiplePacketsTest,
}));
EXPECT_TRUE(creator_.HasPendingFrames());
{
+ QuicConnectionId client_connection_id = TestConnectionId(1);
+ QuicConnectionId server_connection_id = TestConnectionId(2);
// Set a different address via context which should trigger flush.
- QuicPacketCreator::ScopedPeerAddressContext context(&creator_, peer_addr1);
+ QuicPacketCreator::ScopedPeerAddressContext context(
+ &creator_, peer_addr1, client_connection_id, server_connection_id,
+ /*update_connection_id=*/true);
+ ASSERT_EQ(client_connection_id, creator_.GetClientConnectionId());
+ ASSERT_EQ(server_connection_id, creator_.GetServerConnectionId());
EXPECT_FALSE(creator_.HasPendingFrames());
// Queue another STREAM_FRAME.
QuicConsumedData consumed = creator_.ConsumeData(
@@ -3891,9 +3957,15 @@ TEST_F(QuicPacketCreatorMultiplePacketsTest,
TEST_F(QuicPacketCreatorMultiplePacketsTest,
NestedPeerAddressContextWithDifferentAddress) {
+ QuicConnectionId client_connection_id1 = creator_.GetClientConnectionId();
+ QuicConnectionId server_connection_id1 = creator_.GetServerConnectionId();
QuicSocketAddress peer_addr(QuicIpAddress::Any4(), 12345);
creator_.SetDefaultPeerAddress(peer_addr);
- QuicPacketCreator::ScopedPeerAddressContext context(&creator_, peer_addr);
+ QuicPacketCreator::ScopedPeerAddressContext context(
+ &creator_, peer_addr, client_connection_id1, server_connection_id1,
+ /*update_connection_id=*/true);
+ ASSERT_EQ(client_connection_id1, creator_.GetClientConnectionId());
+ ASSERT_EQ(server_connection_id1, creator_.GetServerConnectionId());
// Send some stream data.
MakeIOVector("foo", &iov_);
@@ -3913,9 +3985,14 @@ TEST_F(QuicPacketCreatorMultiplePacketsTest,
ASSERT_EQ(1u, packet.retransmittable_frames.size());
EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.front().type);
+ QuicConnectionId client_connection_id2 = TestConnectionId(3);
+ QuicConnectionId server_connection_id2 = TestConnectionId(4);
// Set up another context with a different address.
- QuicPacketCreator::ScopedPeerAddressContext context(&creator_,
- peer_addr1);
+ QuicPacketCreator::ScopedPeerAddressContext context(
+ &creator_, peer_addr1, client_connection_id2, server_connection_id2,
+ /*update_connection_id=*/true);
+ ASSERT_EQ(client_connection_id2, creator_.GetClientConnectionId());
+ ASSERT_EQ(server_connection_id2, creator_.GetServerConnectionId());
MakeIOVector("foo", &iov_);
EXPECT_CALL(delegate_, ShouldGeneratePacket(_, _))
.WillRepeatedly(Return(true));
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 5cc593f41bf..d625b5dcb6a 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
@@ -15,7 +15,6 @@
#include "quic/core/quic_versions.h"
#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"
-#include "common/platform/api/quiche_text_utils.h"
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_protocol_flags_list.h b/chromium/net/third_party/quiche/src/quic/core/quic_protocol_flags_list.h
index 5187c61def4..56f83594b8f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_protocol_flags_list.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_protocol_flags_list.h
@@ -249,4 +249,11 @@ QUIC_PROTOCOL_FLAG(
true,
"If true, QUIC QPACK decoder includes 32-bytes overheader per entry while "
"comparing request/response header size against its upper limit.")
+
+QUIC_PROTOCOL_FLAG(
+ bool,
+ quic_reject_retry_token_in_initial_packet,
+ false,
+ "If true, always reject retry_token received in INITIAL packets")
+
#endif
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 a1b78a4fb86..079778cd5d8 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
@@ -205,11 +205,7 @@ QuicTime::Delta QuicReceivedPacketManager::GetMaxAckDelay(
// 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);
- }
- return ack_delay;
+ return std::max(ack_delay, kAlarmGranularity);
}
void QuicReceivedPacketManager::MaybeUpdateAckFrequency(
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 3cfa0ce0a43..da586c67a3d 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
@@ -397,9 +397,6 @@ TEST_F(QuicReceivedPacketManagerTest, SendDelayedAckDecimation) {
}
TEST_F(QuicReceivedPacketManagerTest, SendDelayedAckDecimationMin1ms) {
- if (!GetQuicReloadableFlag(quic_ack_delay_alarm_granularity)) {
- return;
- }
EXPECT_FALSE(HasPendingAck());
// Seed the min_rtt with a kAlarmGranularity signal.
rtt_stats_.UpdateRtt(kAlarmGranularity, QuicTime::Delta::Zero(),
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 13e2396fd86..781f6f95b90 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
@@ -19,7 +19,6 @@
#include "quic/core/congestion_control/send_algorithm_interface.h"
#include "quic/core/congestion_control/uber_loss_algorithm.h"
#include "quic/core/proto/cached_network_parameters_proto.h"
-#include "quic/core/quic_circular_deque.h"
#include "quic/core/quic_packets.h"
#include "quic/core/quic_sustained_bandwidth_recorder.h"
#include "quic/core/quic_time.h"
@@ -28,6 +27,7 @@
#include "quic/core/quic_unacked_packet_map.h"
#include "quic/platform/api/quic_containers.h"
#include "quic/platform/api/quic_export.h"
+#include "common/quiche_circular_deque.h"
namespace quic {
@@ -673,7 +673,8 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
// The history of outstanding max_ack_delays sent to peer. Outstanding means
// a max_ack_delay is sent as part of the last acked AckFrequencyFrame or
// an unacked AckFrequencyFrame after that.
- QuicCircularDeque<std::pair<QuicTime::Delta, /*sequence_number=*/uint64_t>>
+ quiche::QuicheCircularDeque<
+ std::pair<QuicTime::Delta, /*sequence_number=*/uint64_t>>
in_use_sent_ack_delays_;
// Latest received ack frame.
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 7c7aa4d077f..1bcb9dcb7bd 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
@@ -25,7 +25,7 @@
#include "quic/platform/api/quic_map_util.h"
#include "quic/platform/api/quic_server_stats.h"
#include "quic/platform/api/quic_stack_trace.h"
-#include "common/platform/api/quiche_text_utils.h"
+#include "common/quiche_text_utils.h"
using spdy::SpdyPriority;
@@ -686,11 +686,8 @@ bool QuicSession::WillingAndAbleToWrite() const {
if (HasPendingHandshake()) {
return true;
}
- if (GetQuicReloadableFlag(quic_fix_willing_and_able_to_write2)) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_fix_willing_and_able_to_write2);
- if (!IsEncryptionEstablished()) {
- return false;
- }
+ if (!IsEncryptionEstablished()) {
+ return false;
}
}
if (control_frame_manager_.WillingToWrite() ||
@@ -773,10 +770,24 @@ QuicConsumedData QuicSession::WritevData(
perspective() == Perspective::IS_CLIENT);
QUIC_BUG_IF(quic_bug_12435_3, type == NOT_RETRANSMISSION)
<< ENDPOINT << "Try to send new data on stream " << id
- << "before 1-RTT keys are available while 0-RTT is rejected.";
+ << "before 1-RTT keys are available while 0-RTT is rejected. "
+ "Version: "
+ << ParsedQuicVersionToString(version());
+ } else if (version().UsesTls() || perspective() == Perspective::IS_SERVER) {
+ QUIC_BUG(quic_bug_10866_2)
+ << ENDPOINT << "Try to send data of stream " << id
+ << " before encryption is established. Version: "
+ << ParsedQuicVersionToString(version());
} else {
- QUIC_BUG(quic_bug_10866_2) << ENDPOINT << "Try to send data of stream "
- << id << " before encryption is established.";
+ // In QUIC crypto, this could happen when the client sends full CHLO and
+ // 0-RTT request, then receives an inchoate REJ and sends an inchoate
+ // CHLO. The client then gets the ACK of the inchoate CHLO or the client
+ // gets the full REJ and needs to verify the proof (before it sends the
+ // full CHLO), such that there is no outstanding crypto data.
+ // Retransmission alarm fires in TLP mode which tries to retransmit the
+ // 0-RTT request (without encryption).
+ QUIC_DLOG(INFO) << ENDPOINT << "Try to send data of stream " << id
+ << " before encryption is established.";
}
return QuicConsumedData(0, false);
}
@@ -920,15 +931,12 @@ void QuicSession::SendGoAway(QuicErrorCode error_code,
const std::string& reason) {
// GOAWAY frame is not supported in IETF QUIC.
QUICHE_DCHECK(!VersionHasIetfQuicFrames(transport_version()));
- if (GetQuicReloadableFlag(quic_encrypted_goaway)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_encrypted_goaway, 1, 2);
- if (!IsEncryptionEstablished()) {
- QUIC_CODE_COUNT(quic_goaway_before_encryption_established);
- connection_->CloseConnection(
- error_code, reason,
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- return;
- }
+ if (!IsEncryptionEstablished()) {
+ QUIC_CODE_COUNT(quic_goaway_before_encryption_established);
+ connection_->CloseConnection(
+ error_code, reason,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return;
}
if (transport_goaway_sent_) {
return;
@@ -1666,10 +1674,7 @@ void QuicSession::OnTlsHandshakeComplete() {
// Server sends HANDSHAKE_DONE to signal confirmation of the handshake
// to the client.
control_frame_manager_.WriteOrBufferHandshakeDone();
- if (GetQuicReloadableFlag(quic_enable_token_based_address_validation) &&
- connection()->version().HasIetfQuicFrames()) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_token_based_address_validation,
- 1, 2);
+ if (connection()->version().HasIetfQuicFrames()) {
MaybeSendAddressToken();
}
}
@@ -1775,6 +1780,11 @@ void QuicSession::OnHandshakeCallbackDone() {
}
}
+bool QuicSession::PacketFlusherAttached() const {
+ QUICHE_DCHECK(connection_->connected());
+ return connection()->packet_creator().PacketFlusherAttached();
+}
+
void QuicSession::OnCryptoHandshakeMessageSent(
const CryptoHandshakeMessage& /*message*/) {}
@@ -2096,12 +2106,14 @@ void QuicSession::SendAckFrequency(const QuicAckFrequencyFrame& frame) {
}
void QuicSession::SendNewConnectionId(const QuicNewConnectionIdFrame& frame) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 1, 5);
control_frame_manager_.WriteOrBufferNewConnectionId(
frame.connection_id, frame.sequence_number, frame.retire_prior_to,
frame.stateless_reset_token);
}
void QuicSession::SendRetireConnectionId(uint64_t sequence_number) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 2, 5);
control_frame_manager_.WriteOrBufferRetireConnectionId(sequence_number);
}
@@ -2495,11 +2507,6 @@ QuicPacketLength QuicSession::GetGuaranteedLargestMessagePayload() const {
return connection_->GetGuaranteedLargestMessagePayload();
}
-void QuicSession::SendStopSending(QuicRstStreamErrorCode code,
- QuicStreamId stream_id) {
- control_frame_manager_.WriteOrBufferStopSending(code, stream_id);
-}
-
QuicStreamId QuicSession::next_outgoing_bidirectional_stream_id() const {
if (VersionHasIetfQuicFrames(transport_version())) {
return ietf_streamid_manager_.next_outgoing_bidirectional_stream_id();
@@ -2609,15 +2616,19 @@ bool QuicSession::HasPendingPathValidation() const {
return connection_->HasPendingPathValidation();
}
-void QuicSession::MigratePath(const QuicSocketAddress& self_address,
+bool QuicSession::MigratePath(const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
QuicPacketWriter* writer,
bool owns_writer) {
- connection_->MigratePath(self_address, peer_address, writer, owns_writer);
+ return connection_->MigratePath(self_address, peer_address, writer,
+ owns_writer);
}
bool QuicSession::ValidateToken(absl::string_view token) const {
QUICHE_DCHECK_EQ(perspective_, Perspective::IS_SERVER);
+ if (GetQuicFlag(FLAGS_quic_reject_retry_token_in_initial_packet)) {
+ return false;
+ }
if (token.empty() || token[0] != 0) {
// Validate the prefix for token received in NEW_TOKEN frame.
return false;
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 cf366cf5654..b6c1367019f 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
@@ -264,10 +264,6 @@ class QUIC_EXPORT_PRIVATE QuicSession
// Sends a WINDOW_UPDATE frame.
virtual void SendWindowUpdate(QuicStreamId id, QuicStreamOffset byte_offset);
- // Create and transmit a STOP_SENDING frame
- virtual void SendStopSending(QuicRstStreamErrorCode code,
- QuicStreamId stream_id);
-
// Called by stream |stream_id| when it gets closed.
virtual void OnStreamClosed(QuicStreamId stream_id);
@@ -306,6 +302,7 @@ class QUIC_EXPORT_PRIVATE QuicSession
bool is_resumption,
std::string* error_details) override;
void OnHandshakeCallbackDone() override;
+ bool PacketFlusherAttached() const override;
// Implement StreamDelegateInterface.
void OnStreamError(QuicErrorCode error_code,
@@ -458,7 +455,7 @@ class QUIC_EXPORT_PRIVATE QuicSession
bool HasPendingPathValidation() const;
// Switch to the path described in |context| without validating the path.
- void MigratePath(const QuicSocketAddress& self_address,
+ bool MigratePath(const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
QuicPacketWriter* writer,
bool owns_writer);
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 cb6e3aa943c..4b23d3d82cd 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,13 +6,13 @@
#define QUICHE_QUIC_CORE_QUIC_STREAM_SEND_BUFFER_H_
#include "quic/core/frames/quic_stream_frame.h"
-#include "quic/core/quic_circular_deque.h"
#include "quic/core/quic_interval_deque.h"
#include "quic/core/quic_interval_set.h"
#include "quic/core/quic_types.h"
#include "quic/platform/api/quic_iovec.h"
#include "quic/platform/api/quic_mem_slice.h"
#include "quic/platform/api/quic_mem_slice_span.h"
+#include "common/quiche_circular_deque.h"
namespace quic {
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 cf7340bdb65..88a51bd5e08 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
@@ -56,13 +56,10 @@ void QuicStreamSequencer::OnStreamFrame(const QuicStreamFrame& frame) {
(!CloseStreamAtOffset(frame.offset + data_len) || data_len == 0)) {
return;
}
- if (GetQuicReloadableFlag(quic_accept_empty_stream_frame_with_no_fin)) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_accept_empty_stream_frame_with_no_fin);
- if (stream_->version().HasIetfQuicFrames() && data_len == 0) {
- QUICHE_DCHECK(!frame.fin);
- // Ignore empty frame with no fin.
- return;
- }
+ if (stream_->version().HasIetfQuicFrames() && data_len == 0) {
+ QUICHE_DCHECK(!frame.fin);
+ // Ignore empty frame with no fin.
+ return;
}
OnFrameData(byte_offset, data_len, frame.data_buffer);
}
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 e8fe6f367e2..b097bc5bc93 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
@@ -252,8 +252,7 @@ TEST_F(QuicStreamSequencerTest, BlockedThenFullFrameAndFinConsumed) {
}
TEST_F(QuicStreamSequencerTest, EmptyFrame) {
- if (!GetQuicReloadableFlag(quic_accept_empty_stream_frame_with_no_fin) ||
- !stream_.version().HasIetfQuicFrames()) {
+ if (!stream_.version().HasIetfQuicFrames()) {
EXPECT_CALL(stream_,
OnUnrecoverableError(QUIC_EMPTY_STREAM_FRAME_NO_FIN, _));
}
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 739113a9147..2d3298b6fc9 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
@@ -1634,8 +1634,7 @@ TEST_P(QuicStreamTest, RstStreamFrameChangesCloseOffset) {
TEST_P(QuicStreamTest, EmptyStreamFrameWithNoFin) {
Initialize();
QuicStreamFrame empty_stream_frame(stream_->id(), false, 0, "");
- if (GetQuicReloadableFlag(quic_accept_empty_stream_frame_with_no_fin) &&
- stream_->version().HasIetfQuicFrames()) {
+ if (stream_->version().HasIetfQuicFrames()) {
EXPECT_CALL(*connection_,
CloseConnection(QUIC_EMPTY_STREAM_FRAME_NO_FIN, _, _))
.Times(0);
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 a6305b086f3..32b7bf9cd76 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
@@ -12,7 +12,7 @@
#include "absl/strings/str_split.h"
#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"
-#include "common/platform/api/quiche_text_utils.h"
+#include "common/quiche_text_utils.h"
namespace quic {
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 d6fa2da7a10..dbaa38bdefe 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
@@ -18,12 +18,13 @@
#include "quic/core/quic_framer.h"
#include "quic/core/quic_packets.h"
#include "quic/core/quic_utils.h"
+#include "quic/platform/api/quic_bug_tracker.h"
#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
#include "quic/platform/api/quic_map_util.h"
#include "quic/platform/api/quic_socket_address.h"
-#include "common/platform/api/quiche_text_utils.h"
+#include "common/quiche_text_utils.h"
namespace quic {
@@ -324,6 +325,13 @@ void QuicTimeWaitListManager::SendPublicReset(
if (ietf_quic) {
std::unique_ptr<QuicEncryptedPacket> ietf_reset_packet =
BuildIetfStatelessResetPacket(connection_id, received_packet_length);
+ if (GetQuicRestartFlag(quic_fix_stateless_reset2) &&
+ ietf_reset_packet == nullptr) {
+ // This could happen when trying to reject a short header packet of
+ // a connection which is in the time wait list (and with no termination
+ // packet).
+ return;
+ }
QUIC_DVLOG(2) << "Dispatcher sending IETF reset packet for "
<< connection_id << std::endl
<< quiche::QuicheTextUtils::HexDump(
@@ -381,6 +389,10 @@ QuicTimeWaitListManager::BuildIetfStatelessResetPacket(
bool QuicTimeWaitListManager::SendOrQueuePacket(
std::unique_ptr<QueuedPacket> packet,
const QuicPerPacketContext* /*packet_context*/) {
+ if (packet == nullptr) {
+ QUIC_LOG(ERROR) << "Tried to send or queue a null packet";
+ return true;
+ }
if (WriteToWire(packet.get())) {
// Allow the packet to be deleted upon leaving this function.
return true;
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 2018f723306..ac371f2c180 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
@@ -224,7 +224,7 @@ class QUIC_NO_EXPORT QuicTimeWaitListManager
virtual bool SendOrQueuePacket(std::unique_ptr<QueuedPacket> packet,
const QuicPerPacketContext* packet_context);
- const QuicCircularDeque<std::unique_ptr<QueuedPacket>>&
+ const quiche::QuicheCircularDeque<std::unique_ptr<QueuedPacket>>&
pending_packets_queue() const {
return pending_packets_queue_;
}
@@ -318,7 +318,8 @@ 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.
- QuicCircularDeque<std::unique_ptr<QueuedPacket>> pending_packets_queue_;
+ quiche::QuicheCircularDeque<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_time_wait_list_manager_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager_test.cc
index d33e992e372..4e9f957182b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager_test.cc
@@ -19,6 +19,7 @@
#include "quic/core/quic_packet_writer.h"
#include "quic/core/quic_packets.h"
#include "quic/core/quic_utils.h"
+#include "quic/platform/api/quic_expect_bug.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/mock_quic_session_visitor.h"
@@ -749,6 +750,24 @@ TEST_F(QuicTimeWaitListManagerTest,
}
}
+// Regression test for b/184053898.
+TEST_F(QuicTimeWaitListManagerTest, DonotCrashOnNullStatelessReset) {
+ // Received a packet with length <
+ // QuicFramer::GetMinStatelessResetPacketLength(), and this will result in a
+ // null stateless reset.
+ time_wait_list_manager_.SendPublicReset(
+ self_address_, peer_address_, TestConnectionId(1),
+ /*ietf_quic=*/true,
+ /*received_packet_length=*/
+ QuicFramer::GetMinStatelessResetPacketLength() - 1,
+ /*packet_context=*/nullptr);
+}
+
+TEST_F(QuicTimeWaitListManagerTest, SendOrQueueNullPacket) {
+ QuicTimeWaitListManagerPeer::SendOrQueuePacket(&time_wait_list_manager_,
+ nullptr, nullptr);
+}
+
} // namespace
} // namespace test
} // 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 75c835d6c49..676f054b1fb 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
@@ -7,15 +7,14 @@
#include <cstddef>
#include <cstdint>
-#include <deque>
#include "absl/strings/str_cat.h"
-#include "quic/core/quic_circular_deque.h"
#include "quic/core/quic_packets.h"
#include "quic/core/quic_transmission_info.h"
#include "quic/core/session_notifier_interface.h"
#include "quic/platform/api/quic_export.h"
#include "quic/platform/api/quic_flags.h"
+#include "common/quiche_circular_deque.h"
namespace quic {
@@ -113,10 +112,10 @@ class QUIC_EXPORT_PRIVATE QuicUnackedPacketMap {
QuicPacketNumber GetLeastUnacked() const;
using const_iterator =
- QuicCircularDeque<QuicTransmissionInfo>::const_iterator;
+ quiche::QuicheCircularDeque<QuicTransmissionInfo>::const_iterator;
using const_reverse_iterator =
- QuicCircularDeque<QuicTransmissionInfo>::const_reverse_iterator;
- using iterator = QuicCircularDeque<QuicTransmissionInfo>::iterator;
+ quiche::QuicheCircularDeque<QuicTransmissionInfo>::const_reverse_iterator;
+ using iterator = quiche::QuicheCircularDeque<QuicTransmissionInfo>::iterator;
const_iterator begin() const { return unacked_packets_.begin(); }
const_iterator end() const { return unacked_packets_.end(); }
@@ -300,7 +299,7 @@ class QUIC_EXPORT_PRIVATE QuicUnackedPacketMap {
// If the old packet is acked before the new packet, then the old entry will
// be removed from the map and the new entry's retransmittable frames will be
// set to nullptr.
- QuicCircularDeque<QuicTransmissionInfo> unacked_packets_;
+ quiche::QuicheCircularDeque<QuicTransmissionInfo> unacked_packets_;
// The packet at the 0th index of unacked_packets_.
QuicPacketNumber least_unacked_;
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 27b74bb9430..1f0137a91bc 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
@@ -21,8 +21,8 @@
#include "quic/platform/api/quic_bug_tracker.h"
#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"
-#include "quic/platform/api/quic_prefetch.h"
#include "common/platform/api/quiche_logging.h"
+#include "common/platform/api/quiche_prefetch.h"
#include "common/quiche_endian.h"
namespace quic {
@@ -266,9 +266,9 @@ void QuicUtils::CopyToBuffer(const struct iovec* iov,
char* next_base = static_cast<char*>(iov[iovnum + 1].iov_base);
// Prefetch 2 cachelines worth of data to get the prefetcher started; leave
// it to the hardware prefetcher after that.
- QuicPrefetchT0(next_base);
+ quiche::QuichePrefetchT0(next_base);
if (iov[iovnum + 1].iov_len >= 64) {
- QuicPrefetchT0(next_base + ABSL_CACHELINE_SIZE);
+ quiche::QuichePrefetchT0(next_base + ABSL_CACHELINE_SIZE);
}
}
@@ -308,7 +308,6 @@ bool QuicUtils::IsRetransmittableFrame(QuicFrameType type) {
case MTU_DISCOVERY_FRAME:
case PATH_CHALLENGE_FRAME:
case PATH_RESPONSE_FRAME:
- case NEW_CONNECTION_ID_FRAME:
return false;
default:
return true;
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 ab68ddd57d1..ba2ec7ee29e 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
@@ -17,8 +17,8 @@
#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
-#include "common/platform/api/quiche_text_utils.h"
#include "common/quiche_endian.h"
+#include "common/quiche_text_utils.h"
namespace quic {
namespace {
@@ -599,7 +599,6 @@ std::string AlpnForVersion(ParsedQuicVersion parsed_version) {
void QuicVersionInitializeSupportForIetfDraft() {
// Enable necessary flags.
- SetQuicReloadableFlag(quic_fix_key_update_on_first_packet, true);
}
void QuicEnableVersion(const ParsedQuicVersion& version) {
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 3379fcb39df..dbc2ca9173d 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
@@ -9,13 +9,13 @@
#include <cstdint>
#include <utility>
+#include "http2/core/priority_write_scheduler.h"
#include "quic/core/quic_packets.h"
#include "quic/platform/api/quic_bug_tracker.h"
#include "quic/platform/api/quic_containers.h"
#include "quic/platform/api/quic_export.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_map_util.h"
-#include "spdy/core/priority_write_scheduler.h"
namespace quic {
@@ -78,7 +78,7 @@ class QUIC_EXPORT_PRIVATE QuicWriteBlockedList {
bool IsStreamBlocked(QuicStreamId stream_id) const;
private:
- spdy::PriorityWriteScheduler<QuicStreamId> priority_write_scheduler_;
+ http2::PriorityWriteScheduler<QuicStreamId> priority_write_scheduler_;
// If performing batch writes, this will be the stream ID of the stream doing
// batch writes for this priority level. We will allow this stream to write
diff --git a/chromium/net/third_party/quiche/src/quic/core/tls_chlo_extractor.cc b/chromium/net/third_party/quiche/src/quic/core/tls_chlo_extractor.cc
index ae85b07c251..ac1fb180f54 100644
--- a/chromium/net/third_party/quiche/src/quic/core/tls_chlo_extractor.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/tls_chlo_extractor.cc
@@ -17,7 +17,6 @@
#include "quic/core/quic_types.h"
#include "quic/core/quic_versions.h"
#include "quic/platform/api/quic_bug_tracker.h"
-#include "common/platform/api/quiche_text_utils.h"
namespace quic {
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 f8e321663ca..1b9de030860 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
@@ -17,7 +17,7 @@
#include "quic/core/quic_types.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_hostname_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
+#include "common/quiche_text_utils.h"
namespace quic {
@@ -42,12 +42,10 @@ TlsClientHandshaker::TlsClientHandshaker(
has_application_state_(has_application_state),
crypto_config_(crypto_config),
tls_connection_(crypto_config->ssl_ctx(), this) {
- if (GetQuicReloadableFlag(quic_enable_token_based_address_validation)) {
- std::string token =
- crypto_config->LookupOrCreate(server_id)->source_address_token();
- if (!token.empty()) {
- session->SetSourceAddressTokenToSend(token);
- }
+ std::string token =
+ crypto_config->LookupOrCreate(server_id)->source_address_token();
+ if (!token.empty()) {
+ session->SetSourceAddressTokenToSend(token);
}
}
@@ -179,18 +177,16 @@ bool TlsClientHandshaker::SetAlpn() {
}
// Enable ALPS only for versions that use HTTP/3 frames.
- if (enable_alps_) {
- for (const std::string& alpn_string : alpns) {
- ParsedQuicVersion version = ParseQuicVersionString(alpn_string);
- if (!version.IsKnown() || !version.UsesHttp3()) {
- continue;
- }
- if (SSL_add_application_settings(
- ssl(), reinterpret_cast<const uint8_t*>(alpn_string.data()),
- alpn_string.size(), nullptr, /* settings_len = */ 0) != 1) {
- QUIC_BUG(quic_bug_10576_7) << "Failed to enable ALPS.";
- return false;
- }
+ for (const std::string& alpn_string : alpns) {
+ ParsedQuicVersion version = ParseQuicVersionString(alpn_string);
+ if (!version.IsKnown() || !version.UsesHttp3()) {
+ continue;
+ }
+ if (SSL_add_application_settings(
+ ssl(), reinterpret_cast<const uint8_t*>(alpn_string.data()),
+ alpn_string.size(), nullptr, /* settings_len = */ 0) != 1) {
+ QUIC_BUG(quic_bug_10576_7) << "Failed to enable ALPS.";
+ return false;
}
}
@@ -502,20 +498,18 @@ void TlsClientHandshaker::FinishHandshake() {
<< "'";
// Parse ALPS extension.
- if (enable_alps_) {
- const uint8_t* alps_data;
- size_t alps_length;
- SSL_get0_peer_application_settings(ssl(), &alps_data, &alps_length);
- if (alps_length > 0) {
- auto error = session()->OnAlpsData(alps_data, alps_length);
- if (error) {
- // Calling CloseConnection() is safe even in case OnAlpsData() has
- // already closed the connection.
- CloseConnection(
- QUIC_HANDSHAKE_FAILED,
- absl::StrCat("Error processing ALPS data: ", error.value()));
- return;
- }
+ const uint8_t* alps_data;
+ size_t alps_length;
+ SSL_get0_peer_application_settings(ssl(), &alps_data, &alps_length);
+ if (alps_length > 0) {
+ auto error = session()->OnAlpsData(alps_data, alps_length);
+ if (error) {
+ // Calling CloseConnection() is safe even in case OnAlpsData() has
+ // already closed the connection.
+ CloseConnection(
+ QUIC_HANDSHAKE_FAILED,
+ absl::StrCat("Error processing ALPS data: ", error.value()));
+ return;
}
}
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 8fb6da69d2c..eb39ccf9fab 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
@@ -168,9 +168,6 @@ class QUIC_EXPORT_PRIVATE TlsClientHandshaker
std::unique_ptr<TransportParameters> received_transport_params_ = nullptr;
std::unique_ptr<ApplicationState> received_application_state_ = nullptr;
-
- // Latched value of reloadable flag quic_enable_alps_client.
- const bool enable_alps_ = GetQuicReloadableFlag(quic_enable_alps_client);
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker_test.cc b/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker_test.cc
index e498acb9a43..8365f633f0f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker_test.cc
@@ -279,11 +279,7 @@ TEST_P(TlsClientHandshakerTest, ConnectedAfterHandshake) {
TEST_P(TlsClientHandshakerTest, ConnectionClosedOnTlsError) {
// Have client send ClientHello.
stream()->CryptoConnect();
- if (GetQuicReloadableFlag(quic_send_tls_crypto_error_code)) {
- EXPECT_CALL(*connection_, CloseConnection(QUIC_HANDSHAKE_FAILED, _, _, _));
- } else {
- EXPECT_CALL(*connection_, CloseConnection(QUIC_HANDSHAKE_FAILED, _, _));
- }
+ EXPECT_CALL(*connection_, CloseConnection(QUIC_HANDSHAKE_FAILED, _, _, _));
// Send a zero-length ServerHello from server to client.
char bogus_handshake_message[] = {
@@ -621,23 +617,14 @@ TEST_P(TlsClientHandshakerTest, ServerRequiresCustomALPN) {
.WillOnce([kTestAlpn](const std::vector<absl::string_view>& alpns) {
return std::find(alpns.cbegin(), alpns.cend(), kTestAlpn);
});
- if (GetQuicReloadableFlag(quic_send_tls_crypto_error_code)) {
- EXPECT_CALL(
- *server_connection_,
- CloseConnection(
- QUIC_HANDSHAKE_FAILED,
- static_cast<QuicIetfTransportErrorCodes>(CRYPTO_ERROR_FIRST + 120),
- "TLS handshake failure (ENCRYPTION_INITIAL) 120: "
- "no application protocol",
- _));
- } else {
- EXPECT_CALL(
- *server_connection_,
- CloseConnection(QUIC_HANDSHAKE_FAILED,
- "TLS handshake failure (ENCRYPTION_INITIAL) 120: "
- "no application protocol",
- _));
- }
+
+ EXPECT_CALL(*server_connection_,
+ CloseConnection(QUIC_HANDSHAKE_FAILED,
+ static_cast<QuicIetfTransportErrorCodes>(
+ CRYPTO_ERROR_FIRST + 120),
+ "TLS handshake failure (ENCRYPTION_INITIAL) 120: "
+ "no application protocol",
+ _));
stream()->CryptoConnect();
crypto_test_utils::AdvanceHandshake(connection_, stream(), 0,
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 bc8e0b48d4d..9ba5f3c12f6 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
@@ -96,6 +96,13 @@ void TlsHandshaker::AdvanceHandshake() {
return;
}
+ QUICHE_BUG_IF(quic_tls_server_async_done_no_flusher,
+ SSL_is_server(ssl()) && add_packet_flusher_on_async_op_done_ &&
+ !handshaker_delegate_->PacketFlusherAttached())
+ << "is_server:" << SSL_is_server(ssl())
+ << ", add_packet_flusher_on_async_op_done_:"
+ << add_packet_flusher_on_async_op_done_;
+
QUIC_VLOG(1) << ENDPOINT << "Continuing handshake";
int rv = SSL_do_handshake(ssl());
@@ -105,6 +112,7 @@ void TlsHandshaker::AdvanceHandshake() {
// that case. If there are no unprocessed ServerHello, the retry will return a
// non-positive number.
if (retry_handshake_on_early_data_ && rv == 1 && SSL_in_early_data(ssl())) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_tls_retry_handshake_on_early_data, 1, 2);
OnEnterEarlyData();
rv = SSL_do_handshake(ssl());
QUIC_VLOG(1) << ENDPOINT
@@ -335,15 +343,10 @@ void TlsHandshaker::SendAlert(EncryptionLevel level, uint8_t desc) {
"TLS handshake failure (", EncryptionLevelToString(level), ") ",
static_cast<int>(desc), ": ", SSL_alert_desc_string_long(desc));
QUIC_DLOG(ERROR) << error_details;
- if (GetQuicReloadableFlag(quic_send_tls_crypto_error_code)) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_send_tls_crypto_error_code);
- CloseConnection(
- TlsAlertToQuicErrorCode(desc),
- static_cast<QuicIetfTransportErrorCodes>(CRYPTO_ERROR_FIRST + desc),
- error_details);
- } else {
- CloseConnection(QUIC_HANDSHAKE_FAILED, error_details);
- }
+ CloseConnection(
+ TlsAlertToQuicErrorCode(desc),
+ static_cast<QuicIetfTransportErrorCodes>(CRYPTO_ERROR_FIRST + desc),
+ 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 6bf48b548c4..0b5ddc36769 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
@@ -16,6 +16,7 @@
#include "quic/core/crypto/tls_connection.h"
#include "quic/core/quic_session.h"
#include "quic/platform/api/quic_export.h"
+#include "quic/platform/api/quic_flags.h"
namespace quic {
@@ -167,6 +168,9 @@ class QUIC_EXPORT_PRIVATE TlsHandshaker : public TlsConnection::Delegate,
// error code corresponding to the TLS alert description |desc|.
void SendAlert(EncryptionLevel level, uint8_t desc) override;
+ const bool add_packet_flusher_on_async_op_done_ =
+ GetQuicReloadableFlag(quic_add_packet_flusher_on_async_op_done);
+
const bool retry_handshake_on_early_data_ =
GetQuicReloadableFlag(quic_tls_retry_handshake_on_early_data);
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 b628db1744a..efd4d275013 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
@@ -8,6 +8,7 @@
#include <string>
#include "absl/base/macros.h"
+#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "third_party/boringssl/src/include/openssl/pool.h"
#include "third_party/boringssl/src/include/openssl/ssl.h"
@@ -22,7 +23,6 @@
#include "quic/platform/api/quic_hostname_utils.h"
#include "quic/platform/api/quic_logging.h"
#include "quic/platform/api/quic_server_stats.h"
-#include "common/platform/api/quiche_text_utils.h"
#define RECORD_LATENCY_IN_US(stat_name, latency, comment) \
do { \
@@ -47,8 +47,6 @@ void TlsServerHandshaker::DefaultProofSourceHandle::CancelPendingOperation() {
QUIC_DVLOG(1) << "CancelPendingOperation. is_signature_pending="
<< (signature_callback_ != nullptr);
if (signature_callback_) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_tls_use_per_handshaker_proof_source, 3,
- 3);
signature_callback_->Cancel();
signature_callback_ = nullptr;
}
@@ -58,9 +56,11 @@ QuicAsyncStatus
TlsServerHandshaker::DefaultProofSourceHandle::SelectCertificate(
const QuicSocketAddress& server_address,
const QuicSocketAddress& client_address,
+ absl::string_view /*ssl_capabilities*/,
const std::string& hostname,
absl::string_view /*client_hello*/,
const std::string& /*alpn*/,
+ absl::optional<std::string> /*alps*/,
const std::vector<uint8_t>& /*quic_transport_params*/,
const absl::optional<std::vector<uint8_t>>& /*early_data_context*/) {
if (!handshaker_ || !proof_source_) {
@@ -73,7 +73,8 @@ TlsServerHandshaker::DefaultProofSourceHandle::SelectCertificate(
proof_source_->GetCertChain(server_address, client_address, hostname);
handshaker_->OnSelectCertificateDone(
- /*ok=*/true, /*is_sync=*/true, chain.get());
+ /*ok=*/true, /*is_sync=*/true, chain.get(),
+ /*handshake_hints=*/absl::string_view());
if (!handshaker_->select_cert_status().has_value()) {
QUIC_BUG(quic_bug_12423_1)
<< "select_cert_status() has no value after a synchronous select cert";
@@ -119,35 +120,6 @@ QuicAsyncStatus TlsServerHandshaker::DefaultProofSourceHandle::ComputeSignature(
return success ? QUIC_SUCCESS : QUIC_FAILURE;
}
-TlsServerHandshaker::SignatureCallback::SignatureCallback(
- TlsServerHandshaker* handshaker)
- : handshaker_(handshaker) {
- QUICHE_DCHECK(!handshaker_->use_proof_source_handle_);
-}
-
-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);
- }
- int last_expected_ssl_error = handshaker_->expected_ssl_error();
- handshaker_->set_expected_ssl_error(SSL_ERROR_WANT_READ);
- handshaker_->signature_callback_ = nullptr;
- if (last_expected_ssl_error == SSL_ERROR_WANT_PRIVATE_KEY_OPERATION) {
- handshaker_->AdvanceHandshakeFromCallback();
- }
-}
-
-void TlsServerHandshaker::SignatureCallback::Cancel() {
- handshaker_ = nullptr;
-}
-
TlsServerHandshaker::DecryptCallback::DecryptCallback(
TlsServerHandshaker* handshaker)
: handshaker_(handshaker) {}
@@ -217,13 +189,9 @@ TlsServerHandshaker::~TlsServerHandshaker() {
}
void TlsServerHandshaker::CancelOutstandingCallbacks() {
- if (use_proof_source_handle_ && proof_source_handle_) {
+ if (proof_source_handle_) {
proof_source_handle_->CancelPendingOperation();
}
- if (signature_callback_) {
- signature_callback_->Cancel();
- signature_callback_ = nullptr;
- }
if (ticket_decryption_callback_) {
ticket_decryption_callback_->Cancel();
ticket_decryption_callback_ = nullptr;
@@ -232,7 +200,6 @@ void TlsServerHandshaker::CancelOutstandingCallbacks() {
std::unique_ptr<ProofSourceHandle>
TlsServerHandshaker::MaybeCreateProofSourceHandle() {
- QUICHE_DCHECK(use_proof_source_handle_);
return std::make_unique<DefaultProofSourceHandle>(this, proof_source_);
}
@@ -384,6 +351,19 @@ TlsServerHandshaker::CreateCurrentOneRttEncrypter() {
void TlsServerHandshaker::OverrideQuicConfigDefaults(QuicConfig* /*config*/) {}
void TlsServerHandshaker::AdvanceHandshakeFromCallback() {
+ std::unique_ptr<QuicConnection::ScopedPacketFlusher> flusher;
+ if (add_packet_flusher_on_async_op_done_) {
+ if (session()->PacketFlusherAttached()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_add_packet_flusher_on_async_op_done, 1,
+ 2);
+ } else {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_add_packet_flusher_on_async_op_done, 2,
+ 2);
+ }
+ flusher = std::make_unique<QuicConnection::ScopedPacketFlusher>(
+ session()->connection());
+ }
+
AdvanceHandshake();
if (!is_connection_closed()) {
handshaker_delegate()->OnHandshakeCallbackDone();
@@ -541,6 +521,7 @@ std::string TlsServerHandshaker::GetAcceptChValueForOrigin(
void TlsServerHandshaker::FinishHandshake() {
if (retry_handshake_on_early_data_) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_tls_retry_handshake_on_early_data, 2, 2);
QUICHE_DCHECK(!SSL_in_early_data(ssl()));
} else {
if (SSL_in_early_data(ssl())) {
@@ -601,33 +582,19 @@ ssl_private_key_result_t TlsServerHandshaker::PrivateKeySign(
uint16_t sig_alg,
absl::string_view in) {
QUICHE_DCHECK_EQ(expected_ssl_error(), SSL_ERROR_WANT_READ);
- if (use_proof_source_handle_) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_tls_use_per_handshaker_proof_source, 2,
- 3);
- QuicAsyncStatus status = proof_source_handle_->ComputeSignature(
- session()->connection()->self_address(),
- session()->connection()->peer_address(), cert_selection_hostname(),
- sig_alg, in, max_out);
- if (status == QUIC_PENDING) {
- set_expected_ssl_error(SSL_ERROR_WANT_PRIVATE_KEY_OPERATION);
- if (async_op_timer_.has_value()) {
- QUIC_CODE_COUNT(
- quic_tls_server_computing_signature_while_another_op_pending);
- }
- async_op_timer_ = QuicTimeAccumulator();
- async_op_timer_->Start(now());
- }
- return PrivateKeyComplete(out, out_len, max_out);
- }
- signature_callback_ = new SignatureCallback(this);
- proof_source_->ComputeTlsSignature(
+ QuicAsyncStatus status = proof_source_handle_->ComputeSignature(
session()->connection()->self_address(),
- session()->connection()->peer_address(), cert_selection_hostname(),
- sig_alg, in, std::unique_ptr<SignatureCallback>(signature_callback_));
- if (signature_callback_) {
+ session()->connection()->peer_address(), crypto_negotiated_params_->sni,
+ sig_alg, in, max_out);
+ if (status == QUIC_PENDING) {
set_expected_ssl_error(SSL_ERROR_WANT_PRIVATE_KEY_OPERATION);
- return ssl_private_key_retry;
+ if (async_op_timer_.has_value()) {
+ QUIC_CODE_COUNT(
+ quic_tls_server_computing_signature_while_another_op_pending);
+ }
+ async_op_timer_ = QuicTimeAccumulator();
+ async_op_timer_->Start(now());
}
return PrivateKeyComplete(out, out_len, max_out);
}
@@ -673,7 +640,6 @@ void TlsServerHandshaker::OnComputeSignatureDone(
QUIC_DVLOG(1) << "OnComputeSignatureDone. ok:" << ok
<< ", is_sync:" << is_sync
<< ", len(signature):" << signature.size();
- QUICHE_DCHECK(use_proof_source_handle_);
if (ok) {
cert_verify_sig_ = std::move(signature);
proof_source_details_ = std::move(details);
@@ -795,24 +761,21 @@ ssl_select_cert_result_t TlsServerHandshaker::EarlySelectCertCallback(
// EarlySelectCertCallback can be called twice from BoringSSL: If the first
// call returns ssl_select_cert_retry, when cert selection completes,
// SSL_do_handshake will call it again.
- if (use_proof_source_handle_) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_tls_use_per_handshaker_proof_source, 1,
- 3);
- if (select_cert_status_.has_value()) {
- // This is the second call, return the result directly.
- QUIC_DVLOG(1) << "EarlySelectCertCallback called to continue handshake, "
- "returning directly. success:"
- << (select_cert_status_.value() == QUIC_SUCCESS);
- return (select_cert_status_.value() == QUIC_SUCCESS)
- ? ssl_select_cert_success
- : ssl_select_cert_error;
- }
- // This is the first call.
- select_cert_status_ = QUIC_PENDING;
- proof_source_handle_ = MaybeCreateProofSourceHandle();
+ if (select_cert_status_.has_value()) {
+ // This is the second call, return the result directly.
+ QUIC_DVLOG(1) << "EarlySelectCertCallback called to continue handshake, "
+ "returning directly. success:"
+ << (select_cert_status_.value() == QUIC_SUCCESS);
+ return (select_cert_status_.value() == QUIC_SUCCESS)
+ ? ssl_select_cert_success
+ : ssl_select_cert_error;
}
+ // This is the first call.
+ select_cert_status_ = QUIC_PENDING;
+ proof_source_handle_ = MaybeCreateProofSourceHandle();
+
if (!pre_shared_key_.empty()) {
// TODO(b/154162689) add PSK support to QUIC+TLS.
QUIC_BUG(quic_bug_10341_6)
@@ -824,18 +787,17 @@ ssl_select_cert_result_t TlsServerHandshaker::EarlySelectCertCallback(
// function do not work at this point, but SSL_get_servername does.
const char* hostname = SSL_get_servername(ssl(), TLSEXT_NAMETYPE_host_name);
if (hostname) {
- hostname_ = hostname;
crypto_negotiated_params_->sni =
- QuicHostnameUtils::NormalizeHostname(hostname_);
- if (!ValidateHostname(hostname_)) {
+ QuicHostnameUtils::NormalizeHostname(hostname);
+ if (!ValidateHostname(hostname)) {
return ssl_select_cert_error;
}
- if (hostname_ != crypto_negotiated_params_->sni) {
+ if (hostname != crypto_negotiated_params_->sni) {
QUIC_CODE_COUNT(quic_tls_server_hostname_diff);
QUIC_LOG_EVERY_N_SEC(WARNING, 300)
<< "Raw and normalized hostnames differ, but both are valid SNIs. "
"raw hostname:"
- << hostname_ << ", normalized:" << crypto_negotiated_params_->sni;
+ << hostname << ", normalized:" << crypto_negotiated_params_->sni;
} else {
QUIC_CODE_COUNT(quic_tls_server_hostname_same);
}
@@ -843,97 +805,105 @@ ssl_select_cert_result_t TlsServerHandshaker::EarlySelectCertCallback(
QUIC_LOG(INFO) << "No hostname indicated in SNI";
}
- if (use_proof_source_handle_) {
- std::string error_details;
- if (!ProcessTransportParameters(client_hello, &error_details)) {
- CloseConnection(QUIC_HANDSHAKE_FAILED, error_details);
- return ssl_select_cert_error;
- }
- OverrideQuicConfigDefaults(session()->config());
- session()->OnConfigNegotiated();
-
- auto set_transport_params_result = SetTransportParameters();
- if (!set_transport_params_result.success) {
- QUIC_LOG(ERROR) << "Failed to set transport parameters";
- return ssl_select_cert_error;
- }
-
- const QuicAsyncStatus status = proof_source_handle_->SelectCertificate(
- session()->connection()->self_address(),
- session()->connection()->peer_address(), cert_selection_hostname(),
- absl::string_view(
- reinterpret_cast<const char*>(client_hello->client_hello),
- client_hello->client_hello_len),
- AlpnForVersion(session()->version()),
- set_transport_params_result.quic_transport_params,
- set_transport_params_result.early_data_context);
+ std::string error_details;
+ if (!ProcessTransportParameters(client_hello, &error_details)) {
+ CloseConnection(QUIC_HANDSHAKE_FAILED, error_details);
+ return ssl_select_cert_error;
+ }
+ OverrideQuicConfigDefaults(session()->config());
+ session()->OnConfigNegotiated();
- QUICHE_DCHECK_EQ(status, select_cert_status().value());
+ auto set_transport_params_result = SetTransportParameters();
+ if (!set_transport_params_result.success) {
+ QUIC_LOG(ERROR) << "Failed to set transport parameters";
+ return ssl_select_cert_error;
+ }
- if (status == QUIC_PENDING) {
- set_expected_ssl_error(SSL_ERROR_PENDING_CERTIFICATE);
- if (async_op_timer_.has_value()) {
- QUIC_CODE_COUNT(
- quic_tls_server_selecting_cert_while_another_op_pending);
- }
- async_op_timer_ = QuicTimeAccumulator();
- async_op_timer_->Start(now());
- return ssl_select_cert_retry;
+ bssl::UniquePtr<uint8_t> ssl_capabilities;
+ size_t ssl_capabilities_len = 0;
+ absl::string_view ssl_capabilities_view;
+
+ absl::optional<std::string> alps;
+ if (use_handshake_hints_) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_tls_server_use_handshake_hints);
+ if (CryptoUtils::GetSSLCapabilities(ssl(), &ssl_capabilities,
+ &ssl_capabilities_len)) {
+ ssl_capabilities_view = absl::string_view(
+ reinterpret_cast<const char*>(ssl_capabilities.get()),
+ ssl_capabilities_len);
}
- if (status == QUIC_FAILURE) {
+ // Enable ALPS for the session's ALPN.
+ SetApplicationSettingsResult alps_result =
+ SetApplicationSettings(AlpnForVersion(session()->version()));
+ if (!alps_result.success) {
return ssl_select_cert_error;
}
-
- return ssl_select_cert_success;
- }
-
- QuicReferenceCountedPointer<ProofSource::Chain> chain =
- proof_source_->GetCertChain(session()->connection()->self_address(),
- session()->connection()->peer_address(),
- cert_selection_hostname());
- if (!chain || chain->certs.empty()) {
- QUIC_LOG(ERROR) << "No certs provided for host. raw:" << hostname_
- << ", normalized:" << crypto_negotiated_params_->sni;
- return ssl_select_cert_error;
+ alps = alps_result.alps_length > 0
+ ? std::string(alps_result.alps_buffer.get(),
+ alps_result.alps_length)
+ : std::string();
}
- CryptoBuffers cert_buffers = chain->ToCryptoBuffers();
- tls_connection_.SetCertChain(cert_buffers.value);
-
- std::string error_details;
- if (!ProcessTransportParameters(client_hello, &error_details)) {
- CloseConnection(QUIC_HANDSHAKE_FAILED, error_details);
- return ssl_select_cert_error;
+ const QuicAsyncStatus status = proof_source_handle_->SelectCertificate(
+ session()->connection()->self_address(),
+ session()->connection()->peer_address(), ssl_capabilities_view,
+ crypto_negotiated_params_->sni,
+ absl::string_view(
+ reinterpret_cast<const char*>(client_hello->client_hello),
+ client_hello->client_hello_len),
+ AlpnForVersion(session()->version()), std::move(alps),
+ set_transport_params_result.quic_transport_params,
+ set_transport_params_result.early_data_context);
+
+ QUICHE_DCHECK_EQ(status, select_cert_status().value());
+
+ if (status == QUIC_PENDING) {
+ set_expected_ssl_error(SSL_ERROR_PENDING_CERTIFICATE);
+ if (async_op_timer_.has_value()) {
+ QUIC_CODE_COUNT(quic_tls_server_selecting_cert_while_another_op_pending);
+ }
+ async_op_timer_ = QuicTimeAccumulator();
+ async_op_timer_->Start(now());
+ return ssl_select_cert_retry;
}
- OverrideQuicConfigDefaults(session()->config());
- session()->OnConfigNegotiated();
- if (!SetTransportParameters().success) {
- QUIC_LOG(ERROR) << "Failed to set transport parameters";
+ if (status == QUIC_FAILURE) {
return ssl_select_cert_error;
}
- QUIC_DLOG(INFO) << "Set " << chain->certs.size() << " certs for server "
- << "with hostname " << hostname_;
return ssl_select_cert_success;
}
void TlsServerHandshaker::OnSelectCertificateDone(
bool ok,
bool is_sync,
- const ProofSource::Chain* chain) {
+ const ProofSource::Chain* chain,
+ absl::string_view handshake_hints) {
QUIC_DVLOG(1) << "OnSelectCertificateDone. ok:" << ok
- << ", is_sync:" << is_sync;
- QUICHE_DCHECK(use_proof_source_handle_);
-
+ << ", is_sync:" << is_sync
+ << ", len(handshake_hints):" << handshake_hints.size();
select_cert_status_ = QUIC_FAILURE;
if (ok) {
if (chain && !chain->certs.empty()) {
tls_connection_.SetCertChain(chain->ToCryptoBuffers().value);
+ if (use_handshake_hints_) {
+ if (!handshake_hints.empty() &&
+ !SSL_set_handshake_hints(
+ ssl(), reinterpret_cast<const uint8_t*>(handshake_hints.data()),
+ handshake_hints.size())) {
+ // If |SSL_set_handshake_hints| fails, the ssl() object will remain
+ // intact, it is as if we didn't call it. The handshaker will
+ // continue to compute signature/decrypt ticket as normal.
+ QUIC_CODE_COUNT(quic_tls_server_set_handshake_hints_failed);
+ QUIC_DVLOG(1) << "SSL_set_handshake_hints failed";
+ }
+ }
select_cert_status_ = QUIC_SUCCESS;
} else {
- QUIC_LOG(ERROR) << "No certs provided for host '" << hostname_ << "'";
+ QUIC_LOG(ERROR) << "No certs provided for host '"
+ << crypto_negotiated_params_->sni << "', server_address:"
+ << session()->connection()->self_address();
}
}
@@ -1008,40 +978,17 @@ int TlsServerHandshaker::SelectAlpn(const uint8_t** out,
alpn_length);
}
+ // TODO(wub): Remove QuicSession::SelectAlpn. QuicSessions should know the
+ // ALPN on construction.
auto selected_alpn = session()->SelectAlpn(alpns);
if (selected_alpn == alpns.end()) {
QUIC_DLOG(ERROR) << "No known ALPN provided by client";
return SSL_TLSEXT_ERR_NOACK;
}
- // Enable ALPS for the selected ALPN protocol.
- if (GetQuicReloadableFlag(quic_enable_alps_server)) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_enable_alps_server);
-
- const uint8_t* alps_data = nullptr;
- size_t alps_length = 0;
- std::unique_ptr<char[]> buffer;
-
- const std::string& hostname = crypto_negotiated_params_->sni;
- std::string accept_ch_value = GetAcceptChValueForOrigin(hostname);
-
- std::string origin;
- if (GetQuicReloadableFlag(quic_alps_include_scheme_in_origin)) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_alps_include_scheme_in_origin);
- origin = "https://";
- }
- origin.append(crypto_negotiated_params_->sni);
-
- if (!accept_ch_value.empty()) {
- AcceptChFrame frame{{{std::move(origin), std::move(accept_ch_value)}}};
- alps_length = HttpEncoder::SerializeAcceptChFrame(frame, &buffer);
- alps_data = reinterpret_cast<const uint8_t*>(buffer.get());
- }
-
- if (SSL_add_application_settings(
- ssl(), reinterpret_cast<const uint8_t*>(selected_alpn->data()),
- selected_alpn->size(), alps_data, alps_length) != 1) {
- QUIC_DLOG(ERROR) << "Failed to enable ALPS";
+ if (!use_handshake_hints_) {
+ // Enable ALPS for the selected ALPN protocol.
+ if (!SetApplicationSettings(*selected_alpn).success) {
return SSL_TLSEXT_ERR_NOACK;
}
}
@@ -1053,4 +1000,31 @@ int TlsServerHandshaker::SelectAlpn(const uint8_t** out,
return SSL_TLSEXT_ERR_OK;
}
+TlsServerHandshaker::SetApplicationSettingsResult
+TlsServerHandshaker::SetApplicationSettings(absl::string_view alpn) {
+ TlsServerHandshaker::SetApplicationSettingsResult result;
+ const uint8_t* alps_data = nullptr;
+
+ const std::string& hostname = crypto_negotiated_params_->sni;
+ std::string accept_ch_value = GetAcceptChValueForOrigin(hostname);
+ std::string origin = absl::StrCat("https://", hostname);
+
+ if (!accept_ch_value.empty()) {
+ AcceptChFrame frame{{{std::move(origin), std::move(accept_ch_value)}}};
+ result.alps_length =
+ HttpEncoder::SerializeAcceptChFrame(frame, &result.alps_buffer);
+ alps_data = reinterpret_cast<const uint8_t*>(result.alps_buffer.get());
+ }
+
+ if (SSL_add_application_settings(
+ ssl(), reinterpret_cast<const uint8_t*>(alpn.data()), alpn.size(),
+ alps_data, result.alps_length) != 1) {
+ QUIC_DLOG(ERROR) << "Failed to enable ALPS";
+ result.success = false;
+ } else {
+ result.success = true;
+ }
+ return result;
+}
+
} // namespace quic
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 7850d3519a8..260b094bda7 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
@@ -19,6 +19,7 @@
#include "quic/core/quic_types.h"
#include "quic/core/tls_handshaker.h"
#include "quic/platform/api/quic_export.h"
+#include "quic/platform/api/quic_flags.h"
namespace quic {
@@ -88,25 +89,14 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
protected:
// Creates a proof source handle for selecting cert and computing signature.
- // Only called when |use_proof_source_handle_| is true.
virtual std::unique_ptr<ProofSourceHandle> MaybeCreateProofSourceHandle();
- bool use_proof_source_handle() const { return use_proof_source_handle_; }
-
// Hook to allow the server to override parts of the QuicConfig based on SNI
// before we generate transport parameters.
virtual void OverrideQuicConfigDefaults(QuicConfig* config);
virtual bool ValidateHostname(const std::string& hostname) const;
- // The hostname to be used to select certificates and compute signatures.
- // The function should only be called after a successful ValidateHostname().
- const std::string& cert_selection_hostname() const {
- return use_normalized_sni_for_cert_selection_
- ? crypto_negotiated_params_->sni
- : hostname_;
- }
-
const TlsConnection* tls_connection() const override {
return &tls_connection_;
}
@@ -177,7 +167,8 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
// ProofSourceHandleCallback implementation:
void OnSelectCertificateDone(bool ok,
bool is_sync,
- const ProofSource::Chain* chain) override;
+ const ProofSource::Chain* chain,
+ absl::string_view handshake_hints) override;
void OnComputeSignatureDone(
bool ok,
@@ -186,21 +177,6 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
std::unique_ptr<ProofSource::Details> details) override;
private:
- class QUIC_EXPORT_PRIVATE SignatureCallback
- : public ProofSource::SignatureCallback {
- public:
- explicit SignatureCallback(TlsServerHandshaker* handshaker);
- 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();
-
- private:
- TlsServerHandshaker* handshaker_;
- };
-
class QUIC_EXPORT_PRIVATE DecryptCallback
: public ProofSource::DecryptCallback {
public:
@@ -232,9 +208,11 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
QuicAsyncStatus SelectCertificate(
const QuicSocketAddress& server_address,
const QuicSocketAddress& client_address,
+ absl::string_view ssl_capabilities,
const std::string& hostname,
absl::string_view client_hello,
const std::string& alpn,
+ absl::optional<std::string> alps,
const std::vector<uint8_t>& quic_transport_params,
const absl::optional<std::vector<uint8_t>>& early_data_context)
override;
@@ -302,6 +280,13 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
bool ProcessTransportParameters(const SSL_CLIENT_HELLO* client_hello,
std::string* error_details);
+ struct QUIC_NO_EXPORT SetApplicationSettingsResult {
+ bool success = false;
+ std::unique_ptr<char[]> alps_buffer;
+ size_t alps_length = 0;
+ };
+ SetApplicationSettingsResult SetApplicationSettings(absl::string_view alpn);
+
QuicConnectionStats& connection_stats() {
return session()->connection()->mutable_stats();
}
@@ -309,7 +294,6 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
std::unique_ptr<ProofSourceHandle> proof_source_handle_;
ProofSource* proof_source_;
- SignatureCallback* signature_callback_ = nullptr;
// State to handle potentially asynchronous session ticket decryption.
// |ticket_decryption_callback_| points to the non-owned callback that was
@@ -328,7 +312,6 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
// nullopt means select cert hasn't started.
absl::optional<QuicAsyncStatus> select_cert_status_;
- std::string hostname_;
std::string cert_verify_sig_;
std::unique_ptr<ProofSource::Details> proof_source_details_;
@@ -346,11 +329,9 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters>
crypto_negotiated_params_;
TlsServerConnection tls_connection_;
- const bool use_proof_source_handle_ =
- GetQuicReloadableFlag(quic_tls_use_per_handshaker_proof_source);
- const bool use_normalized_sni_for_cert_selection_ =
- GetQuicReloadableFlag(quic_tls_use_normalized_sni_for_cert_selectioon);
const QuicCryptoServerConfig* crypto_config_; // Unowned.
+ const bool use_handshake_hints_ =
+ GetQuicReloadableFlag(quic_tls_server_use_handshake_hints);
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker_test.cc b/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker_test.cc
index fbec2551227..d67c8791d2c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker_test.cc
@@ -400,10 +400,6 @@ TEST_P(TlsServerHandshakerTest, ConnectedAfterTlsHandshake) {
}
TEST_P(TlsServerHandshakerTest, HandshakeWithAsyncSelectCertSuccess) {
- if (!GetQuicReloadableFlag(quic_tls_use_per_handshaker_proof_source)) {
- return;
- }
-
InitializeServerWithFakeProofSourceHandle();
server_handshaker_->SetupProofSourceHandle(
/*select_cert_action=*/FakeProofSourceHandle::Action::DELEGATE_ASYNC,
@@ -426,10 +422,6 @@ TEST_P(TlsServerHandshakerTest, HandshakeWithAsyncSelectCertSuccess) {
}
TEST_P(TlsServerHandshakerTest, HandshakeWithAsyncSelectCertFailure) {
- if (!GetQuicReloadableFlag(quic_tls_use_per_handshaker_proof_source)) {
- return;
- }
-
InitializeServerWithFakeProofSourceHandle();
server_handshaker_->SetupProofSourceHandle(
/*select_cert_action=*/FakeProofSourceHandle::Action::FAIL_ASYNC,
@@ -449,10 +441,6 @@ TEST_P(TlsServerHandshakerTest, HandshakeWithAsyncSelectCertFailure) {
}
TEST_P(TlsServerHandshakerTest, HandshakeWithAsyncSelectCertAndSignature) {
- if (!GetQuicReloadableFlag(quic_tls_use_per_handshaker_proof_source)) {
- return;
- }
-
InitializeServerWithFakeProofSourceHandle();
server_handshaker_->SetupProofSourceHandle(
/*select_cert_action=*/FakeProofSourceHandle::Action::DELEGATE_ASYNC,
@@ -507,10 +495,6 @@ TEST_P(TlsServerHandshakerTest, HandshakeWithAsyncSignature) {
}
TEST_P(TlsServerHandshakerTest, CancelPendingSelectCert) {
- if (!GetQuicReloadableFlag(quic_tls_use_per_handshaker_proof_source)) {
- return;
- }
-
InitializeServerWithFakeProofSourceHandle();
server_handshaker_->SetupProofSourceHandle(
/*select_cert_action=*/FakeProofSourceHandle::Action::DELEGATE_ASYNC,
@@ -557,10 +541,6 @@ TEST_P(TlsServerHandshakerTest, ExtractSNI) {
}
TEST_P(TlsServerHandshakerTest, HostnameForCertSelectionAndComputeSignature) {
- if (!GetQuicReloadableFlag(quic_tls_use_per_handshaker_proof_source)) {
- return;
- }
-
// Client uses upper case letters in hostname. It is considered valid by
// QuicHostnameUtils::IsValidSNI, but it should be normalized for cert
// selection.
@@ -577,23 +557,13 @@ TEST_P(TlsServerHandshakerTest, HostnameForCertSelectionAndComputeSignature) {
EXPECT_EQ(server_stream()->crypto_negotiated_params().sni,
"test.example.com");
- if (GetQuicReloadableFlag(quic_tls_use_normalized_sni_for_cert_selectioon)) {
- EXPECT_EQ(last_select_cert_args().hostname, "test.example.com");
- EXPECT_EQ(last_compute_signature_args().hostname, "test.example.com");
- } else {
- EXPECT_EQ(last_select_cert_args().hostname, "tEsT.EXAMPLE.CoM");
- EXPECT_EQ(last_compute_signature_args().hostname, "tEsT.EXAMPLE.CoM");
- }
+ EXPECT_EQ(last_select_cert_args().hostname, "test.example.com");
+ EXPECT_EQ(last_compute_signature_args().hostname, "test.example.com");
}
TEST_P(TlsServerHandshakerTest, ConnectionClosedOnTlsError) {
- if (GetQuicReloadableFlag(quic_send_tls_crypto_error_code)) {
- EXPECT_CALL(*server_connection_,
- CloseConnection(QUIC_HANDSHAKE_FAILED, _, _, _));
- } else {
- EXPECT_CALL(*server_connection_,
- CloseConnection(QUIC_HANDSHAKE_FAILED, _, _));
- }
+ EXPECT_CALL(*server_connection_,
+ CloseConnection(QUIC_HANDSHAKE_FAILED, _, _, _));
// Send a zero-length ClientHello from client to server.
char bogus_handshake_message[] = {
@@ -601,6 +571,15 @@ TEST_P(TlsServerHandshakerTest, ConnectionClosedOnTlsError) {
1, // HandshakeType client_hello
0, 0, 0, // uint24 length
};
+
+ // Install a packet flusher such that the packets generated by
+ // |server_connection_| in response to this handshake message are more likely
+ // to be coalesced and/or batched in the writer.
+ //
+ // This is required by TlsServerHandshaker because without the flusher, it
+ // tends to generate many small, uncoalesced packets, one per
+ // TlsHandshaker::WriteMessage.
+ QuicConnection::ScopedPacketFlusher flusher(server_connection_);
server_stream()->crypto_message_parser()->ProcessInput(
absl::string_view(bogus_handshake_message,
ABSL_ARRAYSIZE(bogus_handshake_message)),
@@ -613,23 +592,14 @@ TEST_P(TlsServerHandshakerTest, ClientSendingBadALPN) {
const std::string kTestBadClientAlpn = "bad-client-alpn";
EXPECT_CALL(*client_session_, GetAlpnsToOffer())
.WillOnce(Return(std::vector<std::string>({kTestBadClientAlpn})));
- if (GetQuicReloadableFlag(quic_send_tls_crypto_error_code)) {
- EXPECT_CALL(
- *server_connection_,
- CloseConnection(
- QUIC_HANDSHAKE_FAILED,
- static_cast<QuicIetfTransportErrorCodes>(CRYPTO_ERROR_FIRST + 120),
- "TLS handshake failure (ENCRYPTION_INITIAL) 120: "
- "no application protocol",
- _));
- } else {
- EXPECT_CALL(
- *server_connection_,
- CloseConnection(QUIC_HANDSHAKE_FAILED,
- "TLS handshake failure (ENCRYPTION_INITIAL) 120: "
- "no application protocol",
- _));
- }
+
+ EXPECT_CALL(*server_connection_,
+ CloseConnection(QUIC_HANDSHAKE_FAILED,
+ static_cast<QuicIetfTransportErrorCodes>(
+ CRYPTO_ERROR_FIRST + 120),
+ "TLS handshake failure (ENCRYPTION_INITIAL) 120: "
+ "no application protocol",
+ _));
AdvanceHandshakeWithFakeClient();
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 5ed0e08777a..8f20b33c183 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
@@ -120,14 +120,11 @@ void UberReceivedPacketManager::EnableMultiplePacketNumberSpacesSupport(
}
// In IETF QUIC, the peer is expected to acknowledge packets in Initial and
// Handshake packets with minimal delay.
- if (!GetQuicReloadableFlag(quic_delay_initial_ack) ||
- perspective == Perspective::IS_CLIENT) {
+ if (perspective == Perspective::IS_CLIENT) {
// Delay the first server ACK, because server ACKs are padded to
// full size and count towards the amplification limit.
received_packet_managers_[INITIAL_DATA].set_local_max_ack_delay(
kAlarmGranularity);
- } else {
- QUIC_RELOADABLE_FLAG_COUNT(quic_delay_initial_ack);
}
received_packet_managers_[HANDSHAKE_DATA].set_local_max_ack_delay(
kAlarmGranularity);
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 05e4a33aedf..cf612feab1d 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
@@ -478,17 +478,10 @@ TEST_F(UberReceivedPacketManagerTest, AckSendingDifferentPacketNumberSpaces) {
MaybeUpdateAckTimeout(kInstigateAck, ENCRYPTION_INITIAL, 3);
EXPECT_TRUE(HasPendingAck());
// Delayed ack is scheduled.
- if (GetQuicReloadableFlag(quic_delay_initial_ack)) {
- CheckAckTimeout(clock_.ApproximateNow() +
- QuicTime::Delta::FromMilliseconds(25));
- // Send delayed handshake data ACK.
- clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(25));
- } else {
- CheckAckTimeout(clock_.ApproximateNow() +
- QuicTime::Delta::FromMilliseconds(1));
- // Send delayed handshake data ACK.
- clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
- }
+ CheckAckTimeout(clock_.ApproximateNow() +
+ QuicTime::Delta::FromMilliseconds(25));
+ // Send delayed handshake data ACK.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(25));
CheckAckTimeout(clock_.ApproximateNow());
EXPECT_FALSE(HasPendingAck());
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
index 4d0523f5177..920372574a1 100644
--- 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
@@ -22,7 +22,6 @@
#include "quic/platform/api/quic_system_event_loop.h"
#include "quic/tools/fake_proof_verifier.h"
#include "quic/tools/quic_url.h"
-#include "common/platform/api/quiche_text_utils.h"
DEFINE_QUIC_COMMAND_LINE_FLAG(bool,
disable_certificate_verification,
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
index 8793d5319f2..6eee553e076 100644
--- 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
@@ -7,7 +7,6 @@
#include "quic/core/http/spdy_utils.h"
#include "quic/core/quic_data_reader.h"
#include "quic/core/quic_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
namespace quic {
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
index 8413e0d974b..b021b41a0a6 100644
--- 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
@@ -15,7 +15,7 @@
#include "quic/core/quic_types.h"
#include "quic/core/quic_versions.h"
#include "quic/platform/api/quic_containers.h"
-#include "common/platform/api/quiche_text_utils.h"
+#include "common/quiche_text_utils.h"
namespace quic {
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
index 112f3053180..9684ce1956c 100644
--- 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
@@ -90,7 +90,7 @@ bool MasqueServerBackend::MaybeHandleMasqueRequest(
QUIC_DLOG(INFO) << "Sending MASQUE response for "
<< request_headers.DebugString();
- request_handler->OnResponseBackendComplete(response.get(), {});
+ request_handler->OnResponseBackendComplete(response.get());
it->second.responses.emplace_back(std::move(response));
return true;
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
index 036c75fb95c..8a531cab3a0 100644
--- 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
@@ -13,7 +13,6 @@
#include "quic/core/quic_data_reader.h"
#include "quic/core/quic_udp_socket.h"
#include "quic/tools/quic_url.h"
-#include "common/platform/api/quiche_text_utils.h"
namespace quic {
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 fa4610be27b..f7fd922f594 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
@@ -7,47 +7,14 @@
#include "net/quic/platform/impl/quic_containers_impl.h"
-namespace quic {
-
-// The default hasher used by hash tables.
-template <typename Key>
-using QuicDefaultHasher = QuicDefaultHasherImpl<Key>;
-
-// A general-purpose unordered map.
-template <typename Key, typename Value, typename Hash = QuicDefaultHasher<Key>>
-using QuicUnorderedMap = QuicUnorderedMapImpl<Key, Value, Hash>;
+#include "absl/hash/hash.h"
-// A general-purpose unordered map that does not gurantee pointer stability.
-template <typename Key, typename Value, typename Hash = QuicDefaultHasher<Key>>
-using QuicHashMap = QuicHashMapImpl<Key, Value, Hash>;
-
-// A general-purpose unordered set.
-template <typename Key, typename Hash = QuicDefaultHasher<Key>>
-using QuicUnorderedSet = QuicUnorderedSetImpl<Key, Hash>;
-
-// A general-purpose unordered set that does not gurantee pointer stability.
-template <typename Key, typename Hash = QuicDefaultHasher<Key>>
-using QuicHashSet = QuicHashSetImpl<Key, Hash>;
+namespace quic {
// A map which offers insertion-ordered iteration.
-template <typename Key, typename Value, typename Hash = QuicDefaultHasher<Key>>
+template <typename Key, typename Value, typename Hash = absl::Hash<Key>>
using QuicLinkedHashMap = QuicLinkedHashMapImpl<Key, Value, Hash>;
-// Used for maps that are typically small, then it is faster than (for example)
-// hash_map which is optimized for large data sets. QuicSmallMap upgrades itself
-// automatically to a QuicSmallMapImpl-specified map when it runs out of space.
-//
-// DOES NOT GUARANTEE POINTER OR ITERATOR STABILITY!
-template <typename Key, typename Value, int Size>
-using QuicSmallMap = QuicSmallMapImpl<Key, Value, Size>;
-
-// Represents a simple queue which may be backed by a list or
-// a flat circular buffer.
-//
-// DOES NOT GUARANTEE POINTER OR ITERATOR STABILITY!
-template <typename T>
-using QuicQueue = QuicQueueImpl<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_sleep.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_sleep.h
index 8067d458330..00253c3c6fc 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_sleep.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_sleep.h
@@ -6,7 +6,8 @@
#define QUICHE_QUIC_PLATFORM_API_QUIC_SLEEP_H_
#include "quic/core/quic_time.h"
-#include "net/quic/platform/impl/quic_sleep_impl.h"
+// TODO(b/178613777): move into the common QUICHE platform.
+#include "quiche_platform_impl/quiche_sleep_impl.h"
namespace quic {
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 69995c35ff8..58896f76d5e 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
@@ -25,9 +25,6 @@ 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)
#endif // QUICHE_QUIC_PLATFORM_API_QUIC_TEST_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 b5d9c47f3b8..8e39996284e 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
@@ -11,8 +11,8 @@
#include "quic/platform/api/quic_logging.h"
#include "quic/platform/api/quic_mutex.h"
#include "quic/qbone/platform/icmp_packet.h"
-#include "common/platform/api/quiche_text_utils.h"
#include "common/quiche_endian.h"
+#include "common/quiche_text_utils.h"
namespace quic {
namespace {
@@ -98,8 +98,6 @@ bool IcmpReachable::Init() {
epoll_server_->RegisterFD(recv_fd_, &cb_, kEpollFlags);
epoll_server_->RegisterAlarm(0, this);
- epoll_server_->set_timeout_in_us(50000);
-
QuicWriterMutexLock mu(&header_lock_);
icmp_header_.icmp6_type = ICMP6_ECHO_REQUEST;
icmp_header_.icmp6_code = 0;
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/mock_tun_device.h b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/mock_tun_device.h
index d593913d3ae..056346ca000 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/mock_tun_device.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/mock_tun_device.h
@@ -18,6 +18,8 @@ class MockTunDevice : public TunDeviceInterface {
MOCK_METHOD(bool, Down, (), (override));
+ MOCK_METHOD(void, CloseDevice, (), (override));
+
MOCK_METHOD(int, GetFileDescriptor, (), (const, override));
};
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 3ca52e8d6d6..65197cdd4d9 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
@@ -10,6 +10,7 @@
#include <sys/ioctl.h>
#include <sys/socket.h>
+#include "absl/cleanup/cleanup.h"
#include "quic/platform/api/quic_bug_tracker.h"
#include "quic/platform/api/quic_logging.h"
#include "quic/qbone/platform/kernel_interface.h"
@@ -39,7 +40,7 @@ TunDevice::~TunDevice() {
if (!persist_) {
Down();
}
- CleanUpFileDescriptor();
+ CloseDevice();
}
bool TunDevice::Init() {
@@ -63,39 +64,33 @@ bool TunDevice::Init() {
// TODO(pengg): might be better to use netlink socket, once we have a library to
// use
bool TunDevice::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
- // entire struct.
- interface_name_.copy(if_request.ifr_name, IFNAMSIZ);
- if_request.ifr_flags = IFF_UP;
-
- is_interface_up_ =
- NetdeviceIoctl(SIOCSIFFLAGS, reinterpret_cast<void*>(&if_request));
- return is_interface_up_;
- } else {
+ 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 struct.
+ interface_name_.copy(if_request.ifr_name, IFNAMSIZ);
+ if_request.ifr_flags = IFF_UP;
+
+ return NetdeviceIoctl(SIOCSIFFLAGS, reinterpret_cast<void*>(&if_request));
}
// TODO(pengg): might be better to use netlink socket, once we have a library to
// use
bool TunDevice::Down() {
- 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
- // entire struct.
- interface_name_.copy(if_request.ifr_name, IFNAMSIZ);
- if_request.ifr_flags = 0;
-
- is_interface_up_ =
- !NetdeviceIoctl(SIOCSIFFLAGS, reinterpret_cast<void*>(&if_request));
- return !is_interface_up_;
- } else {
+ 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 struct.
+ interface_name_.copy(if_request.ifr_name, IFNAMSIZ);
+ if_request.ifr_flags = 0;
+
+ return NetdeviceIoctl(SIOCSIFFLAGS, reinterpret_cast<void*>(&if_request));
}
int TunDevice::GetFileDescriptor() const {
@@ -103,6 +98,10 @@ int TunDevice::GetFileDescriptor() const {
}
bool TunDevice::OpenDevice() {
+ if (file_descriptor_ != kInvalidFd) {
+ CloseDevice();
+ }
+
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
@@ -116,39 +115,41 @@ bool TunDevice::OpenDevice() {
// 'persist' bit ambiguous.
if_request.ifr_flags = IFF_TUN | IFF_MULTI_QUEUE | IFF_NO_PI;
- // TODO(pengg): port MakeCleanup to quic/platform? This makes the call to
- // CleanUpFileDescriptor nicer and less error-prone.
// When the device is running with IFF_MULTI_QUEUE set, each call to open will
// create a queue which can be used to read/write packets from/to the device.
+ bool successfully_opened = false;
+ auto cleanup = absl::MakeCleanup([this, &successfully_opened]() {
+ if (!successfully_opened) {
+ CloseDevice();
+ }
+ });
+
const std::string tun_device_path =
absl::GetFlag(FLAGS_qbone_client_tun_device_path);
int fd = kernel_.open(tun_device_path.c_str(), O_RDWR);
if (fd < 0) {
QUIC_PLOG(WARNING) << "Failed to open " << tun_device_path;
- CleanUpFileDescriptor();
- return false;
+ return successfully_opened;
}
file_descriptor_ = fd;
if (!CheckFeatures(fd)) {
- CleanUpFileDescriptor();
- return false;
+ return successfully_opened;
}
if (kernel_.ioctl(fd, TUNSETIFF, reinterpret_cast<void*>(&if_request)) != 0) {
QUIC_PLOG(WARNING) << "Failed to TUNSETIFF on fd(" << fd << ")";
- CleanUpFileDescriptor();
- return false;
+ return successfully_opened;
}
if (kernel_.ioctl(
fd, TUNSETPERSIST,
persist_ ? reinterpret_cast<void*>(&if_request) : nullptr) != 0) {
QUIC_PLOG(WARNING) << "Failed to TUNSETPERSIST on fd(" << fd << ")";
- CleanUpFileDescriptor();
- return false;
+ return successfully_opened;
}
- return true;
+ successfully_opened = true;
+ return successfully_opened;
}
// TODO(pengg): might be better to use netlink socket, once we have a library to
@@ -166,7 +167,7 @@ bool TunDevice::ConfigureInterface() {
if_request.ifr_mtu = mtu_;
if (!NetdeviceIoctl(SIOCSIFMTU, reinterpret_cast<void*>(&if_request))) {
- CleanUpFileDescriptor();
+ CloseDevice();
return false;
}
@@ -206,7 +207,7 @@ bool TunDevice::NetdeviceIoctl(int request, void* argp) {
return true;
}
-void TunDevice::CleanUpFileDescriptor() {
+void TunDevice::CloseDevice() {
if (file_descriptor_ != kInvalidFd) {
kernel_.close(file_descriptor_);
file_descriptor_ = kInvalidFd;
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 bff85f5943a..129e1d121c6 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
@@ -49,6 +49,11 @@ class TunDevice : public TunDeviceInterface {
// Marks the interface down to stop receiving packets.
bool Down() override;
+ // Closes the open file descriptor for the TUN device (if one exists).
+ // It is safe to reinitialize and reuse this TunDevice after calling
+ // CloseDevice.
+ void CloseDevice() override;
+
// Gets the file descriptor that can be used to send/receive packets.
// This returns -1 when the TUN device is in an invalid state.
int GetFileDescriptor() const override;
@@ -63,10 +68,6 @@ class TunDevice : public TunDeviceInterface {
// Checks if the required kernel features exists.
bool CheckFeatures(int tun_device_fd);
- // Closes the opened file descriptor and makes sure the file descriptor
- // is no longer available from GetFileDescriptor;
- void CleanUpFileDescriptor();
-
// Opens a socket and makes netdevice ioctl call
bool NetdeviceIoctl(int request, void* argp);
@@ -76,7 +77,6 @@ class TunDevice : public TunDeviceInterface {
const bool setup_tun_;
int file_descriptor_;
KernelInterface& kernel_;
- bool is_interface_up_ = false;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_interface.h b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_interface.h
index e99c547ee7c..3c6f9624960 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_interface.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_interface.h
@@ -12,7 +12,7 @@ namespace quic {
// An interface with methods for interacting with a TUN device.
class TunDeviceInterface {
public:
- virtual ~TunDeviceInterface() {}
+ virtual ~TunDeviceInterface() = default;
// Actually creates/reopens and configures the device.
virtual bool Init() = 0;
@@ -23,6 +23,11 @@ class TunDeviceInterface {
// Marks the interface down to stop receiving packets.
virtual bool Down() = 0;
+ // Closes the open file descriptor for the TUN device (if one exists).
+ // It is safe to reinitialize and reuse this TunDevice after calling
+ // CloseDevice.
+ virtual void CloseDevice() = 0;
+
// Gets the file descriptor that can be used to send/receive packets.
// This returns -1 when the TUN device is in an invalid state.
virtual int GetFileDescriptor() const = 0;
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 21196716760..4783e9cc9c3 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
@@ -11,14 +11,12 @@
namespace quic {
TunDevicePacketExchanger::TunDevicePacketExchanger(
- int fd,
size_t mtu,
KernelInterface* kernel,
QbonePacketExchanger::Visitor* visitor,
size_t max_pending_packets,
StatsInterface* stats)
: QbonePacketExchanger(visitor, max_pending_packets),
- fd_(fd),
mtu_(mtu),
kernel_(kernel),
stats_(stats) {}
@@ -78,8 +76,8 @@ std::unique_ptr<QuicData> TunDevicePacketExchanger::ReadPacket(
return std::make_unique<QuicData>(read_buffer.release(), result, true);
}
-int TunDevicePacketExchanger::file_descriptor() const {
- return fd_;
+void TunDevicePacketExchanger::set_file_descriptor(int fd) {
+ fd_ = fd;
}
const TunDevicePacketExchanger::StatsInterface*
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 1d28fee1dbc..115f5b580c6 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
@@ -35,8 +35,6 @@ class TunDevicePacketExchanger : public QbonePacketExchanger {
ABSL_MUST_USE_RESULT virtual int64_t PacketsWritten() const = 0;
};
- // |fd| is a open file descriptor on a TUN device that's opened for both read
- // and write.
// |mtu| is the mtu of the TUN device.
// |kernel| is not owned but should out live objects of this class.
// |visitor| is not owned but should out live objects of this class.
@@ -44,14 +42,13 @@ class TunDevicePacketExchanger : public QbonePacketExchanger {
// the TUN device become blocked.
// |stats| is notified about packet read/write statistics. It is not owned,
// but should outlive objects of this class.
- TunDevicePacketExchanger(int fd,
- size_t mtu,
+ TunDevicePacketExchanger(size_t mtu,
KernelInterface* kernel,
QbonePacketExchanger::Visitor* visitor,
size_t max_pending_packets,
StatsInterface* stats);
- ABSL_MUST_USE_RESULT int file_descriptor() const;
+ void set_file_descriptor(int fd);
ABSL_MUST_USE_RESULT const StatsInterface* stats_interface() const;
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 4a00c60eb78..c8f3ff0c861 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
@@ -30,14 +30,15 @@ class MockVisitor : public QbonePacketExchanger::Visitor {
class TunDevicePacketExchangerTest : public QuicTest {
protected:
TunDevicePacketExchangerTest()
- : exchanger_(kFd,
- kMtu,
+ : exchanger_(kMtu,
&mock_kernel_,
&mock_visitor_,
kMaxPendingPackets,
- &mock_stats_) {}
+ &mock_stats_) {
+ exchanger_.set_file_descriptor(kFd);
+ }
- ~TunDevicePacketExchangerTest() override {}
+ ~TunDevicePacketExchangerTest() override = default;
MockKernel mock_kernel_;
StrictMock<MockVisitor> mock_visitor_;
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 9c216afe258..6a02f07062e 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
@@ -139,6 +139,7 @@ TEST_F(TunDeviceTest, FailToOpenTunDevice) {
TunDevice tun_device(kDeviceName, 1500, false, true, &mock_kernel_);
EXPECT_FALSE(tun_device.Init());
EXPECT_EQ(tun_device.GetFileDescriptor(), -1);
+ ExpectDown(false);
}
TEST_F(TunDeviceTest, FailToCheckFeature) {
@@ -147,6 +148,7 @@ TEST_F(TunDeviceTest, FailToCheckFeature) {
TunDevice tun_device(kDeviceName, 1500, false, true, &mock_kernel_);
EXPECT_FALSE(tun_device.Init());
EXPECT_EQ(tun_device.GetFileDescriptor(), -1);
+ ExpectDown(false);
}
TEST_F(TunDeviceTest, TooFewFeature) {
@@ -160,6 +162,7 @@ TEST_F(TunDeviceTest, TooFewFeature) {
TunDevice tun_device(kDeviceName, 1500, false, true, &mock_kernel_);
EXPECT_FALSE(tun_device.Init());
EXPECT_EQ(tun_device.GetFileDescriptor(), -1);
+ ExpectDown(false);
}
TEST_F(TunDeviceTest, FailToSetFlag) {
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 857cada50a6..9721e36aa40 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
@@ -10,7 +10,7 @@
#include "absl/strings/string_view.h"
#include "quic/platform/api/quic_test.h"
-#include "common/platform/api/quiche_text_utils.h"
+#include "common/quiche_text_utils.h"
namespace quic {
namespace {
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 df107d63c2f..9da9cb83603 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
@@ -10,7 +10,7 @@
#include "absl/strings/string_view.h"
#include "quic/platform/api/quic_test.h"
-#include "common/platform/api/quiche_text_utils.h"
+#include "common/quiche_text_utils.h"
namespace quic {
namespace {
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 f0d9d16059e..fb9a288cbeb 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
@@ -23,7 +23,6 @@
#include "quic/test_tools/quic_connection_peer.h"
#include "quic/test_tools/quic_session_peer.h"
#include "quic/test_tools/quic_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
namespace quic {
namespace test {
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 6f6d091d71a..ad29a150b58 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
@@ -152,8 +152,10 @@ 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.
- QuicCircularDeque<QuicTransportStream*> incoming_bidirectional_streams_;
- QuicCircularDeque<QuicTransportStream*> incoming_unidirectional_streams_;
+ quiche::QuicheCircularDeque<QuicTransportStream*>
+ incoming_bidirectional_streams_;
+ quiche::QuicheCircularDeque<QuicTransportStream*>
+ incoming_unidirectional_streams_;
};
} // namespace quic
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 c58e658591b..159f8864fd8 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
@@ -21,7 +21,7 @@
#include "quic/test_tools/crypto_test_utils.h"
#include "quic/test_tools/quic_test_utils.h"
#include "quic/test_tools/quic_transport_test_tools.h"
-#include "common/platform/api/quiche_text_utils.h"
+#include "common/quiche_text_utils.h"
namespace quic {
namespace test {
diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/web_transport_fingerprint_proof_verifier.cc b/chromium/net/third_party/quiche/src/quic/quic_transport/web_transport_fingerprint_proof_verifier.cc
index cbe55453af2..7e43341b543 100644
--- a/chromium/net/third_party/quiche/src/quic/quic_transport/web_transport_fingerprint_proof_verifier.cc
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/web_transport_fingerprint_proof_verifier.cc
@@ -14,7 +14,7 @@
#include "quic/core/quic_time.h"
#include "quic/core/quic_types.h"
#include "quic/platform/api/quic_bug_tracker.h"
-#include "common/platform/api/quiche_text_utils.h"
+#include "common/quiche_text_utils.h"
namespace quic {
namespace {
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 968b4140451..00264e59a09 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
@@ -40,7 +40,6 @@
#include "quic/test_tools/quic_stream_peer.h"
#include "quic/test_tools/quic_test_utils.h"
#include "quic/test_tools/simple_quic_framer.h"
-#include "common/platform/api/quiche_text_utils.h"
#include "common/test_tools/quiche_test_utils.h"
namespace quic {
@@ -760,6 +759,12 @@ void MovePackets(PacketSavingConnection* source_conn,
continue;
}
QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
+
+ // Install a packet flusher such that the packets generated by |dest_conn|
+ // in response to this packet are more likely to be coalesced and/or batched
+ // in the writer.
+ QuicConnection::ScopedPacketFlusher flusher(dest_conn);
+
dest_conn->OnDecryptedPacket(
source_conn->encrypted_packets_[index]->length(),
framer.last_decrypted_level());
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 ce45b827551..b1f21158d91 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
@@ -12,7 +12,6 @@
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/mock_clock.h"
-#include "common/platform/api/quiche_text_utils.h"
namespace quic {
namespace test {
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source_handle.cc b/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source_handle.cc
index b239f7d140c..b1fedf8c161 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source_handle.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source_handle.cc
@@ -71,14 +71,16 @@ void FakeProofSourceHandle::CancelPendingOperation() {
QuicAsyncStatus FakeProofSourceHandle::SelectCertificate(
const QuicSocketAddress& server_address,
const QuicSocketAddress& client_address,
+ absl::string_view ssl_capabilities,
const std::string& hostname,
absl::string_view client_hello,
const std::string& alpn,
+ absl::optional<std::string> alps,
const std::vector<uint8_t>& quic_transport_params,
const absl::optional<std::vector<uint8_t>>& early_data_context) {
- all_select_cert_args_.push_back(
- SelectCertArgs(server_address, client_address, hostname, client_hello,
- alpn, quic_transport_params, early_data_context));
+ all_select_cert_args_.push_back(SelectCertArgs(
+ server_address, client_address, ssl_capabilities, hostname, client_hello,
+ alpn, alps, quic_transport_params, early_data_context));
if (select_cert_action_ == Action::DELEGATE_ASYNC ||
select_cert_action_ == Action::FAIL_ASYNC) {
@@ -86,8 +88,9 @@ QuicAsyncStatus FakeProofSourceHandle::SelectCertificate(
all_select_cert_args_.back());
return QUIC_PENDING;
} else if (select_cert_action_ == Action::FAIL_SYNC) {
- callback()->OnSelectCertificateDone(/*ok=*/false,
- /*is_sync=*/true, nullptr);
+ callback()->OnSelectCertificateDone(
+ /*ok=*/false,
+ /*is_sync=*/true, nullptr, /*handshake_hints=*/absl::string_view());
return QUIC_FAILURE;
}
@@ -96,7 +99,8 @@ QuicAsyncStatus FakeProofSourceHandle::SelectCertificate(
delegate_->GetCertChain(server_address, client_address, hostname);
bool ok = chain && !chain->certs.empty();
- callback_->OnSelectCertificateDone(ok, /*is_sync=*/true, chain.get());
+ callback_->OnSelectCertificateDone(ok, /*is_sync=*/true, chain.get(),
+ /*handshake_hints=*/absl::string_view());
return ok ? QUIC_SUCCESS : QUIC_FAILURE;
}
@@ -168,13 +172,15 @@ FakeProofSourceHandle::SelectCertOperation::SelectCertOperation(
void FakeProofSourceHandle::SelectCertOperation::Run() {
if (action_ == Action::FAIL_ASYNC) {
callback_->OnSelectCertificateDone(/*ok=*/false,
- /*is_sync=*/false, nullptr);
+ /*is_sync=*/false, nullptr,
+ /*handshake_hints=*/absl::string_view());
} else if (action_ == Action::DELEGATE_ASYNC) {
QuicReferenceCountedPointer<ProofSource::Chain> chain =
delegate_->GetCertChain(args_.server_address, args_.client_address,
args_.hostname);
bool ok = chain && !chain->certs.empty();
- callback_->OnSelectCertificateDone(ok, /*is_sync=*/false, chain.get());
+ callback_->OnSelectCertificateDone(ok, /*is_sync=*/false, chain.get(),
+ /*handshake_hints=*/absl::string_view());
} else {
QUIC_BUG(quic_bug_10139_1)
<< "Unexpected action: " << static_cast<int>(action_);
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source_handle.h b/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source_handle.h
index 9c05ba4fa66..d2b991896f8 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source_handle.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source_handle.h
@@ -40,9 +40,11 @@ class FakeProofSourceHandle : public ProofSourceHandle {
QuicAsyncStatus SelectCertificate(
const QuicSocketAddress& server_address,
const QuicSocketAddress& client_address,
+ absl::string_view ssl_capabilities,
const std::string& hostname,
absl::string_view client_hello,
const std::string& alpn,
+ absl::optional<std::string> alps,
const std::vector<uint8_t>& quic_transport_params,
const absl::optional<std::vector<uint8_t>>& early_data_context) override;
@@ -62,24 +64,30 @@ class FakeProofSourceHandle : public ProofSourceHandle {
struct SelectCertArgs {
SelectCertArgs(QuicSocketAddress server_address,
QuicSocketAddress client_address,
+ absl::string_view ssl_capabilities,
std::string hostname,
absl::string_view client_hello,
std::string alpn,
+ absl::optional<std::string> alps,
std::vector<uint8_t> quic_transport_params,
absl::optional<std::vector<uint8_t>> early_data_context)
: server_address(server_address),
client_address(client_address),
+ ssl_capabilities(ssl_capabilities),
hostname(hostname),
client_hello(client_hello),
alpn(alpn),
+ alps(alps),
quic_transport_params(quic_transport_params),
early_data_context(early_data_context) {}
QuicSocketAddress server_address;
QuicSocketAddress client_address;
+ std::string ssl_capabilities;
std::string hostname;
std::string client_hello;
std::string alpn;
+ absl::optional<std::string> alps;
std::vector<uint8_t> quic_transport_params;
absl::optional<std::vector<uint8_t>> early_data_context;
};
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/mock_random.cc b/chromium/net/third_party/quiche/src/quic/test_tools/mock_random.cc
index c50c75cf432..a789cdf083b 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/mock_random.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/mock_random.cc
@@ -33,5 +33,10 @@ void MockRandom::ChangeValue() {
increment_++;
}
+void MockRandom::ResetBase(uint32_t base) {
+ base_ = base;
+ increment_ = 0;
+}
+
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/mock_random.h b/chromium/net/third_party/quiche/src/quic/test_tools/mock_random.h
index 63d438d457e..8dba8601f37 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/mock_random.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/mock_random.h
@@ -33,6 +33,9 @@ class MockRandom : public QuicRandom {
// |RandUint64| and the byte that |RandBytes| fills with, to change.
void ChangeValue();
+ // Sets the base to |base| and resets increment to zero.
+ void ResetBase(uint32_t base);
+
private:
uint32_t base_;
uint8_t increment_;
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_peer.cc
index b51684fed04..cc5f010c0e1 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_peer.cc
@@ -10,7 +10,7 @@ namespace quic {
namespace test {
// static
-QpackHeaderTable* QpackEncoderPeer::header_table(QpackEncoder* encoder) {
+QpackEncoderHeaderTable* QpackEncoderPeer::header_table(QpackEncoder* encoder) {
return &encoder->header_table_;
}
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_peer.h
index a824276bc4c..94a308af980 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_peer.h
@@ -10,7 +10,7 @@
namespace quic {
class QpackEncoder;
-class QpackHeaderTable;
+class QpackEncoderHeaderTable;
namespace test {
@@ -18,7 +18,7 @@ class QpackEncoderPeer {
public:
QpackEncoderPeer() = delete;
- static QpackHeaderTable* header_table(QpackEncoder* encoder);
+ static QpackEncoderHeaderTable* header_table(QpackEncoder* encoder);
static uint64_t maximum_blocked_streams(const QpackEncoder* encoder);
static uint64_t smallest_blocking_index(const QpackEncoder* encoder);
};
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_header_table_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_header_table_peer.cc
deleted file mode 100644
index 4dbf09617ed..00000000000
--- a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_header_table_peer.cc
+++ /dev/null
@@ -1,25 +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.
-
-#include "quic/test_tools/qpack/qpack_header_table_peer.h"
-
-#include "quic/core/qpack/qpack_header_table.h"
-
-namespace quic {
-namespace test {
-
-// static
-uint64_t QpackHeaderTablePeer::dynamic_table_capacity(
- const QpackHeaderTable* header_table) {
- return header_table->dynamic_table_capacity_;
-}
-
-// static
-uint64_t QpackHeaderTablePeer::maximum_dynamic_table_capacity(
- const QpackHeaderTable* header_table) {
- return header_table->maximum_dynamic_table_capacity_;
-}
-
-} // namespace test
-} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_header_table_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_header_table_peer.h
deleted file mode 100644
index 19e8d0d64e3..00000000000
--- a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_header_table_peer.h
+++ /dev/null
@@ -1,29 +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_TEST_TOOLS_QPACK_QPACK_HEADER_TABLE_PEER_H_
-#define QUICHE_QUIC_TEST_TOOLS_QPACK_QPACK_HEADER_TABLE_PEER_H_
-
-#include <cstdint>
-
-namespace quic {
-
-class QpackHeaderTable;
-
-namespace test {
-
-class QpackHeaderTablePeer {
- public:
- QpackHeaderTablePeer() = delete;
-
- static uint64_t dynamic_table_capacity(const QpackHeaderTable* header_table);
- static uint64_t maximum_dynamic_table_capacity(
- const QpackHeaderTable* header_table);
-};
-
-} // namespace test
-
-} // namespace quic
-
-#endif // QUICHE_QUIC_TEST_TOOLS_QPACK_QPACK_HEADER_TABLE_PEER_H_
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 6bad8d6ff65..0f681fef83a 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
@@ -38,7 +38,6 @@
#include "quic/platform/api/quic_file_utils.h"
#include "quic/platform/api/quic_logging.h"
#include "quic/test_tools/qpack/qpack_test_utils.h"
-#include "common/platform/api/quiche_text_utils.h"
#include "common/quiche_endian.h"
namespace quic {
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 3f1eaeb16bd..71036cb2512 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
@@ -398,7 +398,11 @@ QuicIdleNetworkDetector& QuicConnectionPeer::GetIdleNetworkDetector(
void QuicConnectionPeer::SetServerConnectionId(
QuicConnection* connection,
const QuicConnectionId& server_connection_id) {
- connection->server_connection_id_ = server_connection_id;
+ if (connection->use_connection_id_on_default_path_) {
+ connection->default_path_.server_connection_id = server_connection_id;
+ } else {
+ connection->server_connection_id_ = server_connection_id;
+ }
connection->InstallInitialCrypters(server_connection_id);
}
@@ -448,6 +452,18 @@ QuicByteCount QuicConnectionPeer::BytesReceivedOnAlternativePath(
}
// static
+QuicConnectionId QuicConnectionPeer::GetClientConnectionIdOnAlternativePath(
+ const QuicConnection* connection) {
+ return connection->alternative_path_.client_connection_id;
+}
+
+// static
+QuicConnectionId QuicConnectionPeer::GetServerConnectionIdOnAlternativePath(
+ const QuicConnection* connection) {
+ return connection->alternative_path_.server_connection_id;
+}
+
+// static
bool QuicConnectionPeer::IsAlternativePathValidated(
QuicConnection* connection) {
return connection->alternative_path_.validated;
@@ -478,5 +494,36 @@ void QuicConnectionPeer::ResetPeerIssuedConnectionIdManager(
QuicConnection* connection) {
connection->peer_issued_cid_manager_ = nullptr;
}
+
+// static
+QuicConnection::PathState* QuicConnectionPeer::GetDefaultPath(
+ QuicConnection* connection) {
+ return &connection->default_path_;
+}
+
+// static
+QuicConnection::PathState* QuicConnectionPeer::GetAlternativePath(
+ QuicConnection* connection) {
+ return &connection->alternative_path_;
+}
+
+// static
+void QuicConnectionPeer::RetirePeerIssuedConnectionIdsNoLongerOnPath(
+ QuicConnection* connection) {
+ connection->RetirePeerIssuedConnectionIdsNoLongerOnPath();
+}
+
+// static
+bool QuicConnectionPeer::HasUnusedPeerIssuedConnectionId(
+ const QuicConnection* connection) {
+ return connection->peer_issued_cid_manager_->HasUnusedConnectionId();
+}
+
+// static
+bool QuicConnectionPeer::HasSelfIssuedConnectionIdToConsume(
+ const QuicConnection* connection) {
+ return connection->self_issued_cid_manager_->HasConnectionIdToConsume();
+}
+
} // 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 1de3ae72f0b..cbc829a7a65 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
@@ -182,6 +182,12 @@ class QuicConnectionPeer {
static QuicByteCount BytesReceivedOnAlternativePath(
QuicConnection* connection);
+ static QuicConnectionId GetClientConnectionIdOnAlternativePath(
+ const QuicConnection* connection);
+
+ static QuicConnectionId GetServerConnectionIdOnAlternativePath(
+ const QuicConnection* connection);
+
static bool IsAlternativePath(QuicConnection* connection,
const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address);
@@ -194,6 +200,19 @@ class QuicConnectionPeer {
static void EnableMultipleConnectionIdSupport(QuicConnection* connection);
static void ResetPeerIssuedConnectionIdManager(QuicConnection* connection);
+
+ static QuicConnection::PathState* GetDefaultPath(QuicConnection* connection);
+
+ static QuicConnection::PathState* GetAlternativePath(
+ QuicConnection* connection);
+
+ static void RetirePeerIssuedConnectionIdsNoLongerOnPath(
+ QuicConnection* connection);
+
+ static bool HasUnusedPeerIssuedConnectionId(const QuicConnection* connection);
+
+ static bool HasSelfIssuedConnectionIdToConsume(
+ const QuicConnection* connection);
};
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_dispatcher_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_dispatcher_peer.cc
index 3a553ce0838..8002170ad90 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_dispatcher_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_dispatcher_peer.cc
@@ -117,31 +117,20 @@ std::string QuicDispatcherPeer::SelectAlpn(
// static
QuicSession* QuicDispatcherPeer::GetFirstSessionIfAny(
QuicDispatcher* dispatcher) {
- if (dispatcher->use_reference_counted_session_map()) {
- if (dispatcher->reference_counted_session_map_.empty()) {
- return nullptr;
- }
- return dispatcher->reference_counted_session_map_.begin()->second.get();
- } else {
- if (dispatcher->session_map_.empty()) {
- return nullptr;
- }
- return dispatcher->session_map_.begin()->second.get();
+ if (dispatcher->reference_counted_session_map_.empty()) {
+ return nullptr;
}
+ return dispatcher->reference_counted_session_map_.begin()->second.get();
}
// static
const QuicSession* QuicDispatcherPeer::FindSession(
const QuicDispatcher* dispatcher,
QuicConnectionId id) {
- if (dispatcher->use_reference_counted_session_map()) {
- auto it = dispatcher->reference_counted_session_map_.find(id);
- return (it == dispatcher->reference_counted_session_map_.end())
- ? nullptr
- : it->second.get();
- }
- auto it = dispatcher->session_map_.find(id);
- return (it == dispatcher->session_map_.end()) ? nullptr : it->second.get();
+ auto it = dispatcher->reference_counted_session_map_.find(id);
+ return (it == dispatcher->reference_counted_session_map_.end())
+ ? nullptr
+ : it->second.get();
}
} // namespace test
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 0caf2635be7..d638959f88b 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
@@ -156,5 +156,11 @@ QuicFrames& QuicPacketCreatorPeer::QueuedFrames(QuicPacketCreator* creator) {
return creator->queued_frames_;
}
+// static
+void QuicPacketCreatorPeer::SetRandom(QuicPacketCreator* creator,
+ QuicRandom* random) {
+ creator->random_ = random;
+}
+
} // 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 12f00867244..259191d214b 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
@@ -10,6 +10,7 @@
namespace quic {
class QuicFramer;
class QuicPacketCreator;
+class QuicRandom;
namespace test {
@@ -61,6 +62,7 @@ class QuicPacketCreatorPeer {
static QuicFramer* framer(QuicPacketCreator* creator);
static std::string GetRetryToken(QuicPacketCreator* creator);
static QuicFrames& QueuedFrames(QuicPacketCreator* creator);
+ static void SetRandom(QuicPacketCreator* creator, QuicRandom* random);
};
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_backend.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_backend.cc
index 9623d752027..eb419b607f5 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_backend.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_backend.cc
@@ -9,7 +9,6 @@
#include "absl/strings/string_view.h"
#include "quic/core/quic_buffer_allocator.h"
-#include "quic/core/quic_circular_deque.h"
#include "quic/core/quic_simple_buffer_allocator.h"
#include "quic/core/web_transport_interface.h"
#include "quic/platform/api/quic_mem_slice.h"
@@ -18,95 +17,6 @@
namespace quic {
namespace test {
-namespace {
-
-class EchoWebTransportServer : public WebTransportVisitor {
- public:
- EchoWebTransportServer(WebTransportSession* session) : session_(session) {}
-
- void OnSessionReady() override {
- if (session_->CanOpenNextOutgoingBidirectionalStream()) {
- OnCanCreateNewOutgoingBidirectionalStream();
- }
- }
-
- void OnIncomingBidirectionalStreamAvailable() override {
- while (true) {
- WebTransportStream* stream =
- session_->AcceptIncomingBidirectionalStream();
- if (stream == nullptr) {
- return;
- }
- QUIC_DVLOG(1) << "EchoWebTransportServer received a bidirectional stream "
- << stream->GetStreamId();
- stream->SetVisitor(
- std::make_unique<WebTransportBidirectionalEchoVisitor>(stream));
- stream->visitor()->OnCanRead();
- }
- }
-
- void OnIncomingUnidirectionalStreamAvailable() override {
- while (true) {
- WebTransportStream* stream =
- session_->AcceptIncomingUnidirectionalStream();
- if (stream == nullptr) {
- return;
- }
- QUIC_DVLOG(1)
- << "EchoWebTransportServer received a unidirectional stream";
- stream->SetVisitor(
- std::make_unique<WebTransportUnidirectionalEchoReadVisitor>(
- stream, [this](const std::string& data) {
- streams_to_echo_back_.push_back(data);
- TrySendingUnidirectionalStreams();
- }));
- stream->visitor()->OnCanRead();
- }
- }
-
- void OnDatagramReceived(absl::string_view datagram) override {
- auto buffer = MakeUniqueBuffer(&allocator_, datagram.size());
- memcpy(buffer.get(), datagram.data(), datagram.size());
- QuicMemSlice slice(std::move(buffer), datagram.size());
- session_->SendOrQueueDatagram(std::move(slice));
- }
-
- void OnCanCreateNewOutgoingBidirectionalStream() override {
- if (!echo_stream_opened_) {
- WebTransportStream* stream = session_->OpenOutgoingBidirectionalStream();
- stream->SetVisitor(
- std::make_unique<WebTransportBidirectionalEchoVisitor>(stream));
- echo_stream_opened_ = true;
- }
- }
- void OnCanCreateNewOutgoingUnidirectionalStream() override {
- TrySendingUnidirectionalStreams();
- }
-
- void TrySendingUnidirectionalStreams() {
- while (!streams_to_echo_back_.empty() &&
- session_->CanOpenNextOutgoingUnidirectionalStream()) {
- QUIC_DVLOG(1)
- << "EchoWebTransportServer echoed a unidirectional stream back";
- WebTransportStream* stream = session_->OpenOutgoingUnidirectionalStream();
- stream->SetVisitor(
- std::make_unique<WebTransportUnidirectionalEchoWriteVisitor>(
- stream, streams_to_echo_back_.front()));
- streams_to_echo_back_.pop_front();
- stream->visitor()->OnCanWrite();
- }
- }
-
- private:
- WebTransportSession* session_;
- SimpleBufferAllocator allocator_;
- bool echo_stream_opened_ = false;
-
- QuicCircularDeque<std::string> streams_to_echo_back_;
-};
-
-} // namespace
-
QuicSimpleServerBackend::WebTransportResponse
QuicTestBackend::ProcessWebTransportRequest(
const spdy::Http2HeaderBlock& request_headers,
@@ -126,7 +36,8 @@ QuicTestBackend::ProcessWebTransportRequest(
if (path == "/echo") {
WebTransportResponse response;
response.response_headers[":status"] = "200";
- response.visitor = std::make_unique<EchoWebTransportServer>(session);
+ response.visitor =
+ std::make_unique<EchoWebTransportSessionVisitor>(session);
return response;
}
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 ed823b1e156..7cc3ff9be3b 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
@@ -28,7 +28,7 @@
#include "quic/test_tools/quic_spdy_stream_peer.h"
#include "quic/test_tools/quic_test_utils.h"
#include "quic/tools/quic_url.h"
-#include "common/platform/api/quiche_text_utils.h"
+#include "common/quiche_text_utils.h"
namespace quic {
namespace test {
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 2f16b1e072b..9fbffe0b76c 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
@@ -929,10 +929,6 @@ class MockQuicSession : public QuicSession {
(override));
MOCK_METHOD(bool, ShouldKeepConnectionAlive, (), (const, override));
- MOCK_METHOD(void,
- SendStopSending,
- (QuicRstStreamErrorCode code, QuicStreamId stream_id),
- (override));
MOCK_METHOD(std::vector<std::string>, GetAlpnsToOffer, (), (const, override));
MOCK_METHOD(std::vector<absl::string_view>::const_iterator,
SelectAlpn,
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_time_wait_list_manager_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_time_wait_list_manager_peer.cc
index 9d60443deb2..8f614e8d89d 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_time_wait_list_manager_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_time_wait_list_manager_peer.cc
@@ -28,5 +28,13 @@ void QuicTimeWaitListManagerPeer::set_clock(QuicTimeWaitListManager* manager,
manager->clock_ = clock;
}
+// static
+bool QuicTimeWaitListManagerPeer::SendOrQueuePacket(
+ QuicTimeWaitListManager* manager,
+ std::unique_ptr<QuicTimeWaitListManager::QueuedPacket> packet,
+ const QuicPerPacketContext* packet_context) {
+ return manager->SendOrQueuePacket(std::move(packet), packet_context);
+}
+
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_time_wait_list_manager_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_time_wait_list_manager_peer.h
index 54fd6dd1768..4e0a4a707ad 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_time_wait_list_manager_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_time_wait_list_manager_peer.h
@@ -21,6 +21,11 @@ class QuicTimeWaitListManagerPeer {
static void set_clock(QuicTimeWaitListManager* manager,
const QuicClock* clock);
+
+ static bool SendOrQueuePacket(
+ QuicTimeWaitListManager* manager,
+ std::unique_ptr<QuicTimeWaitListManager::QueuedPacket> packet,
+ const QuicPerPacketContext* packet_context);
};
} // namespace test
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 f5c9b7e0725..f931567793e 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
@@ -126,7 +126,7 @@ void ServerThread::MaybeNotifyOfHandshakeConfirmation() {
}
void ServerThread::ExecuteScheduledActions() {
- QuicCircularDeque<std::function<void()>> actions;
+ quiche::QuicheCircularDeque<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 fa604a8bf77..81d0bf2a5f5 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
@@ -86,7 +86,7 @@ class ServerThread : public QuicThread {
bool initialized_;
QuicMutex scheduled_actions_lock_;
- QuicCircularDeque<std::function<void()>> scheduled_actions_
+ quiche::QuicheCircularDeque<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.h b/chromium/net/third_party/quiche/src/quic/test_tools/simple_data_producer.h
index 82021e1e1a1..8111c1cc09f 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
@@ -49,23 +49,13 @@ class SimpleDataProducer : public QuicStreamFrameDataProducer {
QuicByteCount data_length,
QuicDataWriter* writer) override;
- // TODO(wub): Allow QuicDefaultHasher to accept a pair. Then remove this.
- class PairHash {
- public:
- template <class T1, class T2>
- size_t operator()(const std::pair<T1, T2>& pair) const {
- return std::hash<T1>()(pair.first) ^ std::hash<T2>()(pair.second);
- }
- };
-
private:
using SendBufferMap =
absl::flat_hash_map<QuicStreamId, std::unique_ptr<QuicStreamSendBuffer>>;
using CryptoBufferMap =
absl::flat_hash_map<std::pair<EncryptionLevel, QuicStreamOffset>,
- absl::string_view,
- PairHash>;
+ absl::string_view>;
SimpleBufferAllocator allocator_;
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 2219c27d1a4..bc76ddc877a 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
@@ -6,10 +6,10 @@
#define QUICHE_QUIC_TEST_TOOLS_SIMPLE_SESSION_NOTIFIER_H_
#include "absl/container/flat_hash_map.h"
-#include "quic/core/quic_circular_deque.h"
#include "quic/core/quic_interval_set.h"
#include "quic/core/session_notifier_interface.h"
#include "quic/platform/api/quic_test.h"
+#include "common/quiche_circular_deque.h"
namespace quic {
@@ -132,7 +132,7 @@ class SimpleSessionNotifier : public SessionNotifierInterface {
bool StreamHasBufferedData(QuicStreamId id) const;
- QuicCircularDeque<QuicFrame> control_frames_;
+ quiche::QuicheCircularDeque<QuicFrame> control_frames_;
QuicLinkedHashMap<QuicControlFrameId, bool> lost_control_frames_;
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 7d2f92dfdc4..5d723859e0c 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,9 +9,9 @@
#include "quic/core/crypto/quic_random.h"
#include "quic/core/quic_bandwidth.h"
-#include "quic/core/quic_circular_deque.h"
#include "quic/test_tools/simulator/actor.h"
#include "quic/test_tools/simulator/port.h"
+#include "common/quiche_circular_deque.h"
namespace quic {
namespace simulator {
@@ -61,7 +61,7 @@ class OneWayLink : public Actor, public ConstrainedPortInterface {
void ScheduleNextPacketDeparture();
UnconstrainedPortInterface* sink_;
- QuicCircularDeque<QueuedPacket> packets_in_transit_;
+ quiche::QuicheCircularDeque<QueuedPacket> packets_in_transit_;
QuicBandwidth bandwidth_;
const QuicTime::Delta propagation_delay_;
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/queue.h b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/queue.h
index 943b8b069a0..7e4be833690 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/queue.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/queue.h
@@ -6,8 +6,8 @@
#define QUICHE_QUIC_TEST_TOOLS_SIMULATOR_QUEUE_H_
#include "quic/core/quic_alarm.h"
-#include "quic/core/quic_circular_deque.h"
#include "quic/test_tools/simulator/link.h"
+#include "common/quiche_circular_deque.h"
namespace quic {
namespace simulator {
@@ -110,7 +110,7 @@ class Queue : public Actor, public UnconstrainedPortInterface {
std::unique_ptr<QuicAlarm> aggregation_timeout_alarm_;
ConstrainedPortInterface* tx_port_;
- QuicCircularDeque<EnqueuedPacket> queue_;
+ quiche::QuicheCircularDeque<EnqueuedPacket> queue_;
ListenerInterface* listener_;
};
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 bd4e7b619d7..eebb47cba03 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
@@ -78,7 +78,7 @@ class Switch {
void DispatchPacket(SwitchPortNumber port_number,
std::unique_ptr<Packet> packet);
- // This can not be a QuicCircularDeque since pointers into this are
+ // This cannot be a quiche::QuicheCircularDeque since pointers into this are
// assumed to be stable.
std::deque<Port> ports_;
absl::flat_hash_map<std::string, Port*> switching_table_;
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 1c5cad87112..64d7ade08f8 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
@@ -17,6 +17,7 @@ class QuicBackendResponse {
public:
// A ServerPushInfo contains path of the push request and everything needed in
// comprising a response for the push request.
+ // TODO(b/171463363): Remove.
struct ServerPushInfo {
ServerPushInfo(QuicUrl request_url,
spdy::Http2HeaderBlock headers,
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 7077f16506e..53c6800a2e5 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
@@ -64,6 +64,7 @@ class QuicClientSocketMigrationValidationResultDelegate
std::unique_ptr<QuicPathValidationContext> context) override {
QUIC_LOG(WARNING) << "Fail to validate path " << *context
<< ", stop migrating.";
+ client_->session()->connection()->OnPathValidationFailureAtClient();
}
private:
@@ -257,6 +258,8 @@ bool QuicClientBase::MigrateSocketWithSpecifiedPort(
const QuicIpAddress& new_host,
int port) {
if (!connected()) {
+ QUICHE_DVLOG(1)
+ << "MigrateSocketWithSpecifiedPort failed as connection has closed";
return false;
}
@@ -264,11 +267,17 @@ bool QuicClientBase::MigrateSocketWithSpecifiedPort(
std::unique_ptr<QuicPacketWriter> writer =
CreateWriterForNewNetwork(new_host, port);
if (writer == nullptr) {
+ QUICHE_DVLOG(1)
+ << "MigrateSocketWithSpecifiedPort failed from writer creation";
+ return false;
+ }
+ if (!session()->MigratePath(network_helper_->GetLatestClientAddress(),
+ session()->connection()->peer_address(),
+ writer.get(), false)) {
+ QUICHE_DVLOG(1)
+ << "MigrateSocketWithSpecifiedPort failed from session()->MigratePath";
return false;
}
- session()->MigratePath(network_helper_->GetLatestClientAddress(),
- session()->connection()->peer_address(), writer.get(),
- false);
set_writer(writer.release());
return true;
}
@@ -465,6 +474,7 @@ class ValidationResultDelegate : public QuicPathValidator::ResultDelegate {
std::unique_ptr<QuicPathValidationContext> context) override {
QUIC_LOG(WARNING) << "Fail to validate path " << *context
<< ", stop migrating.";
+ client_->session()->connection()->OnPathValidationFailureAtClient();
}
private:
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 2049f15f217..9dcc2b35213 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
@@ -74,8 +74,25 @@ bool QuicClientEpollNetworkHelper::CreateUDPSocketAndBind(
client_address = QuicSocketAddress(QuicIpAddress::Any6(), bind_to_port);
}
+ // Some platforms expect that the addrlen given to bind() exactly matches the
+ // size of the associated protocol family's sockaddr struct.
+ // TODO(b/179430548): Revert this when affected platforms are updated to
+ // to support binding with an addrelen of sizeof(sockaddr_storage)
+ socklen_t addrlen;
+ switch (client_address.host().address_family()) {
+ case IpAddressFamily::IP_V4:
+ addrlen = sizeof(sockaddr_in);
+ break;
+ case IpAddressFamily::IP_V6:
+ addrlen = sizeof(sockaddr_in6);
+ break;
+ case IpAddressFamily::IP_UNSPEC:
+ addrlen = 0;
+ break;
+ }
+
sockaddr_storage addr = client_address.generic_address();
- int rc = bind(fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
+ int rc = bind(fd, reinterpret_cast<sockaddr*>(&addr), addrlen);
if (rc < 0) {
QUIC_LOG(ERROR) << "Bind failed: " << strerror(errno)
<< " bind_to_address:" << bind_to_address
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 160f2553142..d932a7b533a 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
@@ -18,7 +18,7 @@
#include "quic/platform/api/quic_test_loopback.h"
#include "quic/test_tools/crypto_test_utils.h"
#include "quic/test_tools/quic_client_peer.h"
-#include "common/platform/api/quiche_text_utils.h"
+#include "common/quiche_text_utils.h"
namespace quic {
namespace test {
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 84830382f48..1fff089445b 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
@@ -24,7 +24,8 @@ std::unique_ptr<QuicSpdyClientBase> QuicEpollClientFactory::CreateClient(
uint16_t port,
ParsedQuicVersionVector versions,
const QuicConfig& config,
- std::unique_ptr<ProofVerifier> verifier) {
+ std::unique_ptr<ProofVerifier> verifier,
+ std::unique_ptr<SessionCache> session_cache) {
QuicSocketAddress addr = tools::LookupAddress(
address_family_for_lookup, host_for_lookup, absl::StrCat(port));
if (!addr.IsInitialized()) {
@@ -34,7 +35,7 @@ std::unique_ptr<QuicSpdyClientBase> QuicEpollClientFactory::CreateClient(
QuicServerId server_id(host_for_handshake, port, false);
return std::make_unique<QuicClient>(addr, server_id, versions, config,
&epoll_server_, std::move(verifier),
- nullptr);
+ std::move(session_cache));
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_epoll_client_factory.h b/chromium/net/third_party/quiche/src/quic/tools/quic_epoll_client_factory.h
index e23eb634ea8..9e78b473619 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_epoll_client_factory.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_epoll_client_factory.h
@@ -20,7 +20,8 @@ class QuicEpollClientFactory : public QuicToyClient::ClientFactory {
uint16_t port,
ParsedQuicVersionVector versions,
const QuicConfig& config,
- std::unique_ptr<ProofVerifier> verifier) override;
+ std::unique_ptr<ProofVerifier> verifier,
+ std::unique_ptr<SessionCache> session_cache) override;
private:
QuicEpollServer epoll_server_;
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 e76a6cffb3c..de2064831f4 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
@@ -15,7 +15,8 @@
#include "quic/platform/api/quic_file_utils.h"
#include "quic/platform/api/quic_logging.h"
#include "quic/platform/api/quic_map_util.h"
-#include "common/platform/api/quiche_text_utils.h"
+#include "quic/tools/web_transport_test_visitors.h"
+#include "common/quiche_text_utils.h"
using spdy::Http2HeaderBlock;
using spdy::kV3LowestPriority;
@@ -313,6 +314,10 @@ void QuicMemoryCacheBackend::GenerateDynamicResponses() {
QuicBackendResponse::GENERATE_BYTES);
}
+void QuicMemoryCacheBackend::EnableWebTransport() {
+ enable_webtransport_ = true;
+}
+
bool QuicMemoryCacheBackend::IsBackendInitialized() const {
return cache_initialized_;
}
@@ -336,11 +341,10 @@ void QuicMemoryCacheBackend::FetchResponseFromBackend(
if (path != request_headers.end()) {
request_url += std::string(path->second);
}
- std::list<ServerPushInfo> resources = GetServerPushResources(request_url);
QUIC_DVLOG(1)
<< "Fetching QUIC response from backend in-memory cache for url "
<< request_url;
- quic_stream->OnResponseBackendComplete(quic_response, resources);
+ quic_stream->OnResponseBackendComplete(quic_response);
}
// The memory cache does not have a per-stream handler
@@ -361,6 +365,35 @@ std::list<ServerPushInfo> QuicMemoryCacheBackend::GetServerPushResources(
return resources;
}
+QuicMemoryCacheBackend::WebTransportResponse
+QuicMemoryCacheBackend::ProcessWebTransportRequest(
+ const spdy::Http2HeaderBlock& request_headers,
+ WebTransportSession* session) {
+ if (!SupportsWebTransport()) {
+ return QuicSimpleServerBackend::ProcessWebTransportRequest(request_headers,
+ session);
+ }
+
+ auto path_it = request_headers.find(":path");
+ if (path_it == request_headers.end()) {
+ WebTransportResponse response;
+ response.response_headers[":status"] = "400";
+ return response;
+ }
+ absl::string_view path = path_it->second;
+ if (path == "/echo") {
+ WebTransportResponse response;
+ response.response_headers[":status"] = "200";
+ response.visitor =
+ std::make_unique<EchoWebTransportSessionVisitor>(session);
+ return response;
+ }
+
+ WebTransportResponse response;
+ response.response_headers[":status"] = "404";
+ return response;
+}
+
QuicMemoryCacheBackend::~QuicMemoryCacheBackend() {
{
QuicWriterMutexLock lock(&response_mutex_);
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 8ba6d605218..b8d28103ced 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
@@ -90,6 +90,7 @@ class QuicMemoryCacheBackend : public QuicSimpleServerBackend {
// some server push resources(resource path, corresponding response status and
// path) associated with it.
// Push resource implicitly come from the same host.
+ // TODO(b/171463363): Remove.
void AddSimpleResponseWithServerPushResources(
absl::string_view host,
absl::string_view path,
@@ -139,7 +140,10 @@ class QuicMemoryCacheBackend : public QuicSimpleServerBackend {
// generated response of that many bytes.
void GenerateDynamicResponses();
+ void EnableWebTransport();
+
// Find all the server push resources associated with |request_url|.
+ // TODO(b/171463363): Remove.
std::list<QuicBackendResponse::ServerPushInfo> GetServerPushResources(
std::string request_url);
@@ -153,6 +157,10 @@ class QuicMemoryCacheBackend : public QuicSimpleServerBackend {
QuicSimpleServerBackend::RequestHandler* quic_server_stream) override;
void CloseBackendResponseStream(
QuicSimpleServerBackend::RequestHandler* quic_server_stream) override;
+ WebTransportResponse ProcessWebTransportRequest(
+ const spdy::Http2HeaderBlock& request_headers,
+ WebTransportSession* session) override;
+ bool SupportsWebTransport() override { return enable_webtransport_; }
private:
void AddResponseImpl(absl::string_view host,
@@ -167,6 +175,7 @@ class QuicMemoryCacheBackend : public QuicSimpleServerBackend {
// Add some server push urls with given responses for specified
// request if these push resources are not associated with this request yet.
+ // TODO(b/171463363): Remove.
void MaybeAddServerPushResources(
absl::string_view request_host,
absl::string_view request_path,
@@ -174,6 +183,7 @@ class QuicMemoryCacheBackend : public QuicSimpleServerBackend {
// Check if push resource(push_host/push_path) associated with given request
// url already exists in server push map.
+ // TODO(b/171463363): Remove.
bool PushResourceExistsInCache(std::string original_request_url,
QuicBackendResponse::ServerPushInfo resource);
@@ -190,6 +200,7 @@ class QuicMemoryCacheBackend : public QuicSimpleServerBackend {
QUIC_GUARDED_BY(response_mutex_);
// A map from request URL to associated server push responses (if any).
+ // TODO(b/171463363): Remove.
std::multimap<std::string, QuicBackendResponse::ServerPushInfo>
server_push_resources_ QUIC_GUARDED_BY(response_mutex_);
@@ -197,6 +208,8 @@ class QuicMemoryCacheBackend : public QuicSimpleServerBackend {
// server threads accessing those responses.
mutable QuicMutex response_mutex_;
bool cache_initialized_;
+
+ bool enable_webtransport_ = false;
};
} // namespace quic
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 97ca71e9c6f..ad357e9b43c 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
@@ -34,7 +34,7 @@
#include "quic/core/quic_types.h"
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_flags.h"
-#include "common/platform/api/quiche_text_utils.h"
+#include "common/quiche_text_utils.h"
DEFINE_QUIC_COMMAND_LINE_FLAG(std::string,
quic_version,
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 aecc8fe1fdf..68443f37d1a 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
@@ -11,7 +11,7 @@
#include "quic/core/crypto/crypto_handshake.h"
#include "quic/core/crypto/crypto_utils.h"
#include "quic/platform/api/quic_flags.h"
-#include "common/platform/api/quiche_text_utils.h"
+#include "common/quiche_text_utils.h"
using quic::CryptoUtils;
using quic::HandshakeFailureReason;
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_backend.h b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_backend.h
index 43ced4bcefb..6411567fc1a 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_backend.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_backend.h
@@ -32,8 +32,7 @@ class QuicSimpleServerBackend {
// Called when the response is ready at the backend and can be send back to
// the QUIC client.
virtual void OnResponseBackendComplete(
- const QuicBackendResponse* response,
- std::list<QuicBackendResponse::ServerPushInfo> resources) = 0;
+ const QuicBackendResponse* response) = 0;
};
struct WebTransportResponse {
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 4075d3ff417..688ca9ff24b 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
@@ -62,39 +62,6 @@ void QuicSimpleServerSession::OnStreamFrame(const QuicStreamFrame& frame) {
QuicSpdySession::OnStreamFrame(frame);
}
-void QuicSimpleServerSession::PromisePushResources(
- const std::string& request_url,
- const std::list<QuicBackendResponse::ServerPushInfo>& resources,
- QuicStreamId original_stream_id,
- const spdy::SpdyStreamPrecedence& /* original_precedence */,
- const spdy::Http2HeaderBlock& original_request_headers) {
- if (!server_push_enabled()) {
- return;
- }
-
- for (const QuicBackendResponse::ServerPushInfo& resource : resources) {
- spdy::Http2HeaderBlock headers = SynthesizePushRequestHeaders(
- request_url, resource, original_request_headers);
- // TODO(b/136295430): Use sequential push IDs for IETF QUIC.
- auto new_highest_promised_stream_id =
- highest_promised_stream_id_ +
- QuicUtils::StreamIdDelta(transport_version());
- if (VersionUsesHttp3(transport_version()) &&
- !CanCreatePushStreamWithId(new_highest_promised_stream_id)) {
- return;
- }
- highest_promised_stream_id_ = new_highest_promised_stream_id;
- SendPushPromise(original_stream_id, highest_promised_stream_id_,
- headers.Clone());
- promised_streams_.push_back(
- PromisedStreamInfo(std::move(headers), highest_promised_stream_id_,
- spdy::SpdyStreamPrecedence(resource.priority)));
- }
-
- // Procese promised push request as many as possible.
- HandlePromisedPushRequests();
-}
-
QuicSpdyStream* QuicSimpleServerSession::CreateIncomingStream(QuicStreamId id) {
if (!ShouldCreateIncomingStream(id)) {
return nullptr;
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 b91966da722..2cc3dcf524f 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
@@ -68,17 +68,6 @@ class QuicSimpleServerSession : public QuicServerSessionBase {
// Override base class to detact client sending data on server push stream.
void OnStreamFrame(const QuicStreamFrame& frame) override;
- // Send out PUSH_PROMISE for all |resources| promised stream id in each frame
- // will increase by 2 for each item in |resources|.
- // And enqueue HEADERS block in those PUSH_PROMISED for sending push response
- // later.
- virtual void PromisePushResources(
- const std::string& request_url,
- const std::list<QuicBackendResponse::ServerPushInfo>& resources,
- QuicStreamId original_stream_id,
- const spdy::SpdyStreamPrecedence& original_precedence,
- const spdy::Http2HeaderBlock& original_request_headers);
-
void OnCanCreateNewOutgoingStream(bool unidirectional) override;
protected:
@@ -155,7 +144,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_.
- QuicCircularDeque<PromisedStreamInfo> promised_streams_;
+ quiche::QuicheCircularDeque<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 62bbae949d5..d23ba5d53c4 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
@@ -9,7 +9,6 @@
#include <utility>
#include "absl/strings/str_cat.h"
-#include "absl/strings/string_view.h"
#include "quic/core/crypto/null_encrypter.h"
#include "quic/core/crypto/quic_crypto_server_config.h"
#include "quic/core/crypto/quic_random.h"
@@ -51,10 +50,11 @@ namespace quic {
namespace test {
namespace {
-using PromisedStreamInfo = QuicSimpleServerSession::PromisedStreamInfo;
-
-const QuicByteCount kHeadersFrameHeaderLength = 2;
-const QuicByteCount kHeadersFramePayloadLength = 9;
+// Data to be sent on a request stream. In Google QUIC, this is interpreted as
+// DATA payload (there is no framing on request streams). In IETF QUIC, this is
+// interpreted as HEADERS frame (type 0x1) with payload length 122 ('z'). Since
+// no payload is included, QPACK decoder will not be invoked.
+const char* const kStreamData = "\1z";
} // namespace
@@ -257,7 +257,7 @@ class QuicSimpleServerSessionTest
kMaxStreamsForTest);
}
- ParsedQuicVersionVector supported_versions = SupportedVersions(GetParam());
+ ParsedQuicVersionVector supported_versions = SupportedVersions(version());
connection_ = new StrictMock<MockQuicConnectionWithSendStreamData>(
&helper_, &alarm_factory_, Perspective::IS_SERVER, supported_versions);
connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
@@ -289,8 +289,10 @@ class QuicSimpleServerSessionTest
transport_version(), n);
}
+ ParsedQuicVersion version() const { return GetParam(); }
+
QuicTransportVersion transport_version() const {
- return GetParam().transport_version;
+ return version().transport_version;
}
void InjectStopSending(QuicStreamId stream_id,
@@ -330,10 +332,9 @@ INSTANTIATE_TEST_SUITE_P(Tests,
::testing::PrintToStringParamName());
TEST_P(QuicSimpleServerSessionTest, CloseStreamDueToReset) {
- // Open a stream, then reset it.
- // Send two bytes of payload to open it.
+ // Send some data open a stream, then reset it.
QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
- absl::string_view("HT"));
+ kStreamData);
session_->OnStreamFrame(data1);
EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
@@ -388,9 +389,8 @@ TEST_P(QuicSimpleServerSessionTest, NeverOpenStreamDueToReset) {
EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
- // Send two bytes of payload.
QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
- absl::string_view("HT"));
+ kStreamData);
session_->OnStreamFrame(data1);
// The stream should never be opened, now that the reset is received.
@@ -399,11 +399,11 @@ TEST_P(QuicSimpleServerSessionTest, NeverOpenStreamDueToReset) {
}
TEST_P(QuicSimpleServerSessionTest, AcceptClosedStream) {
- // Send (empty) compressed headers followed by two bytes of data.
+ // Send some data to open two streams.
QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
- absl::string_view("\1\0\0\0\0\0\0\0HT"));
+ kStreamData);
QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(1), false, 0,
- absl::string_view("\3\0\0\0\0\0\0\0HT"));
+ kStreamData);
session_->OnStreamFrame(frame1);
session_->OnStreamFrame(frame2);
EXPECT_EQ(2u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
@@ -431,9 +431,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,
- absl::string_view("TP"));
+ kStreamData);
QuicStreamFrame frame4(GetNthClientInitiatedBidirectionalId(1), false, 2,
- absl::string_view("TP"));
+ kStreamData);
session_->OnStreamFrame(frame3);
session_->OnStreamFrame(frame4);
// The stream should never be opened, now that the reset is received.
@@ -443,7 +443,7 @@ TEST_P(QuicSimpleServerSessionTest, AcceptClosedStream) {
TEST_P(QuicSimpleServerSessionTest, CreateIncomingStreamDisconnected) {
// EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
- if (GetParam() != AllSupportedVersions()[0]) {
+ if (version() != AllSupportedVersions()[0]) {
return;
}
@@ -467,7 +467,7 @@ TEST_P(QuicSimpleServerSessionTest, CreateIncomingStream) {
TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamDisconnected) {
// EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
- if (GetParam() != AllSupportedVersions()[0]) {
+ if (version() != AllSupportedVersions()[0]) {
return;
}
@@ -486,7 +486,7 @@ TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamDisconnected) {
TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamUnencrypted) {
// EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
- if (GetParam() != AllSupportedVersions()[0]) {
+ if (version() != AllSupportedVersions()[0]) {
return;
}
@@ -510,7 +510,7 @@ 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,
- absl::string_view("HT"));
+ kStreamData);
session_->OnStreamFrame(data1);
EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()) -
@@ -559,7 +559,7 @@ TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamUptoLimit) {
// Create peer initiated stream should have no problem.
QuicStreamFrame data2(GetNthClientInitiatedBidirectionalId(1), false, 0,
- absl::string_view("HT"));
+ kStreamData);
session_->OnStreamFrame(data2);
EXPECT_EQ(2u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()) -
/*outcoming=*/kMaxStreamsForTest);
@@ -567,7 +567,7 @@ TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamUptoLimit) {
TEST_P(QuicSimpleServerSessionTest, OnStreamFrameWithEvenStreamId) {
QuicStreamFrame frame(GetNthServerInitiatedUnidirectionalId(0), false, 0,
- absl::string_view());
+ kStreamData);
EXPECT_CALL(*connection_,
CloseConnection(QUIC_INVALID_STREAM_ID,
"Client sent data on server push stream", _));
@@ -591,451 +591,6 @@ TEST_P(QuicSimpleServerSessionTest, GetEvenIncomingError) {
QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
}
-// In order to test the case where server push stream creation goes beyond
-// limit, server push streams need to be hanging there instead of
-// immediately closing after sending back response.
-// To achieve this goal, this class resets flow control windows so that large
-// responses will not be sent fully in order to prevent push streams from being
-// closed immediately.
-// Also adjust connection-level flow control window to ensure a large response
-// can cause stream-level flow control blocked but not connection-level.
-class QuicSimpleServerSessionServerPushTest
- : public QuicSimpleServerSessionTest {
- protected:
- const size_t kStreamFlowControlWindowSize = 32 * 1024; // 32KB.
-
- QuicSimpleServerSessionServerPushTest() {
- // Reset stream level flow control window to be 32KB.
- if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
- if (VersionHasIetfQuicFrames(transport_version())) {
- QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesUnidirectional(
- &config_, kStreamFlowControlWindowSize);
- } else {
- // In this version, push streams are server-initiated bidirectional
- // streams, which are outgoing since we are the server here.
- QuicConfigPeer::
- SetReceivedInitialMaxStreamDataBytesOutgoingBidirectional(
- &config_, kStreamFlowControlWindowSize);
- }
- } else {
- QuicConfigPeer::SetReceivedInitialStreamFlowControlWindow(
- &config_, kStreamFlowControlWindowSize);
- }
- // Reset connection level flow control window to be 1.5 MB which is large
- // enough that it won't block any stream to write before stream level flow
- // control blocks it.
- QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(
- &config_, kInitialSessionFlowControlWindowForTest);
-
- ParsedQuicVersionVector supported_versions = SupportedVersions(GetParam());
- connection_ = new StrictMock<MockQuicConnectionWithSendStreamData>(
- &helper_, &alarm_factory_, Perspective::IS_SERVER, supported_versions);
- connection_->SetEncrypter(
- ENCRYPTION_FORWARD_SECURE,
- std::make_unique<NullEncrypter>(connection_->perspective()));
- session_ = std::make_unique<MockQuicSimpleServerSession>(
- config_, connection_, &owner_, &stream_helper_, &crypto_config_,
- &compressed_certs_cache_, &memory_cache_backend_);
- session_->Initialize();
- // Needed to make new session flow control window and server push work.
-
- if (VersionHasIetfQuicFrames(transport_version())) {
- EXPECT_CALL(*session_, WriteControlFrame(_, _))
- .WillRepeatedly(Invoke(&ClearControlFrameWithTransmissionType));
- }
- session_->OnConfigNegotiated();
-
- if (!VersionUsesHttp3(transport_version())) {
- session_->UnregisterStreamPriority(
- QuicUtils::GetHeadersStreamId(transport_version()),
- /*is_static=*/true);
- }
- QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), nullptr);
- // Assume encryption already established.
- QuicCryptoServerStreamBase* crypto_stream =
- CreateMockCryptoServerStream(&crypto_config_, &compressed_certs_cache_,
- session_.get(), &stream_helper_);
-
- QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), crypto_stream);
- if (!VersionUsesHttp3(transport_version())) {
- session_->RegisterStreamPriority(
- 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
- // them by sending PUSH_PROMISE for all and sending push responses for as much
- // as possible(limited by kMaxStreamsForTest).
- // If |num_resources| > kMaxStreamsForTest, the left over will be queued.
- // Returns the length of the DATA frame header, or 0 if the version does not
- // use DATA frames.
- QuicByteCount PromisePushResources(size_t num_resources) {
- // testing::InSequence seq;
- // To prevent push streams from being closed the response need to be larger
- // than stream flow control window so stream won't send the full body.
- size_t body_size = 2 * kStreamFlowControlWindowSize; // 64KB.
-
- std::string request_url = "mail.google.com/";
- spdy::Http2HeaderBlock request_headers;
- std::string resource_host = "www.google.com";
- std::string partial_push_resource_path = "/server_push_src";
- std::list<QuicBackendResponse::ServerPushInfo> push_resources;
- std::string scheme = "http";
- QuicByteCount data_frame_header_length = 0;
- for (unsigned int i = 1; i <= num_resources; ++i) {
- QuicStreamId stream_id;
- if (VersionUsesHttp3(transport_version())) {
- stream_id = GetNthServerInitiatedUnidirectionalId(i + 2);
- } else {
- stream_id = GetNthServerInitiatedUnidirectionalId(i - 1);
- }
- std::string path = absl::StrCat(partial_push_resource_path, 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(transport_version())) {
- std::unique_ptr<char[]> buffer;
- data_frame_header_length =
- HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
- std::string header(buffer.get(), data_frame_header_length);
- data = header + body;
- } else {
- data = body;
- }
-
- memory_cache_backend_.AddSimpleResponse(resource_host, path, 200, data);
- push_resources.push_back(QuicBackendResponse::ServerPushInfo(
- resource_url, spdy::Http2HeaderBlock(), QuicStream::kDefaultPriority,
- body));
- // PUSH_PROMISED are sent for all the resources.
- EXPECT_CALL(*session_,
- WritePushPromiseMock(GetNthClientInitiatedBidirectionalId(0),
- stream_id, _));
- if (i <= kMaxStreamsForTest) {
- // |kMaxStreamsForTest| promised responses should be sent.
- // Since flow control window is smaller than response body, not the
- // whole body will be sent.
- QuicStreamOffset offset = 0;
- if (VersionUsesHttp3(transport_version())) {
- EXPECT_CALL(*connection_,
- SendStreamData(stream_id, 1, offset, NO_FIN));
- offset++;
- }
-
- if (VersionUsesHttp3(transport_version())) {
- EXPECT_CALL(*connection_,
- SendStreamData(stream_id, kHeadersFrameHeaderLength,
- offset, NO_FIN));
- offset += kHeadersFrameHeaderLength;
- EXPECT_CALL(*connection_,
- SendStreamData(stream_id, kHeadersFramePayloadLength,
- offset, NO_FIN));
- offset += kHeadersFramePayloadLength;
- }
- if (VersionUsesHttp3(transport_version())) {
- EXPECT_CALL(*connection_,
- SendStreamData(stream_id, data_frame_header_length,
- offset, NO_FIN));
- offset += data_frame_header_length;
- }
- EXPECT_CALL(*connection_, SendStreamData(stream_id, _, offset, NO_FIN))
- .WillOnce(Return(QuicConsumedData(
- kStreamFlowControlWindowSize - offset, false)));
- EXPECT_CALL(*session_, SendBlocked(stream_id));
- }
- }
- session_->PromisePushResources(
- request_url, push_resources, GetNthClientInitiatedBidirectionalId(0),
- spdy::SpdyStreamPrecedence(0, spdy::kHttp2DefaultStreamWeight, false),
- request_headers);
- return data_frame_header_length;
- }
-
- void MaybeConsumeHeadersStreamData() {
- if (!VersionUsesHttp3(transport_version())) {
- QuicStreamId headers_stream_id =
- QuicUtils::GetHeadersStreamId(transport_version());
- EXPECT_CALL(*connection_, SendStreamData(headers_stream_id, _, _, _))
- .Times(AtLeast(1));
- }
- }
-};
-
-ParsedQuicVersionVector SupportedVersionsWithPush() {
- ParsedQuicVersionVector versions;
- for (const ParsedQuicVersion& version : AllSupportedVersions()) {
- if (!version.UsesHttp3()) {
- // Push over HTTP/3 is not supported.
- versions.push_back(version);
- }
- }
- return versions;
-}
-
-INSTANTIATE_TEST_SUITE_P(Tests,
- QuicSimpleServerSessionServerPushTest,
- ::testing::ValuesIn(SupportedVersionsWithPush()));
-
-// Tests that given more than kMaxStreamsForTest resources, all their
-// PUSH_PROMISE's will be sent out and only kMaxStreamsForTest streams will be
-// opened and send push response.
-TEST_P(QuicSimpleServerSessionServerPushTest, TestPromisePushResources) {
- MaybeConsumeHeadersStreamData();
- size_t num_resources = kMaxStreamsForTest + 5;
- PromisePushResources(num_resources);
- EXPECT_EQ(kMaxStreamsForTest,
- QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
-}
-
-// Tests that after promised stream queued up, when an opened stream is marked
-// draining, a queued promised stream will become open and send push response.
-TEST_P(QuicSimpleServerSessionServerPushTest,
- HandlePromisedPushRequestsAfterStreamDraining) {
- MaybeConsumeHeadersStreamData();
- size_t num_resources = kMaxStreamsForTest + 1;
- QuicByteCount data_frame_header_length = PromisePushResources(num_resources);
- QuicStreamId next_out_going_stream_id;
- if (VersionUsesHttp3(transport_version())) {
- next_out_going_stream_id =
- GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest + 3);
- } else {
- next_out_going_stream_id =
- GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest);
- }
-
- // 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(transport_version())) {
- EXPECT_CALL(*connection_,
- SendStreamData(next_out_going_stream_id, 1, offset, NO_FIN));
- offset++;
- }
- if (VersionUsesHttp3(transport_version())) {
- EXPECT_CALL(*connection_,
- SendStreamData(next_out_going_stream_id,
- kHeadersFrameHeaderLength, offset, NO_FIN));
- offset += kHeadersFrameHeaderLength;
- EXPECT_CALL(*connection_,
- SendStreamData(next_out_going_stream_id,
- kHeadersFramePayloadLength, offset, NO_FIN));
- offset += kHeadersFramePayloadLength;
- }
- if (VersionUsesHttp3(transport_version())) {
- EXPECT_CALL(*connection_,
- SendStreamData(next_out_going_stream_id,
- data_frame_header_length, offset, NO_FIN));
- offset += data_frame_header_length;
- }
- EXPECT_CALL(*connection_,
- SendStreamData(next_out_going_stream_id, _, offset, NO_FIN))
- .WillOnce(Return(
- QuicConsumedData(kStreamFlowControlWindowSize - offset, false)));
- EXPECT_CALL(*session_, SendBlocked(next_out_going_stream_id));
-
- if (VersionHasIetfQuicFrames(transport_version())) {
- // The PromisePushedResources call, above, will have used all available
- // stream ids. For version 99, stream ids are not made available until
- // a MAX_STREAMS frame is received. This emulates the reception of one.
- // For pre-v-99, the node monitors its own stream usage and makes streams
- // available as it closes/etc them.
- // Version 99 also has unidirectional static streams, so we need to send
- // MaxStreamFrame of the number of resources + number of static streams.
- session_->OnMaxStreamsFrame(
- QuicMaxStreamsFrame(0, num_resources + 3, /*unidirectional=*/true));
- }
-
- if (VersionUsesHttp3(transport_version())) {
- session_->StreamDraining(GetNthServerInitiatedUnidirectionalId(3),
- /*unidirectional=*/true);
- } else {
- session_->StreamDraining(GetNthServerInitiatedUnidirectionalId(0),
- /*unidirectional=*/true);
- }
- // Number of open outgoing streams should still be the same, because a new
- // stream is opened. And the queue should be empty.
- EXPECT_EQ(kMaxStreamsForTest,
- QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
-}
-
-// Tests that after all resources are promised, a RST frame from client can
-// prevent a promised resource to be send out.
-TEST_P(QuicSimpleServerSessionServerPushTest,
- ResetPromisedStreamToCancelServerPush) {
- if (VersionHasIetfQuicFrames(transport_version())) {
- // This test is resetting a stream that is not opened yet. IETF QUIC has no
- // way to handle this. Some similar tests can be added once CANCEL_PUSH is
- // supported.
- return;
- }
- MaybeConsumeHeadersStreamData();
-
- // 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.
- size_t num_resources = kMaxStreamsForTest + 2;
- if (VersionHasIetfQuicFrames(transport_version())) {
- // V99 will send out a STREAMS_BLOCKED frame when it tries to exceed the
- // limit. This will clear the frames so that they do not block the later
- // rst-stream frame.
- EXPECT_CALL(*session_, WriteControlFrame(_, _))
- .WillOnce(Invoke(&ClearControlFrameWithTransmissionType));
- }
- QuicByteCount data_frame_header_length = PromisePushResources(num_resources);
-
- // Reset the last stream in the queue. It should be marked cancelled.
- QuicStreamId stream_got_reset;
- if (VersionUsesHttp3(transport_version())) {
- stream_got_reset =
- GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest + 4);
- } else {
- stream_got_reset =
- GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest + 1);
- }
- QuicRstStreamFrame rst(kInvalidControlFrameId, stream_got_reset,
- QUIC_STREAM_CANCELLED, 0);
- EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
- EXPECT_CALL(*session_, WriteControlFrame(_, _))
- .WillOnce(Invoke(&ClearControlFrameWithTransmissionType));
- EXPECT_CALL(*connection_,
- OnStreamReset(stream_got_reset, QUIC_RST_ACKNOWLEDGEMENT));
- session_->OnRstStream(rst);
-
- // When the first 2 streams becomes draining, the two queued up stream could
- // 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(transport_version())) {
- stream_not_reset =
- GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest + 3);
- } else {
- stream_not_reset =
- GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest);
- }
- InSequence s;
- QuicStreamOffset offset = 0;
- if (VersionUsesHttp3(transport_version())) {
- EXPECT_CALL(*connection_,
- SendStreamData(stream_not_reset, 1, offset, NO_FIN));
- offset++;
- EXPECT_CALL(*connection_,
- SendStreamData(stream_not_reset, kHeadersFrameHeaderLength,
- offset, NO_FIN));
- offset += kHeadersFrameHeaderLength;
- EXPECT_CALL(*connection_,
- SendStreamData(stream_not_reset, kHeadersFramePayloadLength,
- offset, NO_FIN));
- offset += kHeadersFramePayloadLength;
- EXPECT_CALL(*connection_,
- SendStreamData(stream_not_reset, data_frame_header_length,
- offset, NO_FIN));
- offset += data_frame_header_length;
- }
- EXPECT_CALL(*connection_, SendStreamData(stream_not_reset, _, offset, NO_FIN))
- .WillOnce(Return(
- QuicConsumedData(kStreamFlowControlWindowSize - offset, false)));
- EXPECT_CALL(*session_, SendBlocked(stream_not_reset));
-
- if (VersionHasIetfQuicFrames(transport_version())) {
- // The PromisePushedResources call, above, will have used all available
- // stream ids. For version 99, stream ids are not made available until
- // a MAX_STREAMS frame is received. This emulates the reception of one.
- // For pre-v-99, the node monitors its own stream usage and makes streams
- // available as it closes/etc them.
- session_->OnMaxStreamsFrame(
- QuicMaxStreamsFrame(0, num_resources + 3, /*unidirectional=*/true));
- }
- session_->StreamDraining(GetNthServerInitiatedUnidirectionalId(3),
- /*unidirectional=*/true);
- session_->StreamDraining(GetNthServerInitiatedUnidirectionalId(4),
- /*unidirectional=*/true);
-}
-
-// Tests that closing a open outgoing stream can trigger a promised resource in
-// the queue to be send out.
-TEST_P(QuicSimpleServerSessionServerPushTest,
- CloseStreamToHandleMorePromisedStream) {
- MaybeConsumeHeadersStreamData();
- 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
- // the limit. This will clear the frames so that they do not block the later
- // rst-stream frame.
- EXPECT_CALL(*session_, WriteControlFrame(_, _))
- .WillOnce(Invoke(&ClearControlFrameWithTransmissionType));
- }
- QuicByteCount data_frame_header_length = PromisePushResources(num_resources);
- QuicStreamId stream_to_open;
- if (VersionUsesHttp3(transport_version())) {
- stream_to_open =
- GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest + 3);
- } else {
- stream_to_open = GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest);
- }
-
- // Resetting an open stream will close the stream and give space for extra
- // stream to be opened.
- QuicStreamId stream_got_reset = GetNthServerInitiatedUnidirectionalId(3);
- EXPECT_CALL(*session_, WriteControlFrame(_, _));
- if (!VersionHasIetfQuicFrames(transport_version())) {
- EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
- // For version 99, this is covered in InjectStopSending()
- EXPECT_CALL(*connection_,
- OnStreamReset(stream_got_reset, QUIC_RST_ACKNOWLEDGEMENT));
- }
- QuicStreamOffset offset = 0;
- if (VersionUsesHttp3(transport_version())) {
- EXPECT_CALL(*connection_,
- SendStreamData(stream_to_open, 1, offset, NO_FIN));
- offset++;
- EXPECT_CALL(*connection_,
- SendStreamData(stream_to_open, kHeadersFrameHeaderLength,
- offset, NO_FIN));
- offset += kHeadersFrameHeaderLength;
- EXPECT_CALL(*connection_,
- SendStreamData(stream_to_open, kHeadersFramePayloadLength,
- offset, NO_FIN));
- offset += kHeadersFramePayloadLength;
- EXPECT_CALL(*connection_,
- SendStreamData(stream_to_open, data_frame_header_length, offset,
- NO_FIN));
- offset += data_frame_header_length;
- }
- EXPECT_CALL(*connection_, SendStreamData(stream_to_open, _, offset, NO_FIN))
- .WillOnce(Return(
- QuicConsumedData(kStreamFlowControlWindowSize - offset, false)));
-
- EXPECT_CALL(*session_, SendBlocked(stream_to_open));
- QuicRstStreamFrame rst(kInvalidControlFrameId, stream_got_reset,
- QUIC_STREAM_CANCELLED, 0);
- if (VersionHasIetfQuicFrames(transport_version())) {
- // The PromisePushedResources call, above, will have used all available
- // stream ids. For version 99, stream ids are not made available until
- // a MAX_STREAMS frame is received. This emulates the reception of one.
- // For pre-v-99, the node monitors its own stream usage and makes streams
- // available as it closes/etc them.
- session_->OnMaxStreamsFrame(
- QuicMaxStreamsFrame(0, num_resources + 3, /*unidirectional=*/true));
- } else {
- session_->OnRstStream(rst);
- }
- // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
- // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes
- // a one-way close.
- InjectStopSending(stream_got_reset, QUIC_STREAM_CANCELLED);
-}
-
} // namespace
} // namespace test
} // namespace quic
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 f4afeb241c0..ac95e46fb97 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
@@ -214,8 +214,7 @@ std::string QuicSimpleServerStream::peer_host() const {
}
void QuicSimpleServerStream::OnResponseBackendComplete(
- const QuicBackendResponse* response,
- std::list<QuicBackendResponse::ServerPushInfo> resources) {
+ const QuicBackendResponse* response) {
if (response == nullptr) {
QUIC_DVLOG(1) << "Response not found in cache.";
SendNotFoundResponse();
@@ -285,15 +284,6 @@ void QuicSimpleServerStream::OnResponseBackendComplete(
}
}
- if (!resources.empty()) {
- QUIC_DVLOG(1) << "Stream " << id() << " found " << resources.size()
- << " push resources.";
- QuicSimpleServerSession* session =
- static_cast<QuicSimpleServerSession*>(spdy_session());
- session->PromisePushResources(request_url, resources, id(), precedence(),
- request_headers_);
- }
-
if (response->response_type() == QuicBackendResponse::INCOMPLETE_RESPONSE) {
QUIC_DVLOG(1)
<< "Stream " << id()
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 2dd59f9fc91..6395345518b 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
@@ -57,9 +57,7 @@ class QuicSimpleServerStream : public QuicSpdyServerStreamBase,
QuicConnectionId connection_id() const override;
QuicStreamId stream_id() const override;
std::string peer_host() const override;
- void OnResponseBackendComplete(
- const QuicBackendResponse* response,
- std::list<QuicBackendResponse::ServerPushInfo> resources) override;
+ void OnResponseBackendComplete(const QuicBackendResponse* response) override;
protected:
// Sends a basic 200 response using SendHeaders for the headers and WriteData
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 bf80d476020..25423114fab 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
@@ -187,25 +187,6 @@ class MockQuicSimpleServerSession : public QuicSimpleServerSession {
MaybeSendStopSendingFrame,
(QuicStreamId stream_id, QuicRstStreamErrorCode error),
(override));
- // Matchers cannot be used on non-copyable types like Http2HeaderBlock.
- void PromisePushResources(
- const std::string& request_url,
- const std::list<QuicBackendResponse::ServerPushInfo>& resources,
- QuicStreamId original_stream_id,
- const spdy::SpdyStreamPrecedence& original_precedence,
- const spdy::Http2HeaderBlock& original_request_headers) override {
- original_request_headers_ = original_request_headers.Clone();
- PromisePushResourcesMock(request_url, resources, original_stream_id,
- original_precedence, original_request_headers);
- }
- MOCK_METHOD(void,
- PromisePushResourcesMock,
- (const std::string&,
- const std::list<QuicBackendResponse::ServerPushInfo>&,
- QuicStreamId,
- const spdy::SpdyStreamPrecedence&,
- const spdy::Http2HeaderBlock&),
- ());
using QuicSession::ActivateStream;
@@ -546,46 +527,6 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithValidHeaders) {
EXPECT_TRUE(stream_->write_side_closed());
}
-TEST_P(QuicSimpleServerStreamTest, SendResponseWithPushResources) {
- // Tests that if a response has push resources to be send, SendResponse() will
- // call PromisePushResources() to handle these resources.
-
- // Add a request and response with valid headers into cache.
- std::string host = "www.google.com";
- std::string request_path = "/foo";
- std::string body = "Yummm";
- std::unique_ptr<char[]> buffer;
- QuicByteCount header_length =
- HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
- QuicBackendResponse::ServerPushInfo push_info(
- QuicUrl(host, "/bar"), spdy::Http2HeaderBlock(),
- QuicStream::kDefaultPriority, "Push body");
- std::list<QuicBackendResponse::ServerPushInfo> push_resources;
- push_resources.push_back(push_info);
- memory_cache_backend_.AddSimpleResponseWithServerPushResources(
- host, request_path, 200, body, push_resources);
-
- spdy::Http2HeaderBlock* request_headers = stream_->mutable_headers();
- (*request_headers)[":path"] = request_path;
- (*request_headers)[":authority"] = host;
- (*request_headers)[":method"] = "GET";
-
- QuicStreamPeer::SetFinReceived(stream_);
- InSequence s;
- EXPECT_CALL(session_, PromisePushResourcesMock(
- host + request_path, _,
- GetNthClientInitiatedBidirectionalStreamId(
- connection_->transport_version(), 0),
- _, _));
- EXPECT_CALL(*stream_, WriteHeadersMock(false));
- if (UsesHttp3()) {
- EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _, _));
- }
- EXPECT_CALL(session_, WritevData(_, body.length(), _, FIN, _, _));
- stream_->DoSendResponse();
- EXPECT_EQ(*request_headers, session_.original_request_headers_);
-}
-
TEST_P(QuicSimpleServerStreamTest, SendResponseWithEarlyHints) {
std::string host = "www.google.com";
std::string request_path = "/foo";
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 974344ed4aa..4f51eb47eba 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
@@ -13,7 +13,7 @@
#include "quic/core/quic_server_id.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
-#include "common/platform/api/quiche_text_utils.h"
+#include "common/quiche_text_utils.h"
using spdy::Http2HeaderBlock;
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 15cdc291d27..8d227913ce5 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
@@ -59,9 +59,10 @@
#include "quic/platform/api/quic_ip_address.h"
#include "quic/platform/api/quic_socket_address.h"
#include "quic/platform/api/quic_system_event_loop.h"
+#include "quic/test_tools/simple_session_cache.h"
#include "quic/tools/fake_proof_verifier.h"
#include "quic/tools/quic_url.h"
-#include "common/platform/api/quiche_text_utils.h"
+#include "common/quiche_text_utils.h"
namespace {
@@ -194,6 +195,12 @@ DEFINE_QUIC_COMMAND_LINE_FLAG(
false,
"If true, do not change local port after each request.");
+DEFINE_QUIC_COMMAND_LINE_FLAG(bool,
+ one_connection_per_request,
+ false,
+ "If true, close the connection after each "
+ "request. This allows testing 0-RTT.");
+
DEFINE_QUIC_COMMAND_LINE_FLAG(int32_t,
server_connection_id_length,
-1,
@@ -260,6 +267,10 @@ int QuicToyClient::SendRequestsAndPrintResponses(
} else {
proof_verifier = quic::CreateDefaultProofVerifier(url.host());
}
+ std::unique_ptr<quic::SessionCache> session_cache;
+ if (num_requests > 1 && GetQuicFlag(FLAGS_one_connection_per_request)) {
+ session_cache = std::make_unique<test::SimpleSessionCache>();
+ }
QuicConfig config;
std::string connection_options_string = GetQuicFlag(FLAGS_connection_options);
@@ -293,7 +304,7 @@ int QuicToyClient::SendRequestsAndPrintResponses(
// Build the client, and try to connect.
std::unique_ptr<QuicSpdyClientBase> client = client_factory_->CreateClient(
url.host(), host, address_family_for_lookup, port, versions, config,
- std::move(proof_verifier));
+ std::move(proof_verifier), std::move(session_cache));
if (client == nullptr) {
std::cerr << "Failed to create client." << std::endl;
@@ -356,7 +367,8 @@ int QuicToyClient::SendRequestsAndPrintResponses(
if (sp.empty()) {
continue;
}
- std::vector<absl::string_view> kv = absl::StrSplit(sp, ':');
+ std::vector<absl::string_view> kv =
+ absl::StrSplit(sp, absl::MaxSplits(':', 1));
QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&kv[0]);
QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&kv[1]);
header_block[kv[0]] = kv[1];
@@ -429,11 +441,26 @@ int QuicToyClient::SendRequestsAndPrintResponses(
return 1;
}
- // Change the ephemeral port if there are more requests to do.
- if (!GetQuicFlag(FLAGS_disable_port_changes) && i + 1 < num_requests) {
- if (!client->ChangeEphemeralPort()) {
- std::cerr << "Failed to change ephemeral port." << std::endl;
- return 1;
+ if (i + 1 < num_requests) { // There are more requests to perform.
+ if (GetQuicFlag(FLAGS_one_connection_per_request)) {
+ std::cout << "Disconnecting client between requests." << std::endl;
+ client->Disconnect();
+ if (!client->Initialize()) {
+ std::cerr << "Failed to reinitialize client between requests."
+ << std::endl;
+ return 1;
+ }
+ if (!client->Connect()) {
+ std::cerr << "Failed to reconnect client between requests."
+ << std::endl;
+ return 1;
+ }
+ } else if (!GetQuicFlag(FLAGS_disable_port_changes)) {
+ // Change the ephemeral port.
+ if (!client->ChangeEphemeralPort()) {
+ std::cerr << "Failed to change ephemeral port." << std::endl;
+ return 1;
+ }
}
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.h b/chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.h
index 085e749e310..81b3733c46f 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.h
@@ -29,7 +29,8 @@ class QuicToyClient {
uint16_t port,
ParsedQuicVersionVector versions,
const QuicConfig& config,
- std::unique_ptr<ProofVerifier> verifier) = 0;
+ std::unique_ptr<ProofVerifier> verifier,
+ std::unique_ptr<SessionCache> session_cache) = 0;
};
// Constructs a new toy client that will use |client_factory| to create the
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 93f699ba55a..e7b4e1ecd7a 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
@@ -46,6 +46,11 @@ DEFINE_QUIC_COMMAND_LINE_FLAG(
"QUIC versions to enable, e.g. \"h3-25,h3-27\". If not set, then all "
"available versions are enabled.");
+DEFINE_QUIC_COMMAND_LINE_FLAG(bool,
+ enable_webtransport,
+ false,
+ "If true, WebTransport support is enabled.");
+
namespace quic {
std::unique_ptr<quic::QuicSimpleServerBackend>
@@ -58,6 +63,9 @@ QuicToyServer::MemoryCacheBackendFactory::CreateBackend() {
memory_cache_backend->InitializeBackend(
GetQuicFlag(FLAGS_quic_response_cache_dir));
}
+ if (GetQuicFlag(FLAGS_enable_webtransport)) {
+ memory_cache_backend->EnableWebTransport();
+ }
return memory_cache_backend;
}
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 2d3be8a0fe2..a51eab66952 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
@@ -73,7 +73,7 @@ class QuicTransportSimpleServerSession
size_t pending_outgoing_bidirectional_streams_ = 0u;
Mode mode_;
std::vector<url::Origin> accepted_origins_;
- QuicCircularDeque<std::string> streams_to_echo_back_;
+ quiche::QuicheCircularDeque<std::string> streams_to_echo_back_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/tools/web_transport_test_visitors.h b/chromium/net/third_party/quiche/src/quic/tools/web_transport_test_visitors.h
index 9bf6e6bca84..e348750a474 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/web_transport_test_visitors.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/web_transport_test_visitors.h
@@ -7,8 +7,10 @@
#include <string>
+#include "quic/core/quic_simple_buffer_allocator.h"
#include "quic/core/web_transport_interface.h"
#include "quic/platform/api/quic_logging.h"
+#include "common/quiche_circular_deque.h"
namespace quic {
@@ -132,6 +134,95 @@ class WebTransportUnidirectionalEchoWriteVisitor
std::string data_;
};
+// A session visitor which sets unidirectional or bidirectional stream visitors
+// to echo.
+class EchoWebTransportSessionVisitor : public WebTransportVisitor {
+ public:
+ EchoWebTransportSessionVisitor(WebTransportSession* session)
+ : session_(session) {}
+
+ void OnSessionReady() override {
+ if (session_->CanOpenNextOutgoingBidirectionalStream()) {
+ OnCanCreateNewOutgoingBidirectionalStream();
+ }
+ }
+
+ void OnIncomingBidirectionalStreamAvailable() override {
+ while (true) {
+ WebTransportStream* stream =
+ session_->AcceptIncomingBidirectionalStream();
+ if (stream == nullptr) {
+ return;
+ }
+ QUIC_DVLOG(1)
+ << "EchoWebTransportSessionVisitor received a bidirectional stream "
+ << stream->GetStreamId();
+ stream->SetVisitor(
+ std::make_unique<WebTransportBidirectionalEchoVisitor>(stream));
+ stream->visitor()->OnCanRead();
+ }
+ }
+
+ void OnIncomingUnidirectionalStreamAvailable() override {
+ while (true) {
+ WebTransportStream* stream =
+ session_->AcceptIncomingUnidirectionalStream();
+ if (stream == nullptr) {
+ return;
+ }
+ QUIC_DVLOG(1)
+ << "EchoWebTransportSessionVisitor received a unidirectional stream";
+ stream->SetVisitor(
+ std::make_unique<WebTransportUnidirectionalEchoReadVisitor>(
+ stream, [this](const std::string& data) {
+ streams_to_echo_back_.push_back(data);
+ TrySendingUnidirectionalStreams();
+ }));
+ stream->visitor()->OnCanRead();
+ }
+ }
+
+ void OnDatagramReceived(absl::string_view datagram) override {
+ auto buffer = MakeUniqueBuffer(&allocator_, datagram.size());
+ memcpy(buffer.get(), datagram.data(), datagram.size());
+ QuicMemSlice slice(std::move(buffer), datagram.size());
+ session_->SendOrQueueDatagram(std::move(slice));
+ }
+
+ void OnCanCreateNewOutgoingBidirectionalStream() override {
+ if (!echo_stream_opened_) {
+ WebTransportStream* stream = session_->OpenOutgoingBidirectionalStream();
+ stream->SetVisitor(
+ std::make_unique<WebTransportBidirectionalEchoVisitor>(stream));
+ echo_stream_opened_ = true;
+ }
+ }
+ void OnCanCreateNewOutgoingUnidirectionalStream() override {
+ TrySendingUnidirectionalStreams();
+ }
+
+ void TrySendingUnidirectionalStreams() {
+ while (!streams_to_echo_back_.empty() &&
+ session_->CanOpenNextOutgoingUnidirectionalStream()) {
+ QUIC_DVLOG(1)
+ << "EchoWebTransportServer echoed a unidirectional stream back";
+ WebTransportStream* stream = session_->OpenOutgoingUnidirectionalStream();
+ stream->SetVisitor(
+ std::make_unique<WebTransportUnidirectionalEchoWriteVisitor>(
+ stream, streams_to_echo_back_.front()));
+ streams_to_echo_back_.pop_front();
+ stream->visitor()->OnCanWrite();
+ }
+ }
+
+ private:
+ WebTransportSession* session_;
+ SimpleBufferAllocator allocator_;
+ bool echo_stream_opened_ = false;
+
+ quiche::QuicheCircularDeque<std::string> streams_to_echo_back_;
+};
+
} // namespace quic
#endif // QUICHE_QUIC_TOOLS_WEB_TRANSPORT_TEST_VISITORS_H_
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_constants.cc b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_constants.cc
index 231fd547460..a8e48a2feb5 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_constants.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_constants.cc
@@ -9,8 +9,8 @@
#include <vector>
#include "absl/base/macros.h"
+#include "common/platform/api/quiche_logging.h"
#include "spdy/core/hpack/hpack_static_table.h"
-#include "spdy/platform/api/spdy_logging.h"
namespace spdy {
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.cc b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.cc
index 4d03cc50018..3fd6ebcf87d 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.cc
@@ -6,9 +6,8 @@
#include "http2/decoder/decode_buffer.h"
#include "http2/decoder/decode_status.h"
+#include "common/platform/api/quiche_logging.h"
#include "spdy/platform/api/spdy_estimate_memory_usage.h"
-#include "spdy/platform/api/spdy_flags.h"
-#include "spdy/platform/api/spdy_logging.h"
using ::http2::DecodeBuffer;
@@ -27,13 +26,13 @@ HpackDecoderAdapter::HpackDecoderAdapter()
HpackDecoderAdapter::~HpackDecoderAdapter() = default;
void HpackDecoderAdapter::ApplyHeaderTableSizeSetting(size_t size_setting) {
- SPDY_DVLOG(2) << "HpackDecoderAdapter::ApplyHeaderTableSizeSetting";
+ QUICHE_DVLOG(2) << "HpackDecoderAdapter::ApplyHeaderTableSizeSetting";
hpack_decoder_.ApplyHeaderTableSizeSetting(size_setting);
}
void HpackDecoderAdapter::HandleControlFrameHeadersStart(
SpdyHeadersHandlerInterface* handler) {
- SPDY_DVLOG(2) << "HpackDecoderAdapter::HandleControlFrameHeadersStart";
+ QUICHE_DVLOG(2) << "HpackDecoderAdapter::HandleControlFrameHeadersStart";
QUICHE_DCHECK(!header_block_started_);
listener_adapter_.set_handler(handler);
}
@@ -41,8 +40,8 @@ void HpackDecoderAdapter::HandleControlFrameHeadersStart(
bool HpackDecoderAdapter::HandleControlFrameHeadersData(
const char* headers_data,
size_t headers_data_length) {
- SPDY_DVLOG(2) << "HpackDecoderAdapter::HandleControlFrameHeadersData: len="
- << headers_data_length;
+ QUICHE_DVLOG(2) << "HpackDecoderAdapter::HandleControlFrameHeadersData: len="
+ << headers_data_length;
if (!header_block_started_) {
// Initialize the decoding process here rather than in
// HandleControlFrameHeadersStart because that method is not always called.
@@ -61,9 +60,9 @@ bool HpackDecoderAdapter::HandleControlFrameHeadersData(
if (headers_data_length > 0) {
QUICHE_DCHECK_NE(headers_data, nullptr);
if (headers_data_length > max_decode_buffer_size_bytes_) {
- SPDY_DVLOG(1) << "max_decode_buffer_size_bytes_ < headers_data_length: "
- << max_decode_buffer_size_bytes_ << " < "
- << headers_data_length;
+ QUICHE_DVLOG(1) << "max_decode_buffer_size_bytes_ < headers_data_length: "
+ << max_decode_buffer_size_bytes_ << " < "
+ << headers_data_length;
error_ = http2::HpackDecodingError::kFragmentTooLong;
detailed_error_ = "";
return false;
@@ -89,12 +88,12 @@ bool HpackDecoderAdapter::HandleControlFrameHeadersData(
bool HpackDecoderAdapter::HandleControlFrameHeadersComplete(
size_t* compressed_len) {
- SPDY_DVLOG(2) << "HpackDecoderAdapter::HandleControlFrameHeadersComplete";
+ QUICHE_DVLOG(2) << "HpackDecoderAdapter::HandleControlFrameHeadersComplete";
if (compressed_len != nullptr) {
*compressed_len = listener_adapter_.total_hpack_bytes();
}
if (!hpack_decoder_.EndDecodingBlock()) {
- SPDY_DVLOG(3) << "EndDecodingBlock returned false";
+ QUICHE_DVLOG(3) << "EndDecodingBlock returned false";
error_ = hpack_decoder_.error();
detailed_error_ = hpack_decoder_.detailed_error();
return false;
@@ -109,7 +108,7 @@ const SpdyHeaderBlock& HpackDecoderAdapter::decoded_block() const {
void HpackDecoderAdapter::set_max_decode_buffer_size_bytes(
size_t max_decode_buffer_size_bytes) {
- SPDY_DVLOG(2) << "HpackDecoderAdapter::set_max_decode_buffer_size_bytes";
+ QUICHE_DVLOG(2) << "HpackDecoderAdapter::set_max_decode_buffer_size_bytes";
max_decode_buffer_size_bytes_ = max_decode_buffer_size_bytes;
hpack_decoder_.set_max_string_size_bytes(max_decode_buffer_size_bytes);
}
@@ -132,7 +131,7 @@ void HpackDecoderAdapter::ListenerAdapter::set_handler(
}
void HpackDecoderAdapter::ListenerAdapter::OnHeaderListStart() {
- SPDY_DVLOG(2) << "HpackDecoderAdapter::ListenerAdapter::OnHeaderListStart";
+ QUICHE_DVLOG(2) << "HpackDecoderAdapter::ListenerAdapter::OnHeaderListStart";
total_hpack_bytes_ = 0;
total_uncompressed_bytes_ = 0;
decoded_block_.clear();
@@ -143,20 +142,20 @@ void HpackDecoderAdapter::ListenerAdapter::OnHeaderListStart() {
void HpackDecoderAdapter::ListenerAdapter::OnHeader(const std::string& name,
const std::string& value) {
- SPDY_DVLOG(2) << "HpackDecoderAdapter::ListenerAdapter::OnHeader:\n name: "
- << name << "\n value: " << value;
+ QUICHE_DVLOG(2) << "HpackDecoderAdapter::ListenerAdapter::OnHeader:\n name: "
+ << name << "\n value: " << value;
total_uncompressed_bytes_ += name.size() + value.size();
if (handler_ == nullptr) {
- SPDY_DVLOG(3) << "Adding to decoded_block";
+ QUICHE_DVLOG(3) << "Adding to decoded_block";
decoded_block_.AppendValueOrAddHeader(name, value);
} else {
- SPDY_DVLOG(3) << "Passing to handler";
+ QUICHE_DVLOG(3) << "Passing to handler";
handler_->OnHeader(name, value);
}
}
void HpackDecoderAdapter::ListenerAdapter::OnHeaderListEnd() {
- SPDY_DVLOG(2) << "HpackDecoderAdapter::ListenerAdapter::OnHeaderListEnd";
+ QUICHE_DVLOG(2) << "HpackDecoderAdapter::ListenerAdapter::OnHeaderListEnd";
// We don't clear the SpdyHeaderBlock here to allow access to it until the
// next HPACK block is decoded.
if (handler_ != nullptr) {
@@ -167,7 +166,7 @@ void HpackDecoderAdapter::ListenerAdapter::OnHeaderListEnd() {
void HpackDecoderAdapter::ListenerAdapter::OnHeaderErrorDetected(
absl::string_view error_message) {
- SPDY_VLOG(1) << error_message;
+ QUICHE_VLOG(1) << error_message;
}
} // namespace spdy
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter_test.cc b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter_test.cc
index 0a12fe49a21..d223ccf9f5a 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter_test.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter_test.cc
@@ -14,17 +14,18 @@
#include <vector>
#include "absl/base/macros.h"
+#include "absl/strings/escaping.h"
#include "http2/hpack/decoder/hpack_decoder_state.h"
#include "http2/hpack/decoder/hpack_decoder_tables.h"
#include "http2/hpack/tools/hpack_block_builder.h"
#include "http2/test_tools/http2_random.h"
+#include "common/platform/api/quiche_logging.h"
#include "common/platform/api/quiche_test.h"
#include "spdy/core/hpack/hpack_constants.h"
#include "spdy/core/hpack/hpack_encoder.h"
#include "spdy/core/hpack/hpack_output_stream.h"
#include "spdy/core/recording_headers_handler.h"
#include "spdy/core/spdy_test_utils.h"
-#include "spdy/platform/api/spdy_logging.h"
#include "spdy/platform/api/spdy_string_utils.h"
using ::http2::HpackEntryType;
@@ -134,7 +135,7 @@ class HpackDecoderAdapterTest
}
bool HandleControlFrameHeadersData(absl::string_view str) {
- SPDY_VLOG(3) << "HandleControlFrameHeadersData:\n" << SpdyHexDump(str);
+ QUICHE_VLOG(3) << "HandleControlFrameHeadersData:\n" << SpdyHexDump(str);
bytes_passed_in_ += str.size();
return decoder_.HandleControlFrameHeadersData(str.data(), str.size());
}
@@ -680,7 +681,7 @@ TEST_P(HpackDecoderAdapterTest, TruncatedHuffmanLiteral) {
// | www.example.com
// | -> :authority: www.example.com
- std::string first = SpdyHexDecode("418cf1e3c2e5f23a6ba0ab90f4ff");
+ std::string first = absl::HexStringToBytes("418cf1e3c2e5f23a6ba0ab90f4ff");
EXPECT_TRUE(DecodeHeaderBlock(first));
first.pop_back();
EXPECT_FALSE(DecodeHeaderBlock(first));
@@ -700,9 +701,9 @@ TEST_P(HpackDecoderAdapterTest, HuffmanEOSError) {
// | www.example.com
// | -> :authority: www.example.com
- std::string first = SpdyHexDecode("418cf1e3c2e5f23a6ba0ab90f4ff");
+ std::string first = absl::HexStringToBytes("418cf1e3c2e5f23a6ba0ab90f4ff");
EXPECT_TRUE(DecodeHeaderBlock(first));
- first = SpdyHexDecode("418df1e3c2e5f23a6ba0ab90f4ffff");
+ first = absl::HexStringToBytes("418df1e3c2e5f23a6ba0ab90f4ffff");
EXPECT_FALSE(DecodeHeaderBlock(first));
}
@@ -749,7 +750,8 @@ TEST_P(HpackDecoderAdapterTest, SectionC4RequestHuffmanExamples) {
// | Decoded:
// | www.example.com
// | -> :authority: www.example.com
- std::string first = SpdyHexDecode("828684418cf1e3c2e5f23a6ba0ab90f4ff");
+ std::string first =
+ absl::HexStringToBytes("828684418cf1e3c2e5f23a6ba0ab90f4ff");
const SpdyHeaderBlock& first_header_set = DecodeBlockExpectingSuccess(first);
EXPECT_THAT(first_header_set,
@@ -786,7 +788,7 @@ TEST_P(HpackDecoderAdapterTest, SectionC4RequestHuffmanExamples) {
// | no-cache
// | -> cache-control: no-cache
- std::string second = SpdyHexDecode("828684be5886a8eb10649cbf");
+ std::string second = absl::HexStringToBytes("828684be5886a8eb10649cbf");
const SpdyHeaderBlock& second_header_set =
DecodeBlockExpectingSuccess(second);
@@ -828,8 +830,8 @@ TEST_P(HpackDecoderAdapterTest, SectionC4RequestHuffmanExamples) {
// | Decoded:
// | custom-value
// | -> custom-key: custom-value
- std::string third =
- SpdyHexDecode("828785bf408825a849e95ba97d7f8925a849e95bb8e8b4bf");
+ std::string third = absl::HexStringToBytes(
+ "828785bf408825a849e95ba97d7f8925a849e95bb8e8b4bf");
const SpdyHeaderBlock& third_header_set = DecodeBlockExpectingSuccess(third);
EXPECT_THAT(
@@ -898,7 +900,7 @@ TEST_P(HpackDecoderAdapterTest, SectionC6ResponseHuffmanExamples) {
// | -> location: https://www.e
// | xample.com
- std::string first = SpdyHexDecode(
+ std::string first = absl::HexStringToBytes(
"488264025885aec3771a4b6196d07abe"
"941054d444a8200595040b8166e082a6"
"2d1bff6e919d29ad171863c78f0b97c8"
@@ -941,7 +943,7 @@ TEST_P(HpackDecoderAdapterTest, SectionC6ResponseHuffmanExamples) {
// | idx = 63
// | -> location:
// | https://www.example.com
- std::string second = SpdyHexDecode("4883640effc1c0bf");
+ std::string second = absl::HexStringToBytes("4883640effc1c0bf");
const SpdyHeaderBlock& second_header_set =
DecodeBlockExpectingSuccess(second);
@@ -1013,7 +1015,7 @@ TEST_P(HpackDecoderAdapterTest, SectionC6ResponseHuffmanExamples) {
// | -> set-cookie: foo=ASDJKHQ
// | KBZXOQWEOPIUAXQWEOIU;
// | max-age=3600; version=1
- std::string third = SpdyHexDecode(
+ std::string third = absl::HexStringToBytes(
"88c16196d07abe941054d444a8200595"
"040b8166e084a62d1bffc05a839bd9ab"
"77ad94e7821dd7f2e6c7b335dfdfcd5b"
@@ -1116,7 +1118,7 @@ TEST_P(HpackDecoderAdapterTest, Cookies) {
SpdyHeaderBlock expected_header_set;
expected_header_set["cookie"] = "foo; bar";
- EXPECT_TRUE(DecodeHeaderBlock(SpdyHexDecode("608294e76003626172")));
+ EXPECT_TRUE(DecodeHeaderBlock(absl::HexStringToBytes("608294e76003626172")));
EXPECT_EQ(expected_header_set, decoded_block());
}
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.cc b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.cc
index 6dc27b9ca7f..27f0444f274 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.cc
@@ -9,13 +9,12 @@
#include <utility>
#include "http2/hpack/huffman/hpack_huffman_encoder.h"
+#include "common/platform/api/quiche_bug_tracker.h"
+#include "common/platform/api/quiche_logging.h"
#include "spdy/core/hpack/hpack_constants.h"
#include "spdy/core/hpack/hpack_header_table.h"
#include "spdy/core/hpack/hpack_output_stream.h"
#include "spdy/platform/api/spdy_estimate_memory_usage.h"
-#include "spdy/platform/api/spdy_flag_utils.h"
-#include "spdy/platform/api/spdy_flags.h"
-#include "spdy/platform/api/spdy_logging.h"
namespace spdy {
@@ -155,14 +154,14 @@ void HpackEncoder::EncodeRepresentations(RepresentationIterator* iter,
}
void HpackEncoder::EmitIndex(size_t index) {
- SPDY_DVLOG(2) << "Emitting index " << index;
+ QUICHE_DVLOG(2) << "Emitting index " << index;
output_stream_.AppendPrefix(kIndexedOpcode);
output_stream_.AppendUint32(index);
}
void HpackEncoder::EmitIndexedLiteral(const Representation& representation) {
- SPDY_DVLOG(2) << "Emitting indexed literal: (" << representation.first << ", "
- << representation.second << ")";
+ QUICHE_DVLOG(2) << "Emitting indexed literal: (" << representation.first
+ << ", " << representation.second << ")";
output_stream_.AppendPrefix(kLiteralIncrementalIndexOpcode);
EmitLiteral(representation);
header_table_.TryAddEntry(representation.first, representation.second);
@@ -170,8 +169,8 @@ void HpackEncoder::EmitIndexedLiteral(const Representation& representation) {
void HpackEncoder::EmitNonIndexedLiteral(const Representation& representation,
bool enable_compression) {
- SPDY_DVLOG(2) << "Emitting nonindexed literal: (" << representation.first
- << ", " << representation.second << ")";
+ QUICHE_DVLOG(2) << "Emitting nonindexed literal: (" << representation.first
+ << ", " << representation.second << ")";
output_stream_.AppendPrefix(kLiteralNoIndexOpcode);
size_t name_index = header_table_.GetByName(representation.first);
if (enable_compression && name_index != kHpackEntryNotFound) {
@@ -198,13 +197,13 @@ void HpackEncoder::EmitString(absl::string_view str) {
size_t encoded_size =
enable_compression_ ? http2::HuffmanSize(str) : str.size();
if (encoded_size < str.size()) {
- SPDY_DVLOG(2) << "Emitted Huffman-encoded string of length "
- << encoded_size;
+ QUICHE_DVLOG(2) << "Emitted Huffman-encoded string of length "
+ << encoded_size;
output_stream_.AppendPrefix(kStringLiteralHuffmanEncoded);
output_stream_.AppendUint32(encoded_size);
http2::HuffmanEncodeFast(str, encoded_size, output_stream_.MutableString());
} else {
- SPDY_DVLOG(2) << "Emitted literal string of length " << str.size();
+ QUICHE_DVLOG(2) << "Emitted literal string of length " << str.size();
output_stream_.AppendPrefix(kStringLiteralIdentityEncoded);
output_stream_.AppendUint32(str.size());
output_stream_.AppendBytes(str);
@@ -216,9 +215,9 @@ void HpackEncoder::MaybeEmitTableSize() {
return;
}
const size_t current_size = CurrentHeaderTableSizeSetting();
- SPDY_DVLOG(1) << "MaybeEmitTableSize current_size=" << current_size;
- SPDY_DVLOG(1) << "MaybeEmitTableSize min_table_size_setting_received_="
- << min_table_size_setting_received_;
+ QUICHE_DVLOG(1) << "MaybeEmitTableSize current_size=" << current_size;
+ QUICHE_DVLOG(1) << "MaybeEmitTableSize min_table_size_setting_received_="
+ << min_table_size_setting_received_;
if (min_table_size_setting_received_ < current_size) {
output_stream_.AppendPrefix(kHeaderTableSizeUpdateOpcode);
output_stream_.AppendUint32(min_table_size_setting_received_);
@@ -347,7 +346,7 @@ HpackEncoder::Encoderator::Encoderator(const Representations& representations,
void HpackEncoder::Encoderator::Next(size_t max_encoded_bytes,
std::string* output) {
- SPDY_BUG_IF(spdy_bug_61_1, !has_next_)
+ QUICHE_BUG_IF(spdy_bug_61_1, !has_next_)
<< "Encoderator::Next called with nothing left to encode.";
const bool enable_compression = encoder_->enable_compression_;
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder_test.cc b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder_test.cc
index 85fa4fbc321..774a06e8129 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder_test.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder_test.cc
@@ -12,7 +12,6 @@
#include "common/platform/api/quiche_test.h"
#include "spdy/core/hpack/hpack_static_table.h"
#include "spdy/core/spdy_simple_arena.h"
-#include "spdy/platform/api/spdy_flags.h"
namespace spdy {
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_entry.cc b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_entry.cc
index b8350df4ff4..4deb0dfcc81 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_entry.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_entry.cc
@@ -6,7 +6,6 @@
#include "absl/strings/str_cat.h"
#include "spdy/platform/api/spdy_estimate_memory_usage.h"
-#include "spdy/platform/api/spdy_logging.h"
namespace spdy {
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.cc b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.cc
index ec69d47b6ae..8536a8523fc 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.cc
@@ -6,10 +6,10 @@
#include <algorithm>
+#include "common/platform/api/quiche_logging.h"
#include "spdy/core/hpack/hpack_constants.h"
#include "spdy/core/hpack/hpack_static_table.h"
#include "spdy/platform/api/spdy_estimate_memory_usage.h"
-#include "spdy/platform/api/spdy_logging.h"
namespace spdy {
@@ -155,9 +155,9 @@ const HpackEntry* HpackHeaderTable::TryAddEntry(absl::string_view name,
if (!index_result.second) {
// An entry with the same name and value already exists in the dynamic
// index. We should replace it with the newly added entry.
- SPDY_DVLOG(1) << "Found existing entry at: " << index_result.first->second
- << " replacing with: " << new_entry->GetDebugString()
- << " at: " << index;
+ QUICHE_DVLOG(1) << "Found existing entry at: " << index_result.first->second
+ << " replacing with: " << new_entry->GetDebugString()
+ << " at: " << index;
QUICHE_DCHECK_GT(index, index_result.first->second);
dynamic_index_.erase(index_result.first);
auto insert_result = dynamic_index_.insert(std::make_pair(
@@ -170,9 +170,9 @@ const HpackEntry* HpackHeaderTable::TryAddEntry(absl::string_view name,
if (!name_result.second) {
// An entry with the same name already exists in the dynamic index. We
// should replace it with the newly added entry.
- SPDY_DVLOG(1) << "Found existing entry at: " << name_result.first->second
- << " replacing with: " << new_entry->GetDebugString()
- << " at: " << index;
+ QUICHE_DVLOG(1) << "Found existing entry at: " << name_result.first->second
+ << " replacing with: " << new_entry->GetDebugString()
+ << " at: " << index;
QUICHE_DCHECK_GT(index, name_result.first->second);
dynamic_name_index_.erase(name_result.first);
auto insert_result =
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.h b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.h
index 893aaa7bb21..49478cd35b2 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.h
@@ -43,11 +43,6 @@ class QUICHE_EXPORT_PRIVATE HpackHeaderTable {
// HpackHeaderTable takes advantage of the deque property that references
// remain valid, so long as insertions & deletions are at the head & tail.
// This precludes the use of base::circular_deque.
- //
- // If this changes (we want to change to circular_deque or we start to drop
- // entries from the middle of the table), this should to be a std::list, in
- // which case |*_index_| can be trivially extended to map to list iterators.
- //
// TODO(b/182349990): Change to a more memory efficient container.
using DynamicEntryTable = std::deque<HpackEntry>;
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_output_stream.cc b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_output_stream.cc
index d2ec46c49c5..7b925680d4b 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_output_stream.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_output_stream.cc
@@ -6,8 +6,8 @@
#include <utility>
+#include "common/platform/api/quiche_logging.h"
#include "spdy/platform/api/spdy_estimate_memory_usage.h"
-#include "spdy/platform/api/spdy_logging.h"
namespace spdy {
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_static_table.cc b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_static_table.cc
index 8c8248c2343..7594943b43e 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_static_table.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_static_table.cc
@@ -5,10 +5,10 @@
#include "spdy/core/hpack/hpack_static_table.h"
#include "absl/strings/string_view.h"
+#include "common/platform/api/quiche_logging.h"
#include "spdy/core/hpack/hpack_constants.h"
#include "spdy/core/hpack/hpack_entry.h"
#include "spdy/platform/api/spdy_estimate_memory_usage.h"
-#include "spdy/platform/api/spdy_logging.h"
namespace spdy {
diff --git a/chromium/net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.cc b/chromium/net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.cc
index cb9c176090a..b20d0032aff 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.cc
@@ -4,9 +4,9 @@
#include "spdy/core/http2_frame_decoder_adapter.h"
-// Logging policy: If an error in the input is detected, SPDY_VLOG(n) is used so
-// that the option exists to debug the situation. Otherwise, this code mostly
-// uses SPDY_DVLOG so that the logging does not slow down production code when
+// Logging policy: If an error in the input is detected, QUICHE_VLOG(n) is used
+// so that the option exists to debug the situation. Otherwise, this code mostly
+// uses QUICHE_DVLOG so that the logging does not slow down production code when
// things are working OK.
#include <stddef.h>
@@ -21,6 +21,8 @@
#include "http2/decoder/http2_frame_decoder_listener.h"
#include "http2/http2_constants.h"
#include "http2/http2_structures.h"
+#include "common/platform/api/quiche_bug_tracker.h"
+#include "common/platform/api/quiche_logging.h"
#include "common/quiche_endian.h"
#include "spdy/core/hpack/hpack_decoder_adapter.h"
#include "spdy/core/hpack/hpack_header_table.h"
@@ -28,10 +30,7 @@
#include "spdy/core/spdy_header_block.h"
#include "spdy/core/spdy_headers_handler_interface.h"
#include "spdy/core/spdy_protocol.h"
-#include "spdy/platform/api/spdy_bug_tracker.h"
#include "spdy/platform/api/spdy_estimate_memory_usage.h"
-#include "spdy/platform/api/spdy_flags.h"
-#include "spdy/platform/api/spdy_logging.h"
#include "spdy/platform/api/spdy_string_utils.h"
using ::spdy::ExtensionVisitorInterface;
@@ -257,7 +256,7 @@ const char* Http2DecoderAdapter::SpdyFramerErrorToString(
}
Http2DecoderAdapter::Http2DecoderAdapter() {
- SPDY_DVLOG(1) << "Http2DecoderAdapter ctor";
+ QUICHE_DVLOG(1) << "Http2DecoderAdapter ctor";
ResetInternal();
}
@@ -335,7 +334,7 @@ size_t Http2DecoderAdapter::EstimateMemoryUsage() const {
// This function is largely based on Http2DecoderAdapter::ValidateFrameHeader
// and some parts of Http2DecoderAdapter::ProcessCommonHeader.
bool Http2DecoderAdapter::OnFrameHeader(const Http2FrameHeader& header) {
- SPDY_DVLOG(1) << "OnFrameHeader: " << header;
+ QUICHE_DVLOG(1) << "OnFrameHeader: " << header;
decoded_frame_header_ = true;
if (!latched_probable_http_response_) {
latched_probable_http_response_ = header.IsProbableHttpResponse();
@@ -347,10 +346,10 @@ bool Http2DecoderAdapter::OnFrameHeader(const Http2FrameHeader& header) {
// Report an unexpected frame error and close the connection if we
// expect a known frame type (probably CONTINUATION) and receive an
// unknown frame.
- SPDY_VLOG(1) << "The framer was expecting to receive a "
- << expected_frame_type_
- << " frame, but instead received an unknown frame of type "
- << header.type;
+ QUICHE_VLOG(1) << "The framer was expecting to receive a "
+ << expected_frame_type_
+ << " frame, but instead received an unknown frame of type "
+ << header.type;
SetSpdyErrorAndNotify(SpdyFramerError::SPDY_UNEXPECTED_FRAME, "");
return false;
}
@@ -366,34 +365,35 @@ bool Http2DecoderAdapter::OnFrameHeader(const Http2FrameHeader& header) {
visitor()->OnUnknownFrame(header.stream_id, raw_frame_type);
if (!valid_stream) {
// Report an invalid frame error if the stream_id is not valid.
- SPDY_VLOG(1) << "Unknown control frame type " << header.type
- << " received on invalid stream " << header.stream_id;
+ QUICHE_VLOG(1) << "Unknown control frame type " << header.type
+ << " received on invalid stream " << header.stream_id;
SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_CONTROL_FRAME, "");
return false;
} else {
- SPDY_DVLOG(1) << "Ignoring unknown frame type " << header.type;
+ QUICHE_DVLOG(1) << "Ignoring unknown frame type " << header.type;
return true;
}
}
SpdyFrameType frame_type = ToSpdyFrameType(header.type);
if (!IsValidHTTP2FrameStreamId(header.stream_id, frame_type)) {
- SPDY_VLOG(1) << "The framer received an invalid streamID of "
- << header.stream_id << " for a frame of type " << header.type;
+ QUICHE_VLOG(1) << "The framer received an invalid streamID of "
+ << header.stream_id << " for a frame of type "
+ << header.type;
SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_STREAM_ID, "");
return false;
}
if (has_expected_frame_type_ && header.type != expected_frame_type_) {
- SPDY_VLOG(1) << "Expected frame type " << expected_frame_type_ << ", not "
- << header.type;
+ QUICHE_VLOG(1) << "Expected frame type " << expected_frame_type_ << ", not "
+ << header.type;
SetSpdyErrorAndNotify(SpdyFramerError::SPDY_UNEXPECTED_FRAME, "");
return false;
}
if (!has_expected_frame_type_ &&
header.type == Http2FrameType::CONTINUATION) {
- SPDY_VLOG(1) << "Got CONTINUATION frame when not expected.";
+ QUICHE_VLOG(1) << "Got CONTINUATION frame when not expected.";
SetSpdyErrorAndNotify(SpdyFramerError::SPDY_UNEXPECTED_FRAME, "");
return false;
}
@@ -411,7 +411,7 @@ bool Http2DecoderAdapter::OnFrameHeader(const Http2FrameHeader& header) {
}
void Http2DecoderAdapter::OnDataStart(const Http2FrameHeader& header) {
- SPDY_DVLOG(1) << "OnDataStart: " << header;
+ QUICHE_DVLOG(1) << "OnDataStart: " << header;
if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
frame_header_ = header;
@@ -422,14 +422,14 @@ void Http2DecoderAdapter::OnDataStart(const Http2FrameHeader& header) {
}
void Http2DecoderAdapter::OnDataPayload(const char* data, size_t len) {
- SPDY_DVLOG(1) << "OnDataPayload: len=" << len;
+ QUICHE_DVLOG(1) << "OnDataPayload: len=" << len;
QUICHE_DCHECK(has_frame_header_);
QUICHE_DCHECK_EQ(frame_header_.type, Http2FrameType::DATA);
visitor()->OnStreamFrameData(frame_header().stream_id, data, len);
}
void Http2DecoderAdapter::OnDataEnd() {
- SPDY_DVLOG(1) << "OnDataEnd";
+ QUICHE_DVLOG(1) << "OnDataEnd";
QUICHE_DCHECK(has_frame_header_);
QUICHE_DCHECK_EQ(frame_header_.type, Http2FrameType::DATA);
if (frame_header().IsEndStream()) {
@@ -439,7 +439,7 @@ void Http2DecoderAdapter::OnDataEnd() {
}
void Http2DecoderAdapter::OnHeadersStart(const Http2FrameHeader& header) {
- SPDY_DVLOG(1) << "OnHeadersStart: " << header;
+ QUICHE_DVLOG(1) << "OnHeadersStart: " << header;
if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
frame_header_ = header;
has_frame_header_ = true;
@@ -462,7 +462,7 @@ void Http2DecoderAdapter::OnHeadersStart(const Http2FrameHeader& header) {
void Http2DecoderAdapter::OnHeadersPriority(
const Http2PriorityFields& priority) {
- SPDY_DVLOG(1) << "OnHeadersPriority: " << priority;
+ QUICHE_DVLOG(1) << "OnHeadersPriority: " << priority;
QUICHE_DCHECK(has_frame_header_);
QUICHE_DCHECK_EQ(frame_type(), Http2FrameType::HEADERS) << frame_header_;
QUICHE_DCHECK(frame_header_.HasPriority());
@@ -470,7 +470,7 @@ void Http2DecoderAdapter::OnHeadersPriority(
on_headers_called_ = true;
ReportReceiveCompressedFrame(frame_header_);
if (!visitor()) {
- SPDY_BUG(spdy_bug_1_1)
+ QUICHE_BUG(spdy_bug_1_1)
<< "Visitor is nullptr, handling priority in headers failed."
<< " priority:" << priority << " frame_header:" << frame_header_;
return;
@@ -483,7 +483,7 @@ void Http2DecoderAdapter::OnHeadersPriority(
}
void Http2DecoderAdapter::OnHpackFragment(const char* data, size_t len) {
- SPDY_DVLOG(1) << "OnHpackFragment: len=" << len;
+ QUICHE_DVLOG(1) << "OnHpackFragment: len=" << len;
on_hpack_fragment_called_ = true;
auto* decoder = GetHpackDecoder();
if (!decoder->HandleControlFrameHeadersData(data, len)) {
@@ -494,14 +494,15 @@ void Http2DecoderAdapter::OnHpackFragment(const char* data, size_t len) {
}
void Http2DecoderAdapter::OnHeadersEnd() {
- SPDY_DVLOG(1) << "OnHeadersEnd";
+ QUICHE_DVLOG(1) << "OnHeadersEnd";
CommonHpackFragmentEnd();
opt_pad_length_.reset();
}
void Http2DecoderAdapter::OnPriorityFrame(const Http2FrameHeader& header,
const Http2PriorityFields& priority) {
- SPDY_DVLOG(1) << "OnPriorityFrame: " << header << "; priority: " << priority;
+ QUICHE_DVLOG(1) << "OnPriorityFrame: " << header
+ << "; priority: " << priority;
if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
visitor()->OnPriority(header.stream_id, priority.stream_dependency,
priority.weight, priority.is_exclusive);
@@ -509,7 +510,7 @@ void Http2DecoderAdapter::OnPriorityFrame(const Http2FrameHeader& header,
}
void Http2DecoderAdapter::OnContinuationStart(const Http2FrameHeader& header) {
- SPDY_DVLOG(1) << "OnContinuationStart: " << header;
+ QUICHE_DVLOG(1) << "OnContinuationStart: " << header;
if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
QUICHE_DCHECK(has_hpack_first_frame_header_);
if (header.stream_id != hpack_first_frame_header_.stream_id) {
@@ -524,12 +525,12 @@ void Http2DecoderAdapter::OnContinuationStart(const Http2FrameHeader& header) {
}
void Http2DecoderAdapter::OnContinuationEnd() {
- SPDY_DVLOG(1) << "OnContinuationEnd";
+ QUICHE_DVLOG(1) << "OnContinuationEnd";
CommonHpackFragmentEnd();
}
void Http2DecoderAdapter::OnPadLength(size_t trailing_length) {
- SPDY_DVLOG(1) << "OnPadLength: " << trailing_length;
+ QUICHE_DVLOG(1) << "OnPadLength: " << trailing_length;
opt_pad_length_ = trailing_length;
QUICHE_DCHECK_LT(trailing_length, 256u);
if (frame_header_.type == Http2FrameType::DATA) {
@@ -539,7 +540,7 @@ void Http2DecoderAdapter::OnPadLength(size_t trailing_length) {
void Http2DecoderAdapter::OnPadding(const char* /*padding*/,
size_t skipped_length) {
- SPDY_DVLOG(1) << "OnPadding: " << skipped_length;
+ QUICHE_DVLOG(1) << "OnPadding: " << skipped_length;
if (frame_header_.type == Http2FrameType::DATA) {
visitor()->OnStreamPadding(stream_id(), skipped_length);
} else {
@@ -549,7 +550,7 @@ void Http2DecoderAdapter::OnPadding(const char* /*padding*/,
void Http2DecoderAdapter::OnRstStream(const Http2FrameHeader& header,
Http2ErrorCode http2_error_code) {
- SPDY_DVLOG(1) << "OnRstStream: " << header << "; code=" << http2_error_code;
+ QUICHE_DVLOG(1) << "OnRstStream: " << header << "; code=" << http2_error_code;
if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
SpdyErrorCode error_code =
ParseErrorCode(static_cast<uint32_t>(http2_error_code));
@@ -558,7 +559,7 @@ void Http2DecoderAdapter::OnRstStream(const Http2FrameHeader& header,
}
void Http2DecoderAdapter::OnSettingsStart(const Http2FrameHeader& header) {
- SPDY_DVLOG(1) << "OnSettingsStart: " << header;
+ QUICHE_DVLOG(1) << "OnSettingsStart: " << header;
if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
frame_header_ = header;
has_frame_header_ = true;
@@ -567,7 +568,7 @@ void Http2DecoderAdapter::OnSettingsStart(const Http2FrameHeader& header) {
}
void Http2DecoderAdapter::OnSetting(const Http2SettingFields& setting_fields) {
- SPDY_DVLOG(1) << "OnSetting: " << setting_fields;
+ QUICHE_DVLOG(1) << "OnSetting: " << setting_fields;
const auto parameter = static_cast<SpdySettingsId>(setting_fields.parameter);
visitor()->OnSetting(parameter, setting_fields.value);
if (extension_ != nullptr) {
@@ -576,12 +577,12 @@ void Http2DecoderAdapter::OnSetting(const Http2SettingFields& setting_fields) {
}
void Http2DecoderAdapter::OnSettingsEnd() {
- SPDY_DVLOG(1) << "OnSettingsEnd";
+ QUICHE_DVLOG(1) << "OnSettingsEnd";
visitor()->OnSettingsEnd();
}
void Http2DecoderAdapter::OnSettingsAck(const Http2FrameHeader& header) {
- SPDY_DVLOG(1) << "OnSettingsAck: " << header;
+ QUICHE_DVLOG(1) << "OnSettingsAck: " << header;
if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
visitor()->OnSettingsAck();
}
@@ -591,8 +592,9 @@ void Http2DecoderAdapter::OnPushPromiseStart(
const Http2FrameHeader& header,
const Http2PushPromiseFields& promise,
size_t total_padding_length) {
- SPDY_DVLOG(1) << "OnPushPromiseStart: " << header << "; promise: " << promise
- << "; total_padding_length: " << total_padding_length;
+ QUICHE_DVLOG(1) << "OnPushPromiseStart: " << header
+ << "; promise: " << promise
+ << "; total_padding_length: " << total_padding_length;
if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
if (promise.promised_stream_id == 0) {
SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_CONTROL_FRAME, "");
@@ -608,14 +610,14 @@ void Http2DecoderAdapter::OnPushPromiseStart(
}
void Http2DecoderAdapter::OnPushPromiseEnd() {
- SPDY_DVLOG(1) << "OnPushPromiseEnd";
+ QUICHE_DVLOG(1) << "OnPushPromiseEnd";
CommonHpackFragmentEnd();
opt_pad_length_.reset();
}
void Http2DecoderAdapter::OnPing(const Http2FrameHeader& header,
const Http2PingFields& ping) {
- SPDY_DVLOG(1) << "OnPing: " << header << "; ping: " << ping;
+ QUICHE_DVLOG(1) << "OnPing: " << header << "; ping: " << ping;
if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
visitor()->OnPing(ToSpdyPingId(ping), false);
}
@@ -623,7 +625,7 @@ void Http2DecoderAdapter::OnPing(const Http2FrameHeader& header,
void Http2DecoderAdapter::OnPingAck(const Http2FrameHeader& header,
const Http2PingFields& ping) {
- SPDY_DVLOG(1) << "OnPingAck: " << header << "; ping: " << ping;
+ QUICHE_DVLOG(1) << "OnPingAck: " << header << "; ping: " << ping;
if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
visitor()->OnPing(ToSpdyPingId(ping), true);
}
@@ -631,7 +633,7 @@ void Http2DecoderAdapter::OnPingAck(const Http2FrameHeader& header,
void Http2DecoderAdapter::OnGoAwayStart(const Http2FrameHeader& header,
const Http2GoAwayFields& goaway) {
- SPDY_DVLOG(1) << "OnGoAwayStart: " << header << "; goaway: " << goaway;
+ QUICHE_DVLOG(1) << "OnGoAwayStart: " << header << "; goaway: " << goaway;
if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
frame_header_ = header;
has_frame_header_ = true;
@@ -642,18 +644,19 @@ void Http2DecoderAdapter::OnGoAwayStart(const Http2FrameHeader& header,
}
void Http2DecoderAdapter::OnGoAwayOpaqueData(const char* data, size_t len) {
- SPDY_DVLOG(1) << "OnGoAwayOpaqueData: len=" << len;
+ QUICHE_DVLOG(1) << "OnGoAwayOpaqueData: len=" << len;
visitor()->OnGoAwayFrameData(data, len);
}
void Http2DecoderAdapter::OnGoAwayEnd() {
- SPDY_DVLOG(1) << "OnGoAwayEnd";
+ QUICHE_DVLOG(1) << "OnGoAwayEnd";
visitor()->OnGoAwayFrameData(nullptr, 0);
}
void Http2DecoderAdapter::OnWindowUpdate(const Http2FrameHeader& header,
uint32_t increment) {
- SPDY_DVLOG(1) << "OnWindowUpdate: " << header << "; increment=" << increment;
+ QUICHE_DVLOG(1) << "OnWindowUpdate: " << header
+ << "; increment=" << increment;
if (IsOkToStartFrame(header)) {
visitor()->OnWindowUpdate(header.stream_id, increment);
}
@@ -666,9 +669,9 @@ void Http2DecoderAdapter::OnWindowUpdate(const Http2FrameHeader& header,
void Http2DecoderAdapter::OnAltSvcStart(const Http2FrameHeader& header,
size_t origin_length,
size_t value_length) {
- SPDY_DVLOG(1) << "OnAltSvcStart: " << header
- << "; origin_length: " << origin_length
- << "; value_length: " << value_length;
+ QUICHE_DVLOG(1) << "OnAltSvcStart: " << header
+ << "; origin_length: " << origin_length
+ << "; value_length: " << value_length;
if (!IsOkToStartFrame(header)) {
return;
}
@@ -679,24 +682,24 @@ void Http2DecoderAdapter::OnAltSvcStart(const Http2FrameHeader& header,
}
void Http2DecoderAdapter::OnAltSvcOriginData(const char* data, size_t len) {
- SPDY_DVLOG(1) << "OnAltSvcOriginData: len=" << len;
+ QUICHE_DVLOG(1) << "OnAltSvcOriginData: len=" << len;
alt_svc_origin_.append(data, len);
}
// Called when decoding the Alt-Svc-Field-Value of an ALTSVC;
// the field is uninterpreted.
void Http2DecoderAdapter::OnAltSvcValueData(const char* data, size_t len) {
- SPDY_DVLOG(1) << "OnAltSvcValueData: len=" << len;
+ QUICHE_DVLOG(1) << "OnAltSvcValueData: len=" << len;
alt_svc_value_.append(data, len);
}
void Http2DecoderAdapter::OnAltSvcEnd() {
- SPDY_DVLOG(1) << "OnAltSvcEnd: origin.size(): " << alt_svc_origin_.size()
- << "; value.size(): " << alt_svc_value_.size();
+ QUICHE_DVLOG(1) << "OnAltSvcEnd: origin.size(): " << alt_svc_origin_.size()
+ << "; value.size(): " << alt_svc_value_.size();
SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
if (!SpdyAltSvcWireFormat::ParseHeaderFieldValue(alt_svc_value_,
&altsvc_vector)) {
- SPDY_DLOG(ERROR) << "SpdyAltSvcWireFormat::ParseHeaderFieldValue failed.";
+ QUICHE_DLOG(ERROR) << "SpdyAltSvcWireFormat::ParseHeaderFieldValue failed.";
SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_CONTROL_FRAME, "");
return;
}
@@ -711,9 +714,9 @@ void Http2DecoderAdapter::OnAltSvcEnd() {
void Http2DecoderAdapter::OnPriorityUpdateStart(
const Http2FrameHeader& header,
const Http2PriorityUpdateFields& priority_update) {
- SPDY_DVLOG(1) << "OnPriorityUpdateStart: " << header
- << "; prioritized_stream_id: "
- << priority_update.prioritized_stream_id;
+ QUICHE_DVLOG(1) << "OnPriorityUpdateStart: " << header
+ << "; prioritized_stream_id: "
+ << priority_update.prioritized_stream_id;
if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header) &&
HasRequiredStreamId(priority_update.prioritized_stream_id)) {
frame_header_ = header;
@@ -724,13 +727,13 @@ void Http2DecoderAdapter::OnPriorityUpdateStart(
void Http2DecoderAdapter::OnPriorityUpdatePayload(const char* data,
size_t len) {
- SPDY_DVLOG(1) << "OnPriorityUpdatePayload: len=" << len;
+ QUICHE_DVLOG(1) << "OnPriorityUpdatePayload: len=" << len;
priority_field_value_.append(data, len);
}
void Http2DecoderAdapter::OnPriorityUpdateEnd() {
- SPDY_DVLOG(1) << "OnPriorityUpdateEnd: priority_field_value.size(): "
- << priority_field_value_.size();
+ QUICHE_DVLOG(1) << "OnPriorityUpdateEnd: priority_field_value.size(): "
+ << priority_field_value_.size();
visitor()->OnPriorityUpdate(prioritized_stream_id_, priority_field_value_);
priority_field_value_.clear();
}
@@ -738,7 +741,7 @@ void Http2DecoderAdapter::OnPriorityUpdateEnd() {
// Except for BLOCKED frames, all other unknown frames are either dropped or
// passed to a registered extension.
void Http2DecoderAdapter::OnUnknownStart(const Http2FrameHeader& header) {
- SPDY_DVLOG(1) << "OnUnknownStart: " << header;
+ QUICHE_DVLOG(1) << "OnUnknownStart: " << header;
if (IsOkToStartFrame(header)) {
if (extension_ != nullptr) {
const uint8_t type = static_cast<uint8_t>(header.type);
@@ -753,19 +756,19 @@ void Http2DecoderAdapter::OnUnknownPayload(const char* data, size_t len) {
if (handling_extension_payload_) {
extension_->OnFramePayload(data, len);
} else {
- SPDY_DVLOG(1) << "OnUnknownPayload: len=" << len;
+ QUICHE_DVLOG(1) << "OnUnknownPayload: len=" << len;
}
}
void Http2DecoderAdapter::OnUnknownEnd() {
- SPDY_DVLOG(1) << "OnUnknownEnd";
+ QUICHE_DVLOG(1) << "OnUnknownEnd";
handling_extension_payload_ = false;
}
void Http2DecoderAdapter::OnPaddingTooLong(const Http2FrameHeader& header,
size_t missing_length) {
- SPDY_DVLOG(1) << "OnPaddingTooLong: " << header
- << "; missing_length: " << missing_length;
+ QUICHE_DVLOG(1) << "OnPaddingTooLong: " << header
+ << "; missing_length: " << missing_length;
if (header.type == Http2FrameType::DATA) {
if (header.payload_length == 0) {
QUICHE_DCHECK_EQ(1u, missing_length);
@@ -778,7 +781,7 @@ void Http2DecoderAdapter::OnPaddingTooLong(const Http2FrameHeader& header,
}
void Http2DecoderAdapter::OnFrameSizeError(const Http2FrameHeader& header) {
- SPDY_DVLOG(1) << "OnFrameSizeError: " << header;
+ QUICHE_DVLOG(1) << "OnFrameSizeError: " << header;
size_t recv_limit = recv_frame_size_limit_;
if (header.payload_length > recv_limit) {
SetSpdyErrorAndNotify(SpdyFramerError::SPDY_OVERSIZED_PAYLOAD, "");
@@ -809,8 +812,8 @@ size_t Http2DecoderAdapter::ProcessInputFrame(const char* data, size_t len) {
if (spdy_state_ != SpdyState::SPDY_ERROR) {
DetermineSpdyState(status);
} else {
- SPDY_VLOG(1) << "ProcessInputFrame spdy_framer_error_="
- << SpdyFramerErrorToString(spdy_framer_error_);
+ QUICHE_VLOG(1) << "ProcessInputFrame spdy_framer_error_="
+ << SpdyFramerErrorToString(spdy_framer_error_);
if (spdy_framer_error_ == SpdyFramerError::SPDY_INVALID_PADDING &&
has_frame_header_ && frame_type() != Http2FrameType::DATA) {
// spdy_framer_test checks that all of the available frame payload
@@ -818,11 +821,11 @@ size_t Http2DecoderAdapter::ProcessInputFrame(const char* data, size_t len) {
size_t total = remaining_total_payload();
if (total <= frame_header().payload_length) {
size_t avail = db.MinLengthRemaining(total);
- SPDY_VLOG(1) << "Skipping past " << avail << " bytes, of " << total
- << " total remaining in the frame's payload.";
+ QUICHE_VLOG(1) << "Skipping past " << avail << " bytes, of " << total
+ << " total remaining in the frame's payload.";
db.AdvanceCursor(avail);
} else {
- SPDY_BUG(spdy_bug_1_2)
+ QUICHE_BUG(spdy_bug_1_2)
<< "Total remaining (" << total
<< ") should not be greater than the payload length; "
<< frame_header();
@@ -841,11 +844,11 @@ void Http2DecoderAdapter::DetermineSpdyState(DecodeStatus status) {
QUICHE_DCHECK(!HasError()) << spdy_framer_error_;
switch (status) {
case DecodeStatus::kDecodeDone:
- SPDY_DVLOG(1) << "ProcessInputFrame -> DecodeStatus::kDecodeDone";
+ QUICHE_DVLOG(1) << "ProcessInputFrame -> DecodeStatus::kDecodeDone";
ResetBetweenFrames();
break;
case DecodeStatus::kDecodeInProgress:
- SPDY_DVLOG(1) << "ProcessInputFrame -> DecodeStatus::kDecodeInProgress";
+ QUICHE_DVLOG(1) << "ProcessInputFrame -> DecodeStatus::kDecodeInProgress";
if (decoded_frame_header_) {
if (IsDiscardingPayload()) {
set_spdy_state(SpdyState::SPDY_IGNORE_REMAINING_PAYLOAD);
@@ -865,7 +868,7 @@ void Http2DecoderAdapter::DetermineSpdyState(DecodeStatus status) {
}
break;
case DecodeStatus::kDecodeError:
- SPDY_VLOG(1) << "ProcessInputFrame -> DecodeStatus::kDecodeError";
+ QUICHE_VLOG(1) << "ProcessInputFrame -> DecodeStatus::kDecodeError";
if (IsDiscardingPayload()) {
if (remaining_total_payload() == 0) {
// Push the Http2FrameDecoder out of state kDiscardPayload now
@@ -873,11 +876,11 @@ void Http2DecoderAdapter::DetermineSpdyState(DecodeStatus status) {
DecodeBuffer tmp("", 0);
DecodeStatus status = frame_decoder_->DecodeFrame(&tmp);
if (status != DecodeStatus::kDecodeDone) {
- SPDY_BUG(spdy_bug_1_3)
+ QUICHE_BUG(spdy_bug_1_3)
<< "Expected to be done decoding the frame, not " << status;
SetSpdyErrorAndNotify(SPDY_INTERNAL_FRAMER_ERROR, "");
} else if (spdy_framer_error_ != SPDY_NO_ERROR) {
- SPDY_BUG(spdy_bug_1_4)
+ QUICHE_BUG(spdy_bug_1_4)
<< "Expected to have no error, not "
<< SpdyFramerErrorToString(spdy_framer_error_);
} else {
@@ -921,7 +924,7 @@ void Http2DecoderAdapter::ResetInternal() {
}
void Http2DecoderAdapter::set_spdy_state(SpdyState v) {
- SPDY_DVLOG(2) << "set_spdy_state(" << StateToString(v) << ")";
+ QUICHE_DVLOG(2) << "set_spdy_state(" << StateToString(v) << ")";
spdy_state_ = v;
}
@@ -930,8 +933,8 @@ void Http2DecoderAdapter::SetSpdyErrorAndNotify(SpdyFramerError error,
if (HasError()) {
QUICHE_DCHECK_EQ(spdy_state_, SpdyState::SPDY_ERROR);
} else {
- SPDY_VLOG(2) << "SetSpdyErrorAndNotify(" << SpdyFramerErrorToString(error)
- << ")";
+ QUICHE_VLOG(2) << "SetSpdyErrorAndNotify(" << SpdyFramerErrorToString(error)
+ << ")";
QUICHE_DCHECK_NE(error, SpdyFramerError::SPDY_NO_ERROR);
spdy_framer_error_ = error;
set_spdy_state(SpdyState::SPDY_ERROR);
@@ -974,33 +977,33 @@ size_t Http2DecoderAdapter::remaining_total_payload() const {
bool Http2DecoderAdapter::IsReadingPaddingLength() {
bool result = frame_header_.IsPadded() && !opt_pad_length_;
- SPDY_DVLOG(2) << "Http2DecoderAdapter::IsReadingPaddingLength: " << result;
+ QUICHE_DVLOG(2) << "Http2DecoderAdapter::IsReadingPaddingLength: " << result;
return result;
}
bool Http2DecoderAdapter::IsSkippingPadding() {
bool result = frame_header_.IsPadded() && opt_pad_length_ &&
frame_decoder_->remaining_payload() == 0 &&
frame_decoder_->remaining_padding() > 0;
- SPDY_DVLOG(2) << "Http2DecoderAdapter::IsSkippingPadding: " << result;
+ QUICHE_DVLOG(2) << "Http2DecoderAdapter::IsSkippingPadding: " << result;
return result;
}
bool Http2DecoderAdapter::IsDiscardingPayload() {
bool result = decoded_frame_header_ && frame_decoder_->IsDiscardingPayload();
- SPDY_DVLOG(2) << "Http2DecoderAdapter::IsDiscardingPayload: " << result;
+ QUICHE_DVLOG(2) << "Http2DecoderAdapter::IsDiscardingPayload: " << result;
return result;
}
// Called from OnXyz or OnXyzStart methods to decide whether it is OK to
// handle the callback.
bool Http2DecoderAdapter::IsOkToStartFrame(const Http2FrameHeader& header) {
- SPDY_DVLOG(3) << "IsOkToStartFrame";
+ QUICHE_DVLOG(3) << "IsOkToStartFrame";
if (HasError()) {
- SPDY_VLOG(2) << "HasError()";
+ QUICHE_VLOG(2) << "HasError()";
return false;
}
QUICHE_DCHECK(!has_frame_header_);
if (has_expected_frame_type_ && header.type != expected_frame_type_) {
- SPDY_VLOG(1) << "Expected frame type " << expected_frame_type_ << ", not "
- << header.type;
+ QUICHE_VLOG(1) << "Expected frame type " << expected_frame_type_ << ", not "
+ << header.type;
SetSpdyErrorAndNotify(SpdyFramerError::SPDY_UNEXPECTED_FRAME, "");
return false;
}
@@ -1009,15 +1012,15 @@ bool Http2DecoderAdapter::IsOkToStartFrame(const Http2FrameHeader& header) {
}
bool Http2DecoderAdapter::HasRequiredStreamId(uint32_t stream_id) {
- SPDY_DVLOG(3) << "HasRequiredStreamId: " << stream_id;
+ QUICHE_DVLOG(3) << "HasRequiredStreamId: " << stream_id;
if (HasError()) {
- SPDY_VLOG(2) << "HasError()";
+ QUICHE_VLOG(2) << "HasError()";
return false;
}
if (stream_id != 0) {
return true;
}
- SPDY_VLOG(1) << "Stream Id is required, but zero provided";
+ QUICHE_VLOG(1) << "Stream Id is required, but zero provided";
SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_STREAM_ID, "");
return false;
}
@@ -1027,15 +1030,15 @@ bool Http2DecoderAdapter::HasRequiredStreamId(const Http2FrameHeader& header) {
}
bool Http2DecoderAdapter::HasRequiredStreamIdZero(uint32_t stream_id) {
- SPDY_DVLOG(3) << "HasRequiredStreamIdZero: " << stream_id;
+ QUICHE_DVLOG(3) << "HasRequiredStreamIdZero: " << stream_id;
if (HasError()) {
- SPDY_VLOG(2) << "HasError()";
+ QUICHE_VLOG(2) << "HasError()";
return false;
}
if (stream_id == 0) {
return true;
}
- SPDY_VLOG(1) << "Stream Id was not zero, as required: " << stream_id;
+ QUICHE_VLOG(1) << "Stream Id was not zero, as required: " << stream_id;
SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_STREAM_ID, "");
return false;
}
@@ -1062,7 +1065,7 @@ HpackDecoderAdapter* Http2DecoderAdapter::GetHpackDecoder() {
}
void Http2DecoderAdapter::CommonStartHpackBlock() {
- SPDY_DVLOG(1) << "CommonStartHpackBlock";
+ QUICHE_DVLOG(1) << "CommonStartHpackBlock";
QUICHE_DCHECK(!has_hpack_first_frame_header_);
if (!frame_header_.IsEndHeaders()) {
hpack_first_frame_header_ = frame_header_;
@@ -1074,7 +1077,7 @@ void Http2DecoderAdapter::CommonStartHpackBlock() {
SpdyHeadersHandlerInterface* handler =
visitor()->OnHeaderFrameStart(stream_id());
if (handler == nullptr) {
- SPDY_BUG(spdy_bug_1_5) << "visitor_->OnHeaderFrameStart returned nullptr";
+ QUICHE_BUG(spdy_bug_1_5) << "visitor_->OnHeaderFrameStart returned nullptr";
SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INTERNAL_FRAMER_ERROR, "");
return;
}
@@ -1091,9 +1094,9 @@ void Http2DecoderAdapter::MaybeAnnounceEmptyFirstHpackFragment() {
}
void Http2DecoderAdapter::CommonHpackFragmentEnd() {
- SPDY_DVLOG(1) << "CommonHpackFragmentEnd: stream_id=" << stream_id();
+ QUICHE_DVLOG(1) << "CommonHpackFragmentEnd: stream_id=" << stream_id();
if (HasError()) {
- SPDY_VLOG(1) << "HasError(), returning";
+ QUICHE_VLOG(1) << "HasError(), returning";
return;
}
QUICHE_DCHECK(has_frame_header_);
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.cc b/chromium/net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.cc
index 5b6af98a9ac..94218f697da 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.cc
@@ -9,7 +9,8 @@
#include <limits>
#include "absl/strings/str_cat.h"
-#include "spdy/platform/api/spdy_logging.h"
+
+#include "common/platform/api/quiche_logging.h"
#include "spdy/platform/api/spdy_string_utils.h"
namespace spdy {
@@ -195,9 +196,9 @@ bool SpdyAltSvcWireFormat::ParseHeaderFieldValue(
// hq=":443";quic=51303338
// ... will be stored in |versions| as 0x51303338.
uint32_t quic_version;
- if (!SpdyHexDecodeToUInt32(absl::string_view(&*parameter_value_begin,
- c - parameter_value_begin),
- &quic_version) ||
+ if (!HexDecodeToUInt32(absl::string_view(&*parameter_value_begin,
+ c - parameter_value_begin),
+ &quic_version) ||
quic_version == 0) {
return false;
}
@@ -314,12 +315,12 @@ bool SpdyAltSvcWireFormat::PercentDecode(absl::string_view::const_iterator c,
return false;
}
// Network byte order is big-endian.
- char decoded = SpdyHexDigitToInt(*c) << 4;
+ char decoded = HexDigitToInt(*c) << 4;
++c;
if (c == end || !std::isxdigit(*c)) {
return false;
}
- decoded += SpdyHexDigitToInt(*c);
+ decoded += HexDigitToInt(*c);
output->push_back(decoded);
}
return true;
@@ -388,4 +389,41 @@ bool SpdyAltSvcWireFormat::ParsePositiveInteger32(
return ParsePositiveIntegerImpl<uint32_t>(c, end, value);
}
+// static
+char SpdyAltSvcWireFormat::HexDigitToInt(char c) {
+ QUICHE_DCHECK(std::isxdigit(c));
+
+ if (std::isdigit(c)) {
+ return c - '0';
+ }
+ if (c >= 'A' && c <= 'F') {
+ return c - 'A' + 10;
+ }
+ if (c >= 'a' && c <= 'f') {
+ return c - 'a' + 10;
+ }
+
+ return 0;
+}
+
+// static
+bool SpdyAltSvcWireFormat::HexDecodeToUInt32(absl::string_view data,
+ uint32_t* value) {
+ if (data.empty() || data.length() > 8u) {
+ return false;
+ }
+
+ *value = 0;
+ for (char c : data) {
+ if (!std::isxdigit(c)) {
+ return false;
+ }
+
+ *value <<= 4;
+ *value += HexDigitToInt(c);
+ }
+
+ return true;
+}
+
} // namespace spdy
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.h b/chromium/net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.h
index fccda75ac6e..a8e10948a8c 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.h
@@ -66,21 +66,40 @@ class QUICHE_EXPORT_PRIVATE SpdyAltSvcWireFormat {
const AlternativeServiceVector& altsvc_vector);
private:
+ // Forward |*c| over space and tab or until |end| is reached.
static void SkipWhiteSpace(absl::string_view::const_iterator* c,
absl::string_view::const_iterator end);
+ // Decode percent-decoded string between |c| and |end| into |*output|.
+ // Return true on success, false if input is invalid.
static bool PercentDecode(absl::string_view::const_iterator c,
absl::string_view::const_iterator end,
std::string* output);
+ // Parse the authority part of Alt-Svc between |c| and |end| into |*host| and
+ // |*port|. Return true on success, false if input is invalid.
static bool ParseAltAuthority(absl::string_view::const_iterator c,
absl::string_view::const_iterator end,
std::string* host,
uint16_t* port);
+ // Parse a positive integer between |c| and |end| into |*value|.
+ // Return true on success, false if input is not a positive integer or it
+ // cannot be represented on uint16_t.
static bool ParsePositiveInteger16(absl::string_view::const_iterator c,
absl::string_view::const_iterator end,
uint16_t* value);
+ // Parse a positive integer between |c| and |end| into |*value|.
+ // Return true on success, false if input is not a positive integer or it
+ // cannot be represented on uint32_t.
static bool ParsePositiveInteger32(absl::string_view::const_iterator c,
absl::string_view::const_iterator end,
uint32_t* value);
+ // Parse |c| as hexadecimal digit, case insensitive. |c| must be [0-9a-fA-F].
+ // Output is between 0 and 15.
+ static char HexDigitToInt(char c);
+ // Parse |data| as hexadecimal number into |*value|. |data| must only contain
+ // hexadecimal digits, no "0x" prefix.
+ // Return true on success, false if input is empty, not valid hexadecimal
+ // number, or cannot be represented on uint32_t.
+ static bool HexDecodeToUInt32(absl::string_view data, uint32_t* value);
};
} // namespace spdy
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format_test.cc b/chromium/net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format_test.cc
index e698c2f690b..497f19dad86 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format_test.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format_test.cc
@@ -5,7 +5,6 @@
#include "spdy/core/spdy_alt_svc_wire_format.h"
#include "common/platform/api/quiche_test.h"
-#include "spdy/platform/api/spdy_logging.h"
namespace spdy {
@@ -39,10 +38,14 @@ class SpdyAltSvcWireFormatPeer {
uint32_t* max_age) {
return SpdyAltSvcWireFormat::ParsePositiveInteger32(c, end, max_age);
}
+ static char HexDigitToInt(char c) {
+ return SpdyAltSvcWireFormat::HexDigitToInt(c);
+ }
+ static bool HexDecodeToUInt32(absl::string_view data, uint32_t* value) {
+ return SpdyAltSvcWireFormat::HexDecodeToUInt32(data, value);
+ }
};
-} // namespace test
-
namespace {
// Generate header field values, possibly with multiply defined parameters and
@@ -389,13 +392,13 @@ TEST(SpdyAltSvcWireFormatTest, ParseTruncatedHeaderFieldValue) {
TEST(SpdyAltSvcWireFormatTest, SkipWhiteSpace) {
absl::string_view input("a \tb ");
absl::string_view::const_iterator c = input.begin();
- test::SpdyAltSvcWireFormatPeer::SkipWhiteSpace(&c, input.end());
+ SpdyAltSvcWireFormatPeer::SkipWhiteSpace(&c, input.end());
ASSERT_EQ(input.begin(), c);
++c;
- test::SpdyAltSvcWireFormatPeer::SkipWhiteSpace(&c, input.end());
+ SpdyAltSvcWireFormatPeer::SkipWhiteSpace(&c, input.end());
ASSERT_EQ(input.begin() + 3, c);
++c;
- test::SpdyAltSvcWireFormatPeer::SkipWhiteSpace(&c, input.end());
+ SpdyAltSvcWireFormatPeer::SkipWhiteSpace(&c, input.end());
ASSERT_EQ(input.end(), c);
}
@@ -403,20 +406,20 @@ TEST(SpdyAltSvcWireFormatTest, SkipWhiteSpace) {
TEST(SpdyAltSvcWireFormatTest, PercentDecodeValid) {
absl::string_view input("");
std::string output;
- ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::PercentDecode(
- input.begin(), input.end(), &output));
+ ASSERT_TRUE(SpdyAltSvcWireFormatPeer::PercentDecode(input.begin(),
+ input.end(), &output));
EXPECT_EQ("", output);
input = absl::string_view("foo");
output.clear();
- ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::PercentDecode(
- input.begin(), input.end(), &output));
+ ASSERT_TRUE(SpdyAltSvcWireFormatPeer::PercentDecode(input.begin(),
+ input.end(), &output));
EXPECT_EQ("foo", output);
input = absl::string_view("%2ca%5Cb");
output.clear();
- ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::PercentDecode(
- input.begin(), input.end(), &output));
+ ASSERT_TRUE(SpdyAltSvcWireFormatPeer::PercentDecode(input.begin(),
+ input.end(), &output));
EXPECT_EQ(",a\\b", output);
}
@@ -426,8 +429,8 @@ TEST(SpdyAltSvcWireFormatTest, PercentDecodeInvalid) {
for (const char* invalid_input : invalid_input_array) {
absl::string_view input(invalid_input);
std::string output;
- EXPECT_FALSE(test::SpdyAltSvcWireFormatPeer::PercentDecode(
- input.begin(), input.end(), &output))
+ EXPECT_FALSE(SpdyAltSvcWireFormatPeer::PercentDecode(input.begin(),
+ input.end(), &output))
<< input;
}
}
@@ -437,19 +440,19 @@ TEST(SpdyAltSvcWireFormatTest, ParseAltAuthorityValid) {
absl::string_view input(":42");
std::string host;
uint16_t port;
- ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseAltAuthority(
+ ASSERT_TRUE(SpdyAltSvcWireFormatPeer::ParseAltAuthority(
input.begin(), input.end(), &host, &port));
EXPECT_TRUE(host.empty());
EXPECT_EQ(42, port);
input = absl::string_view("foo:137");
- ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseAltAuthority(
+ ASSERT_TRUE(SpdyAltSvcWireFormatPeer::ParseAltAuthority(
input.begin(), input.end(), &host, &port));
EXPECT_EQ("foo", host);
EXPECT_EQ(137, port);
input = absl::string_view("[2003:8:0:16::509d:9615]:443");
- ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseAltAuthority(
+ ASSERT_TRUE(SpdyAltSvcWireFormatPeer::ParseAltAuthority(
input.begin(), input.end(), &host, &port));
EXPECT_EQ("[2003:8:0:16::509d:9615]", host);
EXPECT_EQ(443, port);
@@ -478,7 +481,7 @@ TEST(SpdyAltSvcWireFormatTest, ParseAltAuthorityInvalid) {
absl::string_view input(invalid_input);
std::string host;
uint16_t port;
- EXPECT_FALSE(test::SpdyAltSvcWireFormatPeer::ParseAltAuthority(
+ EXPECT_FALSE(SpdyAltSvcWireFormatPeer::ParseAltAuthority(
input.begin(), input.end(), &host, &port))
<< input;
}
@@ -488,12 +491,12 @@ TEST(SpdyAltSvcWireFormatTest, ParseAltAuthorityInvalid) {
TEST(SpdyAltSvcWireFormatTest, ParseIntegerValid) {
absl::string_view input("3");
uint16_t value;
- ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16(
+ ASSERT_TRUE(SpdyAltSvcWireFormatPeer::ParsePositiveInteger16(
input.begin(), input.end(), &value));
EXPECT_EQ(3, value);
input = absl::string_view("1337");
- ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16(
+ ASSERT_TRUE(SpdyAltSvcWireFormatPeer::ParsePositiveInteger16(
input.begin(), input.end(), &value));
EXPECT_EQ(1337, value);
}
@@ -505,7 +508,7 @@ TEST(SpdyAltSvcWireFormatTest, ParseIntegerInvalid) {
for (const char* invalid_input : invalid_input_array) {
absl::string_view input(invalid_input);
uint16_t value;
- EXPECT_FALSE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16(
+ EXPECT_FALSE(SpdyAltSvcWireFormatPeer::ParsePositiveInteger16(
input.begin(), input.end(), &value))
<< input;
}
@@ -516,38 +519,38 @@ TEST(SpdyAltSvcWireFormatTest, ParseIntegerOverflow) {
// Largest possible uint16_t value.
absl::string_view input("65535");
uint16_t value16;
- ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16(
+ ASSERT_TRUE(SpdyAltSvcWireFormatPeer::ParsePositiveInteger16(
input.begin(), input.end(), &value16));
EXPECT_EQ(65535, value16);
// Overflow uint16_t, ParsePositiveInteger16() should return false.
input = absl::string_view("65536");
- ASSERT_FALSE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16(
+ ASSERT_FALSE(SpdyAltSvcWireFormatPeer::ParsePositiveInteger16(
input.begin(), input.end(), &value16));
// However, even if overflow is not checked for, 65536 overflows to 0, which
// returns false anyway. Check for a larger number which overflows to 1.
input = absl::string_view("65537");
- ASSERT_FALSE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16(
+ ASSERT_FALSE(SpdyAltSvcWireFormatPeer::ParsePositiveInteger16(
input.begin(), input.end(), &value16));
// Largest possible uint32_t value.
input = absl::string_view("4294967295");
uint32_t value32;
- ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger32(
+ ASSERT_TRUE(SpdyAltSvcWireFormatPeer::ParsePositiveInteger32(
input.begin(), input.end(), &value32));
EXPECT_EQ(4294967295, value32);
// Overflow uint32_t, ParsePositiveInteger32() should return false.
input = absl::string_view("4294967296");
- ASSERT_FALSE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger32(
+ ASSERT_FALSE(SpdyAltSvcWireFormatPeer::ParsePositiveInteger32(
input.begin(), input.end(), &value32));
// However, even if overflow is not checked for, 4294967296 overflows to 0,
// which returns false anyway. Check for a larger number which overflows to
// 1.
input = absl::string_view("4294967297");
- ASSERT_FALSE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger32(
+ ASSERT_FALSE(SpdyAltSvcWireFormatPeer::ParsePositiveInteger32(
input.begin(), input.end(), &value32));
}
@@ -567,6 +570,64 @@ TEST(SpdyAltSvcWireFormatTest, ParseIPLiteral) {
EXPECT_THAT(altsvc_vector[0].version, ::testing::ElementsAre(36, 35));
}
+TEST(SpdyAltSvcWireFormatTest, HexDigitToInt) {
+ EXPECT_EQ(0, SpdyAltSvcWireFormatPeer::HexDigitToInt('0'));
+ EXPECT_EQ(1, SpdyAltSvcWireFormatPeer::HexDigitToInt('1'));
+ EXPECT_EQ(2, SpdyAltSvcWireFormatPeer::HexDigitToInt('2'));
+ EXPECT_EQ(3, SpdyAltSvcWireFormatPeer::HexDigitToInt('3'));
+ EXPECT_EQ(4, SpdyAltSvcWireFormatPeer::HexDigitToInt('4'));
+ EXPECT_EQ(5, SpdyAltSvcWireFormatPeer::HexDigitToInt('5'));
+ EXPECT_EQ(6, SpdyAltSvcWireFormatPeer::HexDigitToInt('6'));
+ EXPECT_EQ(7, SpdyAltSvcWireFormatPeer::HexDigitToInt('7'));
+ EXPECT_EQ(8, SpdyAltSvcWireFormatPeer::HexDigitToInt('8'));
+ EXPECT_EQ(9, SpdyAltSvcWireFormatPeer::HexDigitToInt('9'));
+
+ EXPECT_EQ(10, SpdyAltSvcWireFormatPeer::HexDigitToInt('a'));
+ EXPECT_EQ(11, SpdyAltSvcWireFormatPeer::HexDigitToInt('b'));
+ EXPECT_EQ(12, SpdyAltSvcWireFormatPeer::HexDigitToInt('c'));
+ EXPECT_EQ(13, SpdyAltSvcWireFormatPeer::HexDigitToInt('d'));
+ EXPECT_EQ(14, SpdyAltSvcWireFormatPeer::HexDigitToInt('e'));
+ EXPECT_EQ(15, SpdyAltSvcWireFormatPeer::HexDigitToInt('f'));
+
+ EXPECT_EQ(10, SpdyAltSvcWireFormatPeer::HexDigitToInt('A'));
+ EXPECT_EQ(11, SpdyAltSvcWireFormatPeer::HexDigitToInt('B'));
+ EXPECT_EQ(12, SpdyAltSvcWireFormatPeer::HexDigitToInt('C'));
+ EXPECT_EQ(13, SpdyAltSvcWireFormatPeer::HexDigitToInt('D'));
+ EXPECT_EQ(14, SpdyAltSvcWireFormatPeer::HexDigitToInt('E'));
+ EXPECT_EQ(15, SpdyAltSvcWireFormatPeer::HexDigitToInt('F'));
+}
+
+TEST(SpdyAltSvcWireFormatTest, HexDecodeToUInt32) {
+ uint32_t out;
+ EXPECT_TRUE(SpdyAltSvcWireFormatPeer::HexDecodeToUInt32("0", &out));
+ EXPECT_EQ(0u, out);
+ EXPECT_TRUE(SpdyAltSvcWireFormatPeer::HexDecodeToUInt32("00", &out));
+ EXPECT_EQ(0u, out);
+ EXPECT_TRUE(SpdyAltSvcWireFormatPeer::HexDecodeToUInt32("0000000", &out));
+ EXPECT_EQ(0u, out);
+ EXPECT_TRUE(SpdyAltSvcWireFormatPeer::HexDecodeToUInt32("00000000", &out));
+ EXPECT_EQ(0u, out);
+ EXPECT_TRUE(SpdyAltSvcWireFormatPeer::HexDecodeToUInt32("1", &out));
+ EXPECT_EQ(1u, out);
+ EXPECT_TRUE(SpdyAltSvcWireFormatPeer::HexDecodeToUInt32("ffffFFF", &out));
+ EXPECT_EQ(0xFFFFFFFu, out);
+ EXPECT_TRUE(SpdyAltSvcWireFormatPeer::HexDecodeToUInt32("fFfFffFf", &out));
+ EXPECT_EQ(0xFFFFFFFFu, out);
+ EXPECT_TRUE(SpdyAltSvcWireFormatPeer::HexDecodeToUInt32("01AEF", &out));
+ EXPECT_EQ(0x1AEFu, out);
+ EXPECT_TRUE(SpdyAltSvcWireFormatPeer::HexDecodeToUInt32("abcde", &out));
+ EXPECT_EQ(0xABCDEu, out);
+ EXPECT_TRUE(SpdyAltSvcWireFormatPeer::HexDecodeToUInt32("1234abcd", &out));
+ EXPECT_EQ(0x1234ABCDu, out);
+
+ EXPECT_FALSE(SpdyAltSvcWireFormatPeer::HexDecodeToUInt32("", &out));
+ EXPECT_FALSE(SpdyAltSvcWireFormatPeer::HexDecodeToUInt32("111111111", &out));
+ EXPECT_FALSE(SpdyAltSvcWireFormatPeer::HexDecodeToUInt32("1111111111", &out));
+ EXPECT_FALSE(SpdyAltSvcWireFormatPeer::HexDecodeToUInt32("0x1111", &out));
+}
+
} // namespace
+} // namespace test
+
} // namespace spdy
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_frame_builder.cc b/chromium/net/third_party/quiche/src/spdy/core/spdy_frame_builder.cc
index ee63594ca6c..0b75271bf44 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_frame_builder.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_frame_builder.cc
@@ -9,10 +9,10 @@
#include <limits>
#include <new>
+#include "common/platform/api/quiche_bug_tracker.h"
+#include "common/platform/api/quiche_logging.h"
#include "spdy/core/spdy_protocol.h"
#include "spdy/core/zero_copy_output_buffer.h"
-#include "spdy/platform/api/spdy_bug_tracker.h"
-#include "spdy/platform/api/spdy_logging.h"
namespace spdy {
@@ -69,7 +69,7 @@ bool SpdyFrameBuilder::BeginNewFrame(SpdyFrameType type,
QUICHE_DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
bool success = true;
if (length_ > 0) {
- SPDY_BUG(spdy_bug_73_1)
+ QUICHE_BUG(spdy_bug_73_1)
<< "SpdyFrameBuilder doesn't have a clean state when BeginNewFrame"
<< "is called. Leftover length_ is " << length_;
offset_ += length_;
@@ -91,7 +91,7 @@ bool SpdyFrameBuilder::BeginNewFrame(SpdyFrameType type,
uint8_t raw_frame_type = SerializeFrameType(type);
QUICHE_DCHECK(IsDefinedFrameType(raw_frame_type));
QUICHE_DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
- SPDY_BUG_IF(spdy_bug_73_2, length > kHttp2DefaultFramePayloadLimit)
+ QUICHE_BUG_IF(spdy_bug_73_2, length > kHttp2DefaultFramePayloadLimit)
<< "Frame length " << length_ << " is longer than frame size limit.";
return BeginNewFrameInternal(raw_frame_type, flags, stream_id, length);
}
@@ -168,8 +168,9 @@ bool SpdyFrameBuilder::CanWrite(size_t length) const {
if (output_ == nullptr) {
if (offset_ + length_ + length > capacity_) {
- SPDY_DLOG(FATAL) << "Requested: " << length << " capacity: " << capacity_
- << " used: " << offset_ + length_;
+ QUICHE_DLOG(FATAL) << "Requested: " << length
+ << " capacity: " << capacity_
+ << " used: " << offset_ + length_;
return false;
}
} else {
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_frame_builder.h b/chromium/net/third_party/quiche/src/spdy/core/spdy_frame_builder.h
index 01fce6be819..4625aa18a41 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_frame_builder.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_frame_builder.h
@@ -10,11 +10,11 @@
#include <memory>
#include "absl/strings/string_view.h"
+#include "common/platform/api/quiche_bug_tracker.h"
#include "common/platform/api/quiche_export.h"
#include "common/quiche_endian.h"
#include "spdy/core/spdy_protocol.h"
#include "spdy/core/zero_copy_output_buffer.h"
-#include "spdy/platform/api/spdy_bug_tracker.h"
namespace spdy {
@@ -66,10 +66,10 @@ class QUICHE_EXPORT_PRIVATE SpdyFrameBuilder {
// Takes the buffer from the SpdyFrameBuilder.
SpdySerializedFrame take() {
- SPDY_BUG_IF(spdy_bug_39_1, output_ != nullptr)
+ QUICHE_BUG_IF(spdy_bug_39_1, output_ != nullptr)
<< "ZeroCopyOutputBuffer is used to build "
<< "frames. take() shouldn't be called";
- SPDY_BUG_IF(spdy_bug_39_2, kMaxFrameSizeLimit < length_)
+ QUICHE_BUG_IF(spdy_bug_39_2, kMaxFrameSizeLimit < length_)
<< "Frame length " << length_
<< " is longer than the maximum possible allowed length.";
SpdySerializedFrame rv(buffer_.release(), length(), true);
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_framer.cc b/chromium/net/third_party/quiche/src/spdy/core/spdy_framer.cc
index bc7cd1767a0..d6f0f889876 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_framer.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_framer.cc
@@ -13,12 +13,12 @@
#include "absl/memory/memory.h"
#include "http2/platform/api/http2_macros.h"
+#include "common/platform/api/quiche_bug_tracker.h"
+#include "common/platform/api/quiche_logging.h"
#include "spdy/core/spdy_bitmasks.h"
#include "spdy/core/spdy_frame_builder.h"
#include "spdy/core/spdy_frame_reader.h"
-#include "spdy/platform/api/spdy_bug_tracker.h"
#include "spdy/platform/api/spdy_estimate_memory_usage.h"
-#include "spdy/platform/api/spdy_logging.h"
#include "spdy/platform/api/spdy_string_utils.h"
namespace spdy {
@@ -129,7 +129,8 @@ bool SerializeHeadersGivenEncoding(const SpdyHeadersIR& headers,
}
if (!ret) {
- SPDY_DLOG(WARNING) << "Failed to build HEADERS. Not enough space in output";
+ QUICHE_DLOG(WARNING)
+ << "Failed to build HEADERS. Not enough space in output";
}
return ret;
}
@@ -159,7 +160,7 @@ bool SerializePushPromiseGivenEncoding(const SpdyPushPromiseIR& push_promise,
ok = builder.WriteBytes(padding.data(), padding.length());
}
- SPDY_DLOG_IF(ERROR, !ok)
+ QUICHE_DLOG_IF(ERROR, !ok)
<< "Failed to write PUSH_PROMISE encoding, not enough "
<< "space in output";
return ok;
@@ -177,8 +178,8 @@ bool WritePayloadWithContinuation(SpdyFrameBuilder* builder,
} else if (type == SpdyFrameType::PUSH_PROMISE) {
end_flag = PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
} else {
- SPDY_DLOG(FATAL) << "CONTINUATION frames cannot be used with frame type "
- << FrameTypeToString(type);
+ QUICHE_DLOG(FATAL) << "CONTINUATION frames cannot be used with frame type "
+ << FrameTypeToString(type);
}
// Write all the padding payload and as much of the data payload as possible
@@ -294,7 +295,7 @@ SpdyFramer::SpdyFrameIterator::~SpdyFrameIterator() = default;
size_t SpdyFramer::SpdyFrameIterator::NextFrame(ZeroCopyOutputBuffer* output) {
const SpdyFrameIR& frame_ir = GetIR();
if (!has_next_frame_) {
- SPDY_BUG(spdy_bug_75_1)
+ QUICHE_BUG(spdy_bug_75_1)
<< "SpdyFramer::SpdyFrameIterator::NextFrame called without "
<< "a next frame.";
return false;
@@ -422,7 +423,7 @@ std::unique_ptr<SpdyFrameSequence> SpdyFramer::CreateIterator(
frame_ir.release())));
}
case SpdyFrameType::DATA: {
- SPDY_DVLOG(1) << "Serialize a stream end DATA frame for VTL";
+ QUICHE_DVLOG(1) << "Serialize a stream end DATA frame for VTL";
HTTP2_FALLTHROUGH;
}
default: {
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_framer_test.cc b/chromium/net/third_party/quiche/src/spdy/core/spdy_framer_test.cc
index d7fb6a7a332..c4b5979a874 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_framer_test.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_framer_test.cc
@@ -14,6 +14,7 @@
#include <vector>
#include "absl/base/macros.h"
+#include "common/platform/api/quiche_logging.h"
#include "common/platform/api/quiche_test.h"
#include "spdy/core/array_output_buffer.h"
#include "spdy/core/mock_spdy_framer_visitor.h"
@@ -23,8 +24,6 @@
#include "spdy/core/spdy_frame_reader.h"
#include "spdy/core/spdy_protocol.h"
#include "spdy/core/spdy_test_utils.h"
-#include "spdy/platform/api/spdy_flags.h"
-#include "spdy/platform/api/spdy_logging.h"
#include "spdy/platform/api/spdy_string_utils.h"
using ::http2::Http2DecoderAdapter;
@@ -62,7 +61,7 @@ MATCHER_P(IsFrameUnionOf, frame_list, "") {
size_t size_verified = 0;
for (const auto& frame : *frame_list) {
if (arg.size() < size_verified + frame.size()) {
- SPDY_LOG(FATAL)
+ QUICHE_LOG(FATAL)
<< "Incremental header serialization should not lead to a "
<< "higher total frame length than non-incremental method.";
return false;
@@ -268,16 +267,16 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
void OnError(Http2DecoderAdapter::SpdyFramerError error,
std::string /*detailed_error*/) override {
- SPDY_VLOG(1) << "SpdyFramer Error: "
- << Http2DecoderAdapter::SpdyFramerErrorToString(error);
+ QUICHE_VLOG(1) << "SpdyFramer Error: "
+ << Http2DecoderAdapter::SpdyFramerErrorToString(error);
++error_count_;
}
void OnDataFrameHeader(SpdyStreamId stream_id,
size_t length,
bool fin) override {
- SPDY_VLOG(1) << "OnDataFrameHeader(" << stream_id << ", " << length << ", "
- << fin << ")";
+ QUICHE_VLOG(1) << "OnDataFrameHeader(" << stream_id << ", " << length
+ << ", " << fin << ")";
++data_frame_count_;
header_stream_id_ = stream_id;
}
@@ -285,30 +284,30 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
void OnStreamFrameData(SpdyStreamId stream_id,
const char* data,
size_t len) override {
- SPDY_VLOG(1) << "OnStreamFrameData(" << stream_id << ", data, " << len
- << ", "
- << ") data:\n"
- << SpdyHexDump(absl::string_view(data, len));
+ QUICHE_VLOG(1) << "OnStreamFrameData(" << stream_id << ", data, " << len
+ << ", "
+ << ") data:\n"
+ << SpdyHexDump(absl::string_view(data, len));
EXPECT_EQ(header_stream_id_, stream_id);
data_bytes_ += len;
}
void OnStreamEnd(SpdyStreamId stream_id) override {
- SPDY_VLOG(1) << "OnStreamEnd(" << stream_id << ")";
+ QUICHE_VLOG(1) << "OnStreamEnd(" << stream_id << ")";
EXPECT_EQ(header_stream_id_, stream_id);
++end_of_stream_count_;
}
void OnStreamPadLength(SpdyStreamId stream_id, size_t value) override {
- SPDY_VLOG(1) << "OnStreamPadding(" << stream_id << ", " << value << ")\n";
+ QUICHE_VLOG(1) << "OnStreamPadding(" << stream_id << ", " << value << ")\n";
EXPECT_EQ(header_stream_id_, stream_id);
// Count the padding length field byte against total data bytes.
data_bytes_ += 1;
}
void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {
- SPDY_VLOG(1) << "OnStreamPadding(" << stream_id << ", " << len << ")\n";
+ QUICHE_VLOG(1) << "OnStreamPadding(" << stream_id << ", " << len << ")\n";
EXPECT_EQ(header_stream_id_, stream_id);
data_bytes_ += len;
}
@@ -329,34 +328,34 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
}
void OnRstStream(SpdyStreamId stream_id, SpdyErrorCode error_code) override {
- SPDY_VLOG(1) << "OnRstStream(" << stream_id << ", " << error_code << ")";
+ QUICHE_VLOG(1) << "OnRstStream(" << stream_id << ", " << error_code << ")";
++fin_frame_count_;
}
void OnSetting(SpdySettingsId id, uint32_t value) override {
- SPDY_VLOG(1) << "OnSetting(" << id << ", " << std::hex << value << ")";
+ QUICHE_VLOG(1) << "OnSetting(" << id << ", " << std::hex << value << ")";
++setting_count_;
}
void OnSettingsAck() override {
- SPDY_VLOG(1) << "OnSettingsAck";
+ QUICHE_VLOG(1) << "OnSettingsAck";
++settings_ack_received_;
}
void OnSettingsEnd() override {
- SPDY_VLOG(1) << "OnSettingsEnd";
+ QUICHE_VLOG(1) << "OnSettingsEnd";
++settings_ack_sent_;
}
void OnPing(SpdyPingId unique_id, bool is_ack) override {
- SPDY_LOG(DFATAL) << "OnPing(" << unique_id << ", " << (is_ack ? 1 : 0)
- << ")";
+ QUICHE_LOG(DFATAL) << "OnPing(" << unique_id << ", " << (is_ack ? 1 : 0)
+ << ")";
}
void OnGoAway(SpdyStreamId last_accepted_stream_id,
SpdyErrorCode error_code) override {
- SPDY_VLOG(1) << "OnGoAway(" << last_accepted_stream_id << ", " << error_code
- << ")";
+ QUICHE_VLOG(1) << "OnGoAway(" << last_accepted_stream_id << ", "
+ << error_code << ")";
++goaway_count_;
}
@@ -367,9 +366,9 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
bool exclusive,
bool fin,
bool end) override {
- SPDY_VLOG(1) << "OnHeaders(" << stream_id << ", " << has_priority << ", "
- << weight << ", " << parent_stream_id << ", " << exclusive
- << ", " << fin << ", " << end << ")";
+ QUICHE_VLOG(1) << "OnHeaders(" << stream_id << ", " << has_priority << ", "
+ << weight << ", " << parent_stream_id << ", " << exclusive
+ << ", " << fin << ", " << end << ")";
++headers_frame_count_;
InitHeaderStreaming(SpdyFrameType::HEADERS, stream_id);
if (fin) {
@@ -381,8 +380,8 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
}
void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) override {
- SPDY_VLOG(1) << "OnWindowUpdate(" << stream_id << ", " << delta_window_size
- << ")";
+ QUICHE_VLOG(1) << "OnWindowUpdate(" << stream_id << ", "
+ << delta_window_size << ")";
last_window_update_stream_ = stream_id;
last_window_update_delta_ = delta_window_size;
}
@@ -390,8 +389,8 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
void OnPushPromise(SpdyStreamId stream_id,
SpdyStreamId promised_stream_id,
bool end) override {
- SPDY_VLOG(1) << "OnPushPromise(" << stream_id << ", " << promised_stream_id
- << ", " << end << ")";
+ QUICHE_VLOG(1) << "OnPushPromise(" << stream_id << ", "
+ << promised_stream_id << ", " << end << ")";
++push_promise_frame_count_;
InitHeaderStreaming(SpdyFrameType::PUSH_PROMISE, stream_id);
last_push_promise_stream_ = stream_id;
@@ -399,7 +398,7 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
}
void OnContinuation(SpdyStreamId stream_id, bool end) override {
- SPDY_VLOG(1) << "OnContinuation(" << stream_id << ", " << end << ")";
+ QUICHE_VLOG(1) << "OnContinuation(" << stream_id << ", " << end << ")";
++continuation_count_;
}
@@ -407,8 +406,8 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
absl::string_view origin,
const SpdyAltSvcWireFormat::AlternativeServiceVector&
altsvc_vector) override {
- SPDY_VLOG(1) << "OnAltSvc(" << stream_id << ", \"" << origin
- << "\", altsvc_vector)";
+ QUICHE_VLOG(1) << "OnAltSvc(" << stream_id << ", \"" << origin
+ << "\", altsvc_vector)";
test_altsvc_ir_ = std::make_unique<SpdyAltSvcIR>(stream_id);
if (origin.length() > 0) {
test_altsvc_ir_->set_origin(std::string(origin));
@@ -423,19 +422,20 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
SpdyStreamId parent_stream_id,
int weight,
bool exclusive) override {
- SPDY_VLOG(1) << "OnPriority(" << stream_id << ", " << parent_stream_id
- << ", " << weight << ", " << (exclusive ? 1 : 0) << ")";
+ QUICHE_VLOG(1) << "OnPriority(" << stream_id << ", " << parent_stream_id
+ << ", " << weight << ", " << (exclusive ? 1 : 0) << ")";
++priority_count_;
}
void OnPriorityUpdate(SpdyStreamId prioritized_stream_id,
absl::string_view priority_field_value) override {
- SPDY_VLOG(1) << "OnPriorityUpdate(" << prioritized_stream_id << ", "
- << priority_field_value << ")";
+ QUICHE_VLOG(1) << "OnPriorityUpdate(" << prioritized_stream_id << ", "
+ << priority_field_value << ")";
}
bool OnUnknownFrame(SpdyStreamId stream_id, uint8_t frame_type) override {
- SPDY_VLOG(1) << "OnUnknownFrame(" << stream_id << ", " << frame_type << ")";
+ QUICHE_VLOG(1) << "OnUnknownFrame(" << stream_id << ", " << frame_type
+ << ")";
return on_unknown_frame_result_;
}
@@ -443,8 +443,8 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
SpdyFrameType type,
size_t payload_len,
size_t frame_len) override {
- SPDY_VLOG(1) << "OnSendCompressedFrame(" << stream_id << ", " << type
- << ", " << payload_len << ", " << frame_len << ")";
+ QUICHE_VLOG(1) << "OnSendCompressedFrame(" << stream_id << ", " << type
+ << ", " << payload_len << ", " << frame_len << ")";
last_payload_len_ = payload_len;
last_frame_len_ = frame_len;
}
@@ -452,8 +452,8 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
void OnReceiveCompressedFrame(SpdyStreamId stream_id,
SpdyFrameType type,
size_t frame_len) override {
- SPDY_VLOG(1) << "OnReceiveCompressedFrame(" << stream_id << ", " << type
- << ", " << frame_len << ")";
+ QUICHE_VLOG(1) << "OnReceiveCompressedFrame(" << stream_id << ", " << type
+ << ", " << frame_len << ")";
last_frame_len_ = frame_len;
}
@@ -479,8 +479,9 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
void InitHeaderStreaming(SpdyFrameType header_control_type,
SpdyStreamId stream_id) {
if (!IsDefinedFrameType(SerializeFrameType(header_control_type))) {
- SPDY_DLOG(FATAL) << "Attempted to init header streaming with "
- << "invalid control frame type: " << header_control_type;
+ QUICHE_DLOG(FATAL) << "Attempted to init header streaming with "
+ << "invalid control frame type: "
+ << header_control_type;
}
memset(header_buffer_.get(), 0, header_buffer_size_);
header_buffer_length_ = 0;
@@ -4817,8 +4818,8 @@ TEST_P(SpdyFramerTest, ProcessAllInput) {
const size_t frame1_size = frame1.size();
const size_t frame2_size = frame2.size();
- SPDY_VLOG(1) << "frame1_size = " << frame1_size;
- SPDY_VLOG(1) << "frame2_size = " << frame2_size;
+ QUICHE_VLOG(1) << "frame1_size = " << frame1_size;
+ QUICHE_VLOG(1) << "frame2_size = " << frame2_size;
std::string input_buffer;
input_buffer.append(frame1.data(), frame1_size);
@@ -4827,7 +4828,7 @@ TEST_P(SpdyFramerTest, ProcessAllInput) {
const char* buf = input_buffer.data();
const size_t buf_size = input_buffer.size();
- SPDY_VLOG(1) << "buf_size = " << buf_size;
+ QUICHE_VLOG(1) << "buf_size = " << buf_size;
size_t processed = deframer_.ProcessInput(buf, buf_size);
EXPECT_EQ(buf_size, processed);
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_header_block.cc b/chromium/net/third_party/quiche/src/spdy/core/spdy_header_block.cc
index 59a9069a220..b5790470e02 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_header_block.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_header_block.cc
@@ -10,8 +10,8 @@
#include <utility>
#include "absl/strings/str_cat.h"
+#include "common/platform/api/quiche_logging.h"
#include "spdy/platform/api/spdy_estimate_memory_usage.h"
-#include "spdy/platform/api/spdy_logging.h"
namespace spdy {
namespace {
@@ -144,14 +144,14 @@ Http2HeaderBlock::ValueProxy& Http2HeaderBlock::ValueProxy::operator=(
*spdy_header_block_value_size_ += value.size();
SpdyHeaderStorage* storage = &block_->storage_;
if (lookup_result_ == block_->map_.end()) {
- SPDY_DVLOG(1) << "Inserting: (" << key_ << ", " << value << ")";
+ QUICHE_DVLOG(1) << "Inserting: (" << key_ << ", " << value << ")";
lookup_result_ =
block_->map_
.emplace(std::make_pair(
key_, HeaderValue(storage, key_, storage->Write(value))))
.first;
} else {
- SPDY_DVLOG(1) << "Updating key: " << key_ << " with value: " << value;
+ QUICHE_DVLOG(1) << "Updating key: " << key_ << " with value: " << value;
*spdy_header_block_value_size_ -= lookup_result_->second.SizeEstimate();
lookup_result_->second = HeaderValue(storage, key_, storage->Write(value));
}
@@ -232,7 +232,7 @@ std::string Http2HeaderBlock::DebugString() const {
void Http2HeaderBlock::erase(absl::string_view key) {
auto iter = map_.find(key);
if (iter != map_.end()) {
- SPDY_DVLOG(1) << "Erasing header with name: " << key;
+ QUICHE_DVLOG(1) << "Erasing header with name: " << key;
key_size_ -= key.size();
value_size_ -= iter->second.SizeEstimate();
map_.erase(iter);
@@ -252,12 +252,12 @@ void Http2HeaderBlock::insert(const Http2HeaderBlock::value_type& value) {
auto iter = map_.find(value.first);
if (iter == map_.end()) {
- SPDY_DVLOG(1) << "Inserting: (" << value.first << ", " << value.second
- << ")";
+ QUICHE_DVLOG(1) << "Inserting: (" << value.first << ", " << value.second
+ << ")";
AppendHeader(value.first, value.second);
} else {
- SPDY_DVLOG(1) << "Updating key: " << iter->first
- << " with value: " << value.second;
+ QUICHE_DVLOG(1) << "Updating key: " << iter->first
+ << " with value: " << value.second;
value_size_ -= iter->second.SizeEstimate();
iter->second =
HeaderValue(&storage_, iter->first, storage_.Write(value.second));
@@ -266,16 +266,16 @@ void Http2HeaderBlock::insert(const Http2HeaderBlock::value_type& value) {
Http2HeaderBlock::ValueProxy Http2HeaderBlock::operator[](
const absl::string_view key) {
- SPDY_DVLOG(2) << "Operator[] saw key: " << key;
+ QUICHE_DVLOG(2) << "Operator[] saw key: " << key;
absl::string_view out_key;
auto iter = map_.find(key);
if (iter == map_.end()) {
// We write the key first, to assure that the ValueProxy has a
// reference to a valid absl::string_view in its operator=.
out_key = WriteKey(key);
- SPDY_DVLOG(2) << "Key written as: " << std::hex
- << static_cast<const void*>(key.data()) << ", " << std::dec
- << key.size();
+ QUICHE_DVLOG(2) << "Key written as: " << std::hex
+ << static_cast<const void*>(key.data()) << ", " << std::dec
+ << key.size();
} else {
out_key = iter->first;
}
@@ -288,13 +288,13 @@ void Http2HeaderBlock::AppendValueOrAddHeader(const absl::string_view key,
auto iter = map_.find(key);
if (iter == map_.end()) {
- SPDY_DVLOG(1) << "Inserting: (" << key << ", " << value << ")";
+ QUICHE_DVLOG(1) << "Inserting: (" << key << ", " << value << ")";
AppendHeader(key, value);
return;
}
- SPDY_DVLOG(1) << "Updating key: " << iter->first
- << "; appending value: " << value;
+ QUICHE_DVLOG(1) << "Updating key: " << iter->first
+ << "; appending value: " << value;
value_size_ += SeparatorForKey(key).size();
iter->second.Append(storage_.Write(value));
}
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_header_storage.cc b/chromium/net/third_party/quiche/src/spdy/core/spdy_header_storage.cc
index 207a3be6e00..e99590568b9 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_header_storage.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_header_storage.cc
@@ -2,7 +2,7 @@
#include <cstring>
-#include "spdy/platform/api/spdy_logging.h"
+#include "common/platform/api/quiche_logging.h"
namespace spdy {
namespace {
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_prefixed_buffer_reader.cc b/chromium/net/third_party/quiche/src/spdy/core/spdy_prefixed_buffer_reader.cc
index 0cb07cf48b0..767dea36074 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_prefixed_buffer_reader.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_prefixed_buffer_reader.cc
@@ -6,7 +6,7 @@
#include <new>
-#include "spdy/platform/api/spdy_logging.h"
+#include "common/platform/api/quiche_logging.h"
namespace spdy {
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol.cc b/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol.cc
index ea90b6500ed..4bde56a29d7 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol.cc
@@ -8,7 +8,7 @@
#include <ostream>
#include "absl/strings/str_cat.h"
-#include "spdy/platform/api/spdy_bug_tracker.h"
+#include "common/platform/api/quiche_bug_tracker.h"
namespace spdy {
@@ -28,7 +28,7 @@ SpdyPriority ClampSpdy3Priority(SpdyPriority priority) {
"The value of given priority shouldn't be smaller than highest "
"priority. Check this invariant explicitly.");
if (priority > kV3LowestPriority) {
- SPDY_BUG(spdy_bug_22_1)
+ QUICHE_BUG(spdy_bug_22_1)
<< "Invalid priority: " << static_cast<int>(priority);
return kV3LowestPriority;
}
@@ -37,11 +37,11 @@ SpdyPriority ClampSpdy3Priority(SpdyPriority priority) {
int ClampHttp2Weight(int weight) {
if (weight < kHttp2MinStreamWeight) {
- SPDY_BUG(spdy_bug_22_2) << "Invalid weight: " << weight;
+ QUICHE_BUG(spdy_bug_22_2) << "Invalid weight: " << weight;
return kHttp2MinStreamWeight;
}
if (weight > kHttp2MaxStreamWeight) {
- SPDY_BUG(spdy_bug_22_3) << "Invalid weight: " << weight;
+ QUICHE_BUG(spdy_bug_22_3) << "Invalid weight: " << weight;
return kHttp2MaxStreamWeight;
}
return weight;
@@ -92,7 +92,7 @@ bool IsDefinedFrameType(uint8_t frame_type_field) {
}
SpdyFrameType ParseFrameType(uint8_t frame_type_field) {
- SPDY_BUG_IF(spdy_bug_22_4, !IsDefinedFrameType(frame_type_field))
+ QUICHE_BUG_IF(spdy_bug_22_4, !IsDefinedFrameType(frame_type_field))
<< "Frame type not defined: " << static_cast<int>(frame_type_field);
return static_cast<SpdyFrameType>(frame_type_field);
}
@@ -462,7 +462,7 @@ SpdyFrameType SpdyContinuationIR::frame_type() const {
size_t SpdyContinuationIR::size() const {
// We don't need to get the size of CONTINUATION frame directly. It is
// calculated in HEADERS or PUSH_PROMISE frame.
- SPDY_DLOG(WARNING) << "Shouldn't not call size() for CONTINUATION frame.";
+ QUICHE_DLOG(WARNING) << "Shouldn't not call size() for CONTINUATION frame.";
return 0;
}
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol.h b/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol.h
index d4a671b8933..16d6b9a7ecd 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol.h
@@ -21,11 +21,10 @@
#include "absl/strings/string_view.h"
#include "common/platform/api/quiche_export.h"
+#include "common/platform/api/quiche_logging.h"
#include "spdy/core/spdy_alt_svc_wire_format.h"
#include "spdy/core/spdy_bitmasks.h"
#include "spdy/core/spdy_header_block.h"
-#include "spdy/platform/api/spdy_bug_tracker.h"
-#include "spdy/platform/api/spdy_logging.h"
namespace spdy {
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol_test.cc b/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol_test.cc
index 966c4716c75..dbea0e328ca 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol_test.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol_test.cc
@@ -9,9 +9,9 @@
#include <memory>
#include "common/platform/api/quiche_test.h"
+#include "common/platform/api/quiche_test_helpers.h"
#include "spdy/core/spdy_bitmasks.h"
#include "spdy/core/spdy_test_utils.h"
-#include "spdy/platform/api/spdy_test_helpers.h"
namespace spdy {
@@ -31,16 +31,16 @@ std::ostream& operator<<(std::ostream& os,
namespace test {
TEST(SpdyProtocolTest, ClampSpdy3Priority) {
- EXPECT_SPDY_BUG(EXPECT_EQ(7, ClampSpdy3Priority(8)), "Invalid priority: 8");
+ EXPECT_QUICHE_BUG(EXPECT_EQ(7, ClampSpdy3Priority(8)), "Invalid priority: 8");
EXPECT_EQ(kV3LowestPriority, ClampSpdy3Priority(kV3LowestPriority));
EXPECT_EQ(kV3HighestPriority, ClampSpdy3Priority(kV3HighestPriority));
}
TEST(SpdyProtocolTest, ClampHttp2Weight) {
- EXPECT_SPDY_BUG(EXPECT_EQ(kHttp2MinStreamWeight, ClampHttp2Weight(0)),
- "Invalid weight: 0");
- EXPECT_SPDY_BUG(EXPECT_EQ(kHttp2MaxStreamWeight, ClampHttp2Weight(300)),
- "Invalid weight: 300");
+ EXPECT_QUICHE_BUG(EXPECT_EQ(kHttp2MinStreamWeight, ClampHttp2Weight(0)),
+ "Invalid weight: 0");
+ EXPECT_QUICHE_BUG(EXPECT_EQ(kHttp2MaxStreamWeight, ClampHttp2Weight(300)),
+ "Invalid weight: 300");
EXPECT_EQ(kHttp2MinStreamWeight, ClampHttp2Weight(kHttp2MinStreamWeight));
EXPECT_EQ(kHttp2MaxStreamWeight, ClampHttp2Weight(kHttp2MaxStreamWeight));
}
@@ -175,14 +175,14 @@ TEST(SpdyStreamPrecedenceTest, Basic) {
}
TEST(SpdyStreamPrecedenceTest, Clamping) {
- EXPECT_SPDY_BUG(EXPECT_EQ(7, SpdyStreamPrecedence(8).spdy3_priority()),
- "Invalid priority: 8");
- EXPECT_SPDY_BUG(EXPECT_EQ(kHttp2MinStreamWeight,
- SpdyStreamPrecedence(3, 0, false).weight()),
- "Invalid weight: 0");
- EXPECT_SPDY_BUG(EXPECT_EQ(kHttp2MaxStreamWeight,
- SpdyStreamPrecedence(3, 300, false).weight()),
- "Invalid weight: 300");
+ EXPECT_QUICHE_BUG(EXPECT_EQ(7, SpdyStreamPrecedence(8).spdy3_priority()),
+ "Invalid priority: 8");
+ EXPECT_QUICHE_BUG(EXPECT_EQ(kHttp2MinStreamWeight,
+ SpdyStreamPrecedence(3, 0, false).weight()),
+ "Invalid weight: 0");
+ EXPECT_QUICHE_BUG(EXPECT_EQ(kHttp2MaxStreamWeight,
+ SpdyStreamPrecedence(3, 300, false).weight()),
+ "Invalid weight: 300");
}
TEST(SpdyStreamPrecedenceTest, Copying) {
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol_test_utils.cc b/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol_test_utils.cc
index 63917499eb9..1888176d673 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol_test_utils.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol_test_utils.cc
@@ -17,7 +17,7 @@ namespace test {
::testing::AssertionResult VerifySpdyFrameWithHeaderBlockIREquals(
const SpdyFrameWithHeaderBlockIR& expected,
const SpdyFrameWithHeaderBlockIR& actual) {
- SPDY_VLOG(1) << "VerifySpdyFrameWithHeaderBlockIREquals";
+ QUICHE_VLOG(1) << "VerifySpdyFrameWithHeaderBlockIREquals";
VERIFY_TRUE(actual.header_block() == expected.header_block());
return ::testing::AssertionSuccess();
}
@@ -40,7 +40,7 @@ namespace test {
::testing::AssertionResult VerifySpdyFrameIREquals(const SpdyDataIR& expected,
const SpdyDataIR& actual) {
- SPDY_VLOG(1) << "VerifySpdyFrameIREquals SpdyDataIR";
+ QUICHE_VLOG(1) << "VerifySpdyFrameIREquals SpdyDataIR";
VERIFY_EQ(expected.stream_id(), actual.stream_id());
VERIFY_EQ(expected.fin(), actual.fin());
VERIFY_EQ(expected.data_len(), actual.data_len());
@@ -56,7 +56,7 @@ namespace test {
::testing::AssertionResult VerifySpdyFrameIREquals(const SpdyGoAwayIR& expected,
const SpdyGoAwayIR& actual) {
- SPDY_VLOG(1) << "VerifySpdyFrameIREquals SpdyGoAwayIR";
+ QUICHE_VLOG(1) << "VerifySpdyFrameIREquals SpdyGoAwayIR";
VERIFY_EQ(expected.last_good_stream_id(), actual.last_good_stream_id());
VERIFY_EQ(expected.error_code(), actual.error_code());
VERIFY_EQ(expected.description(), actual.description());
@@ -66,7 +66,7 @@ namespace test {
::testing::AssertionResult VerifySpdyFrameIREquals(
const SpdyHeadersIR& expected,
const SpdyHeadersIR& actual) {
- SPDY_VLOG(1) << "VerifySpdyFrameIREquals SpdyHeadersIR";
+ QUICHE_VLOG(1) << "VerifySpdyFrameIREquals SpdyHeadersIR";
VERIFY_EQ(expected.stream_id(), actual.stream_id());
VERIFY_EQ(expected.fin(), actual.fin());
VERIFY_SUCCESS(VerifySpdyFrameWithHeaderBlockIREquals(expected, actual));
@@ -80,7 +80,7 @@ namespace test {
::testing::AssertionResult VerifySpdyFrameIREquals(const SpdyPingIR& expected,
const SpdyPingIR& actual) {
- SPDY_VLOG(1) << "VerifySpdyFrameIREquals SpdyPingIR";
+ QUICHE_VLOG(1) << "VerifySpdyFrameIREquals SpdyPingIR";
VERIFY_EQ(expected.id(), actual.id());
VERIFY_EQ(expected.is_ack(), actual.is_ack());
return ::testing::AssertionSuccess();
@@ -89,7 +89,7 @@ namespace test {
::testing::AssertionResult VerifySpdyFrameIREquals(
const SpdyPriorityIR& expected,
const SpdyPriorityIR& actual) {
- SPDY_VLOG(1) << "VerifySpdyFrameIREquals SpdyPriorityIR";
+ QUICHE_VLOG(1) << "VerifySpdyFrameIREquals SpdyPriorityIR";
VERIFY_EQ(expected.stream_id(), actual.stream_id());
VERIFY_SUCCESS(VerifySpdyFrameWithPriorityIREquals(expected, actual));
return ::testing::AssertionSuccess();
@@ -98,7 +98,7 @@ namespace test {
::testing::AssertionResult VerifySpdyFrameIREquals(
const SpdyPushPromiseIR& expected,
const SpdyPushPromiseIR& actual) {
- SPDY_VLOG(1) << "VerifySpdyFrameIREquals SpdyPushPromiseIR";
+ QUICHE_VLOG(1) << "VerifySpdyFrameIREquals SpdyPushPromiseIR";
VERIFY_EQ(expected.stream_id(), actual.stream_id());
VERIFY_SUCCESS(VerifySpdyFrameWithPaddingIREquals(expected, actual));
VERIFY_EQ(expected.promised_stream_id(), actual.promised_stream_id());
@@ -109,7 +109,7 @@ namespace test {
::testing::AssertionResult VerifySpdyFrameIREquals(
const SpdyRstStreamIR& expected,
const SpdyRstStreamIR& actual) {
- SPDY_VLOG(1) << "VerifySpdyFrameIREquals SpdyRstStreamIR";
+ QUICHE_VLOG(1) << "VerifySpdyFrameIREquals SpdyRstStreamIR";
VERIFY_EQ(expected.stream_id(), actual.stream_id());
VERIFY_EQ(expected.error_code(), actual.error_code());
return ::testing::AssertionSuccess();
@@ -118,7 +118,7 @@ namespace test {
::testing::AssertionResult VerifySpdyFrameIREquals(
const SpdySettingsIR& expected,
const SpdySettingsIR& actual) {
- SPDY_VLOG(1) << "VerifySpdyFrameIREquals SpdySettingsIR";
+ QUICHE_VLOG(1) << "VerifySpdyFrameIREquals SpdySettingsIR";
// Note, ignoring non-HTTP/2 fields such as clear_settings.
VERIFY_EQ(expected.is_ack(), actual.is_ack());
@@ -145,7 +145,7 @@ namespace test {
::testing::AssertionResult VerifySpdyFrameIREquals(
const SpdyWindowUpdateIR& expected,
const SpdyWindowUpdateIR& actual) {
- SPDY_VLOG(1) << "VerifySpdyFrameIREquals SpdyWindowUpdateIR";
+ QUICHE_VLOG(1) << "VerifySpdyFrameIREquals SpdyWindowUpdateIR";
VERIFY_EQ(expected.stream_id(), actual.stream_id());
VERIFY_EQ(expected.delta(), actual.delta());
return ::testing::AssertionSuccess();
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol_test_utils.h b/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol_test_utils.h
index daccebb06a4..de716d50984 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol_test_utils.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol_test_utils.h
@@ -20,10 +20,10 @@
#include <typeinfo>
#include "http2/platform/api/http2_test_helpers.h"
+#include "common/platform/api/quiche_logging.h"
#include "common/platform/api/quiche_test.h"
#include "spdy/core/spdy_protocol.h"
#include "spdy/core/spdy_test_utils.h"
-#include "spdy/platform/api/spdy_logging.h"
namespace spdy {
namespace test {
@@ -38,7 +38,7 @@ namespace test {
template <class T>
::testing::AssertionResult VerifySpdyFrameWithPaddingIREquals(const T& expected,
const T& actual) {
- SPDY_VLOG(1) << "VerifySpdyFrameWithPaddingIREquals";
+ QUICHE_VLOG(1) << "VerifySpdyFrameWithPaddingIREquals";
VERIFY_EQ(expected.padded(), actual.padded());
if (expected.padded()) {
VERIFY_EQ(expected.padding_payload_len(), actual.padding_payload_len());
@@ -52,7 +52,7 @@ template <class T>
::testing::AssertionResult VerifySpdyFrameWithPriorityIREquals(
const T& expected,
const T& actual) {
- SPDY_VLOG(1) << "VerifySpdyFrameWithPriorityIREquals";
+ QUICHE_VLOG(1) << "VerifySpdyFrameWithPriorityIREquals";
VERIFY_EQ(expected.parent_stream_id(), actual.parent_stream_id());
VERIFY_EQ(expected.weight(), actual.weight());
VERIFY_EQ(expected.exclusive(), actual.exclusive());
@@ -123,12 +123,12 @@ template <class E>
::testing::AssertionResult VerifySpdyFrameIREquals(const E* expected,
const SpdyFrameIR* actual) {
if (expected == nullptr || actual == nullptr) {
- SPDY_VLOG(1) << "VerifySpdyFrameIREquals one null";
+ QUICHE_VLOG(1) << "VerifySpdyFrameIREquals one null";
VERIFY_EQ(expected, nullptr);
VERIFY_EQ(actual, nullptr);
return ::testing::AssertionSuccess();
}
- SPDY_VLOG(1) << "VerifySpdyFrameIREquals not null";
+ QUICHE_VLOG(1) << "VerifySpdyFrameIREquals not null";
VERIFY_EQ(actual->frame_type(), expected->frame_type());
const E* actual2 = static_cast<const E*>(actual);
return VerifySpdyFrameIREquals(*expected, *actual2);
@@ -139,7 +139,7 @@ template <class E>
template <class E>
::testing::AssertionResult VerifySpdyFrameIREquals(const E& expected,
const SpdyFrameIR* actual) {
- SPDY_VLOG(1) << "VerifySpdyFrameIREquals";
+ QUICHE_VLOG(1) << "VerifySpdyFrameIREquals";
return VerifySpdyFrameIREquals(&expected, actual);
}
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_simple_arena.cc b/chromium/net/third_party/quiche/src/spdy/core/spdy_simple_arena.cc
index 15c8fea2614..4df224629c6 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_simple_arena.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_simple_arena.cc
@@ -7,7 +7,7 @@
#include <algorithm>
#include <cstring>
-#include "spdy/platform/api/spdy_logging.h"
+#include "common/platform/api/quiche_logging.h"
namespace spdy {
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_test_utils.cc b/chromium/net/third_party/quiche/src/spdy/core/spdy_test_utils.cc
index 482d8e24263..4ea1ce82895 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_test_utils.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_test_utils.cc
@@ -11,9 +11,9 @@
#include <utility>
#include <vector>
+#include "common/platform/api/quiche_logging.h"
#include "common/platform/api/quiche_test.h"
#include "common/quiche_endian.h"
-#include "spdy/platform/api/spdy_logging.h"
namespace spdy {
namespace test {
@@ -27,7 +27,7 @@ std::string HexDumpWithMarks(const unsigned char* data,
const int kSizeLimit = 1024;
if (length > kSizeLimit || mark_length > kSizeLimit) {
- SPDY_LOG(ERROR) << "Only dumping first " << kSizeLimit << " bytes.";
+ QUICHE_LOG(ERROR) << "Only dumping first " << kSizeLimit << " bytes.";
length = std::min(length, kSizeLimit);
mark_length = std::min(mark_length, kSizeLimit);
}
diff --git a/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_bug_tracker.h b/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_bug_tracker.h
deleted file mode 100644
index f00bbc8b376..00000000000
--- a/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_bug_tracker.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_SPDY_PLATFORM_API_SPDY_BUG_TRACKER_H_
-#define QUICHE_SPDY_PLATFORM_API_SPDY_BUG_TRACKER_H_
-
-#include "net/spdy/platform/impl/spdy_bug_tracker_impl.h"
-
-#define SPDY_BUG SPDY_BUG_IMPL
-#define SPDY_BUG_IF(bug_id, condition) SPDY_BUG_IF_IMPL(bug_id, condition)
-
-#define FLAGS_spdy_always_log_bugs_for_tests \
- FLAGS_spdy_always_log_bugs_for_tests_impl
-
-#endif // QUICHE_SPDY_PLATFORM_API_SPDY_BUG_TRACKER_H_
diff --git a/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_containers.h b/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_containers.h
index 9e3813f5b42..2adf3f4b87a 100644
--- a/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_containers.h
+++ b/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_containers.h
@@ -13,12 +13,6 @@ namespace spdy {
template <typename Key, typename Value, typename Hash, typename Eq>
using SpdyLinkedHashMap = SpdyLinkedHashMapImpl<Key, Value, Hash, Eq>;
-// Used for maps that are typically small, then it is faster than (for example)
-// hash_map which is optimized for large data sets. SpdySmallMap upgrades itself
-// automatically to a SpdySmallMapImpl-specified map when it runs out of space.
-template <typename Key, typename Value, int Size>
-using SpdySmallMap = SpdySmallMapImpl<Key, Value, Size>;
-
} // namespace spdy
#endif // QUICHE_SPDY_PLATFORM_API_SPDY_CONTAINERS_H_
diff --git a/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_flag_utils.h b/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_flag_utils.h
deleted file mode 100644
index 07c97fbc343..00000000000
--- a/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_flag_utils.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// 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_SPDY_PLATFORM_API_SPDY_FLAG_UTILS_H_
-#define QUICHE_SPDY_PLATFORM_API_SPDY_FLAG_UTILS_H_
-
-#include "common/platform/api/quiche_flag_utils.h"
-
-#define SPDY_RELOADABLE_FLAG_COUNT QUICHE_RELOADABLE_FLAG_COUNT
-#define SPDY_RELOADABLE_FLAG_COUNT_N QUICHE_RELOADABLE_FLAG_COUNT_N
-
-#define SPDY_RESTART_FLAG_COUNT QUICHE_RESTART_FLAG_COUNT
-#define SPDY_RESTART_FLAG_COUNT_N QUICHE_RESTART_FLAG_COUNT_N
-
-#define SPDY_CODE_COUNT QUICHE_CODE_COUNT
-#define SPDY_CODE_COUNT_N QUICHE_CODE_COUNT_N
-
-#endif // QUICHE_SPDY_PLATFORM_API_SPDY_FLAG_UTILS_H_
diff --git a/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_flags.h b/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_flags.h
deleted file mode 100644
index f8cb5a60d5b..00000000000
--- a/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_flags.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 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.
-
-#ifndef QUICHE_SPDY_PLATFORM_API_SPDY_FLAGS_H_
-#define QUICHE_SPDY_PLATFORM_API_SPDY_FLAGS_H_
-
-#include "common/platform/api/quiche_flags.h"
-
-#define GetSpdyReloadableFlag(flag) GetQuicheReloadableFlag(spdy, flag)
-#define SetSpdyReloadableFlag(flag, value) \
- SetQuicheReloadableFlag(spdy, flag, value)
-#define GetSpdyRestartFlag(flag) GetQuicheRestartFlag(spdy, flag)
-#define SetSpdyRestartFlag(flag, value) SetQuicheRestartFlag(spdy, flag, value)
-#define GetSpdyFlag(flag) GetQuicheFlag(flag)
-#define SetSpdyFlag(flag, value) SetQuicheFlag(flag, value)
-
-#endif // QUICHE_SPDY_PLATFORM_API_SPDY_FLAGS_H_
diff --git a/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_logging.h b/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_logging.h
deleted file mode 100644
index c1f5268e287..00000000000
--- a/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_logging.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// 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_SPDY_PLATFORM_API_SPDY_LOGGING_H_
-#define QUICHE_SPDY_PLATFORM_API_SPDY_LOGGING_H_
-
-#include "common/platform/api/quiche_logging.h"
-
-#define SPDY_LOG(severity) QUICHE_LOG(severity)
-
-#define SPDY_VLOG(verbose_level) QUICHE_VLOG(verbose_level)
-
-#define SPDY_DLOG(severity) QUICHE_DLOG(severity)
-
-#define SPDY_DLOG_IF(severity, condition) QUICHE_DLOG_IF(severity, condition)
-
-#define SPDY_DVLOG(verbose_level) QUICHE_DVLOG(verbose_level)
-
-#define SPDY_DVLOG_IF(verbose_level, condition) \
- QUICHE_DVLOG_IF(verbose_level, condition)
-
-#endif // QUICHE_SPDY_PLATFORM_API_SPDY_LOGGING_H_
diff --git a/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_string_utils.h b/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_string_utils.h
index 178415b0ed6..83660bab06f 100644
--- a/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_string_utils.h
+++ b/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_string_utils.h
@@ -6,29 +6,12 @@
#define QUICHE_SPDY_PLATFORM_API_SPDY_STRING_UTILS_H_
#include <string>
-#include <utility>
#include "absl/strings/string_view.h"
#include "net/spdy/platform/impl/spdy_string_utils_impl.h"
namespace spdy {
-inline char SpdyHexDigitToInt(char c) {
- return SpdyHexDigitToIntImpl(c);
-}
-
-inline std::string SpdyHexDecode(absl::string_view data) {
- return SpdyHexDecodeImpl(data);
-}
-
-inline bool SpdyHexDecodeToUInt32(absl::string_view data, uint32_t* out) {
- return SpdyHexDecodeToUInt32Impl(data, out);
-}
-
-inline std::string SpdyHexEncode(const char* bytes, size_t size) {
- return SpdyHexEncodeImpl(bytes, size);
-}
-
inline std::string SpdyHexDump(absl::string_view data) {
return SpdyHexDumpImpl(data);
}
diff --git a/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_string_utils_test.cc b/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_string_utils_test.cc
deleted file mode 100644
index cb73a9b2ece..00000000000
--- a/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_string_utils_test.cc
+++ /dev/null
@@ -1,78 +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.
-
-#include "spdy/platform/api/spdy_string_utils.h"
-
-#include <cstdint>
-
-#include "absl/strings/string_view.h"
-#include "common/platform/api/quiche_test.h"
-
-namespace spdy {
-namespace test {
-namespace {
-
-TEST(SpdyStringUtilsTest, SpdyHexDigitToInt) {
- EXPECT_EQ(0, SpdyHexDigitToInt('0'));
- EXPECT_EQ(1, SpdyHexDigitToInt('1'));
- EXPECT_EQ(2, SpdyHexDigitToInt('2'));
- EXPECT_EQ(3, SpdyHexDigitToInt('3'));
- EXPECT_EQ(4, SpdyHexDigitToInt('4'));
- EXPECT_EQ(5, SpdyHexDigitToInt('5'));
- EXPECT_EQ(6, SpdyHexDigitToInt('6'));
- EXPECT_EQ(7, SpdyHexDigitToInt('7'));
- EXPECT_EQ(8, SpdyHexDigitToInt('8'));
- EXPECT_EQ(9, SpdyHexDigitToInt('9'));
-
- EXPECT_EQ(10, SpdyHexDigitToInt('a'));
- EXPECT_EQ(11, SpdyHexDigitToInt('b'));
- EXPECT_EQ(12, SpdyHexDigitToInt('c'));
- EXPECT_EQ(13, SpdyHexDigitToInt('d'));
- EXPECT_EQ(14, SpdyHexDigitToInt('e'));
- EXPECT_EQ(15, SpdyHexDigitToInt('f'));
-
- EXPECT_EQ(10, SpdyHexDigitToInt('A'));
- EXPECT_EQ(11, SpdyHexDigitToInt('B'));
- EXPECT_EQ(12, SpdyHexDigitToInt('C'));
- EXPECT_EQ(13, SpdyHexDigitToInt('D'));
- EXPECT_EQ(14, SpdyHexDigitToInt('E'));
- EXPECT_EQ(15, SpdyHexDigitToInt('F'));
-}
-
-TEST(SpdyStringUtilsTest, SpdyHexDecodeToUInt32) {
- uint32_t out;
- EXPECT_TRUE(SpdyHexDecodeToUInt32("0", &out));
- EXPECT_EQ(0u, out);
- EXPECT_TRUE(SpdyHexDecodeToUInt32("00", &out));
- EXPECT_EQ(0u, out);
- EXPECT_TRUE(SpdyHexDecodeToUInt32("0000000", &out));
- EXPECT_EQ(0u, out);
- EXPECT_TRUE(SpdyHexDecodeToUInt32("00000000", &out));
- EXPECT_EQ(0u, out);
- EXPECT_TRUE(SpdyHexDecodeToUInt32("1", &out));
- EXPECT_EQ(1u, out);
- EXPECT_TRUE(SpdyHexDecodeToUInt32("ffffFFF", &out));
- EXPECT_EQ(0xFFFFFFFu, out);
- EXPECT_TRUE(SpdyHexDecodeToUInt32("fFfFffFf", &out));
- EXPECT_EQ(0xFFFFFFFFu, out);
- EXPECT_TRUE(SpdyHexDecodeToUInt32("01AEF", &out));
- EXPECT_EQ(0x1AEFu, out);
- EXPECT_TRUE(SpdyHexDecodeToUInt32("abcde", &out));
- EXPECT_EQ(0xABCDEu, out);
-
- EXPECT_FALSE(SpdyHexDecodeToUInt32("", &out));
- EXPECT_FALSE(SpdyHexDecodeToUInt32("111111111", &out));
- EXPECT_FALSE(SpdyHexDecodeToUInt32("1111111111", &out));
- EXPECT_FALSE(SpdyHexDecodeToUInt32("0x1111", &out));
-}
-
-TEST(SpdyStringUtilsTest, SpdyHexEncode) {
- unsigned char bytes[] = {0x01, 0xff, 0x02, 0xfe, 0x03, 0x80, 0x81};
- EXPECT_EQ("01ff02fe038081",
- SpdyHexEncode(reinterpret_cast<char*>(bytes), sizeof(bytes)));
-}
-
-} // namespace
-} // namespace test
-} // namespace spdy
diff --git a/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_test_helpers.h b/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_test_helpers.h
deleted file mode 100644
index 367d330b6c9..00000000000
--- a/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_test_helpers.h
+++ /dev/null
@@ -1,12 +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_SPDY_PLATFORM_API_SPDY_TEST_HELPERS_H_
-#define QUICHE_SPDY_PLATFORM_API_SPDY_TEST_HELPERS_H_
-
-#include "net/spdy/platform/impl/spdy_test_helpers_impl.h"
-
-#define EXPECT_SPDY_BUG EXPECT_SPDY_BUG_IMPL
-
-#endif // QUICHE_SPDY_PLATFORM_API_SPDY_TEST_HELPERS_H_
diff --git a/chromium/net/third_party/uri_template/DIR_METADATA b/chromium/net/third_party/uri_template/DIR_METADATA
index 23af0ebe901..c56cf205cc7 100644
--- a/chromium/net/third_party/uri_template/DIR_METADATA
+++ b/chromium/net/third_party/uri_template/DIR_METADATA
@@ -1,10 +1,10 @@
# Metadata information for this directory.
#
# For more information on DIR_METADATA files, see:
-# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md
+# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md
#
# For the schema of this file, see Metadata message:
-# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto
+# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto
monorail {
component: "Internals>Network>DNS"